Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 508
HukeLau_DABA Avatar asked Aug 03 '19 22:08

HukeLau_DABA


People also ask

What is a build variant?

Build variants are the result of Gradle using a specific set of rules to combine settings, code, and resources configured in your build types and product flavors. Although you do not configure build variants directly, you do configure the build types and product flavors that form them.

What is a flavor dimension?

Flavor dimensions are groupings of product flavors, and you can combine flavors from different dimensions.

What is buildtype in Gradle?

A build type determines how an app is packaged. By default, the Android plug-in for Gradle supports two different types of builds: debug and release . Both can be configured inside the buildTypes block inside of the module build file.

How to change build variant in Android Studio?

Change the build variant By default, Android Studio builds the debug version of your app, which is intended for use only during development, when you click Run. To change the build variant Android Studio uses, select Build > Select Build Variant in the menu bar.


1 Answers

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.

like image 134
esentsov Avatar answered Oct 23 '22 05:10

esentsov