Do testCompile and androidTestCompile dependencies go into the built apk? - android

By default are testCompile and androidTestCompile dependencies along with any test cases written get packaged into the debug or release apk? If so, do we need to add some Proguard rules and or remove test cases before building release apk?

No, they are not. Or, more accurately, they are not included in any regular builds (e.g., debug, release). That is why the code is isolated in separate source sets and why the dependencies have the specific prefixes (test, androidTest).

Instrumentation-tests dependencies specified using androidTestCompile (now androidTestImplementation) generally end up in a different, designated .apk (e.g. app-debug-androidTest.apk) - which gets installed on the device separately right before the tests are run, and they're not part of your app.
Unit-test dependencies specified by testCompile (now testImplementation) only get compiled into a temporary location, and thus do not get bundled into anything.
So in either case - no, these dependencies will not be part of the .apk.

Related

Exclude subproject in Gradle

I have two library projects, A and B, both depending on a third library project C.
I am trying to use both A and B in my app project by having the following in my app/build.gradle:
implementation project(':libraryA')
implementation project(':libraryB')
This works fine when creating a release build, but fails for debug ones with the following error:
> Task :app:transformDexArchiveWithDexMergerForDebug FAILED
D8: Program type already present: com.libraryc.SomeClass
It looks like it is fine to bring library project C twice in release because the names get obfuscated separately and there are no conflicts (since I have minifyEnabled true for release builds). However, this doesn't fly in debug.
Since both libraryA and libraryB require a dependency to libraryC, I guess the solution is to keep those dependencies but exclude one of them from the app's app/build.gradle. It's not clear to me how to do this.
I have read on how to exclude modules and groups, but doing something like:
implementation project(':libraryA') {
exclude module: 'libraryC'
}
or
implementation project(':libraryA') {
exclude group: 'com.libraryc'
}
doesn't work, as Gradle doesn't seem to recognize the commands (my guess it's because 'libraryC' is a project, not a module?).
What ended up working was, in the build.gradle of libraryA, using compileOnly for libraryC if on debug mode and compile if in release mode.
My understanding of why this work is the following:
In release mode both versions of libraryC are pulled from the app. Since they are both proguarded (obfuscated) there are no conflicts, as before.
In debug mode only libraryB's version of libraryC is pulled from the app. Since there is no proguarding here, libraryA can use the exported version from libraryB no problem.
In my case I can determine the build type by checking an environment variable which gets manually set as part of the whole build process, so this is what ends up in libraryA's build.gradle:
if(System.getenv('DEBUG_BUILD') != "1") {
compile project(':libraryC')
} else {
compileOnly project(':libraryC')
}
Note that DEBUG_BUILD is an environment variable that I set myself when I launch a debug build, so do not expect this to work by simply copy-pasting into your project.

Dependencies by flavor or build type using androidTestUtil

Is it possible to have dependencies by flavor or build type using androidTestUtil?
I'm using test-butler and using this line to get the apk onto the device before tests run:
androidTestUtil 'com.linkedin.testbutler:test-butler-app:1.3.1#apk'
However I want to be able to run tests on a physical device without test-butler, without having to modify my gradle file when I'm testing.
The solution provided by this question dependencies by flavor in android studio build.gradle file, is it possible? doesn't really work with this androidTestUtil, I'm wondering if there is another way?
With the flavor releaseTest:
releaseTestandroidTestUtil 'com.linkedin.testbutler:test-butler-app:1.3.1#apk'

Confused about testCompile and androidTestCompile in Android Gradle

I'm new to testing world and even more to Android testing world. While doing research on Robolectric that aids with tests on android one thing confuses me the most. Sometimes on the web I see people using testCompile keyword in dependencies of the gradle build script when referencing Robolectric while others use androidTestCompile. Certainly both can't be valid?
Can somebody explain the difference between the both and which of these should be the one used when using Robolectric?
Simply testCompile is the configuration for unit tests (those located in src/test) and androidTestCompile is used for the test api (that located in src/androidTest). Since you are intending to write unit tests, you should use testCompile.
Update: The main distinction between the two is the test sourceset runs in a regular Java JVM, whereas the androidTest sourceset tests run on an Android device (or an emulator).
To answer your question - Use testCompile for robolectric
why, because robolectric runs on the JVM mocking all the android device behaviour.
testCompile and androidTestCompile are "by convention" android folders which gradle uses while running tasks provided by android plugin.
androidTestDebug picks tests from androidTest folder,
testDebug picks tests from test folder,
Again these are only by convention folders you can give source sets for these configurations
Note: espresso is such an awesome library try to move away from robolectric :)
//unit testing
testCompile 'junit:junit:4.12'
The above code is a dependency of JUnit 4 in build.gradle file in android studio.
You see that it has testCompile, beacuse JUnit runs on JVM and does not require a device or emulator to run. That also means that JUnit tests will not require the application context to run and if they require we would need to "MOCK" them.
//Insturmented Unit Testing
androidTestCompile('com.android.support.test:runner:0.5', {
exclude group: 'com.android.support', module: 'support-annotations'
})
Now we see androidTestCompile here, because this time we intend to use the device or emulator for tests, that is Instrumentation testing. For beter clarification I would suggest to read from developer.android.com
To add Dependency for JVM testing or Unit testing (testing those rely only on java environment, we don’t need any android environment).
We Use testCompile directive. Example:
dependencies {
testCompile gradleTestKit()
}
To add Dependency for Instrumentation test (Those testing mainly rely on Android environment), we use the androidTestCompile directive.

Testing using Mockito

Apologies for what may seem an idiotic post.
How do you run Mockito on the newest version of Android Studio SDK?
and can you run multiple tests using Mockito using the Android Studio platform?
I've used Mockito on Eclipse and ran as much as 6 tests in the same window. But I'm trying to figure out how to do this on the Android Studio platform and I cannot find any website or tutorial with an answer.
Android Studio 1.1 now has built-in support for unit testing. From Unit testing support - Android Tools Project Site:
Unit tests run on a local JVM on your development machine. Our gradle plugin will compile source code found in src/test/java and execute it using the usual Gradle testing mechanisms. At runtime, tests will be executed against a modified version of android.jar where all final modifiers have been stripped off. This lets you use popular mocking libraries, like Mockito.
You will have to specify your testing dependencies in the build.gradle file of your android module. For example:
dependencies {
testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:1.9.5"
}
The page also contains a step-by-step guide for setting up Android Studio for unit testing, including creating a separate directory for unit tests:
Create a directory for your testing source code, i.e. src/test/java. You can do this from the command line or using the Project view in the Project tool window. The new directory should be highlighted in green at this point. Note: names of the test source directories are determined by the gradle plugin based on a convention.
I'm currently working on a project using junit 4.12 and Mockito 2.0.5 beta for unit testing in Android Studio 1.1, and haven't had any issues:
dependencies {
// ...
testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:2.0.5-beta"
}
As far as running multiple tests at the same time, do you mean test cases? Test classes? Test suites? Please clarify, and I'll update my answer, if needed.
Open your app/build.gradle file in your application and add mockito to the dependencies, if dependencies isn't there you can go ahead and create it.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile 'org.mockito:mockito-core:1.10.8'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'
}
Then in your unit tests, just create a mock object as you normally would:
http://site.mockito.org/#how
Unit tests should be under the app/src/androidTest/ folder.
I can verify that the accepted answer is correct however just to further to the answer, there will be an androidTest folder alongside your main folder. Normally you would use the androidTest folder for instrumentation tests. Just make sure that under the build variants panel, the Test Artifact: is selected to be "Unit Tests" otherwise the testCompile in build.gradle will not work. It took me a while to figure this part of out.
Hope it helps.

Dependency conflict error in my Android app which has Android Tests

I'm using AndroidStudio and Gradle to build my Android app with tests in the 'androidTest' source directory. I added a new dependency and am now getting the following issue when running Android Tests either in AndroidStudio or via './gradlew connectedCheck'. What's the preferred way to resolve this?
'Warning:Conflict with dependency 'org.somelibrary:library-core'. Resolved versions for app and test app differ.'
As of Android Gradle Plugin 1.1.1 the error displays like this:
"Warning:Conflict with dependency 'com.google.code.findbugs:jsr305'. Resolved versions for app (1.3.9) and test app (2.0.1) differ."
When you build and run Android Tests for your app the Android Gradle plugin builds two APKs (the app and the test APK). During the gradle run the dependencies for the app and test builds are compared. Dependencies that exist in both are removed from the test build when the version numbers are the same. When the same dependencies are in use, but differ by version number then you will need to manually resolve the dependency conflict and this error is presented.
To resolve the conflict you first need to figure out the two versions that are conflicting. If you aren't already using the Android Gradle Plugin v1.1.1+ then if you upgrade to that version the error message will give you the conflicting version numbers. Choose which one you need.
*When choosing between the conflict numbers it might be important to keep in mind that unless you've overridden the default gradle dependency resolution strategy (failOnVersionConflict) then conflicts internally within the app and test builds (separately) will be resolved by choosing the greater version.
Now you need to decide how to resolve the conflict. If you need to force the use of the lower version (1.2) of the library you will need to force the dependency to be resolved for both the app and test builds to a specific version of the library like this:
// Needed to resolve app vs test dependencies, specifically, transitive dependencies of
// libraryq and libraryz. Forcing the use of the smaller version after regression testing.
configurations.all {
resolutionStrategy.force 'org.somelibrary:library-core:1.2'
}
If you need to use the 2.1 version of the dependency then you can use the snippet above as well, but you will never start using a newer version of the library regardless of whether transitive dependency updates require it. Alternatively, you can also add a new normal dependency to either the app or the test builds (whichever was trying to use the 1.2 version of the dependency). This will force the app or test build to depend on the (previously mentioned) gradle dependency resolution strategy and therefore use the 2.1 version of the library for that build.
// Force the use of 2.1 because the app requires that version in libraryq transitively.
androidTestCompile 'org.somelibrary:library-core:2.1'
or
// Force the use of 2.1 because the Android Tests require that version in libraryz.
compile 'org.somelibrary:library-core:2.1'
In this solution the error could resurface, if say version 3.3, started to be used in only one of either the test or the app builds, but this is typically OK because you'll be notified of another incompatibility at build time and can take action.
Update: A few new solutions to this question now also list excluding a particular transitive dependency from a declared dependency. This is a valid solution, but puts more onus on the developers. In the same way that the forced dependency resolution suggestion above above hard codes a version into the build, the exclude-transitive-dependency solution specifically overrides the stated requirements of a library. Sometimes library developers have bugs or work around bugs in various other libraries so when you implement these solutions you take some risk in potentially having to chase down very obscure bugs.
Had similar problem.
First - I upgrade the gradle plugin to 1.1.1 (in the project's gradle):
classpath 'com.android.tools.build:gradle:1.1.1'
which helped me realize that the problem was the app referring to:
com.android.support:support-annotations:21.0.3
while the test app was referring to:
com.android.support:support-annotations:20.0.0
(due to specifying androidTestCompile 'com.squareup.assertj:assertj-android-appcompat-v7:1.0.0')
solved it by specifying:
androidTestCompile 'com.android.support:support-annotations:21.0.3'
Alternatively, one can exclude the conflicting dependency (e.g. support annotations library) pulled in by the test app dependency (e.g. assertj-android), by using the following:
testCompile('com.squareup.assertj:assertj-android:1.0.0') {
exclude group: 'com.android.support', module: 'support-annotations'
}
Gradle has Resolution Strategy Mechanism.
You can resolve this conflict by adding below lines to app level build.gradle file:
configurations.all {
resolutionStrategy {
force 'com.google.code.findbugs:jsr305:1.3.9', 'com.google.code.findbugs:jsr305:2.0.1'
}
}
If you look at the (generated) .iml file(s), you can see the conflicting version numbers quite easily. In my case:
<orderEntry type="library" exported="" scope="TEST" name="support-annotations-20.0.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
Going back to version 1.0.1 of the gradle plugin resolves the problem.

Categories

Resources