This post has been migrated to http://www.thinkcode.se/blog/2015/04/29/separating-acceptance-tests
It is very convenient to run the unit tests separated from other, slower, tests. There are different ways to do this. One way is to have a separate module for the acceptance tests.
Separating the modules is acceptable in some cases. It is not acceptable in others. There is a simple way to separate the source code for the acceptance tests while keeping the it in the same project if you use Gradle. Separate the tests with different source sets.
Separation on source sets means that you will keep all the acceptance tests in another directory structure than the unit tests. If you use the usual separation of production code and test code, then all you want to do is to add a new source set that contains the acceptance tests.
The regular source code structure used by Gradle is a
src directory and then a
main directory for the production code and
test for the test code. This is a good separation. We will add another directory under
acceptanceTest that will contain the source code used for acceptance testing the system.
The magic is in the Gradle build script. When you apply the
java plugin, Gradle defines
sourceSets. It will read
src/main for the production code and
src/test for the test code.
To be able to add acceptance tests in the same module you need to add an additional source set and call it something describing.
This my exact strategy in the example below:
Notice that you don’t replace the current
sourceSets definition, you enhance it.
I want to have access to the output from the production and test code for the acceptance tests. The way to get that access is to sum the output and place it in my compile classpath
compileClasspath += main.output + test.output + configurations.testRuntime
The runtime class path for the acceptance tests should be the same as the compile class path and the result of the compilation of the acceptance tests.
The next thing is to add a specific acceptance test task so I can execute my acceptance test separately.
The description of the task is easy, write whatever you want here. Make sure that is descriptive though.
After that I want to add my task to a group that it should belong to. The group should be set to
verification. This is strictly not necessary, but the task will be grouped properly when you execute gradle tasks.
Defining the task as a
test task will give me access to the properties
classpath. To connect them to my acceptance test stuff, I set them to
Separating the execution reports are nice. I do that by setting
reports.html.destination to something different compared to the unit tests. This allows me to get specific reports for the acceptance tests.
The last thing I want to do is to include the acceptance tests in the task chain at a reasonable place. I want the the acceptance tests to be executed after the unit tests. The unit tests are fast so executing them before the slower acceptance tests is reasonable. The solution is to add a dependency from the acceptanceTest to the test task. I want the acceptanceTest to be executed when
check is executed so I add a dependency from the check task to the acceptanceTest task. This will give the desired execution order and I will always execute the acceptance tests when check is executed.
That is all you have to do to separate the acceptance test from the unit tests and get a specific task that will execute the acceptance tests.
The result is that you now have the possibility to organize your code like this:
example |-- build.gradle `-- src |-- acceptanceTest | |-- java | `-- resources |-- main | |-- java | `-- resources `-- test |-- java `-- resources
I would like to thank Malin Ekholm, Johan Helmfrid and Alexandru Bolboaca for proof reading.
- Gradle Test DSL – The official test task documentation
- Gradle Test class – The official test task api documentation
- Gradle Report DSL – The official report task documentation
- Gradle Report class – The official report task api documentation
- More reading – My other blog posts about Gradle
- Thomas Sundberg – The author