Java unit tests, directory layout

JavaUnit Testing

Java Problem Overview


When building a suite of unit tests for Java code, is there a convention for where to place test code in relation to source code?

For example, if I have a directory /java that contains a bunch of .java source files, is it better to put the test cases in /java itself or use something like /java/test.

If the latter is preferred, how do you test the internals of the code when the private /protected members of a class aren't available outside the package?

Java Solutions


Solution 1 - Java

I recommend following the Apache Software Foundation's standard directory structure, which yields this:

module/
  src/
    main/
      java/
    test/
      java/

This keeps tests separate from source, but at the same level in the directory structure. If you read through how Apache defines their structure, you'll see it helps partition other concerns out as well, including resources, config files, other languages, etc.

This structure also allows unit tests to test package and protected level methods of the units under test, assuming you place your test cases in the same package as what they test. Regarding testing private methods - I would not bother. Something else, either public, package, or protected calls them and you should be able to get full test coverage testing those things.

By the way, the link above is to Maven, Apache's standard build tool. Every Java project they have conforms to this standard, as well as every project I have encountered that is built with Maven.

Solution 2 - Java

You can put the tests in the same package as the original classes, even if the source code is under its own directory root:

PROJECT_ROOT
    +--- src/
    +----test/

You can declare a class com.foo.MyClass under src and its test com.foo.MyClassTest under test.

As for access to private members, you can use reflection to invoke the methods (altering their accessibility via Class.getDeclaredMethod.setAccessible), or you could use something like testng/junit5 to put some annotation-driven tests on the source code itself (I personally think this is a bad idea).

Why not check out some projects on java.net to see how they've organized things, for example swinglabs (the SVN repository is pretty slow I'm afraid)?

Solution 3 - Java

Most of the times is done like this:

<SOME_DIR>/project/src/com/foo/Application.java
<SOME_DIR>/project/test/com/foo/ApplicationTest.java

So, you keep them separated and you can still test the package/protected functionality because the test is in the same package.

You can't test private stuff, unless it is declared inside the class it self.

Upon delivery, you just pack the .class generated by src, not the tests

Solution 4 - Java

Actually it makes a lot of sense to separate your Production and Test projects into 2 separate entities, but have the same package structure in both projects.

So if I have a project 'my-project' I also create 'my-project-test', so I have the following directory structure:

my-project
  +--- src/com/foo
my-project-test
  +---test/com/foo

This approach ensures that test code dependencies do not pollute production code.

In my personal opinion, package private and protected methods should be tested as well as public methods. Hence I want my test classes in the same package as production classes.

Solution 5 - Java

This is how we have it set up and we like it.

build/
src/
test/build/
test/src/

All testing code compiles into its own build directory. This is because we don't want production to contain test classes by mistake.

Solution 6 - Java

When creating a Java library module in Android Studio it creates a default class under:

[module]
   + src/main/java/[com/foo/bar]

If you look into [module].iml file, you will find that path as well as the path for tests, that you can utilize. The below is a summary:

<module>
  <component>
	<content>
	  <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
	  <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
	  <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
	  <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
	</content>
  </component>
</module>

What you can do in particular is to create a directory for tests to have the following structure:

[module]
   + src/main/java/[com/foo/bar]
   + src/test/java/[com/foo/bar]

The above structure will be recognized by Android Studio and your files underneath will be included into the module.

I assume that that structure is a recommended layout for code and tests.

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
QuestionMikeView Question on Stackoverflow
Solution 1 - JavaSingleShotView Answer on Stackoverflow
Solution 2 - Javaoxbow_lakesView Answer on Stackoverflow
Solution 3 - JavaOscarRyzView Answer on Stackoverflow
Solution 4 - JavaAlexander PogrebnyakView Answer on Stackoverflow
Solution 5 - JavaChristianView Answer on Stackoverflow
Solution 6 - JavaRyszard DżeganView Answer on Stackoverflow