4ntoine
4ntoine

Reputation: 20422

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'.

Upvotes: 1

Views: 2585

Answers (3)

4ntoine
4ntoine

Reputation: 20422

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')
}

Upvotes: 0

OneCricketeer
OneCricketeer

Reputation: 191854

Not completely sure this will work for your scenario, but you can update the root of the androidTest sourceSet like this

android {
    sourceSets {
        androidTest.setRoot('src')
    }
}

There is also a test source set if it's just Java code, nothing Android specific.

You could also play around with the java.srcDir setting...

The above setting will look at these locations for your files.

<project>/<module>/src/AndroidManifest.xml
<project>/<module>/src/java

If you'd like to move both into the /src directory, you can use

sourceSets {
    androidTest {
        setRoot 'src'
        java.srcDirs = ['src']
    }
}

More Android Gradle details can be read at Configuring the Structure


You are welcome to debug these settings yourself with this setup

sourceSets {
    androidTest {
        setRoot 'src'
        java.srcDirs = ['./src']
    }

    println "androidTest.manifest.srcFile = ${androidTest.manifest.srcFile}"
    println "androidTest.java.srcDirs = ${androidTest.java.srcDirs}"
}

When you just clean the project, you'll see those lines being printed to the console

Upvotes: 1

sschuberth
sschuberth

Reputation: 29867

Instead of sources {} you should use sourceSets {} and the androidTest source set to customize the test source code location:

model { // Required for experimental plugin.
    android {
        sourceSets {
            androidTest {
                manifest.srcFile '../AppTest/AndroidManifest.xml'
                java.srcDirs = ['../AppTest/src']
                res.srcDirs = ['../AppTest/res']
                assets.srcDirs = ['../AppTest/assets']
            }
        }
    }
}

Note that this not not apply to unit test. For unit test (like with Robolectric), use the test source set.

Upvotes: 0

Related Questions