- improved build performance
- enables on-demand delivery
- pushes you to build reusable, discrete components
Sounds great, right? Are there any downsides? There is one in particular which has been a a pain point for many.
Often times when you’re writing tests, you’ll want to use some test doubles like fakes or fixtures in order to help simulate the system under test. Maybe you have a
FakeUser instance that you use in your tests to avoid having to mock a
User every time your test calls for one. Generally these classes live alongside tests in
src/test directories and are used to test out your code within a module.
For example, maybe you have a model object like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
You might have some code in
src/test that creates a bunch of fake users for your tests like:
1 2 3 4 5
This works great if you’re testing code within a module, but as soon as you’d like to use these fake users in other modules, you’ll note that these classes aren’t shared!
This code can’t be shared between modules because Gradle doesn’t expose the output of your test source set as a build artifact. There are all kinds of solutions for this problem out there, including creating a special module for all your fixtures, and using gradle dependency hacks to wire up source sets.
However, that’s not necessary anymore! As of version 5.6, Gradle now ships a new ‘test-fixtures’ plugin! This plugin creates a new
testFixtures source set, and configures that source set so that:
- classes in this set can see the main source set classes
- test sources can see the test fixtures classes
Using the Plugin
You can apply the
java-test-fixtures plugin in your build.gradle script:
1 2 3
This plugin will define the necessary source set, and handle all the wiring up of test artifacts. We can now move those test fixtures from
src/testFixtures/java, and that’s it! These classes will be ready to be consumed by other modules.
Wiring it all together
Finally, we need to use a special keyword to pull these new fixtures in as a dependency for our tests. In our gradle configuration, we add a test dependency (either API or Implementation) like so:
1 2 3
And that’s it! Our other module can now consume these test fixtures without any sort of intermediate modules or workarounds.
If you’d like to check out the complete configuration with examples sharing fixtures between both Kotlin and Java modules to a shared “app” module, I’ve uploaded a sample project demonstrating how to use this new configuration here.
It’s important to note that this feature is currently only available with the
java-library plugin, and has limited functionality in Kotlin modules, and not yet available for Android modules. There are currently feature requests on YouTrack and the Android Issue Tracker to take advantage of this new functionality.