Sharing Integration Test Code across modules

I’m trying to build a multi-module kotlin app with some integration test classes in a “Utilities” module including abstract base classes which are derived from in other modules. I can organise the compile order to support this but I cannot get the shared classes on the compile classpath. I’ve been tring things like

configurations {
  integrationTestImplementation.extendsFrom (
      project (':Utilities').configurations.getByName ('integrationTestImplementation')
  )
}

But when the compiler hits the file which inherrits from the Utilities base class I get an unresolved reference exception.

Any help appreciated :slight_smile: :grinning:

Never ever event try something like that, i.e. reaching into the model of another project.
Neither to configure something, nor to retrieve something.

Besides that you just configure to get the same dependencies as the Utilities integ tests.

Read Sharing outputs between projects to find out how to properly and safely publish things between projects.

Hi Björn,

Thanks for responding :grinning:

I’m not trying to reach into the model of another project. I’m tring to share a utility class between multiple modules in the same project. All the modules are part of my project.

In this case, I’m sharing a class CsAnnotaionSpec which derives from the kotest AnnotationSpec class. This allows all my modules to declare classes derived from CsAnnotationSpec and share common test code. I think that’s a credible and sensible use case as I have three modules which all conduct tests in a similar manner.

I’ve looked through your article and I appreciate the points made, but this is way over the top for my requirements. Interestingly enough, I never publish this particular application in jars! The application works as an extension of graddle for creating virtual infrastructure in AWS. This means I know that each module is always talking to the other module in exactly the same build which is a great simplification.

I’ve currently resolved the situation by removing Utilities as a module (taking it out of settings.gradle and removing the build file). This just leaves a folder structure. I can then reference the folder structure as follows:

testing {
  suites {
    integrationTest (JvmTestSuite) {
      sources {
        kotlin {
          //noinspection GroovyAssignabilityCheck
          srcDirs = [
              'src/integrationTest/kotlin',
              '../Utilities/src/integrationTest/kotlin'
              ]
        }
      }
    }
  }
}

This works, but it’s not optimal and it’s not very elegant either.

As an experiment I’ve just run the jar task on this app. The resulting jar just conatins a manifest and my logging configuration file. All the code is in the build scripts and inside the buildSrc directory. Not the normal use case I admit but it is working well.

Cheers,
Steve

I’m not trying to reach into the model of another project.

Whether you try it or not, you do it, you showed it. :wink:

All the modules are part of my project.

Ah, you confuse the terms.
What you call “project” is a “build”.
What you call “model” is a “project”.
When talking about Gradle, you should adapt to Gradle terminology, or you confuse yourself and others. :wink:

I’m tring to share a utility class between multiple modules in the same project.

Yes, I fully understood and linked you to the according doc page.
Besides that you might simply be after test fixtures not that I think about it.

Not the normal use case I admit but it is working well.

The use-case is quite normal, as I said, just use test fixtures for that.
The “solution” is quite suboptimal though and even if it is just because you recompile the same code multiple times.

Thanks Björn,

I tried test fixtures before but couldn’t get it working. However I’ve tried again and got it working now. Following our discussion I had a much better idea of what it was doing.

Many thanks for your help.

For anyone else reading my code is as follows:

build.gradle (Utilities module)

plugins {
  id 'org.jetbrains.kotlin.jvm'
  id 'java-test-fixtures'
}

dependencies {
  // My dependencies for fixtures
  testFixturesImplementation "io.kotest:kotest-runner-junit5-jvm:$kotestVersion"
}

Source code to be shared is under src/testFixtures/kotlin/

build.gradle (Consuming module)

plugins {
  id 'org.jetbrains.kotlin.jvm'
  id 'java-test-fixtures'
}

// Probably not required as I put Utilities first in settings.gradle
evaluationDependsOn (':Utilities')

dependencies {
  integrationTestImplementation (testFixtures(project(":Utilities")))
}

Cheers, Steve

Please have a look at the formatting help to learn how to use code-blocks, so that I don’t have to edit your post every time to make them somewhat readable. :wink:

Regarding your solution, now remove the useless java-test-fixtures plugin on the consumer and the non-sense evaluationDependsOn :slight_smile:

And no, the order in the settings script has nothing to do with whether you need the latter or not.

You only need the latter if you do non-sense things. :smiley:

Thanks Björn,

I’ve made the changes you suggested and it’s all working fine. Updated code below (hopefully correctly formatted).

build.gradle (Utilities module)

plugins {
  id 'org.jetbrains.kotlin.jvm'
  id 'java-test-fixtures'
}

dependencies {
  // My dependencies for fixtures
  testFixturesImplementation "io.kotest:kotest-runner-junit5-jvm:$kotestVersion"
}

Source code to be shared is under src/testFixtures/kotlin/

build.gradle (Consuming module)

plugins {
  id 'org.jetbrains.kotlin.jvm'
}

dependencies {
  integrationTestImplementation (testFixtures(project(":Utilities")))
}

Cheers & Thanks, Steve

1 Like