How do I prevent a flavor specific unit test from being compiled in another flavor?
Asked Answered
T

1

8

I'm trying to do this, but with a single dimension so it's simpler: How to specify unit test folder in two-dimension flavor

app module build.gradle specifies 2 flavors, free and premium:

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'

    android {
        compileSdkVersion 28
        defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner 
    "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android- 
     optimize.txt'), 'proguard-rules.pro'
        }
    }
    flavorDimensions 'someFlavor'
    productFlavors {
        premium {
            applicationIdSuffix '.premium'
        }

        free
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
        debug.java.srcDirs += 'src/debug/kotlin'
        release.java.srcDirs += 'src/release/kotlin'

        free {
            java.srcDirs += 'src/free/kotlin'
            test.java.srcDirs += 'src/test/kotlin'
        }

        premium {
            java.srcDirs += 'src/premium/kotlin'
            test.java.srcDirs += ['src/test/kotlin', 
        'src/testPremium/kotlin']
        }
    }
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:design:28.0.0'
}

Android Studio's Project view shows:

app
  src
    free
      kotlin (empty folder for now)
    main
      java
        com.example.myapplication
          MainActivity.java
    premium
      kotlin
        com.example.myapplication
          PremiumFile.kt
    test
      kotlin
        com.example.myapplication
          MainTest.kt
    testPremium
      kotlin
        com.example.myapplication
          PremiumTest.kt

PremiumFile.kt

class PremiumFile {
  companion obnject {
    const val PREMIUM_NUM = 10
  }
}

MainTest.kt

class MainTest {
    @Test
    fun basicMainTest() {
      assertEquals(1, 1)
    }
}

PremiumTest.kt

class PremiumTest {
    @Test
    fun premiumTest() {
        assertEquals(PremiumFile.Premium_NUM, 1)
    }
}

As you can see, I lack any unit tests specific to the free flavor. I expected that running ./gradlew compileFreeReleaseUnitTestKotlin would compile the shared unit test inside src/test, but it also compiles the Premium unit tests inside src/testPremium. How can I make sure that PremiumTest.kt is only compiled for Premium tasks such as ./gradlew compilePremiumReleaseUnitTestKotlin?

Teller answered 3/8, 2019 at 22:1 Comment(6)
Out of interest can I ask why you would want this behaviour?Finbar
I have a Premium flavor for paid users. Premium tests test Premium features. compilePremiumReleaseUnitTestKotlin would compile tests for free and premium. compileFreeReleaseUnitTestKotlin would only compile tests for free inside src/test.Teller
so you mean you want to speed up your build by doing less tests for each flavor?Finbar
I dont care about build time. I want to compile src/testPremium and src/test for premium flavor, src/test for anything elseTeller
in the post I added every file you need to reproduce. Simply create a new empty android application, copy/paste my build.gradle and create the additional directories and files I've pasted above. Try running ./gradlew compileFreeReleaseUnitTestKotlin and ./gradlew compilePremiumReleaseUnitTestKotlin.Teller
Could you share the complete sample project code on GitHub or somewhere?Beecher
E
6

If you run gradlew sourceSets on your project, you'll get the following section among the others :

test
----
Compile configuration: testCompile
build.gradle name: android.sourceSets.test
Java sources: [app\src\test\java, app\src\test\kotlin, app\src\testPremium\kotlin]
Java-style resources: [app\src\test\resources]

testPremium
-----------
Compile configuration: testPremiumCompile
build.gradle name: android.sourceSets.testPremium
Java sources: [app\src\testPremium\java]
Java-style resources: [app\src\testPremium\resources]

As you can see app\src\testPremium\kotlin is in the main test configuration, not in the testPremium. And because test is shared among all the flavors, its sources included in all of them (e.g. testFree configuration will include sources specified in both test and testFree configurations).

It also suggests you how to fix the issue - use testPremium in the configuration block. So instead of

premium {
    java.srcDirs += 'src/premium/kotlin' 
    test.java.srcDirs += ['src/test/kotlin', 'src/testPremium/kotlin']
}

Write

premium {
    java.srcDirs += 'src/premium/kotlin'
}
test{
    java.srcDirs += 'src/test/kotlin'
}
testPremium {
    java.srcDirs += 'src/testPremium/kotlin'
}

So gradlew sourseSets will give you:

test
----
Compile configuration: testCompile
build.gradle name: android.sourceSets.test
Java sources: [app\src\test\java, app\src\test\kotlin]
Java-style resources: [app\src\test\resources]

testPremium
-----------
Compile configuration: testPremiumCompile
build.gradle name: android.sourceSets.testPremium
Java sources: [app\src\testPremium\java, app\src\testPremium\kotlin]
Java-style resources: [app\src\testPremium\resources]

Because test does not exist in AndroidSourceSet, it's not a 'type' of sources like 'java', 'resources' and so on. Instead, test is another instance of AndroidSourceSet. So when you're writing test.java.srcDirs, you are actually configuring this top-level test source set, not tests inside premium.

Esposito answered 11/8, 2019 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.