如何使用Gradle运行一组特定的Android检测测试?

时间:2021-07-23 02:23:29

I have multiple test packages:

我有多个测试包:

com.mypackage.blackbox    - Robotium UI tests
com.mypackage.integration - REST integration tests
com.mypackage.unit        - low level unit tests

Our server team needs to be able to run just the integration tests on every push (they take a couple of minutes), but then run all tests every night (the black box UI tests take more than 10 minutes).

我们的服务器团队需要能够在每次推送时运行集成测试(它们需要几分钟),然后每晚运行所有测试(黑盒UI测试需要超过10分钟)。

This great answer provides a slightly hacky (but effective) way to do it by overloading an existing JUnit annotation like @SmallTest or @LargeTest.

这个好的答案通过重载现有的JUnit注释(如@SmallTest或@LargeTest)来提供一种稍微有点(但有效)的方法。

The Gradle documentation suggests that test filters are the way to do this, e.g.

Gradle文档表明测试过滤器是实现此目的的方法,例如:

./gradlew connectedAndroidTestDevDebug --tests com.mypackage.integration.*

However, that fails with an > Unknown command-line option '--tests'. error (presumably because the Android Gradle plugin doesn't support everything that vanilla Gradle does?).

但是,使用>未知命令行选项'--test'失败。错误(可能是因为Android Gradle插件不支持vanilla Gradle所做的一切?)。

The same documentation says in future they plan to support these alternatives:

同样的文档说他们将来计划支持这些替代方案:

  • Filtering based on custom annotations (future)
  • 基于自定义注释的过滤(未来)
  • Filtering based on test hierarchy; executing all tests that extend ceratain base class (future)
  • 基于测试层次的过滤;执行扩展ceratain基类的所有测试(未来)
  • Filtering based on some custom runtime rule, e.g. particular value of a system property or some static state (future)
  • 基于某些自定义运行时规则进行过滤,例如,系统属性的特定值或某些静态(未来)

Does anybody know a clean way to get this to work right now? For now I'm planning to use the @MediumTest annotation on the base class that all my integration tests extend, but I'd love to be able to specify particular package(s) instead. Using @MediumTest or @LargeTest abuses those annotations, as both my integration and black box tests are large tests according to the guidelines.

有没有人知道一个干净的方法让它现在正常工作?现在我打算在我的所有集成测试扩展的基类上使用@MediumTest注释,但我希望能够指定特定的包。使用@MediumTest或@LargeTest会滥用这些注释,因为我的集成和黑盒测试都是根据指​​南进行的大型测试。

3 个解决方案

#1


3  

This is now possible with the addition of Android's recent Testing Support Library, you can now use AndroidJUnitRunner and filter the tests you run by your own custom annotations.

现在可以通过添加Android最新的测试支持库来实现,您现在可以使用AndroidJUnitRunner并过滤由您自己的自定义注释运行的测试。

Filter test run to tests with a custom annotation (com.myapp.MyAnnotation in this example):

使用自定义注释过滤测试运行到测试(在此示例中为com.myapp.MyAnnotation):

adb shell am \
  instrument -w -e annotation com.myapp.MyAnnotation \
  com.myapp/android.support.test.runner.AndroidJUnitRunner

Complete AndroidJUnitRunner Documentation

完整的AndroidJUnitRunner文档

You'll need to annotate your test cases with your custom annotation to get this to work. Example test case:

您需要使用自定义注释对测试用例进行注释才能使其正常工作。示例测试用例:

import android.support.test.runner.AndroidJUnit4;
import com.myapp.MyAnnotation;

@RunWith(AndroidJUnit4.class)
public class CalculatorTest {

    @MyAnnotation
    @Test
    public void testAddition() {
        //Do testing here
    }

}

Here is what your "MyAnnotation" would look like:

以下是您的“MyAnnotation”的样子:

package com.myapp;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * My custom Annotation to specify a type of tests to run.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
}

#2


1  

To run specific tests using gradle you have to create custom instrumentation test runner class and run tests using that class. I.e. create class

要使用gradle运行特定测试,您必须创建自定义检测测试运行器类并使用该类运行测试。即创造课堂

package com.my.package;

public class MyInstrumentationTestRunner extends InstrumentationTestRunner {
    @Override
    public void onCreate(Bundle instrumentationArguments) {
        instrumentationArguments.putString("size", "medium"); // Run medium tests
        // Add more ...
        super.onCreate(instrumentationArguments);
    }
}

Then in your build.gradle set testInstrumentationRunner (it's under android -> defaultConfig, i.e.

然后在你的build.gradle中设置testInstrumentationRunner(它在android - > defaultConfig下,即

// ...

android {
    // ...

    defaultConfig {
        // ...
        testInstrumentationRunner "com.my.package.MyInstrumentationTestRunner"
    }
}

// ...

Hope it helps!

希望能帮助到你!

Note. build.gradle is from :lib, the tests are located under src/androidTest/java where the MyInstrumentationTestRunner is created.

注意。 build.gradle来自:lib,测试位于src / androidTest / java下,其中创建了MyInstrumentationTestRunner。

#3


1  

Sam's answer is the most versatile answer. However, the simplest solution is probably to use the -e package option on the InstrumentationTestRunner:

Sam的答案是最通用的答案。但是,最简单的解决方案可能是在InstrumentationTestRunner上使用-e package选项:

Running all tests in a java package: adb shell am instrument -w -e package com.android.foo.subpkg com.android.foo/android.test.InstrumentationTestRunner

在java包中运行所有测试:adb shell am instrument -w -e package com.android.foo.subpkg com.android.foo/android.test.InstrumentationTestRunner

You can combine this option with using Square's Spoon library, as it allows you to specify either individual classes, or use -e to pass options through to the test runner (e.g. the package option):

您可以将此选项与Square的Spoon库结合使用,因为它允许您指定单个类,或使用-e将选项传递给测试运行器(例如包选项):

--class-name        Test class name to run (fully-qualified)

--method-name       Test method name to run (must also use --class-name)

--e                 Arguments to pass to the Instrumentation Runner. This can be used
                    multiple times for multiple entries. Usage: --e <NAME>=<VALUE>.
                    The supported arguments varies depending on which test runner 
                    you are using, e.g. see the API docs for AndroidJUnitRunner.

For the record, Shazam's Fork has a more powerful regex option:

为了记录,Shazam's Fork有一个更强大的正则表达式选项:

android.test.classes=REGEX - comma separated regexes that specify a pattern for the classes/packages to run

#1


3  

This is now possible with the addition of Android's recent Testing Support Library, you can now use AndroidJUnitRunner and filter the tests you run by your own custom annotations.

现在可以通过添加Android最新的测试支持库来实现,您现在可以使用AndroidJUnitRunner并过滤由您自己的自定义注释运行的测试。

Filter test run to tests with a custom annotation (com.myapp.MyAnnotation in this example):

使用自定义注释过滤测试运行到测试(在此示例中为com.myapp.MyAnnotation):

adb shell am \
  instrument -w -e annotation com.myapp.MyAnnotation \
  com.myapp/android.support.test.runner.AndroidJUnitRunner

Complete AndroidJUnitRunner Documentation

完整的AndroidJUnitRunner文档

You'll need to annotate your test cases with your custom annotation to get this to work. Example test case:

您需要使用自定义注释对测试用例进行注释才能使其正常工作。示例测试用例:

import android.support.test.runner.AndroidJUnit4;
import com.myapp.MyAnnotation;

@RunWith(AndroidJUnit4.class)
public class CalculatorTest {

    @MyAnnotation
    @Test
    public void testAddition() {
        //Do testing here
    }

}

Here is what your "MyAnnotation" would look like:

以下是您的“MyAnnotation”的样子:

package com.myapp;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * My custom Annotation to specify a type of tests to run.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
}

#2


1  

To run specific tests using gradle you have to create custom instrumentation test runner class and run tests using that class. I.e. create class

要使用gradle运行特定测试,您必须创建自定义检测测试运行器类并使用该类运行测试。即创造课堂

package com.my.package;

public class MyInstrumentationTestRunner extends InstrumentationTestRunner {
    @Override
    public void onCreate(Bundle instrumentationArguments) {
        instrumentationArguments.putString("size", "medium"); // Run medium tests
        // Add more ...
        super.onCreate(instrumentationArguments);
    }
}

Then in your build.gradle set testInstrumentationRunner (it's under android -> defaultConfig, i.e.

然后在你的build.gradle中设置testInstrumentationRunner(它在android - > defaultConfig下,即

// ...

android {
    // ...

    defaultConfig {
        // ...
        testInstrumentationRunner "com.my.package.MyInstrumentationTestRunner"
    }
}

// ...

Hope it helps!

希望能帮助到你!

Note. build.gradle is from :lib, the tests are located under src/androidTest/java where the MyInstrumentationTestRunner is created.

注意。 build.gradle来自:lib,测试位于src / androidTest / java下,其中创建了MyInstrumentationTestRunner。

#3


1  

Sam's answer is the most versatile answer. However, the simplest solution is probably to use the -e package option on the InstrumentationTestRunner:

Sam的答案是最通用的答案。但是,最简单的解决方案可能是在InstrumentationTestRunner上使用-e package选项:

Running all tests in a java package: adb shell am instrument -w -e package com.android.foo.subpkg com.android.foo/android.test.InstrumentationTestRunner

在java包中运行所有测试:adb shell am instrument -w -e package com.android.foo.subpkg com.android.foo/android.test.InstrumentationTestRunner

You can combine this option with using Square's Spoon library, as it allows you to specify either individual classes, or use -e to pass options through to the test runner (e.g. the package option):

您可以将此选项与Square的Spoon库结合使用,因为它允许您指定单个类,或使用-e将选项传递给测试运行器(例如包选项):

--class-name        Test class name to run (fully-qualified)

--method-name       Test method name to run (must also use --class-name)

--e                 Arguments to pass to the Instrumentation Runner. This can be used
                    multiple times for multiple entries. Usage: --e <NAME>=<VALUE>.
                    The supported arguments varies depending on which test runner 
                    you are using, e.g. see the API docs for AndroidJUnitRunner.

For the record, Shazam's Fork has a more powerful regex option:

为了记录,Shazam's Fork有一个更强大的正则表达式选项:

android.test.classes=REGEX - comma separated regexes that specify a pattern for the classes/packages to run