Shared srcDirs between test and androidTest, unresolved references after upgrade to Android Studio Chipmunk (IntelliJ 2021.2.1)
Asked Answered
E

2

42

I just upgraded from Bumblebee to Chipmunk, and I am having multiple dependency-resolution issues in my instrumented androidTests.

These are what my source sets look like:

sourceSets {
    test.java.srcDirs += 'src/testShared/kotlin'
    test.resources.srcDirs += 'src/testShared/resources'
    androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    androidTest.java.srcDirs += 'src/testShared/kotlin'
    androidTest.resources.srcDirs += 'src/testShared/resources'
}

The idea is to share test data between unit tests and instrumented tests. Keep in mind, the tests can build and execute, but the dependencies show up as red in the IDE. Also, it may not be related, but string resources I reference (that are in a resource module) are also red in the IDE.

Also, when I comment out either the unit test sourceSets that point to testShared, the IDE errors dissapear in my AndroidTests

This was not an issue in the previous version of Android Studio. I think the issue is related to the base IntelliJ IDE platform. Does anyone have any ideas how to fix this issue, or have any workarounds?

Edit: Here is a basic sample project that demonstrates the issue, when running in Chipmunk and above. In bumblebee, there are no unresolved reference errors in androidTest. Also, you may have to tweak the AGP version, as I built this project using Dolphin beta01, but the issue is the same in Chipmunk https://drive.google.com/file/d/1ZCcEwuqM-m4E5qe94vCn52yWMON8rd5P/view?usp=sharing

Emperor answered 12/5, 2022 at 15:50 Comment(5)
Can you share a sample project to investigate?Fancyfree
@Fancyfree Just linked a basic sample project. Thanks for any help provided!Emperor
Thank you! Yes, this looks like a bug in the Android model. Because for ordinary Gradle projects, it works. I think it makes sense to file issue to file a but in Android Studio issue tracker:developer.android.com/studio/report-bugsFancyfree
Can you link the issue if you opened one with Google? I found that the issue comes from IntelliJ 2021.2 which Chipmunk is based on. The issue isn't resolved in IntelliJ 2021.3 which is Dolphin based on so until then best thing to do is to stay on Bumblebee until Electric Eel is stable enough.Junkman
@Junkman Linked the issue and updated my answerEmperor
E
22

Looks like this feature is no longer supported in new iterations of the Android Studio IDE and IntelliJ platforms.

Edit: Sharing code this way no longer works. BUT, there is another method to make it work:

Basically, create an android library (sharedTestCode), depend on it in your app via testImplementation and androidTestImplementation. In the sharedTestCode build.gradle file, depend on the app. You should now be able to create shared test data and reference them in both types of tests.

Here is a sample project with this setup working:

https://drive.google.com/file/d/1I2CZhTxHGRgCN9UCEjIuWUfFnGxTF_Cv/view?usp=sharing

Second edit: Make sure that any module that depends on the :app project also defines productFlavors and flavorDimensions, matching the build.gradle configuration of the app's build.gradle file.

So for example, I had to add this code to my sharedTestModule's build.gradle file:

flavorDimensions "environment"

productFlavors {
    local {
        dimension "environment"
    }
    gae {
        dimension "environment"
    }
}

Previous response:

I created a support thread: https://issuetracker.google.com/issues/232420188

and here is the answer from Google about this old way of referencing test data:

Sharing code in this way is not longer supported in the IDE. The reason this was working before is that in pre-chipmunk we ran Android studio import with the intellij options set to create a single module per Gradle project. This option has been removed from IDEA for a good number of years. Importing this way comes with a lot of issues due to the fact that intellij modules can only be set up with two scopes for dependencies and other information, these are compile and test. By default Android modules effectively have three different scopes (which roughly correspond to Gradle source sets per variant) main, unitTest and androidTest. The mapping of these to intellij modules with this option require us to merge the dependencies of unitTest and androidTest. Also any custom source set's need to be merged as well. This caused a lot of incorrect symbol resolution within the editors along with a host of other issues.

In chipmunk we switch to creating a module per (roughly) Gradle source set. This allows us to map the information correctly but unfortunately does result in sharing information between source sets such as this becoming unsupported by the IDE.

To summarize, in order to be correct each source file must only be present in one module otherwise the IDE has no way of knowing which context to use. This can also sometimes result in subtle issues with build. To share sources between test modules you should be able to use put the code in a separate project and consume it as a dependency with both testImplementation and androidTestImplementation.

Emperor answered 25/5, 2022 at 11:53 Comment(6)
excellent... I've no clue to resolve the main app's classes, your assist by declaring the same flavors help me a lot, thank youLaveen
to anyone who won't declare the dependencies twice, you can share the library by using api instead of implementation, the api can be declared either in the main app module or in the shared test module and also declare the repository sources in the shared test moduleLaveen
@AgiMaulana what's the difference between implementation and API?Kattegat
Where do you write the test inside the sharedTest module? do you write in directly in src/main/java or do we write it in either src/test/java/src/androidTest/java?Ascensive
@ArchieG.Quiñones you do not write any tests in that module. The goal of the module is to have shared test data, to avoid duplication between integration and unit tests. But the itself is in the src/main/java folder.Emperor
That is insane. I have two classes that I want to share, this requires creating a full library???Humphries
D
7

To solve this, move your shared test dependencies into a separate module. Here's how:

  • Right click in the project window and go to New -> Module
  • Choose the "Android library" template
  • Module name shared-test
  • Package name should be whatever it is in your main app
  • Click "Finish"

enter image description here

Move your shared code inside the :shared-test module.

Now, in your app's build.gradle file add a dependency on the :shared-test module for the unit and instrumented test build configurations:

testImplementation(project(":shared-test"))
androidTestImplementation(project(":shared-test"))

If your shared test code is dependent on code in your app (for example, you have Hilt modules which reference app interfaces), add a dependency in your shared-test module's build.gradle file on the app module:

compileOnly(project(":app"))

It's important to use compileOnly and not implementation here, otherwise you might end up with com.android.builder.dexing.DexArchiveMergerExceptions because classes are defined in multiple DEX files.

Example on GitHub here: https://github.com/android/architecture-samples

Doehne answered 14/3, 2023 at 18:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.