I have around 25 tests on my android tests package. I have some tests that I to run during integration and some tests that run as normal instrumentation tests. I am trying to call the integration tests using Gradle tasks but it seems impossible for instrumentation tests. I have checked for unit tests and it's possible with something like this-
task integrationTest(
type: Test,
description: 'Run integration tests only. Pass in \'-Pintegration=true\'',
dependsOn: ['testDebugUnitTest', 'clean'] ) {
//Here for task completion, not actually used since sub task of testDebugUnitTest
testClassesDir = file("src/integrationTest/java/");
classpath = files("$System.env.ANDROID_HOME/sources/android-18")
//
//Turn on integration testing when argument exists and is true
//
if (project.hasProperty('integration')) {
println integration
if (integration == 'true') {
integrationTests = true
}
}
}
and doing something like this
testOptions {
unitTests.all {
useJUnit()
if (integrationTests.toBoolean()) {
println "Integration Tests Only for " + it.name
options {
excludeCategories 'com.example.reactivemvp.categories.UnitTest'
}
} else {
println "Unit Tests Only for " + it.name
options {
excludeCategories 'com.example.reactivemvp.categories.IntegrationTest'
}
}
}
}
I have seen that the testOptions only works with unit tests and not with instrumentation tests. I found out what is the method for access the instrumentation tests-
testVariants.all { variant ->
if(connectedInstrumentTest.name)
variant.connectedInstrumentTest.doFirst {
println "This will be executed right after our connectedInstrumentTest!"
println "The name of the test type: $connectedInstrumentTest.name"
if (intergrationTests == true) {
exclude '**/*androidTest.functionalTests*'
}
}
}
I get the error as
Could not find method exclude() for arguments [**/*androidTest.functionalTests*] on task ':app:connectedAndroidTest'
Is there a way to call only a section of the instrumentation tests by some Gradle task?
Related
Tried the Android code as given in the Docs.
I am unable to exclude the files.
testOptions {
unitTests.all {
if (name == "testDebugUnitTest") {
kover {
disabled = false
binaryReportFile.set(file("$buildDir/custom/debug-report.bin"))
// includes = ['com.example.*']
excludes = [
"com.makeappssimple.abhimanyu.financemanager.android.navigation.di.NavigationManagerModule"
]
}
}
}
}
I expect this code to exclude com.makeappssimple.abhimanyu.financemanager.android.navigation.di.NavigationManagerModule file, but it is not working.
Also tried with wildcard names.
Kover setup,
plugins {
id "com.android.application"
id "kotlin-android"
id "kotlin-kapt"
id "dagger.hilt.android.plugin"
id "com.google.gms.google-services"
id "org.jetbrains.kotlinx.kover" version "0.5.0"
}
// Kover
kover {
disabled = false // true to disable instrumentation of all test tasks in all projects
coverageEngine.set(kotlinx.kover.api.CoverageEngine.INTELLIJ) // change instrumentation agent and reporter
intellijEngineVersion.set('1.0.656') // change version of IntelliJ agent and reporter
jacocoEngineVersion.set('0.8.7') // change version of JaCoCo agent and reporter
generateReportOnCheck = true // false to do not execute `koverMergedReport` task before `check` task
disabledProjects = [] // ["project-name"] or [":project-name"] to disable coverage for project with path `:project-name` (`:` for the root project)
instrumentAndroidPackage = false // true to instrument packages `android.*` and `com.android.*`
runAllTestsForProjectTask = false // true to run all tests in all projects if `koverHtmlReport`, `koverXmlReport`, `koverReport`, `koverVerify` or `check` tasks executed on some project
}
P.S: I have also raised the same issue here
You can also try to add a filter the kover plugin like this version 0.6.0
kover {
instrumentation {
excludeTasks.add("testReleaseUnitTest")
}
filters {
classes {
excludes += listOf(
"dagger.hilt.internal.aggregatedroot.codegen.*",
"hilt_aggregated_deps.*",
"*ComposableSingletons*",
"*_HiltModules*",
"*Hilt_*",
"*BuildConfig",
".*_Factory.*",
)
}
}
}
Thanks to shanshin's comment, I understood the issue.
Fixed the unit test coverage report exclusion list using this code
tasks.koverHtmlReport {
excludes = [
// Hilt
"*.di.*",
"dagger.hilt.**",
"hilt_aggregated_deps.*",
"<package_name>.*.*_Factory",
// Room
// MyRoomDatabase_AutoMigration_*_Impl, *Dao_Impl
"<package_name>.*.*_Impl*",
// BuildConfig
"<package_name>.BuildConfig",
// Moshi - Json Adapter
"<package_name>.*.*JsonAdapter",
]
}
The exclusion list mentioned in the question is to exclude tests.
I am using this code in build.gradle:
android {
applicationVariants.all { variant ->
variant.packageApplicationProvider.configure { packageApplicationTask ->
doLast {
packageApplicationTask.apkNames.each { apkName ->
def apkDir = "./build/outputs/apk/${flavorName}/${buildType.name}"
def apkDestName = apkName.replace("app-", "stickerly-android-" + variant.versionName + "-").replace(".apk", "-" + getDate() + ".apk")
println "#####Rename ${variant.name} Apk File"
copy {
from("$apkDir/$apkName").into(apkDir).rename { String fileName -> apkDestName }
}
println "#####Copy mapping File"
def mappingDir = "./build/outputs/mapping/${flavorName}${buildType.name.capitalize()}"
copy {
from("$mappingDir/mapping.txt").into(mappingDir).rename {
"mapping-stickerly-${variant.versionName}.txt"
}
}
}
}
}
}
}
With this code I rename apk file and copy mapping file. I worked in android gradle plugin 4.0, but it does not work in 4.1 with this message
Where:
Script '/Users/snow/workspace/stickerly-android/app/build-android-extra.gradle' line: 5
What went wrong:
Execution failed for task ':app:packageExternalArm8Debug'.
Could not get unknown property 'apkNames' for task ':app:packageExternalArm8Debug' of type com.android.build.gradle.tasks.PackageApplication.
I think API has changed but I can not find any documents. Someone can help me?
Thanks.
property apkNames is removed in AGP 4.1
you can try this
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (!state.failure
&& task.project.name == project.name
&& task.name.startsWith("package")
&& !task.name.endsWith("UnitTest")) {
def outputDir = task.outputDirectory.getAsFile().get()
task.variantOutputs.getOrNull()?.each { variant ->
println "" + outputDir + "/" + variant.outputFileName.get()
}
}
}
add this at the end of your build.gradle file.
change println to whatever logic you want.
by the way, if you want to check the properties you may use, just add gradle plugin as a dependency of your project, click Sync in Android Stuido, then you can find it in External Librarys (key map: Command + 1, and switch to project view).
like this
dependencies {
implementation 'com.android.tools.build:gradle:4.1.0'
}
and these properties and tasks are intentionally invisible in lib com.android.tools.build:gradle-api, modifications in future releases are expected.
I am facing an issue when I try to stop gradle when a condition is not met.
I want when I execute a specific task and a file is not present to throw a GradleException but instead it fails to sync with Android Studio.
My code:
def mapFile = project.rootProject.file('../../maps.json')
buildConfigField "error", "BUILD_ERROR", '"maps.json is missing"'
if(!mapFile.exists()) throw new GradleException("File does not exist")
I have found this solution(don't really like it) with code:
buildConfigField "error", "BUILD_ERROR", '"maps.json is missing"'
so the BuildConfig will generate an error variable and the gradle will stop. Any other options of actually throwing an exception and the sync does not fail?
To let the task fail and not the whole build, you must raise the exception at task execution:
task myTask(type: MyType) {
def mapFile = project.rootProject.file('../../maps.json')
// do some configuration ...
doFirst {
if(!mapFile.exists()) throw new GradleException("File does not exist")
}
}
I'm trying to upload to Crittercism on build, and I put this at the bottom of my gradle file. However, it doesn't seem to be working when I build debug. What am I doing wrong?
task uploadMappingToProd() << {
def critterAppId = "abcde"
def appVersionName = "1.0.1"
def appVersionCode = "DEBUG"
def critterKey = "12345"
commandLine 'curl',
"https://app.crittercism.com/api_beta/proguard/$critterAppId",
'-F', 'proguard=#build/outputs/mapping/production/release/mapping.txt',
'-F', "app_version=$appVersionName-$appVersionCode",
'-F', "key=$critterKey"
type Exec
dependsOn 'assembleDebug'
}
The way you've done it, the task that you have defined, uploadMappingToProd, will if invoked by some reason also invoke assembleDebug. Because you have asked uploadMappingToProd to depend on assembleDebug - not the reverse. Therefore assembleDebug will happily finish without getting anywhere close to uploadMappingToProd.
If you want the reverse dependency i.e. assembleDebug to depend on uploadMappingToProd then you need to add this line after defining your task.
afterEvaluate {
tasks.assembleDebug.dependsOn uploadMappingToProd
}
This will guarantee uploadMappingToProd is invoked everytime and before assembleDebug is invoked.
My solution is working fine.(local build and jenkins build)
for me, only working when build is from jenkins
make sure your APPID, APPKEY, and path(release_jenkins.... normally release)
build.gradle (app) (add at the end)
task uploadPro << {
logger.error("Uploading mapping.txt file to crittercism")
String temp = projectDir;
temp = temp.replace("\\", "/");
String[] cmd = ["curl", "-k", "https://app.crittercism.com/api_beta/proguard/AppIDSting",
"-F", "proguard=#" + temp + "/build/outputs/mapping/release_jenkins/mapping.txt",
"-F", "app_version=" + VERSION_NAME + '-' + VERSION_CODE,
"-F", "key=API_KEY"]
logger.error("CMD : " + cmd)
ProcessBuilder builder = new ProcessBuilder(cmd);
Process process = builder.start();
process.waitFor()
println process.err.text
println process.text
}
gradle.buildFinished {
//check your build type. I am not sure it's the best way to do it.
logger.error("JSC : 이름 ! - " + gradle.startParameter.taskNames);
if (gradle.startParameter.taskNames.contains("assembleRelease_jenkins")) {
logger.error("JSC : 올리기 시작 ! - " + gradle.startParameter.taskNames);
tasks.uploadPro.execute()
} else {
logger.error("JSC : PASS")
}
}
sample project -> https://github.com/SinsangMarket/CrittercismMappingTXT
I have a library that is being build within a Travis CI instance. After the build completes, I would like it to upload the artifact using ./gradlew uploadArchives. The problem right now is that, while I can do this locally, the Travis instance doesn't have my server key in its .ssh/known_hosts file (it probably doesn't even HAVE a .ssh/known_hosts file.
I am using the following configuration of uploadArchives in my gradle configuration:
uploadArchives {
repositories {
mavenDeployer {
pom.packaging = "aar"
pom.groupId = project.CORE_GROUP
pom.version = project.CORE_VERSION_NAME
}
}
}
gradle.taskGraph.beforeTask { Task aTask ->
if (aTask == uploadArchives) {
checkArtifactPublishProperties()
aTask.repositories.mavenDeployer.configuration = configurations.deployerJars
aTask.repositories.mavenDeployer.repository(url: "scp://" + project.publishArtifactHost + ":" + getArtifactTargetDirectory()) {
authentication(userName: project.publishArtifactUsername, privateKey: ext.publishArtifactKeyFile)
}
}
}
I'm not sure how to specify the StrictHostKeyChecking=no as a parameter to this method. My gut tells me that I have to add it to the configuration configurations.deployerJars, but I'm not sure how to do this.
Can someone point me to the documentation for this and perhaps provide a sample of how I might go about this?