Gradle configuration feedback for `test-support` code

I have been thinking about this a lot lately and wanted to get some feedback on the idea that I had a couple of days ago.

Problem:

In a typical code base, each module has an initial set of main and test . This may work pretty well for some time, but sooner or later I always come across a situation where I would like to combine a group of classes that make it easier to test code that includes a specific module. A good example is the set of hamcrest classes for this module.

  • Assumption 1:
    Since hamcrest is a library for test code, these sockets should not be part of the main source set.

  • Assumption 2: These classes should also not go into the original test set, since the source dependency test is just a workaround for these classes. Usually usually no dependency on actual tests is required. In addition, it is not recommended (according to Netflix) to determine the dependence on the initial set of test projects.

Solution 1 :

Create a dedicated module that contains these classes in the original main set, and simply define the dependence of the test on this module, wherever you need it.

It was an approach that I have been with for quite some time, but I donโ€™t really like it.

  • Firstly, I never came up with a pretty name other than adding testSupport to the name of the source module, resulting in names like core-testSupport , persistence-testSupport , etc.

  • Secondly, it creates many modules, and the project tree becomes polluted by these modules.

Solution 2 : (The one I would appreciate feedback on)

 configurations { testSupportCompile.extendsFrom compile testSupportRuntime.extendsFrom runtime } sourceSets { testSupport { compileClasspath += sourceSets.main.output + configurations.testSupportCompile runtimeClasspath += compileClasspath + configurations.testSupportRuntime } } task testSupportJar(type: Jar) { from sourceSets.testSupport.output classifier 'testSupport' } artifacts { testSupportCompile testSupportJar } 

The above gradle configuration can go in a file called testSupport.gradle and apply to any module that needs this dedicated source set to provide classes that can be reused in tests.

A dependency definition will work as follows:

 testCompile project(path: ':core', configuration: 'testSupportCompile') 

I'm still new to gradle and have researched a lot, but I still have a few questions.

  • I understand that declaring a new source set automatically creates two configurations: <sourceSet>Compile and <sourceSet>Runtime . What I don't like about this approach is that when declaring a dependency, you need to use the testSupport Compile configuration. Is there a way to testSupport this to just testSupport or something like that?

  • At the moment, my project is compiling fine. However, I am not sure if I am doing the right thing. How can this configuration be improved?

  • Are there other ways to achieve the desired functionality? During the study, I did not understand much about this topic, which made me feel that I was either using the wrong search conditions or doing something stupid that simply should not be done.

I know this is kind of a broad question, but I'm not sure where to get the right feedback on things other than here.

+6
source share
1 answer

I have a similar situation, and I put off the solution for a while, using various hacks and workarounds. Your question was the last incentive to study.

Here's what I got - EDIT , done in collaboration with Thomas:

 configurations { // create a new configuration and inherit everything from compile testlib.extendsFrom compile } sourceSets { testlib { // We will at least need access to our main sourceSet and all dependencies that are declared for our configuration. compileClasspath += sourceSets.main.output + configurations.testlib } } task testlibJar(type: Jar) { from sourceSets.testlib.output classifier 'testlib' } artifacts { testlib testlibJar // include the classes into the new configuration archives testlibJar // optional: include the support JAR into "uploadArchives", so it may also be used in other projects } 

Then in the dependent module just use:

 dependencies { testCompile project(path: ':otherproject', configuration: 'testlib') } 

Note that the (empty) testlibCompile and testlibRuntime are still created (as a result of introducing a new set of testlib source files), but I find it safe to just ignore them.

In addition, it often happens that you need to use testlib to configure your test project (project tests depend on general test support). In this case, you can either add a dependency between two configurations of the same project:

 testCompile project(path: ':myproject', configuration: 'testlib') 

Or individually extend compilation classes and runtimes:

 configurations { testlib.extendsFrom compile testCompile.extendsFrom testlib } sourceSets { test { compileClasspath += sourceSets.testlib.output runtimeClasspath += sourceSets.testlib.output } } 
+1
source

Source: https://habr.com/ru/post/1012324/


All Articles