I'm having issues sharing code across different modules for testing my app.
I have a couple of classes (TestCoroutineContextProvider and CoroutinesTestRule) which I have placed in my presentation fragment.
In order to share the code between unit tests and UI tests, I have in my presentation build.gradle the following:
sourceSets {
test {
java.srcDirs += "$projectDir/src/testShared"
}
androidTest {
java.srcDirs += "$projectDir/src/testShared"
}
}
This way I think I can have access to those two files in both my ViewModel and Fragment tests.
Nevertheless, although the files are imported correctly and there's no IDE error, when trying to run the tests I get the following:
e: /features/account/src/test/java/me/myapp/account/AccountViewModelTest.kt: (35, 30): Unresolved reference: CoroutinesTestRule
and the same thing for the other file.
Am I doing something wrong?
Thanks a lot in advance!
You need to do the following to share the code across unit tests and instrumented tests:
In your app level build.gradle file, add the following:
sourceSets {
// Share test utils between unit and instrumented tests
test.java.srcDirs += 'src/sharedTest/kotlin'
androidTest.java.srcDirs += 'src/sharedTest/kotlin'
}
where sharedTest is the directory / module name where the shared utilities will go in
Go to your module in which the build.gradle is located then navigate to src and create a directory named sharedTest and inside it create kotlin
Mark the kotlin directory as "Test Sources Root" by right clicking -> Mark As -> Test Sources Root so the IDE shows it as a test directory
Put your test utils in there
Do gradle sync
Enjoy!
Note: Even after this sometimes IDE shows errors / warnings when you try to use those shared utilities but if you run those tests, they will pass also when executing via gradle. Usually I have seen this problem to disappear after doing a gradle sync or re-launching Android Studio
Related
We have a multi-module Android project, in which some modules contain UI tests and some contain Unit tests. We wish to run all UI tests from all modules using a single Gradle command and do the same thing for Unit tests.
The only way that we found to do this was with the following config inside the main app module that implements all the other sub-modules (basically make the app module know about all the other androidTest and test folders in the project):
app/build.gradle:
sourceSets {
androidTest.java.srcDirs += ["${project(':feature-login').projectDir}/src/androidTest/java"]
test.java.srcDirs += ["${project(':feature-login').projectDir}/src/test/java"]
test.java.srcDirs += ["${project(':core').projectDir}/src/test/java"]
}
Then we run the following Gradle commands:
./gradlew app:connectedDemoDebugAndroidTest
./gradlew app:testDemoDebugUnitTest
Question: Is there a better/simpler way to achieve this? Or is there a way to add the androidTest and test folders from the above solution dynamically (using a relative path), instead of having to write the srcDirs line for each and every module (we have 40+ modules)?
just run in terminal:
./gradlew test
Please, see docs for more options
I do that every day (I usually have a source set for unit tests and one for slower integration tests): ./gradlew check. It runs all test tasks.
From the gradle docs:
check
Depends on: test
Aggregate task that performs verification tasks, such as running the tests. Some plugins add their own verification tasks to check. You should also attach any custom Test tasks to this lifecycle task if you want them to execute for a full build. This task is added by the Base Plugin.
I'm trying to share some code between my unit tests and my instrumentation tests. I've implemented something like the following in my build.gradle:
sourceSets {
String sharedTestDir = 'src/sharedTest/java'
test {
java.srcDir sharedTestDir
}
androidTest {
java.srcDir sharedTestDir
}
}
This seems to work just fine for normal code. However, code that is generated from an annotation seems to produce problems in Android Studio only. (The code runs fine, but it produces red squiggles in Android Studio) Basically, Android Studio can't seem to find the generated classes for code that lives in src/sharedTest - even though the actual build is fine.
In case it's helpful, the generated classes are coming from Dagger (as I share a component/module between the two types of tests). I've got a custom Application object that lives in sharedTest which is where I notice the Android Studio error:
createApplicationComponent() {
return DaggerMockApplicationComponent.create();
}
I've also added the apt command to both test and androidTest:
dependencies {
testApt 'com.google.dagger:dagger-compiler:2.7'
androidTestApt 'com.google.dagger:dagger-compiler:2.7'
}
I'm clearly missing something in my understanding around source sets here. Is there a cleaner way to share the code between test and androidTest? Is there a way to get Android Studio to see this generated code? Or, worst case, can I make Android Studio at least ignore this error more easily?
I have added a folder for unit testing in my android studio project. The default folder is andoidTest but I have added a new folder and name in test instead. (like robolectric sample tests)
When I add test Dependency in my build.gradle under module such as
testCompile("junit:junit:${junitVersion}")
testCompile ("org.robolectric:robolectric:${robolectricVersion}")
They do not get added to external libraries under project, but when I use the default configuration and use androidTestCompile, it can added external libraries.
Then I thought that maybe I should setRoot for tests in gradle, so I used following in android tag in build.gradle:
sourceSets {
androidTest.setRoot('src/test')
}
But still problem remained. I can run tests using gradlew, but imports in classes in test folder do not apply as well as no external library for test purpose is visible.
Anyone have any solution for this issue?
I was searching and didn't find answer that I thought already covered this. So decided to create new one for the future.
Answer
Android Studio is not picking up unit tests automatically right now. I know it is planned for 1.3 version.
So you have to change test artifact value from Android Instrumental Tests to Unit Tests in Build Variants tool window:
Almost fine your Gradle script but try do that:
sourceSets {
androidTest.setRoot('src/test')
androidTest {
java.srcDirs = ['src/test/java']
}
}
So ultimately I'm trying to separate my integration tests from the unit tests in an Android Studio project. I've found a few resources on the subject:
http://selimober.com/blog/2014/01/24/separate-unit-and-integration-tests-using-gradle/
https://blog.safaribooksonline.com/2013/08/22/gradle-test-organization/
Separating integration tests from unit tests in Android Studio
All these seem to indicate that the way to go is to create a new sourceSet for the integration tests, and then to create a new test task which builds and runs the tests in that source set. I can't get past the first step of creating a source set which is recognized by Android Studio.
Here's what I have within app/build.gradle, which builds without errors, but does not result in an integrationTest source root I can add classes to:
android{
...
sourceSets{
integrationTest {
java.srcDir('src/integrationTest/java')
}
}
}
My questions are:
Where precisely do I have to add the sourceSets block? In build.gradle? in app/build.gradle? In app/build.gradle inside the android block?
Once I've added my source set in he right place using the correct syntax, is this sufficient for Android Studio to detect and present it in the UI along side the main and test sources, or are there additional steps?
edit:
I've attempted to follow the instructions in marius' answer, but integrationTest isn't showing up in my build variants. Here's what I'm seeing:
This is enough:
android{
...
productFlavors{
integrationTest {
}
}
}
Regarding your 1st question: The productFlavors block should be in your app/build.gradle, inside android block.
Regarding your 2nd question: Once you add this to your build.gradle file, you also need to create your folders /src/integrationTest and /src/integrationTest/java . Once that is done, sync your gradle files and choose your new Build Variant from the Build Variant window, in order for the IDE to detect it as the active source folder.
i think tests in the instruementTest should relevant to android, so need i add an addtional source folder such as src/test/java?
it looking that the testfile in src/test/java didn't compiled.
how can i run a junit test independently?
how can i run the junit test only in a command line, no the instrumentTest about android?
or
put and junit test in the instruementTest folder and call
./gradlew connectedInstrumentTest
but,the unit test won't run at all.
I think this is not possible if you only have the Android plugin in your build.gradle. The only testing that is supported in the Android plugin is in the InstrumentTest folder. The normal test folder is only used by other plugins.
Next to that there is probably support needed in Android Studio itself. But not sure about that.
First, You should built appropriate folder structure in order to match default structure that Gradle is expecting. In Your gradle.build inside android{} section You should add:
sourceSets {
instrumentTest.setRoot('src/instrumentTest')
}
then You should create appropriate folder structure in your src/ folder. Now You should have main/java/your/package/name/YourActivity.java . In order for Gradle to find Your tests You should create structure in src/ folder to mirror Your main structure, like: instrumentTest/java/your/package/name/YourActivityTest.java
next, for Gradle to compile your dependencies You should add in Your gradle.build:
dependencies {
instrumentTestCompile 'com.jayway.android.robotium:robotium-solo:4.2'
instrumentTestCompile 'junit:junit:4.10'
}
Remember, that those are dependencies outside Your buildscript{} section. After You apply those changes You should be able to run Your JUnit tests as well as Robotium tests. Do not forget to hit the 'make' button couple of times for Gradle to catch up.
Right click on the test file in the Project view. Choose Run ...
Don't forget, the directories structures for tests and tested classes must fit. Yours seem dubiously. Here is how to do it easily.