With Android Studio 3.0 / android_gradle_version = '3.0.1' / gradle-4.5
Let's say I have two android modules
module-base
module-a
When I want to access sources from module-base in module-a , I just need to write this in my
module-a.gradle
dependencies {
implementation project(path: ':module-base')
}
But, what if I want to access test sources from module-base in test of module-a?
Here does not work approach like above
dependencies {
testImplementation project(path: ':module-base')
}
I found lot of advices (few years old) which says something like
compileTestJava.dependsOn tasks.getByPath(':module-base:testClasses')
testCompile files(project(':module-base').sourceSets.test.output.classesDir)
or
testCompile project(':module-base).sourceSets.test.classes
But no one from mentioned works. There is always something wrong from the compiler point of view :-/
Can you someone help me how to create Android test code dependency between two modules?
In case anyone else ends up here, one way to accomplish this is to define the target module as a source set. Let's assume test-mdoule is the module we want to import stuff from, we can do it this way:
android {
sourceSets {
// non-instrumental test example
test {
java.srcDir project(":test-module").file("src/test/java")
}
// instrumental test example
androidTest {
java.srcDir project(":test-module").file("src/androidTest/java")
}
}
}
Reference: https://jonnycaley.medium.com/sharing-test-code-in-a-multi-module-android-project-7ce4de788016
Actually I find just workaround for this. Don't use test sources from module-base but use sources from test related module module-testutils which is defined like this
dependencies{
testImplementation project(':module-testutils')
}
Thus you can share common test code which will be excluded for non-testable apk.
Related
I defined an integration test suite for our gradle build like this:
testing {
suites {
integrationTest(JvmTestSuite) {
dependencies {
implementation project
}
}
}
}
And to get my integration tests to see the test dependencies, I added these configurations:
configurations {
// This configuration allows us to define spring-devtools as available only in dev mode
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
integrationTestImplementation.extendsFrom testImplementation
integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
}
That works except for one problem: My integration tests cannot see utility classes defined in the unit tests (src/test). I've searched for a solution but I cannot find out how to get the integration tests to have the unit tests on the classpath.
Can someone people tell me how to configure Gradle for this?
Thanks
The java-test-fixtures plugin was designed to share common code between test suites, even across project boundaries. I'd suggest to use it for your test model and utility classes. See the linked documentation on how to configure it.
I started playing around with Spock testing framework and my build.gradle dependencies section looks like this:
dependencies {
testCompile "org.spockframework:spock-core:1.3-groovy-2.5"
}
I have a (useless) Spock test that requires creation of a stub:
def 'A test that will fail'() {
given: ''
def random = Stub(Random)
}
When launched, the test fails with the given error:
CannotCreateMockException: Cannot create mock for class java.util.Random. Mocking of non-interface types requires a code generation library. Please put an up-to-date version of byte-buddy or cglib-nodep on the class path.
This error is mentioned in Spock documentation and it's caused by cglib or byte-buddy not being available at runtime.
Considering that spock-core's pom lists both byte-buddy and cglib as compile dependencies, why are they not retained at runtime? In other words, why do we need to explicitly add the following runtime dependency to our build.gradle file?
testRuntime "net.bytebuddy:byte-buddy:1.9.3"
Because both (byte-buddy and cglib-nodep) are marked as <optional>true</optional>, where from Gradle point of view they are as compileOnly dependencies - see: https://blog.gradle.org/introducing-compile-only-dependencies
Compile-only dependencies are distinctly different than regular
compile dependencies. They are not included on the runtime classpath
and they are non-transitive, meaning they are not included in
dependent projects.
They are optional dependencies, so you need to include them if you want that functionality
https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
I have an Android project in process of migration from Java to Kotlin. In this project, I have a pure Kotlin module where I'm implementing a API Client with the following build.gradle:
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
implementation "com.squareup.retrofit2:retrofit:${retrofit_version}"
implementation "com.squareup.retrofit2:converter-gson:${retrofit_version}"
implementation "com.google.code.gson:gson:${gson_version}"
implementation "com.squareup.okhttp3:logging-interceptor:${okhttp_version}"
implementation "io.reactivex.rxjava2:rxjava:${rx_java_version}"
implementation "io.reactivex.rxjava2:rxkotlin:${rx_kotlin_version}"
implementation "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:${retrofit2_rxjava2_adapter_version}"
compileOnly "javax.annotation:jsr250-api:${jsr250_version}"
implementation "com.google.dagger:dagger:${dagger_version}"
kapt "com.google.dagger:dagger-compiler:${dagger_version}"
testImplementation "junit:junit:${junit_version}"
testImplementation "org.mockito:mockito-core:${mockito_version}"
testImplementation "org.hamcrest:hamcrest-junit:${hamcrest_version}"
testImplementation "com.squareup.okhttp3:mockwebserver:${mockwebserver_version}"
// Dependence injection
kaptTest "com.google.dagger:dagger-compiler:${dagger_version}"
}
There is an Annotation Processor dependency for unit tests:
kaptTest "com.google.dagger:dagger-compiler:${dagger_version}"
I can see the generated sources on build/generated/source/kapt/test directory, but they are not visible to the test sources, that is, is not possible to import the generated DaggerUnitTestComponent to inject dependencies, for exemple. And I'm having trouble to get it done.
This kind of thing I had already done with success on a Android project, with the help of this StackOverflow answer and the following snippet added to build.gradle, but for a pure Kotlin/Java project, it is not applicable.
android.applicationVariants.all {
def aptOutputDir = new File(buildDir, "generated/source/apt/${it.unitTestVariant.dirName}")
it.unitTestVariant.addJavaSourceFoldersToModel(aptOutputDir)
}
Is valid to say that I'm using Android Studio 3.0.1 and Kotlin 1.2.10. The sources of Kotlin library module lies on src/main/java and src/test/java.
You might want to take a look at an example of a Kotlin project that uses dagger: (here)
From what I see, the test sources that use the generated classes should compile just fine during a Gradle build, but the IDE might not pick them up correctly.
Try updating Kotlin to a newer version in the project (1.2.10 should handle this). If that does not help, try using the idea plugin as in the example above, configured for the test generated sources as follows:
apply plugin: 'idea'
idea {
module {
testSourceDirs += file('build/generated/source/kapt/test')
generatedSourceDirs += file('build/generated/source/kapt/test')
}
}
I am trying to test my code using Kotlin. When trying to import the kotlin.test package, nothing appears.
Do I have to add the dependency somewhere first? And how can I run my unit test afterwards?
The kotlin.test package is packaged in kotlin-test module, so you need add the dependencies in your build.gradle as below:
dependencies{
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
Beside that, you need to add an unit test framework in the build.gradle like as junit-4, for example:
dependencies{
testCompile "junit:junit:4.12"
}
How to write a JUnit Test? you can see it in junit.org as further.
I have set up a project on top of Qt (so source is written in C++) and I wanted to try Gradle for automatic builds on that. It took me some time to get into the details of configuring a multi project build (there is an executable and two libs) and now I am trying to tell the cpp-exe and the cpp-lib plugin how my source tree is structured.
I have set up a task that should print all of the source sets (there should be at least the default ones right?) and it looks like this:
task projectinfo {
description = "Informations about the current project"
group = INFORMATIONS_GROUP
doFirst {
task -> print ("""${task.project.sourceSets.all}""")
}
If I run this task Gradle tells me that there is no property "sourceSets" for the project. The documentation of the plugin tells me that it is possible to customize the source locations, but not how.
So my question would be: How can I tell the Gradle cpp plugin which source files to use. If there is any documentation about the cpp plugin apart from its API documentation and the Gradle user guide that would be helping too.
Have a look at Adam Murdoch's usage of Gradle's 'cpp plugin'. I believe he's one of the main Gradle submitters, so he should know how to use this better than anyone:
Exert from native-platform/build.gradle
cpp {
sourceSets {
main {
source.exclude 'curses.cpp'
}
curses {
source.srcDirs = ['src/main/cpp']
source.include 'curses.cpp'
source.include 'generic.cpp'
source.include 'generic_posix.cpp'
}
}
}
Then, within the 'libraries' node, refer to all/any combination of architecture and source sets:
sourceSets << cpp.sourceSets.main
sourceSets << cpp.sourceSets.curses
I've not had too long to look over it myself, but it looks like he defines a number of OS architecture based source code include combinations and stores these in the variants variable. He then processes them into platform JARs (I haven't actually ran the build yet, maybe I should).
Also, take a look at https://github.com/rklaren/GradleJNI, it uses the cpp plugin but looks to be a little Windows-oriented.
Update - I also found https://github.com/alkemist/gradle-cpp-demo, which has an example of the 'cpp-exe' plugin building an executable.