Intellij not recognizing directory as tests - android

I added another source set, and a task of type test that uses that source set. I can execute the task and run the tests fine.
However, Intellij doesn't consider this src/newTests/java as tests. If I 'Mark directory as test sources' in the UI, it will forget it he next time build.gradle is synced. How do I make it remember this?

Try this:
android {
sourceSets {
test {
java.srcDir file('src/newTest/java')
}
}
}
Result:

Related

How to add gradle's task parameter in Android Studio?

We are going to debug our Android app by adding some properties in app.properties and pre-process it in the Kotlin codes.
We wrote build.gradle like:
task dailytest {
doLast {
File testProperty = new File('assets/app.properties')
testProperty.append("\ndaily_test=true")
testProperty.append("\nfps_sample_interval_ms=")
testProperty.append(fps_sample_interval_ms)
testProperty.append("\ndrop_stack_sample_interval_ms=")
testProperty.append(drop_stack_sample_interval_ms)
testProperty.append("\nmin_drop_count_to_log=")
testProperty.append(min_drop_count_to_log)
}
}
And we compile it in command line using:
./gradlew dailytest -Pfps_sample_interval_ms="100" -Pdrop_stack_sample_interval_ms="100" -Pmin_drop_count_to_log="1" :connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.myapp.sub.MainActivityTest#test_click_shelf
I was wondering if maybe we could run this test case in Android Studio by adding some confirmations?
We did try to add ::dailytest in the Before launch part, but we couldn't manage to find a way to add the custom parameters.
You can have an afterEvaluate block in your build.gradle to run your task when you build your app, something like this:
afterEvaluate {
lint.dependsOn dailytest
}

Isolating test APK build

I have a situation where in an Android project with instrumentation tests I have all of the production code precompiled and ready to be installed as an .apk (a React Native environment).
Whenever I run instrumentation tests, I initially build the AndroidTest .apk using Gradle by running:
./gradlew assembleDebugAndroidTest -DtestBuildType=debug
(i.e. in a pretty standard way).
Trouble is that despite explicitly specifying only the xxxAndroidTest task, all of the production code assembly Gradle tasks are run as well. This is an extreme time waster to me since - as I explained, the production apk is already there, and thus code compilation (and packaging, signing, etc.) is scarce.
In essence, I have no dependency in production code from the instrumentation code -- even the ActivityTestRule I use is created dynamically and isn't directly bound to my main activity:
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(launchIntent, 0);
Class<?> activityClass = Class.forName(resolveInfo.activityInfo.name);
ActivityTestRule<?> activityTestRule = new ActivityTestRule(activityClass, false, false);
Question is: How can I isolate / restrict Gradle's work so it would only include test-related tasks? I even tried inspecting the tasks tree using this Gradle plugin, but couldn't find a clear place to "cut the tree" down.
Well so far I've come up with this (heuristic) solution, that does 2 things:
I noticed that most of the time that goes to waste is due to sub-projects that are not needed for the job. Therefore, the solution provides an easy way to exclude implementations from test building.
Out of the tasks remaining in the list, still - the plugin iteratively force-disables tasks that are not related but run nonetheless.
It boils down to this helper Gradle script:
// turbo-test-apk.gradle
def isEnabled = System.getProperty('TURBO_TEST_APK') != null
project.ext.dependenciesExcludeTest = { depsClosure ->
if (!isEnabled) {
dependencies(depsClosure)
}
}
gradle.taskGraph.whenReady { graph ->
if (isEnabled) {
def disabledTasks = new ArrayList<Task>(graph.allTasks.size())
[/.*JsAndAssets.*/, /package.*Release/, /package.*Debug/, /compile.*/, /.*[Pp]roguard.*/, /.*[Nn]ew[Rr]elic.*/, /.*AndroidTest.*/].forEach { regex ->
graph.allTasks.findAll { it.name ==~ regex }.forEach({ task ->
disabledTasks.add(task)
task.enabled = false
})
}
graph.allTasks.findAll { it.name ==~ /.*AndroidTest.*/ }.forEach({ task ->
task.enabled = true
})
println '--- Turbo test build: task scanning ---'
disabledTasks.forEach { task ->
if (!task.enabled) {
println 'Force-skipping ' + task
}
}
println '---------------------------------------'
}
}
Namely, the dependenciesExcludeTest enabled the exclusion of unwanted subprojects, and the task-graph-ready callback does the disabling. NOTE that the regex list is custom made, and is not generic. It makes sense for my project as react native projects have a heavy-weight JS-bundling tasks called bundleJsAndAssets, and I also have new relic installed. Nevertheless, this can be easily tailored to any project.
Also, the app.gradle looks something like this:
apply plugin: 'com.android.application'
apply from: './turbo-test-apk.gradle'
dependencies {
implementation "org.jetbrains.kotlin:$kotlin_stdlib:$kotlinVersion"
implementation "com.android.support:support-v4:$supportLibraryVersion"
implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
// etc.
}
// These will be excluded when executing test-only mode
dependenciesExcludeTest {
implementation project(':#react-native-community_async-storage')
implementation project(':any-unneeded-sub-project')
}
So when gradle is run like this (i.e. with a custom TURBO_TEST_APK property):
./gradlew assembleDebugAndroidTest -DtestBuildType=debug -DTURBO_TEST_APK
the script will apply its work and reduce the overall build time.
This solution isn't optimal: tricky to maintain, doesn't omit all of the unnecessary work. I'd be very happy to see more effective solutions.

How to make conditional build task on android build gradle

In android, we would like to make one app build with different application id depends on the pre-installed app package.
So it contains flavor in the build gradle with different applicationId set.
But we don't want all these flavors been build, we just want to only build the one based on pre-installed app package name to save sometime on build server.
If used
task prepareA(dependsOn:['assembleADebug']){}
task prepareB(dependsOn:['assembleBDebug']){}
task prepareTest(dependsOn:['prepareA', 'prepareB']) {}
Then when called prepareTest, both prepareA and prepareB would be executed with both assembleADebug and assembleBDebug executed.
I only want to build either prepareA or prepareB be executed based on one condition check (if ...).
The answer I found after some hours invesigation, it is that we can use afterEvaluate method, which would execute before dependsOn is running.
Remove the predefined dependsOn the the prepareA and prepareB.
Then
afterEvaluate {
if (isPackageInstalled(packageName)) {
tasks.findByName("prepareTest").dependsOn("prepareA")
} else {
tasks.findByName("prepareTest").dependsOn("prepareB")
}
}

Could not find property 'uninstallDebug' on project

In my project I want to run my custom task "MyTask" to run before uninstall happens. Code for the same is
uninstallDebug.dependsOn "MyTask"
When I run this, it fails with an error
Could not find property 'uninstallDebug' on project
whereas, I see a gradle task listed in the Gradle window with that name.
What may be going wrong?
project.afterEvaluate { p ->
p.tasks.uninstallDebug.doFirst {
println 'before uninstall'
}
}
gradle.taskGraph.whenReady {
// if your MyTask is in the same project
uninstallDebug.dependsOn "MyTask"
// if it is else where
uninstallDebug.dependsOn project("someProject").project("subProject).tasks["MyTask"]
}
uninstallDebug along with several other tasks, especially those that have flavor or buildType name in their name are created and added to the gradle taskGraph quite late in the configuration step by the android plugin. What that means, as you have discovered is that you may not be able to refer to them by name early in the config step since they do not exist yet.
The way around this as the other answers point out is to wait until the tasks in question are added to the taskgraph. You can use your line uninstallDebug.dependsOn "MyTask" in either gradle.taskgraph.whenRead{} or project.afterEvaluate {}

Gradle Skip Test

I am looking for a way to skip tests from one of the projects in a multi-build project. I don't want to use gradle build -x test because then it will skip test for all sub - projects.
Root
Sub P1
build.gradle
Sub P2
build.gradle
Sub P3
build.gradle
build.gradle
settings.gradle
I want to skip tests only for "Sub P3"
Can i configure my project(Sub P3) build file to skip tests?
Due to official user guide, there are 3 ways to skip some task in gradle.
The first 2, are: using predicate and exception throwing. Predicates are resolved during the configuration phase and may not pass to your requirements. StopExecutionExeptionthrowing could be added to the doFirst of every test and be throwed according to some condition. Bit that seems to be not very clear, because you have to modify both root script to set the condition and subroject sripts test tasks.
And the 3rd one is - disabling the tasks. Every task, has a enabled property (default is true), which is preventing task execution, if it was set to false. Only thing you have to do is to set this property for test task in your subproject. This can be done in sub projects buil script root, as:
test.enabled = false
This will work, if you didn't specify custom test tasks, if you did, you can disable all test by task type, as:
project(':subProject').tasks.withType(Test){
enabled = false
}
Previews 2 configurations must be included to the build script of the subproject, but since you have a root project, you can configure subprojecst from it's build script, via project() providing subproject's name:
project(':subProject').tasks.withType(Test){
enabled = false
}
For android there is no test task available in gradle
To skip unit tests in android you have to do this
android {
.
.
.
testOptions {
unitTests.all {
enabled false
}
}
}

Categories

Resources