SharedTest got warning "Duplicate content root detected" on Android Studio Chipmunk

5.6k views Asked by At

After upgrade to Android Studio Chipmunk, my test failed because I can't access file inside shared folder that defined in build.gradle like this.

sourceSets {
    androidTest.java.srcDirs += "src/sharedTest/java"
    test.java.srcDirs += "src/sharedTest/java" }

It show warning pop up with message "Duplicate content root detected". Path [sharedTest] of module [unitTest] was removed from modules [androidTest]. Anyone can resolve this?

5

There are 5 answers

6
MikeMcC399 On BEST ANSWER

According to https://issuetracker.google.com/issues/232007221 ("Duplicate content roots detected" with Android Gradle plugin 7.2.0) Google no longer supports this construct in Android Studio Chipmunk 2021.2.1.

https://issuetracker.google.com/issues/232007221#comment17 says "Source sets can no longer contain shared roots as this is impossible to represent in the IDE."

To follow the on-going discussions, subscribe to https://issuetracker.google.com/232007221 and
https://issuetracker.google.com/232420188

0
ipcjs On

You can use symbolic links to get around the problem.

Execute the following command in app/src directory:

ln -s sharedTest sharedAndroidTest

Edit the build.gradle file:

sourceSets {
    androidTest.java.srcDirs += "src/sharedAndroidTest/java"
    test.java.srcDirs += "src/sharedTest/java" 
}
0
k4dima On

https://issuetracker.google.com/issues/232420188#comment19

The current recommendation is to use a separate com.android.library Gradle project to store any shared code required across test and androidTest.

0
becke-ch On

According to (@kreker thx for the hint): https://issuetracker.google.com/issues/232420188#comment19

The current recommendation is to use a separate com.android.library Gradle project to store any shared code required across test and androidTest.

But often (at least for me) it is enough just to create a separate java project, move the shared test code into this new project and create two additional testImplementation and androidTestImplementation project dependencies to the new shared project.

Step-by-step (maybe it helps) I did it as follows: 1. next to the app folder create a new folder called sharedTest (or something similar). 2. create the sub-directories sharedTest/src/main. 3. Move (or rather git mv in order not to loose the version history) the shared test code: git mv app/src/sharedTest/java sharedTest/src/main/ (and do not forget to check-in). 3. in sharedTest create a new (minimal) sharedTest/build.gradle.kts file:

plugins {
    java
}

dependencies {
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
}

4.Edit the settings.gradle.kts file and add the new shared project: include(":sharedTest"). 5. Edit the app/build.gradle.kts file: remove the conflicting shared source-set section android{...} and add 2 new dependencies:

dependencies {
    //Share Code between androidTest and test
    //https://stackoverflow.com/questions/72358843/sharedtest-got-warning-duplicate-content-root-detected-on-android-studio-chipm
    testImplementation(project(path = ":sharedTest"))
    androidTestImplementation(project(path = ":sharedTest"))
}
0
AndrewStone On

If you are now getting this error, its probably not the fixed bug described above (in Gradle 8.2.1 anyway). Instead, you may be actually including the same source files in multiple targets, using something like:

sourceSets {
   val AndroidMain by getting {
      dependencies {
          srcDirs("src/your_common_files")
       }
  }
   val jvmMain by getting {
      dependencies {
          srcDirs("src/your_common_files")
       }
  }

Gradle does not like this extremely common code reuse technique, possibly because gradle was designed to frustrate innocent developers :-).

Instead, gradle wants you to make a separate "sourceset" and then depend on it. Almost but not quite like this:

sourceSets {
        create("commonJvm") {
            kotlin.srcDirs("src/commonJvm")
        }
        
        val androidMain by getting {
            dependencies {
                sourceSets.named("commonJvm")
            }
        }
       val jvmMain by getting {
            dependencies {
                sourceSets.named("commonJvm")
            }
        }
}

Instead, use this:

sourceSets {
        create("commonJvm") {
            kotlin.srcDirs("src/commonJvm")
        }
        
        val androidMain by getting {
            dependsOn(sourceSets.named("commonJvm").get())
            dependencies {
            }
        }
       val jvmMain by getting {
            dependsOn(sourceSets.named("commonJvm").get())
            dependencies {
            }
        }
}

I guess its not a "dependency" but it just "depends on" the common source set! /s
Makes sense to someone I guess?!?!

Personally, I think that all 3 of these ways ought to work, so I'm leaving this cookie crumb to save you 4 hours of head banging pain.

Note that you could also "cheat" and just use symlinks. But mswindows does not like that.