After having read the android guide on testing with the android gradle plugin, I wanted to set up JUnit tests for my POJO's that don't run with the instrumented tests. The idea was that tests for code that doesn't depend on Android should be very fast (and facilitate TDD).
Is there a standard way to set up a source set and task in build.gradle to accomplish this? That is the main question, the secondary question is what's wrong with my attempt below...
I'm using Android Studio 0.4.2 and Gradle 1.9, experimenting with a simple JUnit test class in a new "test" folder. Here is what I have so far, but when I run "gradle testPojo" I get this result:
:android:assemble UP-TO-DATE
:android:compileUnitTestJava UP-TO-DATE
:android:processUnitTestResources UP-TO-DATE
:android:unitTestClasses UP-TO-DATE
:android:testPojo FAILED
* What went wrong:
Execution failed for task ':android:testPojo'.
> failed to read class file
/path/to/project/android-app/build/classes/unitTest/TestClass.class
I verified that the class is in fact there, so I'm confused as to why the task is not able to read the file.
Here is the build.gradle file:
...
sourceSets {
unitTest {
java.srcDir file('src/test/java')
resources.srcDir file('src/test/resources')
}
}
dependencies {
...
unitTestCompile 'junit:junit:4.11'
}
configurations {
unitTestCompile.extendsFrom instrumentTestCompile
unitTestRuntime.extendsFrom instrumentTestRuntime
}
task testPojo(type: Test, dependsOn: assemble){
description = "Run pojo unit tests (located in src/test/java...)."
testClassesDir = sourceSets.unitTest.output.classesDir
android.sourceSets.main.java.srcDirs.each { dir ->
def buildDir = dir.getAbsolutePath().split('/')
buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/')
sourceSets.unitTest.compileClasspath += files(buildDir)
sourceSets.unitTest.runtimeClasspath += files(buildDir)
}
classpath = sourceSets.unitTest.runtimeClasspath
}
check.dependsOn testPojo
I'd suggest you to use robolectric, declare it like this:
classpath 'org.robolectric:robolectric-gradle-plugin:0.11.+'
And then apply the plugin:
apply plugin: 'robolectric'
Related
In my Android application, I want exclude some test cases in a package so that I used test task in build.gradle file. for example:
apply plugin: 'com.android.library'
test{
exclude '**/calltest/Summary.class'
}
If sync the project I got following exception:
* What went wrong:
A problem occurred evaluating project ':SdkModule'.
> Could not find method test() for arguments [build_4g3vf7b615x3x1p7i9ty0pt1l$_run_closure1#73d026ca] on project ':SdkModule' of type org.gradle.api.Project.
If I add apply plugin : 'java'
CONFIGURE FAILED in 1s
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
Please help me on this.
Got similar problem when try to generate XML test report for my Jenkins build.
Test related settings should be in testOptions. My file:
android {
testOptions {
unitTests.includeAndroidResources = true
unitTests.all {
reports {
junitXml.enabled = true
html.enabled = false
}
}
}
Instead of
test {
exclude '**/calltest/Summary.class'
}
try in Groovy
tasks.withType(Test) {
exclude '**/calltest/Summary.class'
}
or in Kotlin DSL (build.gradle.kts)
tasks.withType<Test> {
exclude("**/calltest/Summary.class")
}
i want to use checkstyle plugin in my gradle project, the gradle documentation says that it will add a few tasks:
https://docs.gradle.org/current/userguide/checkstyle_plugin.html
checkstyleMain, checkstyleTest, checkstyleSourceSet
I added this into my app build.gradle file:
apply plugin: 'checkstyle'
I want to run gradle task from cmd to perform code style check, but there are no one checkstyle task. I checked the whole list by typing:
./gradlew tasks
I also tried to add checkstyle jar as library dependency to app module.
Can anyone tell me what i am doing wrong and how can i get my checkstyle tasks?
Well, the checkstyle plugin adds its tasks in the Other tasks virtual task group. Those are really the tasks which have not been assigned to a task group. So, they are shown only when you run ./gradlew tasks --all (note the --all).
Complete working build.gradle:
apply plugin: 'java';
apply plugin: 'checkstyle';
Then run ./gradlew tasks --all, output:
<...snip...>
Other tasks
-----------
checkstyleMain - Run Checkstyle analysis for main classes
checkstyleTest - Run Checkstyle analysis for test classes
<...snip...>
If you want the Checkstyle tasks to appear without --all, then assign them to a task group, for example:
tasks.withType(Checkstyle).each {
it.group = 'verification'
}
Looking at other Android projects, built with Gradle, that run checkstyle (thanks Square) I found that I needed to do some setup for the task to appear. Without the task declaration I would still see my initial error.
build.gradle:
...
apply plugin: 'checkstyle'
...
checkstyle {
configFile rootProject.file('checkstyle.xml')
ignoreFailures false
showViolations true
toolVersion = "7.8.1"
}
task Checkstyle(type: Checkstyle) {
configFile rootProject.file('checkstyle.xml')
source 'src/main/java'
ignoreFailures false
showViolations true
include '**/*.java'
classpath = files()
}
// adds checkstyle task to existing check task
afterEvaluate {
if (project.tasks.getByName("check")) {
check.dependsOn('checkstyle')
}
}
You also need a checkstyle configuration file, either by placing one at the default location as documented or by configuring it explicitly.
For example:
checkstyle {
config = resources.text.fromFile('config/checkstyle.xml')
}
I updated the following:
//gradle
classpath 'com.android.tools.build:gradle:3.0.0-beta6'
// library dependencies
implementation "com.android.support:appcompat-v7:26.1.0"
implementation "com.google.code.gson:gson:2.7"
implementation "com.google.android.gms:play-services-location:11.2.2"
I am now getting the following exception kinds of exceptions for the gradle task androidJavadocs.
error: package com.google.android.gms.security does not exist
error: package com.google.gson does not exist
error: cannot find symbol class NonNull
Here is the gradle task that used to allow me to package up the javadocs but this no longer suffices:
libraryVariants.all { variant ->
if (variant.name == 'release') {
task docs(type: Javadoc) {
println 'docs task'
source = variant.javaCompiler.source
classpath += files(((Object) android.bootClasspath.join(File.pathSeparator)))
classpath += files(variant.javaCompiler.classpath.files)
}
}
}
I have tried lots of different combinations of gradle tasks and workarounds that I've found searching around but nothing works and I continue to get these errors. I have tried cleaning the project and invalidating the cache. Any ideas?
Adding the following to my upload-archives.gradle file fixed the problem:
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
// this is new
android.libraryVariants.all { variant ->
if (variant.name == 'release') {
owner.classpath += variant.javaCompiler.classpath
}
}
// end of new
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
I have been using this tutorial to educate myself on how to build APK outside Eclipse by just using command line (and Ant) - http://www.androidengineer.com/2010/06/using-ant-to-automate-building-android.html
Now that build system will be shifting toward Gradle I would like to have similar advanced tutorial for reference. Most of the tutorials out there (like this one)deal just with basic stuff but I would like to know how to perform some "advanced" things like automatically replacing values in code during build (so that I can have multiple variants of APK).
Standard examples provided by Google are here
http://tools.android.com/tech-docs/new-build-system/gradle-samples-0.4.2.zip?attredirects=0&d=1
For automatically changing values in code use BuildConfig class. Examples are in the link above.
Variants are explained here http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
UPDATE
as this example gets bit stale here is pasetbin to newer version http://pastebin.com/FmcCZwA5
main difference is Robolectric support provided by plugin, and support library fetched from SDK internal repo
Older version
Less basic example with Robolectric and AndroidAnnotations
Use nexus
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
use AndroidAnnotation processor, Robolectric local tests and Jackson
configurations {
compile
testLocalCompile.extendsFrom(compile)
androidannotations.extendsFrom(compile)
}
dependencies {
compile files('libs/android-support-v4.jar')
compile 'org.androidannotations:androidannotations-api:3.0-SNAPSHOT'
compile 'com.github.japgolly.android:svg-android:2.0.3'
compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.12'
testLocalCompile 'junit:junit:4.8.2'
testLocalCompile 'org.robolectric:robolectric:2.2-SNAPSHOT'
testLocalCompile 'com.google.android:android:4.0.1.2'
testLocalCompile 'com.google.android:support-v4:r6'
testLocalCompile 'org.roboguice:roboguice:2.0'
androidannotations 'org.androidannotations:androidannotations:3.0-SNAPSHOT'
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
Configure standard instrumentation tests
defaultConfig {
minSdkVersion 7
targetSdkVersion 16
testPackageName "com.mypackage.myapp.test"
testInstrumentationRunner "com.maypackage.myapp.test.Runner"
}
}
Invoke AndroidAnnotations processor on all variants
afterEvaluate { project ->
android.applicationVariants.each { variant ->
variant.javaCompile.options.compilerArgs += [
'-classpath', configurations.compile.asPath,
'-processorpath', configurations.androidannotations.asPath,
'-processor', 'org.androidannotations.AndroidAnnotationProcessor',
'-AandroidManifestFile=' + variant.processResources.manifestFile
]
}
}
Define sourcesets for Robolectric local tests
sourceSets {
testLocal {
java.srcDir file('src/test/java')
resources.srcDir file('src/test/resources')
}
}
Local Robolectric tests task
task localTest(type: Test, dependsOn: assemble) {
testClassesDir = sourceSets.testLocal.output.classesDir
android.sourceSets.main.java.srcDirs.each { dir ->
def buildDir = dir.getAbsolutePath().split('/')
buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/')
sourceSets.testLocal.compileClasspath += files(buildDir)
sourceSets.testLocal.runtimeClasspath += files(buildDir)
}
classpath = sourceSets.testLocal.runtimeClasspath
}
Run Robolectric in debug mode
localTest.doFirst {
jvmArgs '-Xdebug',
'-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005'
}
I'm evaluating the ability of the new gradle-based build system to reproduce our current ant-based build process and, as a gradle beginner, I failed to get checkstyle running with the android gradle plugin.
Environment:
gradle 1.6 running fine on a standard java project (checkstyle check target included)
up-to-date android SDK (22.0.1 with platform tools and build tools 17)
no eclipse, no android studio, only my lovely terminal
Symptom:
The target project is https://github.com/nibua-r/LigoTextDemo and I succeeded to build it using gradle but if I naively add apply plugin: checkstyle to my build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.2'
}
}
apply plugin: 'android'
apply plugin: 'checkstyle'
android {
buildToolsVersion '17'
compileSdkVersion 15
testBuildType 'debug'
defaultConfig {
versionCode = 1
versionName = '1.0'
minSdkVersion 12
targetSdkVersion 15
}
buildTypes {
debug {
packageNameSuffix = '.debug'
}
}
}
then gradle check doesn't even complain on not finding the checkstyle.xml file (at the default config/checkstyle location) and returns:
:check UP-TO-DATE
BUILD SUCCESSFUL
What's needed:
First, I just need a running checkstyle target. Then, I need to automate checkstyle running as a dependency of the compilation (but lets get the chekstyle target up and running first).
Assumption:
This may be related to the fact that (from the [user guide][1]):
The Android plugin […] uses its own sourceSets
but I'm not enough gradle-efficient to understand what I'm missing there. Please, gradle Master, enlighten me with your valuable knowledge!
I got pmd, findbugs, and checkstyle working with Gradle 1.12 android plugin 0.12.+ using the following script:
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
check.dependsOn 'checkstyle', 'findbugs', 'pmd'
task checkstyle(type: Checkstyle) {
configFile file("${project.rootDir}/config/quality/checkstyle/checkstyle.xml")
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
}
task findbugs(type: FindBugs) {
ignoreFailures = true
effort = "max"
reportLevel = "high"
excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml")
classes = files("$project.buildDir/intermediates/classes/")
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml {
destination "$project.buildDir/reports/findbugs/findbugs.xml"
xml.withMessages true
}
}
classpath = files()
}
task pmd(type: Pmd) {
ruleSetFiles = files("${project.rootDir}/config/quality/pmd/pmd-ruleset.xml")
ignoreFailures = true
ruleSets = ["basic", "braces", "strings"]
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = true
html.enabled = false
}
}
Running gradle build in command line will run all code quality plugins and generate xml reports in app/build/reports/ which are then ready to be viewed or parsed by CI tools.
Someone has a great answer to solve integrating PMD, findbugs and checkstyle with Gradle for Android.
Unfortunately, the only solution for now is based on ant :
http://sethrylan.org/2013/07/14/gradle-android-findbugs.html
I wish gradle will one day allow to do as much as maven for Android.
--- Update as of October 2013
With Gradle 1.8 and Android plugin for Gradle 0.6.+, you don't need this anymore. Android sourcesets and configurations are now compatible with the java plugin and all quality plugin work out of the box.
This includes pmd, findbugs, checkstyle and classycle.
--- Update
A configuration, largely inspired from the project mentioned above, is proposed in this open source project as well, plus other tools.
To get this to work with my Android project, I had to declare the task explicitly.
Here's what worked for me:
apply plugin: 'checkstyle'
task checkstyle(type: Checkstyle) {
source 'src'
include '**/*.java'
exclude '**/gen/**'
// empty classpath
classpath = files()
}
Be mindful that the Android plugin may choose to create a task of the same name in the future or work in conjunction with the checkstyle plugin in different ways.
You can try Android Check plugin (https://github.com/noveogroup/android-check):
Checkstyle
PMD
Configuration:
buildscript {
repositories { jcenter() }
dependencies {
...
classpath 'com.noveogroup.android:check:+'
...
}
}
apply plugin: 'com.noveogroup.android.check'
You can use hardcore configuration:
check {
abortOnError true
checkstyle { config hard() }
pmd { config hard() }
}
I found by digging on the web that the Android plugin depends on java-base and not java (i.e. the sourceSets management is specific) and the checkstyle plugin rely on java. As a consequence, some gradle upstream modification are needed to get the thing done. The gradle team is working on that, as seen on twitter:
#anzix Android source sets will be soon understood by the generic code quality plugins. Work on that has already started.— Gradle Build System (#Gradleware) May 26, 2013
Take a look at the Soter Gradle plugin to semlessly add support for Findbugs, Checkstyle and PMD to Android projects.