This week's book giveaway is in the Design forum.
We're giving away four copies of Design for the Mind and have Victor S. Yocco on-line!
See this thread for details.
Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

unit testing class name preferences: TestCow vs. CowTest

 
paul wheaton
Trailboss
Pie
Posts: 21379
Firefox Browser IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
prefix: TestCow
  • tests are in the same dir, they are seperated in a directory view - easy to find files without having to pick through the tests.
  • Easier to pick files in an IDE - Typing "Co" would bring up just "Cow" instead of "Cow" and "CowTest"


  • postfix: CowTest
  • if tests are in the same dir, they are mixed in a directory view - easy to spot classes with no test.
  • More OO - class name is more of a noun (object) than a verb (procedural).


  • What is your preference?
    [ April 14, 2003: Message edited by: Paul Wheaton ]
     
    Max Habibi
    town drunk
    ( and author)
    Sheriff
    Posts: 4118
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    1. It's more JUnit friendly.
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Jim Yingst
    Wanderer
    Sheriff
    Posts: 18671
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    [Max]: 1. It's more JUnit friendly.
    It is? We're talking about class names, not method names, right? Most examples I've seen for JUnit class names end in Test, indicating that they extend TestCase (which paradoxically doesn't end in Test, but it's the exception). Am I missing something?
    I prefer CowTest over TestCow, as CowTest sounds like a noun, as it should. Paul's other concerns can be alleviated by putting the test classes in a separate directory as God intended.
    One other problem with TextCow is that, while it does put all the Test stuff in one place when you sort by alphabetical order, it also may encourage you to overlook some non-test stuff if it begins with U, V, W, X, Y, Z. Or quite a few possible T words as well. Cleaner and more reliable to just create a separate namespace if that's what you want. Plus, I see at least as much benefit in putting CowTest next to Cow as I do in putting TestCow next to TestDog.
    [ April 14, 2003: Message edited by: Jim Yingst ]
     
    Frank Carver
    Sheriff
    Posts: 6920
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I'd use CowTest.
    More than that, I've taken to putting all my tests into a "tests" package for at least the last couple years now. It's great, I can re-use tests between projects (and test utilities, such as dumping maps, count an iterator etc.) just by copying.
    More than that, I've taken to putting the tests under a completely different directory structure so ant knows not to build them into the deliverable:
    /appname
    | /src
    | | /delivery
    | | | /java
    | | | | /com
    | | | | | /efsol
    | | | | | | /appname
    | | | | | | | Foo.java
    | | | | | | | Bar.java
    | | | /files
    | | | | index.html etc.
    | | /test
    | | | /java
    | | | | /tests
    | | | | | AllTests.java
    | | | | | CowTest.java
    | | | | | TestUtils.java
    | | | /files
    | | | | foo.prp
    | | | | bar.prp
    | build.xml
    /build
    /lib
    Mixing in the test cases with the delivered code seems like a configuration management nightmare to me!
    [ April 14, 2003: Message edited by: Frank Carver ]
     
    Jessica Sant
    Sheriff
    Posts: 4313
    Android IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    we do similar to Frank.... except you basically recreate the package structure of the "src" in the "test" folder -- that way your tests will have access to protected/pacakge methods and you can make your tests more fine-grained... so in our scenario the environment looks like this:
    /appname
    | /src
    | | /delivery
    | | | /java
    | | | | /com
    | | | | | /efsol
    | | | | | | /appname
    | | | | | | | Foo.java
    | | | | | | | Bar.java
    | | | /files
    | | | | index.html etc.
    | | /test
    | | | /java
    | | | | /com
    | | | | | /efsol
    | | | | | | /appname
    | | | | | | | FooTest.java
    | | | | | | | BarTest.java
    | | | /files
    | | | | foo.prp
    | | | | bar.prp
    | build.xml
    /build
    /lib
     
    Randall Twede
    Ranch Hand
    Posts: 4369
    3
    Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    i cant really speak to the actual question but i do want to comment on which sounds more like a noun. to me, a test cow is the cow you use for testing purposes. a cow test is a test that you make a cow perform. which sounds more like a noun to you?
     
    Frank Carver
    Sheriff
    Posts: 6920
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    we do similar to Frank.... except you basically recreate the package structure of the "src" in the "test" folder -- that way your tests will have access to protected/pacakge methods and you can make your tests more fine-grained
    I used to do that, but I found it very clumsy. I seemed to be always fiddling around changing package statements in the test code whenever I created a new project or moved/renamed packages inside the application.
    I have also found that I dislike designing or working on code where you need to be in the same package to test it. For me, things that are testable should be public. If I find I need to test something which is private or protected, then I either make it public (if it can't leave the object in an inconsistent state), or split the class into smaller ones which are testable using their public interface.
    I also found that putting the test code in the same package as some of the code usually means that it is not in the same package as some other code. I like to be free in my my test code to test user operations (typically using objects of several classes at once), not to be tied to just testing the methods of one class or one package.
    Have you not encountered any of these problems?
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Frank Carver:
    Mixing in the test cases with the delivered code seems like a configuration management nightmare to me!

    Unless you don't mind delivering your test code. Sometimes it can be very handy to run the test suite at the customers installation site - you might find some of the tests failing because of a slightly different JDK installed...
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Frank Carver:
    I have also found that I dislike designing or working on code where you need to be in the same package to test it. For me, things that are testable should be public. If I find I need to test something which is private or protected, then I either make it public (if it can't leave the object in an inconsistent state), or split the class into smaller ones which are testable using their public interface.

    I totally agree!
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Randall Twede:
    to me, a test cow is the cow you use for testing purposes. a cow test is a test that you make a cow perform.

    Agreed. TestCow sounds very much similar to a DummyCow, MockCow etc.
    CowTest sounds like (a) Test(s) for a cow.
     
    Matthew Phillips
    Ranch Hand
    Posts: 2676
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I like CowTest for the very reason that the name is descriptive of a test that I am giving to a cow. I generally do my directory structure the same way Frank does.
     
    Nathan Pruett
    Bartender
    Posts: 4121
    IntelliJ IDE Java Spring
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I prefer CowTest too.

    As another option in the "how to set up directories for test cases" argument, I've been on projects that have used both approches to unit testing. Some put unit tests in another package totally ( i.e. "package test.com.whatever.stuff;" ), this is good if you only need (or want) to test the public interfaces. Some put them in a directory called test and had the same package structure as the code they were testing, this lets you call package private and protected methods. One project also made all the test cases inner classes of the classes they tested. This let them test any method of the class. When it was time for a final build, there was an extra Ant task that went through the build directory and deleted all "*Test.class" files before the build was packaged.
     
    Frank Carver
    Sheriff
    Posts: 6920
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    One project also made all the test cases inner classes of the classes they tested.
    I've seen this too, but usually accompanied by a misunderstanding of what testing is about. These "embedded test cases" were typically full of copy-n-pasted tests of accessors/mutators, and usually one test method for each of the real methods of the class. Unfortunately, this often lead to a sort of "test blindness" where the vital tests of the integration between objects in a wider context were ignored.
    It also has the unfortunate side effect that source files can become swamped with huge amounts more test code than "real" code, making it much harder to find things and complicating the version control process. May I suggest that if the "real" code were to grow that big, we would consider factoring it out into separate classes. So why should "test" code be exempt from that pressure?
     
    Thomas Paul
    mister krabs
    Ranch Hand
    Posts: 13974
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It also has the unfortunate side effect that source files can become swamped with huge amounts more test code than "real" code, making it much harder to find things and complicating the version control process.
    I agree that test code should not be in an inner member class but not for this reason. The whole idea of an inner member class is to isolate chunks of code. There is no reason that an inner member class can't simply be moved to the bottom of your class.
    The advantage of the inner member class for testing is that it forces you to keep it up to date (somewhat) because if you change method names or variable names your code doesn't compile anymore.
     
    Jessica Sant
    Sheriff
    Posts: 4313
    Android IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Just thought I'd add some comments from another source... Right now I'm reading O'Reilly's Java Extreme Programming Cookbook.
    Recipe 4.10 covers Test Naming Conventions:
    They argue that they prefer TestCow rather than CowTest. They use IntelliJ and find that its easier to search for all test cases when they all start with the word "Test" -- they see the main advantage of naming things like CowTest is so you can easily see which classes don't have associated Test Cases.
    They also comment on my practice of having a seperate, parallel directory structure for all Test Cases. They think this is a bad idea 'cause you have to look in two locations to see the tests, and they add you can easily exclude all Test Cases from being included in a build using Ant's <exclude name="**/Test*.java"/> command
     
    Greg Charles
    Sheriff
    Posts: 2985
    12
    Firefox Browser IntelliJ IDE Java Mac Ruby
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    O'Reilly authors notwithstanding, I like having the separate parallel directory structure for test cases. I use JBuilder and this is its preferred structure as well. I'm not sure I understand their criticism. You have to look in two places for test code? No, you only look in the test directory. True, the code you're testing is in a different directory, but so what? It's going to be in a different file anyway.
    As for TestCow vs. CowTest, I have tended to TestCow, but after reading this thread, I think CowTest makes more sense. Another consideration is if your test used inner classes. (OK, maybe its not likely, but it could happen.) An Ant pattern **/Test*.class would still match TestCow$InnerClass.class, but **/*Test.class wouldn't match CowTest$InnerClass.class. Presumably, your inner class wouldn't be a JUnit Test*, so that's another argument for CowTest.

    * If it were, you could call it InnerClassTest and the pattern would still work.
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Jessica Sant:
    They argue that they prefer TestCow rather than CowTest. They use IntelliJ and find that its easier to search for all test cases when they all start with the word "Test"

    I don't remember to ever have wanted to do this. Why would you?
    If you would want to, there are certainly other strategies to get the same result, too. What about searching for "extends TestCase", or using Eclipses "Type Hierarchy" view?
    they add you can easily exclude all Test Cases from being included in a build using Ant's <exclude name="**/Test*.java"/> command

    Of course that would also exclude Testosterone.java ... :roll:
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic