Separation of JUnit classes into special test package? - java

I am learning the concepts of Test-Driven Development through reading the Craftsman articles (click Craftsman under By Topic) recommended in an answer to my previous question, "Sample project for learning JUnit and proper software engineering". I love it so far!
But now I want to sit down and try it myself. I have a question that I hope will need only a simple answer.
How do you organize your JUnit test classes and your actual code? I'm talking mainly about the package structure, but any other concepts of note would be helpful too.
Do you put test classes in org.myname.project.test.* and normal code in org.myname.project.*? Do you put the test classes right alongside the normal classes? Do you prefer to prefix the class names with Test rather than suffix them?
I know this seems like the kind of thing I shouldn't worry about so soon, but I am a very organization-centric person. I'm almost the kind of person that spends more time figuring out methods to keep track of what to get done, rather than actually getting things done.
And I have a project that is currently neatly divided up into packages, but the project became a mess. Instead of trying to refactor everything and write tests, I want to start fresh, tests first and all. But first I need to know where my tests go.
edit: I totally forgot about Maven, but it seems a majority of you are using it! In the past I had a specific use case where Maven completely broke down on me but Ant gave me the flexibility I needed, so I ended up attached to Ant, but I'm thinking maybe I was just taking the wrong approach. I think I'll give Maven another try because it sounds like it will go well with test-driven development.

I prefer putting the test classes into the same package as the project classes they test, but in a different physical directory, like:
myproject/src/com/foo/Bar.java
myproject/test/com/foo/BarTest.java
In a Maven project it would look like this:
myproject/src/main/java/com/foo/Bar.java
myproject/src/test/java/com/foo/BarTest.java
The main point in this is that my test classes can access (and test!) package-scope classes and members.
As the above example shows, my test classes have the name of the tested class plus Test as a suffix. This helps finding them quickly - it's not very funny to try searching among a couple of hundred test classes, each of whose name starts with Test...
Update inspired by #Ricket's comment: this way test classes (typically) show up right after their tested buddy in a project-wise alphabetic listing of class names. (Funny that I am benefiting from this day by day, without having consciously realized how...)
Update2: A lot of developers (including myself) like Maven, but there seems to be at least as many who don't. IMHO it is very useful for "mainstream" Java projects (I would put about 90% of projects into this category... but the other 10% is still a sizeable minority). It is easy to use if one can accept the Maven conventions; however if not, it makes life a miserable struggle. Maven seems to be difficult to comprehend for many people socialized on Ant, as it apparently requires a very different way of thinking. (Myself, having never used Ant, can't compare the two.) One thing is for sure: it makes unit (and integration) testing a natural, first-class step in the process, which helps developers adopt this essential practice.

I put my test classes in the same package as what they are testing but in a different source folder or project. Organizing my test code in this fashion allows me to easily compile and package it separately so that production jar files do not contain test code. It also allows the test code to access package private fields and methods.

I use Maven. The structure that Maven promotes is:-
src/main/java/org/myname/project/MyClass.java
src/test/java/org/myname/project/TestMyClass.java
i.e. a test class with Test prepended to the name of the class under test is in a parallel directory structure to the main test.
One advantage of having the test classes in the same package (not necessarily directory though) is you can leverage package-scope methods to inspect or inject mock test objects.

Related

JUnit: best strategy for placing test-methods

I started a project and using JUnit for the 1st time.
Whats the best practice of putting testcases?
1 testclass for every "real" class.
1 testclass for every package or even the complete project.
Testmethods in the "real" class without a testclass.
As far I see I can technically do every 3 ways but I do not have experience in that so I ask for some guidance to do it right from the very beginning.
EDIT
I am talking about code unit testing. I am using maven too but I think that is not important for my question.
1 test class for every "real" class.
I typically go with this pattern. Of course, tests for interfaces don't make much sense and there are times when small "entity" classes with getter and setter methods only (i.e. no logic) don't need a corresponding test class.
That said, I've been surprised at what utility I've found in unit tests even on very small classes. For example, even entity classes with only get/set methods which are stored in databases through DAO methods should be tested in case some of the database wiring is incorrect. You never know when you have a mismatched get/set method or if the toString(), asymmetric hashcode() or equals(), or other issues.
The entire point of "unit" tests is (IMHO) to test the smallest unit of your code in isolation -- this is the class. So therefore when I have a ContainerUtil class, I look for a corresponding ContainerUtilTest class in the test directory. I run coverage tests often and I expect just about any logic portions of all classes to be covered.
1 test class for every package or even the complete project.
I might have this as well but then I'd consider these to be "integration" tests. Tests that bridge between classes or between various parts of the project to ensure that your project works as a whole.
But these would be in addition to your unit tests.
Test methods in the "real" class without a test class.
Yeah, no. Really bad idea. You don't want your production code to include test code if at all possible. It decreases the readability of your classes, increases the change that you break something while trying to test, etc.. Just say no.
I also keep my test classes away from my sources. I usually use maven so I have my sources in src/main/java and my tests in src/test/java. You don't want your tests to end up in the jar or war files where they might confuse others.
It really depends on how big your project is, but in my experience the best approach would be one test class for every "big" functionality (this may not apply for unit testing), or in this case, for every "real" class.
About the other 2:
1 testclass for every package or even the complete project.
This may grow to big and messy, wouldn't recommend mixing different things in the same test class, the same way that you wouldn't mix classes within the same file
Testmethods in the "real" class without a testclass.
I do not recommend this one either as you lose track of where are the tests and which things have tests implemented vs are missing. Also, your code may require accessing other classes as well, so this may become a mess as again.
For unit testing, i so far have used one test class for each tested class. FOR ME, it seemed to be the least messy order. I put the unit tests under src/test/java in the same package tree as the tested classes in src/main/java. Integration tests are different and have their own files each.
One testclass has different disadvantages. Source code will become unreadable. You will do a lot of unnecessary work in #Before and #BeforeEach methods.
And i don’t get the point of putting tests into the tested class. Lots of imports, and how would you differ between „real“ and test methods? And because of the additional methods, source code will become unreadable.
I would suggest you try the first approach. It is very useful because you can track using some tool as Sonar the percentage of coverage from your unit tests.
Also, I strongly recommend you apply TDD to develop your code: first you write your test code to fail, then you write code to make your test pass and then you refactor.
Allow me to suggest two sources of reading to help you with that:
Test Driven Development: By Example
Refactoring: Improving the Design of Existing Code
These are the same reading resources I used to start building tests and using TDD.
I woudn't recommend you to use the other approaches, as you don't need to ship test code to production and using a single test class would cause a code smell known as "Large Class".

Where to learn about writing test cases?

I'm a CS master student. Throughout my studies I coded many course projects in Java. Soon I will graduate. When I explore some github projects I often find people organize their projects as /main and /test. I have never organized it in such a way, i.e. I always have my source code files without any test directories. I think that folder often contains what I think is called 'test cases' or so.
Since I will find a job soon, then I would like to learn about production-quality code.
My questions:
Why people often have that folder? What does it contain?
Can you provide me with a link to a good tutorial about the practice of testing in java? i.e how to do it? In a nutshell I wanna understand the idea of that /tests/ folder.
I often find people organize their projects as /main and /test
This is a matter of taste. Not 100% sure but at least maven projects have such organization.
From Maven: Introduction to the Standard Directory Layout, this would be the project layout:
src
main
java <-- your Java source code
resources
filters
config
scripts
webapp
test
java <-- your unit tests for Java
resources
filters
it
assembly
site
Why people often have that folder? What does it contain?
Usually, people write test cases to cover the code and check if the code works as expected. This is known as Code Coverage. Code coverage also serves as regression tests in case somebody makes changes in the code for enhancements like code refactoring.
The test cases you will find them usually are for Unit Testing. Depending on the type of the project, you could also find Integration Tests.
There is also Test Driven Development, or TDD, which is a practice whose basis is writing the test cases before writing the real code.
Can you provide me with a link to a good tutorial about the practice of testing in java?
This is off topic for the site. There are plenty tutorials on the net about this.
I don't have a separate folder for mine but usually people keep their Unit Tests in that folder. A unit test generally sets up "fake" data to test a given class so that a developer can easily debug any issues.
The reason people provide a /test folder is to contain unit test for their project.
There are really many ways of testing Java but JUnit is a very commonly used method of testing.
It is a good practice to write tests for your code. Begin with writing Unit Tests. I found this tutorial very useful. Writing test ensures that your code behaves as expected , corner cases are tested and adding new code in the future does not break existing functionality.
There are also mocking frameworks like JMock and Mockito that make writing stubs and drivers for your methods easy.
What is even more interesting is people prefer writing tests before they write the actual implementation. This approach is called Test Driven Development or Extreme Programming. Writing tests first ensure one already has a prep code or pseudo code for the methods in mind.

Best practive for JUnit package naming?

I was trying to find some best practice for naming Java package for testing. I would be thinking something along:
Tests on:
com.example.MyClass
should be in:
com.example.test.MyClassTest
Typically I put the test classes in the same package, but under a different source root. Aside from anything else, this allows you to test members (and indeed classes) which have default visibility. Sometimes I'll even make methods which would otherwise be private, package-level to make testing easier, knowing that it will only have limited impact. This very much depends on the context in which you're developing though. (Most of my code is written in a trusted environment; I want to limit access for elegance, but I'm not worried that anyone will actively try to use a method they shouldn't. And I use an annotation to indicate the intention.)
You definitely want an easy way of separating out your test classes from your production classes, both for deployment purposes and to let you concentrate on "just the prod code" when appropriate. But I don't see any disadvantage in using the same package declaration for both tests and production code.
One of the best options is putting the tests in another source folder. This way you can easily seperate the acctual source from the tests, e.g. when building a release. Take a look at Mavens default directory layout. A propper IDE should be able to handle different source folders even without Maven.
As for the package: If you have two different source folders, you can have the test classes in the same package. This has several advantages like beeing able to access package protected members from your test or using nice plugins like MoreUnit.

How to organize unit tests for a complex class?

I have a complex class (300+ lines), which I'm trying to test from different "points of view". I've already created three different unit tests. Every test is a complex class itself (100+ lines). The question is -- what is the best place to store them, in project directory tree? This is how I'm doing it now (Maven is used):
pom.xml
/src
/main
/java
/com
/Foo
ComplexClass.java
/test
/java
/com
/Foo
/ComplexClass
FirstPointOfViewTest.java
SecondPointOfViewTest.java
ThirdPointOfViewTest.java
Of course, the names are just placeholders, used in order to explain the problem/question. What do you think about this approach?
Your class is so complex that you need three different test classes to test all the aspect of the class? Probably you have mixed too many concerns in a single class. I would suggest refactoring the class using proven design patterns to separate classes with orthogonal concerns that can then be tested individually.
One thing you might want to consider: if you keep your test code package structure the same as your main code package structure---even using different physical directories as you are currently doing---your test classes will be in the same logical package as your main classes. This means they gain access to default/protected members in the tested classes, which is often helpful. You'd have to get rid of the ComplexClass package in the test code to make that happen.
Another thing to consider: (I'll assuming you're testing with JUnit) Test classes are classes, so you can organize and structure them using inheritance. If you have 3 different points of view, maybe extract a base class which contains common functionality, this will make your tests easier to maintain in the long run, especially as more "points of view" are discovered.
Separating the source and test code as you are already doing is a great idea, it gives you more options for building and maintains a logical grouping which makes maintenance more straightforward.
I'd keep what you currently have. The main advantage of this maven structure is that rather than mixing source and test code together and trying to identify which classes to exclude from your build you just ignore the test directory entirely. The point of using the same package is to expose protected methods/variables to your test classes but not to a public API.
One thing I might suggest is something I picked up at a talk by John Smart on Test Driven Development which is to name your test classes in groups of functionality they are testing, so you just have FirstPointOfView.java which is testing the behaviour of your first point of view of the com.foo package. This approach should make it more obvious when you can split a test class into individual classes, if they are actually testing different sets of behaviour.
Edit: if ComplexClass is a directory you should drop that, so that your tests are in the same package, I think I may have missread your example tree

How to divide a large Java project into smaller components

We've trying to separate a big code base into logical modules. I would like some recommendations for tools as well as whatever experiences you might have had with this sort of thing.
The application consists of a server WAR and several rich-clients distributed in JARs. The trouble is that it's all in one big, hairy code base, one source tree of > 2k files war. Each JAR has a dedicated class with a main method, but the tangle of dependencies ensnares quickly. It's not all that bad, good practices were followed consistently and there are components with specific tasks. It just needs some improvement to help our team scale as it grows.
The modules will each be in a maven project, built by a parent POM. The process has already started on moving each JAR/WAR into it's own project, but it's obvious that this will only scratch the surface: a few classes in each app JAR and a mammoth "legacy" project with everything else. Also, there are already some unit and integration tests.
Anyway, I'm interesting in tools, techniques, and general advice to breaking up an overly large and entangled code base into something more manageable. Free/open source is preferred.
Have a look a Structure 101. It is awesome for visualizing dependencies, and showing the dependencies to break on your way to a cleaner structure.
We recently have accomplished a similar task, i.e. a project that consisted of > 1k source files with two main classes that had to be split up. We ended up with four separate projects, one for the base utility classes, one for the client database stuff, one for the server (the project is a rmi-server-client application), and one for the client gui stuff. Our project had to be separated because other applications were using the client as a command line only and if you used any of the gui classes by accident you were experiencing headless exceptions which only occurred when starting on the headless deployment server.
Some things to keep in mind from our experience:
Use an entire sprint for separating the projects (don't let other tasks interfere with the split up for you will need the the whole time of a sprint)
Use version control
Write unit tests before you move any functionality somewhere else
Use a continuous integration system (doesn't matter if home grown or out of the box)
Minimize the number of files in the current changeset (you will save yourself a lot of work when you have to undo some changes)
Use a dependency analysis tool all the way before moving classes (we have made good experiences with DependencyFinder)
Take the time to restructure the packages into reasonable per project package sets
Don't fear to change interfaces but have all dependent projects in the workspace so that you get all the compilation errors
Two advices: The first thing you need is Test suites. The second advice is to work in small steps.
If you have a strong test suite already then you're in a good position. Otherwise, I would some good high level tests (aka: system tests).
The main advantage of high level tests is that a relatively small amount of tests can get you great coverage. They will not help you in pin-pointing a bug, but you won't really need that: if you work in small steps and you make sure to run the tests after each change you'll be able to quickly detect (accidentally introduced) bugs: the root of the bug is in the small portion of the code has changed since the last time you ran the tests.
I would start with the various tasks that you need to accomplish.
I was faced with a similar task recently, given a 15 year old code base that had been made by a series of developers who didn't have any communication with one another (one worked on the project, left, then another got hired, etc, with no crosstalk). The result is a total mishmash of very different styles and quality.
To make it work, we've had to isolate the necessary functionality, distinct from the decorative fluff to make it all work. For instance, there's a lot of different string classes in there, and one person spent what must have been a great deal of time making a 2k line conversion between COleDateTime to const char* and back again; that was fluff, code to solve a task ancillary to the main goal (getting things into and out of a database).
What we ended up having to do was identify a large goal that this code accomplished, and then writing the base logic for that. When there was a task we needed to accomplish that we know had been done before, we found it and wrapped it in library calls, so that it could exist on its own. One code chunk, for instance, activates a USB device driver to create an image; that code is untouched by this current project, but called when necessary via library calls. Another code chunk works the security dongle, and still another queries remote servers for data. That's all necessary code that can be encapsulated. The drawing code, though, was built over 15 years and such an edifice to insanity that a rewrite in OpenGL over the course of a month was a better use of time than to try to figure out what someone else had done and then how to add to it.
I'm being a bit handwavy here, because our project was MFC C++ to .NET C#, but the basic principles apply:
find the major goal
identify all the little goals that make the major goal possible
Isolate the already encapsulated portions of code, if any, to be used as library calls
figure out the logic to piece it all together.
I hope that helps...
To continue Itay's answer, I suggest reading Michael Feathers' "Working Effectively With Legacy Code"(pdf). He also recommends every step to be backed by tests. There is also A book-length version.
Maven allows you to setup small projects as children of a larger one. If you want to extract a portion of your project as a separate library for other projects, then maven lets you do that as well.
Having said that, you definitely need to document your tasks, what each smaller project will accomplish, and then (as has been stated here multiple times) test, test, test. You need tests which work through the whole project, then have tests that work with the individual portions of the project which will wind up as child projects.
When you start to pull out functionality, you need additional tests to make sure that your functionality is consistent, and that you can mock input into your various child projects.

Categories