Parameterized JUnit tests in Android test project

2019-05-08 21:24发布

问题:

When I create parameterized test cases in JUnit 3.x, I usually create a TestSuite with something like

public static Test suite() {
    TestSuite s = new TestSuite();

    for (int i = MIN; i < MAX; ++i) {
        s.addTest(new MyTest(i));
    }
}

This suite() method is called correctly when running JUnit from a desktop command-line. When I tried this with my Android test project, the tests don't run. How do I get my tests to run on the emulator? Or is there a different way to create parameterized tests for Android?

More thoughts:

Typically I run my tests with the command line:

adb shell am instrument -w [-e class <fully qualified test class name>[#<test method name>()]] <Android package name>/android.test.InstrumentationTestRunner

This allows me to select which tests to run from my test suite. Ideally, I want to run the the parameterized tests in this way as well. The link in the comment from @Appu describes building a separate app that runs JUnit tests. As part of that, this app has a custom TestRunner. I can very likely borrow these ideas to create a TestRunner which I can use in place of android.test.InstrumentationTestRunner. This seems like a lot of work for a not uncommon task. I prefer not to reinvent the wheel if there is already a similar solution in the Android API. Does anyone know of such a thing? Also, other alternative solutions will be helpful.

Nevermind, it looks like @dtmilano already posted this as an answer...

回答1:

You can implement a test runner to be able to pass parameters to Android tests. See the example at how to pass an argument to a android junit test (Parameterized tests).



回答2:

Or is there a different way to create parameterized tests for Android?

We (Square) wrote a library called Burst for this purpose. If you add enum parameters in your test constructor, Burst's test runner will generate a test for each combination of enum values. For example:

public class ParameterizedTest extends TestCase {
  enum Drink { COKE, PEPSI, RC_COLA }

  private final Drink drink;

  // Nullary constructor required by Android test framework
  public ConstructorTest() {
    this(null);
  }

  public ConstructorTest(Drink drink) {
    this.drink = drink;
  }

  public void testSomething() {
    assertNotNull(drink);
  }
}


回答3:

Quite a while after originally writing this question, I discovered that I can directly run a test class which contains a static suite() method:

adb shell am instrument -w -e class <fully qualified test class name> <Android package name>/android.test.InstrumentationTestRunner

However, the test suite doesn't run when I try to run all the tests in a given package.

Of course, this has been a while. Now I am using Android Studio instead of the command-line. I can still run the test class individually, but it still doesn't run when I select a package or try to run all of my tests.

A potential alternative is to write a master test class with a suite() method which adds all the tests to the returned TestCase. Unfortunately, this requires some manually editing every time I add a new test class to my suite.