Merge pull request #143 from fknives/issue#35-code-coverage
Issue#35 code coverage
This commit is contained in:
commit
1fa46691d9
25 changed files with 331 additions and 70 deletions
2
.github/workflows/pull-request-jobs.yml
vendored
2
.github/workflows/pull-request-jobs.yml
vendored
|
|
@ -122,7 +122,7 @@ jobs:
|
||||||
force-avd-creation: false
|
force-avd-creation: false
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
disable-animations: true
|
disable-animations: true
|
||||||
script: ./gradlew connectedDebugAndroidTest
|
script: ./gradlew connectedDebugAndroidTest -PdisableAndroidTestCoverage=true
|
||||||
- name: Upload Test Results
|
- name: Upload Test Results
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
if: always()
|
if: always()
|
||||||
|
|
|
||||||
37
README.md
37
README.md
|
|
@ -230,5 +230,42 @@ androidTestImplementation "org.fnives.android.testutil:android:<latestVersion>"
|
||||||
androidTestImplementation "org.fnives.android.testutil:shared-android:<latestVersion>" // test-util-shared-android
|
androidTestImplementation "org.fnives.android.testutil:shared-android:<latestVersion>" // test-util-shared-android
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Code Coverage Report
|
||||||
|
|
||||||
|
For Code Coverage Reporting, Jacoco is setup in [jacoco.config.gradle](./gradlescripts/jacoco.config.gradle).
|
||||||
|
|
||||||
|
- Each sub module has it's own code coverage report, enabled by the gradle script.
|
||||||
|
- Additionally it contains gradle task for an aggregated code coverage report for the project as a whole.
|
||||||
|
|
||||||
|
Feel free to use that script and tweak it for your project and module setup.
|
||||||
|
|
||||||
|
The script is documented, to the best of my understanding, but specific to this project, not prepared for multiple buildFlavours or different buildTypes than debug.
|
||||||
|
|
||||||
|
### Sub module reports
|
||||||
|
To run tests and Jacoco report for a submodule, run task `jacocoTestReport`:
|
||||||
|
- for java it will run unit tests and creates a report
|
||||||
|
- for android it will run jacocoAndroidTestReport and jacocoUnitTestReport and create 2 separate reports.
|
||||||
|
|
||||||
|
> Note:
|
||||||
|
> - jacocoAndroidTestReport is alias to createDebugAndroidTestCoverageReport
|
||||||
|
> - jacocoUnitTestReport is alias to createDebugUnitTestCoverageReport
|
||||||
|
|
||||||
|
### Aggregated reports
|
||||||
|
To see an aggregated code coverage report:
|
||||||
|
- task `jacocoRootReport` will pull together all the submodules report and create a single one from them ($projectDir/build/coverage-report).
|
||||||
|
- task `runTestAndJacocoRootReport` will run all the sub modules reports and tests then run `jacocoRootReport`.
|
||||||
|
|
||||||
|
### Issues
|
||||||
|
- One issue, is that the androidTest reports don't work with the sharedTest module setup, this issue is reported [here](https://issuetracker.google.com/issues/250130118)
|
||||||
|
- Another issue, is that seems like the tests fail with Resource.NotFound on API 21 if `enableAndroidTestCoverage` is true, so I disabled that for CI.
|
||||||
|
|
||||||
|
By shared test module setup I mean a module like `app-shared-test`, which has a dependency graph of:
|
||||||
|
- app-shared-test -> app.main
|
||||||
|
- app.test -> app-shared-test
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
Here are the two articles I used for the jacoco setup script: [jacoco-in-android](https://medium.com/swlh/multi-module-multi-flavored-test-coverage-with-jacoco-in-android-bc4fb4d135a3)
|
||||||
|
[aggregate-test-coverage](https://lkrnac.net/blog/2016/10/aggregate-test-coverage-report/).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[License file](./LICENSE)
|
[License file](./LICENSE)
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.fnives.test.showcase"
|
applicationId "org.fnives.test.showcase"
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
buildConfigField "String", "BASE_URL", '"https://606844a10add49001733fe6b.mockapi.io/"'
|
buildConfigField "String", "BASE_URL", '"https://606844a10add49001733fe6b.mockapi.io/"'
|
||||||
|
|
@ -37,7 +37,7 @@ android {
|
||||||
compose = true
|
compose = true
|
||||||
}
|
}
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion = project.androidx_compose_version
|
kotlinCompilerExtensionVersion = project.compose_compiler_version
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
20
build.gradle
20
build.gradle
|
|
@ -1,27 +1,30 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = "1.6.10"
|
ext.kotlin_version = "1.7.10"
|
||||||
ext.detekt_version = "1.19.0"
|
ext.detekt_version = "1.19.0"
|
||||||
ext.navigation_version = "2.4.2"
|
ext.navigation_version = "2.4.2"
|
||||||
ext.hilt_version = "2.40.5"
|
ext.hilt_version = "2.44"
|
||||||
|
ext.compose_compiler_version = "1.3.1"
|
||||||
|
ext.compileSdkVersion = 32
|
||||||
|
ext.minSdkVersion = 21
|
||||||
|
ext.targetSdkVersion = 32
|
||||||
|
ext.jacoco_version = "0.8.8"
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven { url "https://plugins.gradle.org/m2/" }
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.1.3'
|
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.1"
|
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"
|
||||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
||||||
|
classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.1"
|
||||||
|
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$detekt_version"
|
||||||
|
classpath "org.jacoco:org.jacoco.core:$jacoco_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
|
||||||
id "io.gitlab.arturbosch.detekt" version "$detekt_version"
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
@ -49,3 +52,4 @@ apply from: 'gradlescripts/testoptions.gradle'
|
||||||
apply from: 'gradlescripts/test.tasks.gradle'
|
apply from: 'gradlescripts/test.tasks.gradle'
|
||||||
apply from: 'gradlescripts/testdependencies.gradle'
|
apply from: 'gradlescripts/testdependencies.gradle'
|
||||||
apply from: 'gradlescripts/disable.test.task.gradle'
|
apply from: 'gradlescripts/disable.test.task.gradle'
|
||||||
|
apply from: 'gradlescripts/jacoco.config.gradle'
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
#Thu Jan 27 21:44:07 EET 2022
|
#Fri Sep 30 19:34:26 EEST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
apply plugin: "io.gitlab.arturbosch.detekt"
|
||||||
|
|
||||||
detekt {
|
detekt {
|
||||||
toolVersion = "$detekt_version"
|
toolVersion = "$detekt_version"
|
||||||
|
|
@ -16,14 +17,15 @@ detekt {
|
||||||
source = files(*projectPaths)
|
source = files(*projectPaths)
|
||||||
config = files("$projectDir/detekt/detekt.yml")
|
config = files("$projectDir/detekt/detekt.yml")
|
||||||
baseline = file("$projectDir/detekt/baseline.xml")
|
baseline = file("$projectDir/detekt/baseline.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.getByName("detekt") {
|
||||||
reports {
|
reports {
|
||||||
txt {
|
txt.required.set(true)
|
||||||
enabled = true
|
txt.outputLocation.set(file("build/reports/detekt.txt"))
|
||||||
destination = file("build/reports/detekt.txt")
|
html.required.set(true)
|
||||||
}
|
html.outputLocation.set(file("build/reports/detekt.html"))
|
||||||
html {
|
xml.required.set(false)
|
||||||
enabled = true
|
sarif.required.set(false)
|
||||||
destination = file("build/reports/detekt.html")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
220
gradlescripts/jacoco.config.gradle
Normal file
220
gradlescripts/jacoco.config.gradle
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
// filter of files that shouldn't be part of the report
|
||||||
|
def androidFileFilter =
|
||||||
|
[ //jdk
|
||||||
|
'jdk.internal.*',
|
||||||
|
// data binding
|
||||||
|
'**/databinding/*.class',
|
||||||
|
'**/BR.*',
|
||||||
|
// android
|
||||||
|
'**/R.class',
|
||||||
|
'**/R$*.class',
|
||||||
|
'**/BuildConfig.*',
|
||||||
|
'**/Manifest*.*',
|
||||||
|
'**/*Test*.*',
|
||||||
|
'android/**/*.*',
|
||||||
|
// kotlin
|
||||||
|
'**/META-INF/*',
|
||||||
|
'**/*MapperImpl*.*',
|
||||||
|
'**/*$ViewInjector*.*',
|
||||||
|
'**/*$ViewBinder*.*',
|
||||||
|
'**/BuildConfig.*',
|
||||||
|
'**/*Component*.*',
|
||||||
|
'**/*BR*.*',
|
||||||
|
'**/Manifest*.*',
|
||||||
|
'**/*$Lambda$*.*',
|
||||||
|
'**/*Companion*.*',
|
||||||
|
'**/*Module*.*',
|
||||||
|
'**/*Dagger*.*',
|
||||||
|
'**/*Hilt*.*',
|
||||||
|
'**/*MembersInjector*.*',
|
||||||
|
'**/*_MembersInjector.class',
|
||||||
|
'**/*_Factory*.*',
|
||||||
|
'**/*_Provide*Factory*.*',
|
||||||
|
'**/*Extensions*.*',
|
||||||
|
// sealed and data classes
|
||||||
|
'**/*$Result.*',
|
||||||
|
'**/*$Result$*.*',
|
||||||
|
// adapters generated by moshi
|
||||||
|
'**/*JsonAdapter.*',
|
||||||
|
// room
|
||||||
|
'**/*_Impl.class',
|
||||||
|
'**/*_Impl*.*',
|
||||||
|
// hilt
|
||||||
|
'**/hilt_aggregated_deps/*'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
/ **
|
||||||
|
* Setup Jacoco for Android module.
|
||||||
|
* - applies Plugin to the module.
|
||||||
|
* - sets up the "debug" build type for jacoco
|
||||||
|
* - creates tasks:
|
||||||
|
* - if androidTest folder exists creates a jacocoAndroidTestReport alias for the jacoco coverageReport, otherwise an empty task.
|
||||||
|
* - if test folder exists creates a jacocoUnitTestReport alias for the jacoco coverageReport, otherwise an empty task.
|
||||||
|
* - creates jacocoTestReport which runs both alias tasks created before.
|
||||||
|
*
|
||||||
|
* Note: "jacocoTestReport" is the task name which is default for Java Modules.
|
||||||
|
* /
|
||||||
|
|
||||||
|
def setupAndroidJacoco(Project module, ArrayList<String> fileFilter, String jacocoVersion) {
|
||||||
|
configure(module) {
|
||||||
|
apply plugin: "jacoco"
|
||||||
|
|
||||||
|
module.android.testOptions.unitTests.all {
|
||||||
|
jacoco.includeNoLocationClasses = true
|
||||||
|
jacoco.excludes = fileFilter
|
||||||
|
}
|
||||||
|
// on API 21 enableAndroidTestCoverage makes the tests crash with resource not found issue
|
||||||
|
def disableAndroidTestCoverage = findProperty("disableAndroidTestCoverage") ?: false
|
||||||
|
android.buildTypes.debug.enableAndroidTestCoverage = !disableAndroidTestCoverage
|
||||||
|
android.buildTypes.debug.enableUnitTestCoverage = true
|
||||||
|
|
||||||
|
jacoco.toolVersion = "$jacocoVersion"
|
||||||
|
|
||||||
|
def hasAndroidTests = new File("${module.projectDir}/src/androidTest").exists()
|
||||||
|
def hasUnitTests = new File("${module.projectDir}/src/test").exists()
|
||||||
|
if (hasUnitTests) {
|
||||||
|
task jacocoUnitTestReport(dependsOn: ["createDebugUnitTestCoverageReport"]) {
|
||||||
|
group = "verification"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task jacocoUnitTestReport() {
|
||||||
|
group = "verification"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasAndroidTests) {
|
||||||
|
task jacocoAndroidTestReport(dependsOn: ["createDebugAndroidTestCoverageReport"]) {
|
||||||
|
group = "verification"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task jacocoAndroidTestReport() {
|
||||||
|
group = "verification"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task jacocoTestReport(dependsOn: ["jacocoUnitTestReport", "jacocoAndroidTestReport"]) {
|
||||||
|
group = "verification"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/ **
|
||||||
|
* Setup Jacoco for Java module.
|
||||||
|
* - applies Plugin to the module.
|
||||||
|
* - updates the `jacocoTestReport` task to ignore the `androidFileFilter`
|
||||||
|
* - ensures tests run before `jacocoTestReport`
|
||||||
|
* /
|
||||||
|
|
||||||
|
def setupJavaJacoco(Project module, ArrayList<String> fileFilter) {
|
||||||
|
configure(module) {
|
||||||
|
apply plugin: "jacoco"
|
||||||
|
|
||||||
|
jacocoTestReport {
|
||||||
|
dependsOn test // tests are required to run before generating the report
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
classDirectories.setFrom(files(classDirectories.files.collect {
|
||||||
|
fileTree(dir: it, exclude: fileFilter)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/ **
|
||||||
|
* Setup Jacoco for submodules based on their android or java module type
|
||||||
|
*/
|
||||||
|
subprojects { module ->
|
||||||
|
plugins.withType(JavaPlugin).whenPluginAdded {
|
||||||
|
setupJavaJacoco(module, androidFileFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.withId("com.android.application") {
|
||||||
|
setupAndroidJacoco(module, androidFileFilter, "$jacoco_version")
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.withId("com.android.library") {
|
||||||
|
setupAndroidJacoco(module, androidFileFilter, "$jacoco_version")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/ **
|
||||||
|
* Setup Aggregation tasks for Jacoco.
|
||||||
|
* - jacocoRootReport: can be used to generate the report after submodules `jacocoTestReport` has been ran at least once.
|
||||||
|
* - runTestAndJacocoRootReport: calls the `jacocoTestReport` of each submodule then calls `jacocoRootReport` for aggregation.
|
||||||
|
*
|
||||||
|
* Context, how the aggregated report works:
|
||||||
|
* The jacoco tasks created by the plugin generate .ec and .exec Execution-Data files in specific locations.
|
||||||
|
* - These Execution-Data files are all pulled into one `JacocoReport` task (`executionData.from`).
|
||||||
|
* - All the source files from all the submodules are pulled into the same `JacocoReport` task (`sourceDirectories.from`)
|
||||||
|
* - All the class files from all the submodules are pulled into the same `JacocoReport` task (`classDirectories.from`)
|
||||||
|
* Then finally the report is configured to be generated at root `build\coverage-report`
|
||||||
|
* /
|
||||||
|
configure(rootProject) {
|
||||||
|
apply plugin: "jacoco"
|
||||||
|
def testTypeName = "debug"
|
||||||
|
|
||||||
|
task runTestAndJacocoRootReport(type: JacocoReport, group: 'Coverage reports') {
|
||||||
|
description = 'Run Tests and Generates report from all subprojects'
|
||||||
|
|
||||||
|
// add all non empty subProjects `jacocoTestReport` task as a dependency.
|
||||||
|
// note: these tasks are default Jacoco Task for Java and have been added above for Android modules.
|
||||||
|
def codeProjects = subprojects.findAll({ it.subprojects.isEmpty() })
|
||||||
|
codeProjects.forEach {
|
||||||
|
dependsOn += ["$it.path:jacocoTestReport"]
|
||||||
|
}
|
||||||
|
|
||||||
|
finalizedBy("jacocoRootReport")
|
||||||
|
}
|
||||||
|
|
||||||
|
task jacocoRootReport(type: JacocoReport, group: 'Coverage reports') {
|
||||||
|
description = 'Generates report from all subprojects'
|
||||||
|
|
||||||
|
def codeProjects = subprojects.findAll({ it.subprojects.isEmpty() })
|
||||||
|
sourceDirectories.from = files(codeProjects.collect { "${it.projectDir}/src/main/java" })
|
||||||
|
|
||||||
|
def classFileTrees = codeProjects.collect {
|
||||||
|
def javaClassFilesInJavaModuleTree = fileTree(
|
||||||
|
dir: "${it.buildDir}/classes/java/main",
|
||||||
|
excludes: androidFileFilter
|
||||||
|
)
|
||||||
|
def kotlinClassFilesInJavaModuleTree = fileTree(
|
||||||
|
dir: "${it.buildDir}/classes/kotlin/main",
|
||||||
|
excludes: androidFileFilter
|
||||||
|
)
|
||||||
|
def javaClassFilesInAndroidModuleTree = fileTree(
|
||||||
|
dir: "${it.buildDir}/intermediates/javac/${testTypeName}/classes",
|
||||||
|
excludes: androidFileFilter
|
||||||
|
)
|
||||||
|
def kotlinClassFilesInAndroidModuleTree = fileTree(
|
||||||
|
dir: "${it.buildDir}/tmp/kotlin-classes/${testTypeName}",
|
||||||
|
excludes: androidFileFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
files([javaClassFilesInJavaModuleTree, kotlinClassFilesInJavaModuleTree, javaClassFilesInAndroidModuleTree, kotlinClassFilesInAndroidModuleTree])
|
||||||
|
}.flatten()
|
||||||
|
classDirectories.from = files(classFileTrees)
|
||||||
|
|
||||||
|
def executionDataFiles = codeProjects.collect {
|
||||||
|
def androidTestExecutionData = fileTree(
|
||||||
|
dir: "${it.buildDir}/outputs/code_coverage/${testTypeName}AndroidTest/connected/",
|
||||||
|
includes: ["**/*.ec", "**/*.exec"]
|
||||||
|
)
|
||||||
|
def androidUnitTestExecutionData = fileTree(
|
||||||
|
dir: "${it.buildDir}/outputs/unit_test_code_coverage/",
|
||||||
|
includes: ["**/*.ec", "**/*.exec"]
|
||||||
|
)
|
||||||
|
def javaUnitTestExecutionData = "${it.buildDir}/jacoco/test.exec"
|
||||||
|
|
||||||
|
[androidTestExecutionData, androidUnitTestExecutionData, javaUnitTestExecutionData]
|
||||||
|
}.flatten()
|
||||||
|
executionData.from = files(executionDataFiles)
|
||||||
|
|
||||||
|
reports {
|
||||||
|
html {
|
||||||
|
required = true
|
||||||
|
destination file("${buildDir}/coverage-report")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,9 +7,9 @@ project.ext {
|
||||||
androidx_swiperefreshlayout_version = "1.1.0"
|
androidx_swiperefreshlayout_version = "1.1.0"
|
||||||
room_version = "2.4.3"
|
room_version = "2.4.3"
|
||||||
activity_ktx_version = "1.4.0"
|
activity_ktx_version = "1.4.0"
|
||||||
androidx_navigation = "2.4.0"
|
androidx_navigation = "2.5.1"
|
||||||
|
|
||||||
androidx_compose_version = "1.1.0"
|
androidx_compose_version = "1.2.1"
|
||||||
google_accompanist_version = "0.23.1"
|
google_accompanist_version = "0.23.1"
|
||||||
androidx_compose_constraintlayout_version = "1.0.0"
|
androidx_compose_constraintlayout_version = "1.0.0"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.fnives.test.showcase.hilt"
|
applicationId "org.fnives.test.showcase.hilt"
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
buildConfigField "String", "BASE_URL", '"https://606844a10add49001733fe6b.mockapi.io/"'
|
buildConfigField "String", "BASE_URL", '"https://606844a10add49001733fe6b.mockapi.io/"'
|
||||||
|
|
@ -38,7 +38,7 @@ android {
|
||||||
compose = true
|
compose = true
|
||||||
}
|
}
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion = project.androidx_compose_version
|
kotlinCompilerExtensionVersion = project.compose_compiler_version
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -18,6 +18,7 @@ import org.fnives.test.showcase.android.testutil.synchronization.idlingresources
|
||||||
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.Disposable
|
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.Disposable
|
||||||
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.IdlingResourceDisposable
|
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.IdlingResourceDisposable
|
||||||
import org.fnives.test.showcase.hilt.R
|
import org.fnives.test.showcase.hilt.R
|
||||||
|
import org.fnives.test.showcase.hilt.network.testutil.HttpsConfigurationModuleTemplate
|
||||||
import org.fnives.test.showcase.hilt.network.testutil.NetworkSynchronization
|
import org.fnives.test.showcase.hilt.network.testutil.NetworkSynchronization
|
||||||
import org.fnives.test.showcase.hilt.test.shared.di.TestBaseUrlHolder
|
import org.fnives.test.showcase.hilt.test.shared.di.TestBaseUrlHolder
|
||||||
import org.fnives.test.showcase.hilt.test.shared.testutils.storage.TestDatabaseInitialization
|
import org.fnives.test.showcase.hilt.test.shared.testutils.storage.TestDatabaseInitialization
|
||||||
|
|
@ -56,8 +57,9 @@ class RobolectricAuthActivityInstrumentedTest {
|
||||||
testDispatcher = dispatcher
|
testDispatcher = dispatcher
|
||||||
TestDatabaseInitialization.dispatcher = dispatcher
|
TestDatabaseInitialization.dispatcher = dispatcher
|
||||||
|
|
||||||
mockServerScenarioSetup = MockServerScenarioSetup()
|
val (mockServerScenarioSetup, url) = HttpsConfigurationModuleTemplate.startWithHTTPSMockWebServer()
|
||||||
TestBaseUrlHolder.url = mockServerScenarioSetup.start(false)
|
this.mockServerScenarioSetup = mockServerScenarioSetup
|
||||||
|
TestBaseUrlHolder.url = url
|
||||||
|
|
||||||
hiltRule.inject()
|
hiltRule.inject()
|
||||||
val idlingResources = networkSynchronization.networkIdlingResources()
|
val idlingResources = networkSynchronization.networkIdlingResources()
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ include ':app-shared-test'
|
||||||
include ':hilt:hilt-core'
|
include ':hilt:hilt-core'
|
||||||
include ':hilt:hilt-network'
|
include ':hilt:hilt-network'
|
||||||
include ':hilt:hilt-app'
|
include ':hilt:hilt-app'
|
||||||
include ':examplecase:example-navcontroller'
|
|
||||||
include ':examplecase:example-navcontroller-shared-test'
|
|
||||||
include ':hilt:hilt-network-di-test-util'
|
include ':hilt:hilt-network-di-test-util'
|
||||||
include ':hilt:hilt-app-shared-test'
|
include ':hilt:hilt-app-shared-test'
|
||||||
|
include ':examplecase:example-navcontroller'
|
||||||
|
include ':examplecase:example-navcontroller-shared-test'
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package org.fnives.test.showcase.android.testutil.synchronization.idlingresources
|
package org.fnives.test.showcase.android.testutil.synchronization.idlingresources
|
||||||
|
|
||||||
import androidx.annotation.CheckResult
|
import androidx.annotation.CheckResult
|
||||||
import androidx.annotation.NonNull
|
|
||||||
import androidx.test.espresso.IdlingResource
|
import androidx.test.espresso.IdlingResource
|
||||||
import okhttp3.Dispatcher
|
import okhttp3.Dispatcher
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
|
@ -55,10 +54,7 @@ class OkHttp3IdlingResource private constructor(
|
||||||
* this instance using `Espresso.registerIdlingResources`.
|
* this instance using `Espresso.registerIdlingResources`.
|
||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
@NonNull
|
fun create(name: String, client: OkHttpClient): OkHttp3IdlingResource {
|
||||||
fun create(@NonNull name: String?, @NonNull client: OkHttpClient?): OkHttp3IdlingResource {
|
|
||||||
if (name == null) throw NullPointerException("name == null")
|
|
||||||
if (client == null) throw NullPointerException("client == null")
|
|
||||||
return OkHttp3IdlingResource(name, client.dispatcher)
|
return OkHttp3IdlingResource(name, client.dispatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk rootProject.ext.minSdkVersion
|
||||||
targetSdk 31
|
targetSdk rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue