如何用 Gradle 覆盖 android 测试路径?

How to override android tests path with Gradle?

由于历史原因,仪器测试未存储在 androidTests 目录 as required 中,我无法更改目录结构(实际上整个应用程序是对所用库的测试)。我能够使用 gradle 构建和安装 apk,但未找到测试:

: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

实际上测试在 src 文件夹中,正确编写并且可以 built/runned 使用 Ant:

public abstract class BaseTest extends AndroidTestCase
{
...

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

...

如何使 Gradle 处理 src 文件夹作为 android(仪器)测试?

这是我当前的 build.gradle 文件(它使用 experimental Android Gradle plugin 版本 0.7.2,因为我们有一个 NDK 库):

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

更新 1(对于 sschuberth)

配置:

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

错误

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

不完全确定这是否适用于您的方案,但您可以像这样更新 androidTest sourceSet 的根目录

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

还有一个 test 源集,如果它只是 Java 代码,没有 Android 特定内容。

您也可以使用 java.srcDir 设置...

以上设置将查看这些文件的位置。

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

如果您想将两者都移动到 /src 目录中,您可以使用

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

更多Android Gradle详情可在Configuring the Structure

阅读

欢迎您使用此设置自行调试这些设置

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

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

当您清理项目时,您会看到这些行被打印到控制台

您应该使用 sourceSets {}androidTest 源集来自定义测试源代码位置,而不是 sources {}

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

请注意,这不适不适 适用于单元测试。对于单元测试(与 Robolectric 一样),请使用 test 源集。

这是一个棘手的解决方案:使用实验性 gradle 插件通过 NDK 编译本机代码,并使用常规 gradle 插件来测试应用程序。

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

库gradle(实验):

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(常规):

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