README: Fix typo in package name
1 file changed
tree: b1109b04d291e24f0ef2eb965af1c2cb19f55e63
  1. src/
  2. .gitignore
  3. CONTRIBUTING.md
  4. LICENSE
  5. pom.xml
  6. README.md
README.md

TestParameterInjector

Introduction

Parameterized tests are a great way to avoid code duplication between tests and promote high test coverage for data-driven tests.

Getting started

To start using TestParameterInjector right away, copy the following snippet:

import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import com.google.testing.junit.testparameterinjector.TestParameter;

@RunWith(TestParameterInjector.class)
public class MyTest {

  @TestParameter boolean isDryRun;

  @Test public void test1(@TestParameter boolean enableFlag) {
    // ...
  }

  @Test public void test2(@TestParameter MyEnum myEnum) {
    // ...
  }

  enum MyEnum { VALUE_A, VALUE_B, VALUE_C }
}

Basics

@TestParameter for testing all combinations

Parameterizing a single test method

The simplest way to use this library is to use @TestParameter. For example:

@RunWith(TestParameterInjector.class)
public class MyTest {

  @Test
  public void test(@TestParameter boolean isOwner) {...}
}

In this example, two tests will be automatically generated by the test framework:

  • One with isOwner set to true
  • One with isOwner set to false

When running the tests, the result will show the following test names:

MyTest#test[isOwner=true]
MyTest#test[isOwner=false]

Parameterizing the whole class

@TestParameter can also annotate a field:

@RunWith(TestParameterInjector.class)
public class MyTest {

  @TestParameter private boolean isOwner;

  @Test public void test1() {...}
  @Test public void test2() {...}
}

In this example, both test1 and test2 will be run twice (once for each parameter value).

Supported types

The following examples show most of the supported types. See the @TestParameter javadoc for more details.

// Enums
@TestParameter AnimalEnum a; // Implies all possible values of AnimalEnum
@TestParameter({"CAT", "DOG"}) AnimalEnum a; // Implies AnimalEnum.CAT and AnimalEnum.DOG.

// Strings
@TestParameter({"cat", "dog"}) String animalName;

// Java primitives
@TestParameter boolean b; // Implies {true, false}
@TestParameter({"1", "2", "3"}) int i;
@TestParameter({"1", "1.5", "2"}) double d;

Multiple parameters: All combinations are run

If there are multiple @TestParameter-annotated values applicable to one test method, the test is run for all possible combinations of those values. Example:

@RunWith(TestParameterInjector.class)
public class MyTest {

  @TestParameter private boolean a;

  @Test public void test1(@TestParameter boolean b, @TestParameter boolean c) {
    // Run for these combinations:
    //   (a=false, b=false, c=false)
    //   (a=false, b=false, c=true )
    //   (a=false, b=true,  c=false)
    //   (a=false, b=true,  c=true )
    //   (a=true,  b=false, c=false)
    //   (a=true,  b=false, c=true )
    //   (a=true,  b=true,  c=false)
    //   (a=true,  b=true,  c=true )
  }
}

If you want to explicitly define which combinations are run, see the next sections.

Use a test enum for enumerating more complex parameter combinations

Use this strategy if you want to:

  • Explicitly specify the combination of parameters
  • or your parameters are too large to be encoded in a String in a readable way

Example:

@RunWith(TestParameterInjector.class)
class MyTest {

  enum FruitVolumeTestCase {
    APPLE(Fruit.newBuilder().setName("Apple").setShape(SPHERE).build(), /* expectedVolume= */ 3.1),
    BANANA(Fruit.newBuilder().setName("Banana").setShape(CURVED).build(), /* expectedVolume= */ 2.1),
    MELON(Fruit.newBuilder().setName("Melon").setShape(SPHERE).build(), /* expectedVolume= */ 6);

    final Fruit fruit;
    final double expectedVolume;

    FruitVolumeTestCase(Fruit fruit, double expectedVolume) { ... }
  }

  @Test
  public void calculateVolume_success(@TestParameter FruitVolumeTestCase fruitVolumeTestCase) {
    assertThat(calculateVolume(fruitVolumeTestCase.fruit))
        .isEqualTo(fruitVolumeTestCase.expectedVolume);
  }
}

The enum constant name has the added benefit of making for sensible test names:

MyTest#calculateVolume_success[APPLE]
MyTest#calculateVolume_success[BANANA]
MyTest#calculateVolume_success[MELON]

@TestParameters for defining sets of parameters

You can also explicitly enumerate the sets of test parameters via a list of YAML mappings:

@Test
@TestParameters({
  "{age: 17, expectIsAdult: false}",
  "{age: 22, expectIsAdult: true}",
})
public void personIsAdult(int age, boolean expectIsAdult) { ... }

The string format supports the same types as @TestParameter (e.g. enums). See the @TestParameters javadoc for more info.

@TestParameters works in the same way on the constructor, in which case all tests will be run for the given parameter sets.

Advanced usage

Dynamic parameter generation for @TestParameter

Instead of providing a list of parsable strings, you can implement your own TestParameterValuesProvider as follows:

@Test
public void matchesAllOf_throwsOnNull(
    @TestParameter(valuesProvider = CharMatcherProvider.class) CharMatcher charMatcher) {
  assertThrows(NullPointerException.class, () -> charMatcher.matchesAllOf(null));
}

private static final class CharMatcherProvider implements TestParameterValuesProvider {
  @Override
  public List<CharMatcher> provideValues() {
    return ImmutableList.of(CharMatcher.any(), CharMatcher.ascii(), CharMatcher.whitespace());
  }
}

Note that provideValues() dynamically construct the returned list, e.g. by reading a file. There are no restrictions on the object types returned, but note that toString() will be used for the test names.

Dynamic parameter generation for @TestParameters

Instead of providing a YAML mapping of parameters, you can implement your own TestParametersValuesProvider as follows:

@Test
@TestParameters(valuesProvider = IsAdultValueProvider.class)
public void personIsAdult(int age, boolean expectIsAdult) { ... }

static final class IsAdultValueProvider implements TestParametersValuesProvider {
  @Override public ImmutableList<TestParametersValues> provideValues() {
    return ImmutableList.of(
      TestParametersValues.builder()
        .name("teenager")
        .addParameter("age", 17)
        .addParameter("expectIsAdult", false)
        .build(),
      TestParametersValues.builder()
        .name("young adult")
        .addParameter("age", 22)
        .addParameter("expectIsAdult", true)
        .build()
    );
  }
}