Multi-module gradle project - Executing all Unit tests - android

Our current set-up looks like this: One root-project with nine sub-modules, which are mixed between pure Java libraries and Android libraries.
Each of the modules contains features, one of the modules is the main module which builds the Android app by merging all required modules.
Each of the modules contains a lot of unit tests, and I'd like to execute them all in one gradle step. Right now I'm using gradlew test for this, but since (for example) the main module has multiple product flavors it is executing the unit tests in this module multiple times (for each flavor).
Ideally, I'd like to only execute the main module unit tests once, for a certain flavor and signing configuration, but since the testFlavorDebug tasks are created while evaluating the project (as far as I know) I cannot define this before actually executing the evaluation.
I've tried to find the tasks in afterEvaluate blocks, I've tried to loop over all modules, different combinations and ways, but I can't seem to figure out how to properly set this up.
I'd be glad if someone has some pointers or experience with a set-up like this and could help me out. If you require additional information, let me know and I'll supply them, but as far as the project set-up it's pretty straight forward in regards to the multi-module setting.

You can override the test method in your main module's build.gradle to only run the one time

Related

Generate unit tests on Android

Colleagues,
I am having hard time to find a library/framework/etc... which could help me to generate unit tests in Android.
I know that in Java there are multiple solutions, which could generate unit tests based on the source code. Are you using anything like this for Android?
(My project if fully written in Java).
Use just JUNIT - this should help :
https://developer.android.com/training/testing/unit-testing/local-unit-tests
Use Unit Test Architect
I am in the same boat as you were/are. Although TDD should be the approach for writing tests, but there may be a lot of untested code already written many times in larger projects.
One day I got frustrated with writing test cases of existing, older codebase. Hence, I thought of auto generating all the unit test cases.
I have created an Open-source Gradle Plugin which can be used for the above task. It is already hosted on mavenCentral. I have used it to generate test cases for my projects. But it can be used in any gradle project, (android, java, kotlin, kotlin+java). It may be rough around the edges but it has done it's job well for me.
BuildScript Dependency:
classpath "io.github.orange-3:unit-test-architect:$PLUGIN_VERSION"

Running multi platform Kotlin test in IntelliJ produces No JDK specified error

I have several tests in common module for multi platform Kotlin project. When I execute those tests using gradle, e.g. ./gradlew :android:test, they all go through and the tests run.
I have now encountered a more complicated problem where I would like to debug an actual test in IntelliJ. Unfortunately, upon selecting the debug option in IntelliJ, I get an No JDK specified error.
I am using the following dependencies for testing:
testImplementation "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
with $kotlin_version being 1.2.41.
The common module settings looks like this:
SDKs section also correctly recognises JDKs:
I have tried changing the Module SDK from Kotlin SDK to java, however IntelliJ then wants me to require jUnit for test execution, which I would prefer not to, if possible.
Is there a way how to make the debugger run in IntelliJ for the Kotlin code?
Found the solution.
Just like it does not make sense to execute tests using Gradle in the common module alone, e.g. ./gradlew :common:test and the tests need to be executed for a specific platform ./gradlew :android:test, because the common module might contain expected declarations which are supposed to be implemented per platform using the actual keyword, it also does not make sense to debug in the common module directly.
Instead, for such purposes, the test to be debugged must be placed in a specific platform module, for my purpose I have chosen the Android module, and then it can be executed and debugged.
As I have mentioned, this approach is necessary because in the Android module the expected structures are actually replaced by the actual implementations.

How to run unit test on a android module?

I have a android project that has multiple library modules and I am trying to test a specific package that contains all modules.
I tried this command:
./gradlew -Dtest.single=com.moduleone* testProductionDebug
And it does not work: it doesn't execute the tests inside this module, but instead executes all the unit tests in the main project package class.
How do I test just the one module?
You can use test suits: https://developer.android.com/reference/junit/framework/TestSuite.html . Definition of a suit contains classes of tests you need
Assuming you're trying to execute a gradle task against a single module rather than the entire project, you can supply the name of the module in front of the task separated by a colon (module_name:task)
Per your question, this would look something like
./gradlew -Dtest.single=com.moduleone* your_library_module:testProductionDebug
This is a simple example, assuming you have a simple project setup. You can also find further reading on this in the gradle docs for executing a multi-project build

How to know which project is running in gradle

I have multiple projects and one trunk...
Some times I need to run via cmd:
gradlew Proj1:assembleRelease
And other times:
gradlew Proj2:assembleRelease
How can I in gradle file know what is building Proj1 or Proj2?
You can access this information via the gradle property on any instance of Project. From the docs:
getGradle()
Returns the Gradle invocation which this project belongs to.
The instance of Gradle provides the startParameter property, which contains the information you want. For example, in the root scope:
print project.gradle.startParameter
For my particular invocation, I could print the name of the first task request via
print project.gradle.startParameter.taskRequests[0].args[0]
However, the above is probably quite fragile and will surely fail in a number of important cases.
There are also many other things you may find useful in the Gradle instance, if the above doesn't do exactly what you want, such as the task execution graph and root project for this build. Note that all the above information is available by following links from the documentation for the Project class, which I linked above. I strongly recommend that you peruse this documentation.
On the other hand, why do you want to do this? Usually you would just add configuration to the individual projects themselves and let the task runner take care of running your specific implementations, rather than saying if task1 is running then x else y

Trying to understand android testing

I'm a long time Java developer with many years of Java EE, Ant, Maven, unit testing, mocks, etc. I'm currently using gradle to build android apps and am looking at unit testing them. And it's got me tearing my hair out!
My reading indicates that to test an app, I have to create another app inside it in a test directory. But I'm not sure how this embedded app can see the main apps classes. I presume that google came up with this because of something to do with the manifests which are different. I'm not sure why.
Without doing this embedded app system, I've been able to get unit tests to run by including the test classes with the main classes in the APK, adding the instrumentation declarations to the manifest, deploying it and running the test runners. But I don't want to be compiling test classes with app classes and including all the dependencies so that's not really an option and I'm not really sure of the effects of the changes to the manifest as I cannot find any documentation about the effects.
None of this is understood by gradle which follows the maven system of building. Also note that the android way seems to be that the embedded sub-project (test) is dependant on the main parent project, something that is totally contray to gradle and maven.
Another option seems to be separate the test project so that it's completely outside the app project. But really, I'd like to use a similar convention to maven and simply have tests in a separate directory, along with the manifest in test resources.
Has anyone managed to get testing on the emulators running unit tests following a more maven like directory structure?
You can try Robotium. It provides lots of features for a better testcase. You can have a look at it here.
Do you have to run the unit tests in the emulator? Isn't that too slow? I've been using robolectric ( http://pivotal.github.com/robolectric/ ) which creates shadow objects that work similar to mocks. I use progaurd ( http://proguard.sourceforge.net/ ) to strip out the tests for the release build.

Categories

Resources