Where should I put my JUnit tests?

JavaUnit TestingJunit

Java Problem Overview


I've got 2 questions about organising Unit tests.

  1. Do I have to put test to the same package as tested class, or can I organise tests in different packages?

    For example if I have validity and other tests, is it correct to split them into different packages, even if they are for same class?

  2. What about mock and stub classes? Shall I separate them from packages containing only tests, or put them together?

Java Solutions


Solution 1 - Java

The way we do our JUnit test cases is to put them in the same package, but in a different root directory. Since we use Maven, we just use the standard locations making the structure similar to the following.

src/main/java/com/foo/Bar.java
src/test/java/com/foo/BarTest.java

Obviously there's more to the structure, but this lets us build the tests separately from the mainline code, but still access protected classes and the like. With respect to different types of tests, this is very subjective. When we started our testing effort (which unfortunately started after development), I tried to keep things pretty isolated. Unfortunately, it quickly became a nightmare when we got to the 500+ test case point. I've since tried to do more consolidation. This led to reduced amounts of code to maintain. As I said, though, it's very subjective.

As far as test-only code, we keep it in a separate com.foo.test package that resides only in the src/test/java tree.

Solution 2 - Java

I too tend to put my tests in the same package but under a different root directory. This allows me to test package-private classes or access packing-private classes while testing something else in the package. They are kept in a separate directory tree to allow excluding them from the deployed result (in particular to ensure that test code didn't accidentally get into production code). What matters most, however, is what works for your situation.

In terms of how many test classes per production class, the theory I've seen is that you write one test class per fixture, that is per setup structure. In many cases that is the same (or close enough) to one test class per production class, but I have sometimes written more test classes (in particular equality tests tend to be separated) for a give production class, and occasionally one test class of for a group of (related) production classes (say, for testing the Strategy pattern).

Mostly, I don't worry too much about the theory, but rework the tests as needed to keep duplication to an absolute minimum.

Solution 3 - Java

Keeping it the same package allows you to use package-private visibility for code that is intended to be accessed via the test only.

Regarding using separate root directories, that is a good practice. It also has an advantage for us, since we use IDEA, IDEA recognizes that production code cannot reference test code.

In terms of keeping them separate, there is a great power in having one, and only one, test class per production class at the unit level. Of course, some classes get created in production as part of refactoring that have no test classes at all, and that is fine, but when you want to know what test tests a certain class, having a convention that says ClassNameTest is the tests for ClassName is very helpful.

TestNG is much friendlier to this paradigm than JUnit, though.

Solution 4 - Java

Test classes should be rather in different packages, it's easier to separate them from the production code when you package it for release. I usually keep lots of test fluff in those packages, all sorts of mocks, configurations, scenarios.. But when you build - it doesn't get it. In some situations, it's a good idea to keep your testing stuff even in different projects. Depends.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJakub ArnoldView Question on Stackoverflow
Solution 1 - JavaPaul KuykendallView Answer on Stackoverflow
Solution 2 - JavaKathy Van StoneView Answer on Stackoverflow
Solution 3 - JavaYishaiView Answer on Stackoverflow
Solution 4 - JavaDimaView Answer on Stackoverflow