Search code examples
javaandroidunit-testinggradleandroid-instrumentation

How to override android tests path with Gradle?


For historical reason instrumentation tests are not stored in androidTests directory as required and i can't change directories structure (actually whole app is tests for the library used). I was able to build and install apk with gradle, but no tests were found:

:app-tests:connectedDebugAndroidTest
Tests on test_avd(AVD) - 4.1.2 failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException'

com.android.builder.testing.ConnectedDevice > No tests found.[test_avd(AVD) - 4.1.2] FAILED 
No tests found. This usually means that your test classes are not in the form that your test runner expects (e.g. don't inherit from TestCase or lack @Test annotations).
:app-tests:connectedDebugAndroidTest FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app-tests:connectedDebugAndroidTest'.
> There were failing tests. See the report at: file:///Users/asmirnov/Documents/dev/src/project/app-tests/build/reports/androidTests/connected/index.html

Actually the tests are in src folder, written correctly and can be built/runned using Ant:

public abstract class BaseTest extends AndroidTestCase
{
...

public class AppInfoTest extends BaseTest
{
    @Test
    public void testAllProperties()
    {
        ...

...

How can i make Gradle process src folder as android (instrumentation) tests?

Here is my current build.gradle file (it uses the experimental Android Gradle plugin version 0.7.2 because we have an NDK library):

apply plugin: 'com.android.model.application'

allprojects {
    repositories {
        mavenLocal()
        mavenCentral()
    }
}

repositories {
    mavenLocal()
    mavenCentral()
}

model {
    android {
        compileSdkVersion 16
        buildToolsVersion "22.0.1"

        defaultConfig {
            applicationId "app.tests"
            minSdkVersion.apiLevel 9
            targetSdkVersion.apiLevel 16
            versionCode 359
            versionName "1.3"

            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }

        sources {
            main {
                // overriding paths from default ones to actual ones
                // what about 'androidTests' ?
                manifest { source {
                    srcDir '.'
                    include 'AndroidManifest.xml'
                } }
                java { source { srcDirs = ['src'] } }
                res { source { srcDirs = ['res'] } }
                jni {
                    dependencies {
                        project ":library" // native library dependency
                    }
                }
            }
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile project(':library')
}

UPDATE 1 (for sschuberth):

Config:

apply plugin: 'com.android.model.application'

allprojects {
    repositories {
        mavenLocal()
        mavenCentral()
    }
}

repositories {
    mavenLocal()
    mavenCentral()
}

model {
    android {
        compileSdkVersion 16
        buildToolsVersion "22.0.1"

        defaultConfig {
            applicationId "app.tests"
            minSdkVersion.apiLevel 9
            targetSdkVersion.apiLevel 16
            versionCode 359
            versionName "1.3"

            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }

        sourceSets {
            androidTest {
                manifest.srcFile 'AndroidManifest.xml' // error here
                java.srcDirs = ['src']
                res.srcDirs = ['res']
                assets.srcDirs = ['assets']
            }
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile project(':library')
}

Error

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/asmirnov/Documents/dev/src/project/app-tests/build.gradle' line: 32

* What went wrong:
A problem occurred configuring project ':app-tests'.
> Exception thrown while executing model rule: android { ... } @ app-tests/build.gradle line 16, column 5
   > Could not find property 'manifest' on source set 'android test'.

Solution

  • It was tricky solution: to use experimental gradle plugin to compile native code with NDK and regular gradle plugin for test app.

    build.gradle:

    buildscript {
      repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
      }
      dependencies {
        // experimental gradle plugin for the library to compile native code with NDK
        classpath "com.android.tools.build:gradle-experimental:0.7.2"
    
        // regular gradle plugin for the tests
        classpath 'com.android.tools.build:gradle:2.1.2'
      }
    }
    
    subprojects {
      task listAllDependencies(type: DependencyReportTask) {}
    }
    

    library gradle (experimental):

    apply plugin: 'com.android.model.library'
    
    ...
    
    model {
    
        android {
          ...
          ndk {
              moduleName = "library-jni"
              cppFlags.add("-std=c++11")
              cppFlags.add("-fexceptions")
              stl = "c++_static"
    
              abiFilters.addAll(['armeabi-v7a', 'x86']) // supported abis only
           }
           ...
        }
        ...
    }
    

    app/build.gradle (regular):

    apply plugin: 'com.android.application'
    
    allprojects {
      repositories {
        mavenLocal()
        mavenCentral()
      }
    }
    
    repositories {
      mavenLocal()
      mavenCentral()
    }
    
    android {
      compileSdkVersion 16
      buildToolsVersion "22.0.1"
    
      defaultConfig {
        applicationId "app.tests"
        minSdkVersion 9
        targetSdkVersion 16
        versionCode 359
        versionName "1.3"
    
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
      }
    
      sourceSets {
        main {
          manifest.srcFile 'AndroidManifest.xml'
        }
    
        androidTest {
          manifest.srcFile 'AndroidManifest.xml'
          java.srcDirs = ['src']
    
          jni {
            dependencies {
              project ":library"
            }
          }
        }
      }
    }
    
    dependencies {
      androidTestCompile project(':library')
      androidTestCompile fileTree(include: ['*.jar'], dir: 'libs')
    }