Multi module test code reuse - android

I have a multi module Android Studio project composed of 3 modules:
app (regular and unit-test configs) - contains main app code and tests
common (regular and unit-test configs) - contains common code and tests that are shared with another app
common-testing (regular config only) - contains common testing utility code used in the tests of the other 2 modules
Now common-testing (regular) depends on common (regular) for certain classes. This gets dicey in the common (unit-test) configuration, where a circular dependency develops. The dependencies for that case are mapped below:
common (unit-test) depends on common (regular)
common (unit-test) depends on common-testing (regular) depends on common (regular)
Unfortunately the last line is a circular dependency (common depends on common), and the project fails to evaluate.
Is there a way to instruct Gradle to break out of a circular dependency? Some sort of include guard like in C/C++?
If not, are there alternate ways of organizing the project to successfully share test code (like runners) between modules?

Related

Is it possible to independently develop modules in a multi-module IntelliJ/Gradle project?

I recently learned that I could add modules to an IntelliJ (or Android Studio) project. This provided me with a solution to the problem of showing multiple projects using the IntelliJ Code With Me plugin. I had hoped to use this single multi-module project to independently develop all the projects but I quickly saw that the initial project settings.gradle.kts file was modified, thus breaking independence, much to my chagrin.
The development model that I want to impose would have a single Android app that pretty much only uses Android classes. This app would depend on multiple sub-projects (provided in a Gradle dependencies block) each of which is a single, simple project developed using IntelliJ, persisted to GitLab and deployed to Maven Central. Thus all modules are independently developable and deployable.
From time to time, during a remote meetup or review session, I would like to use the Code With Me plugin to view the app project and all its sub-projects together.
My next attempt will be to create a shadow project which is only used by the Code With Me plugin that contains the app project and all the sub-projects as modules. I will need to git update each module. That is not too onerous but if there is a better way, I'm all ears.
You are right about creating a shadow project. The workaround is to create an "Empty Project" project type in the IDEA and add these projects as modules (File | New | Module/Module from Existing Source from the main menu) into this project.
Feel free to watch the related issue: https://youtrack.jetbrains.com/issue/IDEA-65293/

How to organize common gradle tasks and extract common code blocks

I have an android project consisting of 10+ library modules. Each of these modules contains a lot of gradle code common to all modules. For example, I'm using the Javadoc generation task from this answer in all of my build.gradle files.
How would I go about to extract that task creation logic to a function put in a separate gradle file which can be "included" by each module? The code is identical for all my modules, but obviously depends on variant and project. Is it possible to extract a function that takes a project as parameter and returns a task for that project?
I'm probably going around this backwards since I really suck at Gradle but any pointers leading to me avoiding having the same 60 lines of gradle code in 10 different files (lib1/build.gradle, lib2/build.gradle, ...) would be helpful!
In fact, taking it even further, basically my entire build.gradle is identical for all projects except the dependencies section - there's an android block with buildTypes, compileOptions etc, there are some plugins applied (apply plugin: 'com.android.library' etc), and there are some artifact parameters set up. In fact, only my dependencies differ at all. So I'm wondering if it would be possible to extract a common file completely, like this (pseudo code obviously):
<include common.gradle> // includes android block, common tasks, artifact setup etc.
dependencies {
api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.code.gson:gson:2.8.5'
...
}
You can extract your common settings into a gradle file (lets say common.gradle and then use it as
apply from: '../path/to/common.gradle'
Reference: https://docs.gradle.org/current/userguide/plugins.html#sec:script_plugins
The recommended way of extracting common build logic is to leverage buildSrc and create plugins that are then applied to your projects.
This has a number of benefits of applying a script, as documented.
In addition, I would recommend being explicit through plugin application. While you could develop a single plugin that configures all your projects, with some logic based on project name for example, it is usually better to have different plugins matching the different project types.
That way, when opening a build file you immediately see what kind of project it is.
And of course you can have common code in buildSrc for the common parts.
One more benefit is that moving from a buildSrc plugin to a published plugin is much easier ... just in case your configuration patterns start to appear in different projects.

How can I share a Module's androidTest "Robots" with another module?

I am a big fan of the Robot pattern for keeping UI tests clean. But how can I reuse Robot classes across multiple modules?
:lib-with-ui . // has Robot classes in `src/androidTest`
:app
I fully test my lib-with-ui with the Robot classes, however I want to reuse those same Robot classes in the :app module for some quick smoke testing.
For why the smoke testing is useful, it's because we want to test the integration of all our components as well as catch any possible proguarding issue that may occur (we have a special flavor of our sample app that utilizes proguarded AARs of our libraries).
We've tried a variety of approaches to get this to work, but it has all lead to weird resource issues.
Robot classes are defined in module 'lib-with-ui' and you want to use this in module 'app'?
Add lib-with-ui android library module as dependency to app module. Any code and resources in the Android library is now accessible to your app module, and the library AAR file is bundled into your APK at build time.
https://developer.android.com/studio/projects/android-library.html#AddDependency

Multi-module gradle project - Executing all Unit tests

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

Multiple Android Application Modules Under One Project

I have two 'android application modules' in one project and they create independent apks.
But I want to combine these two modules into one hence creating dependencies between the modules so that one apk can be generated and one 'android application module' can invoke activities from another 'android application modules'.
Most of the examples suggests me to convert one 'android application module' into a 'library module' but I don't want to do that.
Document here suggests that there can exist more than one 'android application module' in one project but never could I find an example that does that.
Please suggest some ideas.
So guys I figured the right way to handle this problem.
So I created a placeholder library module under the project that had 2 android application modules and modified the build.gradle(i.e. I introduced android SourceSet objects) of that library module to point to sources(src and res folders) of the other application module that I wanted to merge into other application module.
In this way both the application module may coexist under the same project and you never have to touch your application module(that you wanted to convert to a library module).
The only difference would be that the manifest file of this library module will not be having a 'LAUNCHER' intent filter for any of its activity since an application module can not have more than one LAUNCH activities.
So this way you can still have 2 independent apks and continue to develop the applications independently and if you want to include one in the other then use a placeholder library module to point sources of the app modules.
Each application module creates a separate APK. What you may want to do is to create a library module to contain code common to both APKs and then add a dependency between them.

Categories

Resources