Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
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?
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.
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)?
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
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.
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.
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.
Related
I am using ServiceLoader to dynamically load Plugins.
In purpose of unit testing I want to Mock some behavior of these Plugins.
These Mock-Plugins should be used when unit testing, but not when building the Project.
How would one do this though?
I feel like this question is IDE / build tool specific, for that matter I am using Eclipse.
Project Structure:
src
app
app.java
scraper
ScraperController.java
Scraper.java
Scrapers
tests
mockups
FailingScraperMock.jar
...
unit_tests
ServiceLoaderWithProvidedMockScrapersTest.java
...
scraper.Scraper.java is the provider interface
Scrapers is where all the Scraper-Providers go
I tried to exclude the Mock-Plugins for the source folder: src/ .
Either I am doing it wrong or that's not intended for what I am trying to do.
Would appreciate any kind of help / information.
If you mark your test folder (/tests) as test code and then it should be excluded from application builds.
This might be a silly question, but I need to know. I'll delete it if it's too silly to answer.
In a maven project in IntelliJ, I have the following structure:
procedure
e2e
cucumber (same level as common)
src
test
java
e2e
support
File: ScenarioState.java
package e2e.support
common (same level as cucumber)
src
main
java
common
testdata
File: Case.java
package common.testdata
Is there any way to import the package e2e.support (where ScenarioState.java resides) into the file Case.java in the common.testdata package?
I've been playing around with maven imports, dependencies etc., but I haven't found a way to do it. I might have to redesign some classes to get around it, but that would impact other parts of the project and I'd like to avoid it if possible.
If you really want to do that (and I would strongly recommend to either leave the project alone or restructure it first), define an additional source directory as in
How to add an extra source directory for maven to compile and include in the build jar?
But beware that a project like this will haunt you till the end of time.
One could have in the common's pom.xml a dependency to cucumber with <type>test-jar</type>.
However this violates the concept of src/main for the final product, and src/test for the unit-tests (not incorporated in the product, separate test classes).
(In src/test there can be other classes, so maybe easiest would be for common to have a src/test instead.)
If ScenarioState has nothing to do in src/main, one could place it in a more low-level library cucumberbase in src/main. And make a dependency in cucumber to cucumberbase with <scope>test</scope>. In <common> a normal dependency to cucumberbase.
Keep this main-test separation as otherwise other developers risk insanity.
I am using IntelliJ to write some integration tests.
Project Structure:
/src
/main
/java
/com.myCompany
/dir
/email
/test
/com
Over time, I will be writing unit, integration, and performance tests. However, I’m confused about how I should structure my directories for testing. I also don’t understand how package naming relates to testing. For instance, I’ve created a basic test that looks like the following:
package com.myCompany.dir.email;
import junit.framework.TestCase;
import org.junit.Test;
public class EmailTest extends TestCase {
private final String username = “[testAccount]”;
private final String password = “[testPassword]”;
#Test
public void thisAlwaysPasses() {
assertTrue(true);
}
}
Unfortunately, I can’t even get that test to run. I get errors ranging from:
Error running All unit tests: Package not found in directory
to
No tests found.
Any insights are much appreciated.
It is a good idea to have your tests packages mirror the package structure of your classes under test. In your concrete case it should look like this:
/src
/main
/java
/com
/myCompany
/dir
/email
MyClass.java
/test
/java
/com
/myCompany
/dir
/email
MyClassTest.java
Regarding your part of the question about Unit-, Integration- and Performance-Tests. We usually follow either one of the following approaches (it kinda depends on the project size):
Create completely separate projects for Integration-Tests (and Performance Tests). In there you place your Tests within an identical package hierachy.
Simply place your Integration-Tests (and Performance Tests) in the same package as your Unit-Tests, but give them some common suffix (e.g. MyClassIntegrationTest.java)
there's no need to extend TestCase--the rest of your code is probably fine.
assuming you're using Maven directory structures (you appear to be), be sure you created a folder structure for tests which looks like: src/test/java/com/myCompany/dir/email--your class needs to be in a folder which matches its package name,
the extra quote in "[test"Password"]; -- you need to remove or escape it.
I'm guessing that #1 is the cause of the exception you're currently seeing.
I am a long time user of Eclipse but a novice when it comes to JUnit. I have lots of java projects and I want to start writing test cases around the methods in those projects. I'm just wondering the best way to set up the Eclipse environment for this purpose. Let's assume I have a typical project with a typical src directory in a specified package. How do I attach test cases to that project. Some concerns:
1. I don't want the test cases to be part of any build that I create on the project.
2. I want to refer to the clases in the test-suite.
Do I set up a separate test directory under the package I want to test? Do I have a separate test package? What is the best way to do this?
It's pretty dead simple:
Drag or otherwise place the JUnit jar file into your lib folder, then
modify your projects build settings to include it.
Create another source folder under your project called 'test'
Create your test packages underneath the 'test' source folder. Best
practice is to mimic the package names of your application.
Create your test classes inside of the test packages. Best practices
is to mimic your application classes that require testing, but append
Test at the end of the name. So for example in your main application
you might have a myapp.service.PrintService and as a corresponding
test you would have myapp.service.PrintServiceTest
Extend each test class from junit.framework.TestCase
Run your test classes using TestRunner.
When you build your application's deployment bundle just exclude the 'test' source folder. Now, if you want really drop dead easy test integration then use Maven to setup your project. It bakes in all the best practices for you right off the bat.
The best (or at least the most common) way to organize the test code it is to have a separate source folder for the test code, thus keeping it nicely separated. In eclipse, you can add source folders under "Build Path" in the project's properties.
However, it is also a good idea to keep your test classes in the same packages as the classes to be tested (i.e. have the same package hierarchy in the test source folder). This allows you test code to call package private and protected methods, making it much easier to test internal behaviour that should not be exposed in the public API.
A simple solution would be to create another source directory specifically for test-related classes. For example, if your main classes live in $PROJECT_ROOT/src, you can put your test-related classes in $PROJECT_ROOT/src-test. I don't have Eclipse handy, but I know that you can modify the $PROJECT_ROOT/.classpath file (it's XML) to include this new directory:
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src-test"/> <!-- ADD THIS ONE -->
...
</classpath>
Now, all your test classes will see the main classes, but they won't be included in your build. I typically make sure that the test class lives in the same package as the class it's testing. That way, any protected members can be accessed from the test code.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Every time I create a new project I copy the last project's ant file to the new one and make the appropriate changes (trying at the same time to make it more flexible for the next project). But since I didn't really thought about it at the beginning, the file started to look really ugly.
Do you have an Ant template that can be easily ported in a new project? Any tips/sites for making one?
Thank you.
An alternative to making a template is to evolve one by gradually generalising your current project's Ant script so that there are fewer changes to make the next time you copy it for use on a new project. There are several things you can do.
Use ${ant.project.name} in file names, so you only have to mention your application name in the project element. For example, if you generate myapp.jar:
<project name="myapp">
...
<target name="jar">
...
<jar jarfile="${ant.project.name}.jar" ...
Structure your source directory structure so that you can package your build by copying whole directories, rather than naming individual files. For example, if you are copying JAR files to a web application archive, do something like:
<copy todir="${war}/WEB-INF/lib" flatten="true">
<fileset dir="lib" includes="**/*.jar">
</copy>
Use properties files for machine-specific and project-specific build file properties.
<!-- Machine-specific property over-rides -->
<property file="/etc/ant/build.properties" />
<!-- Project-specific property over-rides -->
<property file="build.properties" />
<!-- Default property values, used if not specified in properties files -->
<property name="jboss.home" value="/usr/share/jboss" />
...
Note that Ant properties cannot be changed once set, so you override a value by defining a new value before the default value.
You can give http://import-ant.sourceforge.net/ a try.
It is a set of build file snippets that can be used to create simple custom build files.
I had the same problem and generalized my templates and grow them into in own project: Antiplate. Maybe it's also useful for you.
If you are working on several projects with similar directory structures and want to stick with Ant instead of going to Maven use the Import task. It allows you to have the project build files just import the template and define any variables (classpath, dependencies, ...) and have all the real build script off in the imported template. It even allows overriding of the tasks in the template which allows you to put in project specific pre or post target hooks.
I used to do exactly the same thing.... then I switched to maven. Maven relies on a simple xml file to configure your build and a simple repository to manage your build's dependencies (rather than checking these dependencies into your source control system with your code).
One feature I really like is how easy it is to version your jars - easily keeping previous versions available for legacy users of your library. This also works to your benefit when you want to upgrade a library you use - like junit. These dependencies are stored as separate files (with their version info) in your maven repository so old versions of your code always have their specific dependencies available.
It's a better Ant.
I used to do exactly the same thing.... then I switched to maven.
Oh, it's Maven 2. I was afraid that someone was still seriously using Maven nowadays. Leaving the jokes aside: if you decide to switch to Maven 2, you have to take care while looking for information, because Maven 2 is a complete reimplementation of Maven, with some fundamental design decisions changed. Unfortunately, they didn't change the name, which has been a great source of confusion in the past (and still sometimes is, given the "memory" nature of the web).
Another thing you can do if you want to stay in the Ant spirit, is to use Ivy to manage your dependencies.
One thing to look at -- if you're using Eclipse, check out the ant4eclipse tasks. I use a single build script that asks for the details set up in eclipse (source dirs, build path including dependency projects, build order, etc).
This allows you to manage dependencies in one place (eclipse) and still be able to use a command-line build to automation.