A simple yet powerful parameterized test runner for Java.

Overview

TestParameterInjector

Introduction

TestParameterInjector is a JUnit4 test runner that runs its test methods for different combinations of field/parameter values.

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

There are a lot of alternative parameterized test frameworks, such as junit.runners.Parameterized and JUnitParams. We believe TestParameterInjector is an improvement of those because it is more powerful and simpler to use.

This blogpost goes into a bit more detail about how TestParameterInjector compares to other frameworks used at Google.

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

And add the following dependency to your .pom file:

<dependency>
  <groupId>com.google.testparameterinjector</groupId>
  <artifactId>test-parameter-injector</artifactId>
  <version>1.1</version>
</dependency>

or see this maven.org page for instructions for other build tools.

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;

// Bytes
@TestParameter({"!!binary 'ZGF0YQ=='", "some_string"}) byte[] bytes;

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()
    );
  }
}
Comments
  • Support JUnit 5

    Support JUnit 5

    I quite like the look of this API (well done, @nymanjens!). But I'm a JUnit 5 user, so if I wanted to use this library, I'd have to port it to a JUnit 5 extension, or use a potentially more verbose alternative.

    Is this something that's been considered already, by any chance?

    opened by jbduncan 27
  • Run a single test in IntelliJ

    Run a single test in IntelliJ

    Hi, Thank you for this nice runner, I wanted to know if it is possible to run a test unitary without running whole test class each time ? Because if I run only 1 test, i encounter the following error : java.lang.Exception: No tests found matching Method...

    Thank you for your reply, Feel free to close the issue if it will never be possible

    opened by privetr 12
  • Test naming changed from 1.8 to 1.9 for `float`s

    Test naming changed from 1.8 to 1.9 for `float`s

    I had this test:

    @RunWith(TestParameterInjector.class)
    ...
    
    @Test
    public void testLightStateOnDevice(
    	@TestParameter({"45", "0", "-3", "-6", "-9", "-12", "-15", "-18", "-21"}) float angle,
    	@TestParameter Preset preset
    ) {
    

    I'm using it for screenshot test recording, so the test names between previous and next versions has to match (otherwise hard to compare screenshots :). When updating from TPI 1.8 to 1.9 my PR failed:

    java.lang.AssertionError: File src/test/snapshots/images/net.twisterrob.sun.android.logic_SunAngleWidgetViewScreenshotTest_testLightStateOnDevice[45.0,Nice_Preview].png does not exist
    

    when inspecting the golden values on master (1.8) I found:

    net.twisterrob.sun.android.logic_SunAngleWidgetViewScreenshotTest_testLightStateOnDevice[45,Nice_Preview].png
    

    Since the only thing changed in the PR was the TPI version number, it's very likely that this had an unintended behavior change: https://github.com/google/TestParameterInjector/commit/e390bab7bf4c621e54ae7f814ebd405e49d60829#diff-f0f3c84fc90c4da3bd5e1267e7b74d5774029389e86dfe1bba895740b8b886d0R142

    opened by TWiStErRob 6
  • Feature request: shade protobuf dependency

    Feature request: shade protobuf dependency

    We've had some issues with conflicting protobuf dependencies (javalite vs protobuf-lite) due to this dependency and others. Would you be open to shading the protobuf dependency instead?

    opened by ZacSweers 6
  • Support tests written in kotlin with parameter types that are `@JvmInline` value classes

    Support tests written in kotlin with parameter types that are `@JvmInline` value classes

    Kotlin has a feature called "value classes" which currently desugar into primitive types. E.g. the following defines a class that will compile down to just being an float anywhere it's used:

    @JvmInline value class Temp(val value: Float)
    

    When such a class is used as the type of a constructor parameter, Kotlin generates an additional constructor with an extra parameter of type DefaultConstructorMarker. E.g. given the above class, this test class will actually have two constructors:

    @RunWith(TestParameterInjector::class)
    class TestClass(temp: Temp)
    

    This will generate constructors (as described by IntelliJ's "Show Kotlin bytecode" view):

    • private <init>(F)V
    • public synthetic <init>(FLkotlin/jvm/internal/DefaultConstructorMarker;)V

    When ran as a test, this library will see two constructors and give the following error message: "Expected exactly one constructor, but got {list of constructors}".

    Use case

    There are a number of reasons kotlin tests might need to be parameterized on value classes. E.g., the Jetpack Compose project frequently uses value classes to replicate enums but get around the various exhaustiveness checks that Kotlin performs for backwards compatibility. So we'd like to be able to parameterize tests on those types. We still need to explicitly list all the possible values, which is fine, but right now the runner will just crash.

    opened by zach-klippenstein 4
  • Add an `exclude` attribute in `@TestParameter` to exclude enum values.

    Add an `exclude` attribute in `@TestParameter` to exclude enum values.

    Currently the exclude attribute in @TestParameter only supports enums since it may not make any sense to support other types. It should be fairly easy to add support for other types if needed.

    opened by fredyw 4
  • Wrong transitive dependency protobuf

    Wrong transitive dependency protobuf

    đź‘‹ Hi, In the 1.4 release, you mentionned

    Replaced dependency on protobuf-java by a dependency on protobuf-javalite

    But in fact, this is not what has been done in https://github.com/google/TestParameterInjector/commit/acb188b5e8c37e749c872dafa8007bc36f02920d#diff-9c5fb3d1b7e3b0f54bc5c4182965c4fe1f9023d449017cece3005d3f90e8e4d8L137-R138

    -      <artifactId>protobuf-java</artifactId>
    -      <version>3.14.0</version>
    +      <artifactId>protobuf-lite</artifactId>
    +      <version>3.0.1</version>
    

    The switch is from protobuf-java to protobuf-lite. And this is still causing errors when using with firebase-perfs (where GeneratedMessageLite is coming from your transitive dependency instead of firebase's):

    java.lang.NoSuchMethodError: 'void com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(java.lang.Class, com.google.protobuf.GeneratedMessageLite)'	
    at com.google.firebase.perf.v1.TraceMetric.<clinit>(TraceMetric.java:1945)	
    at com.google.firebase.perf.metrics.TraceMetricBuilder.build(TraceMetricBuilder.java:39)	
    at com.google.firebase.perf.metrics.Trace.stop(Trace.java:258)
    

    It's only "recently" that the correct dependency has been restored: https://github.com/google/TestParameterInjector/commit/4d0fe8852d4eda4e2179ac2e82d988e3588e92b9

    -      <artifactId>protobuf-lite</artifactId>
    -      <version>3.0.1</version>
    +      <artifactId>protobuf-javalite</artifactId>
    +      <version>3.20.0</version>
    

    Do you have any plan to release this fix? Regards

    opened by SimonMarquis 3
  • Build fails with firebase dependency

    Build fails with firebase dependency

    This library is using protobuf-java dependency which clashes with Firebase library which contains protobuf-javalite. I'm not sure if there is a way to resolve this dependency issue.

    My android instrumentation builds fails with multiple errors like this:

    Duplicate class com.google.protobuf.AbstractMessageLite found in modules jetified-protobuf-java-3.14.0 (com.google.protobuf:protobuf-java:3.14.0) and jetified-protobuf-lite-3.0.1 (com.google.protobuf:protobuf-lite:3.0.1)

    opened by ggajews 3
  • Support for null strings

    Support for null strings

    Any tips/suggestions for getting null as a value? I know JSR won't allow null to be passed in because it's not a constant but is there any clean way of doing it besides generating my own TestParameterValuesProvider for every parameter that needs to support null?

    // Doesn't work
    @Test
    fun someTest(@TestParameter(value = [null, "", "foo"]) param: String) {
        ...
    }
    
    // Ugly bc you'd have to define the provider for every String argument in every test method
    @Test
    fun someTest(@TestParameter(valuesProvider = FooProvider::class) param: String) {
        ...
    }
    
    class FooProvider : TestParameter.TestParameterValuesProvider {
        override fun provideValues(): MutableList<String?> {
            return mutableListOf(null, "", "foo")
        }
    }
    
    opened by shafty023 3
  • Add Parameter wrapper to support older Android versions

    Add Parameter wrapper to support older Android versions

    Closes #2.

    Note: I haven't tested this on an actual pre-26 Android device yet. Will do later tonight or tomorrow. Just wanted to get the conversation started on the workaround.

    opened by JakeWharton 3
  • Support for Android pre-API 26

    Support for Android pre-API 26

    I'm trying to migrate our codebases from Burst in an effort to deprecate Burst, but this trips us up pretty hard on Android.

    I found this comment:

    https://github.com/google/TestParameterInjector/blob/7a62c43af8c4f10f1451ec84cd21c2ba509dae82/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterAnnotationMethodProcessor.java#L902-L905

    We could probably get this method and associated interface into D8/R8 desugaring since most (all?) of Parameter can be emulated by wrapping the originating Executable and delegating to its methods. Have you spoken to the R8 team at all about this?

    Or would you be open to taking that approach for now while separately we try and convince the R8 team? Since AnnotationWithMetadata is already an abstraction the only change would seem to be to duplicate the getAnnotationWithMetadataListWithType and have it accept the Executable subtypes (Constructor, Method, etc.) to pull out the needed components.

    opened by JakeWharton 3
  • Run in Firebase Test Lab

    Run in Firebase Test Lab

    Looks like the TestParameterInjector is unsupported by the Firebase Test Lab, at least all tests, that use the injector don't run in my case. Isn't it?

    opened by an-gerasimenko 1
  • JUnit 5: Support `@Nested` classes

    JUnit 5: Support `@Nested` classes

    If one runs an @TestParameterInjectorTest test method inside an inner class annotated with JUnit 5's @Nested annotation, it throws the following stack trace.

    Example

    import com.google.testing.junit.testparameterinjector.junit5.TestParameterInjectorTest;
    import com.google.testing.junit.testparameterinjector.junit5.TestParameters;
    import org.junit.jupiter.api.Nested;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    class OuterTests {
    
      @Nested
      class NestedTests {
    
        @TestParameterInjectorTest
        @TestParameters("{input: foo, output: bar}")
        void test(String input, String output) {
          assertEquals(output.length(), input.length());
        }
      }
    }
    
    Stack trace
    java.lang.IllegalStateException: No matching test parameter annotation found for parameter of type OuterTests in method/constructor OuterTests$NestedTests(OuterTests)
    java.lang.AssertionError: java.lang.IllegalStateException: No matching test parameter annotation found for parameter of type OuterTests in method/constructor OuterTests$NestedTests(OuterTests)
    	at com.google.testing.junit.testparameterinjector.junit5.ExecutableValidationResult.assertValid(ExecutableValidationResult.java:66)
    	at com.google.testing.junit.testparameterinjector.junit5.TestParameterInjectorExtension.validateTestMethodAndConstructor(TestParameterInjectorExtension.java:67)
    	at com.google.testing.junit.testparameterinjector.junit5.TestParameterInjectorExtension.provideTestTemplateInvocationContexts(TestParameterInjectorExtension.java:49)
    	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.lambda$execute$0(TestTemplateTestDescriptor.java:106)
    	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
    	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:110)
    	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:44)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    	at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
    	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
    	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
    Caused by: java.lang.IllegalStateException: No matching test parameter annotation found for parameter of type OuterTests in method/constructor OuterTests$NestedTests(OuterTests)
    	at com.google.testing.junit.testparameterinjector.junit5.TestParameterAnnotationMethodProcessor.validateMethodOrConstructorParameters(TestParameterAnnotationMethodProcessor.java:619)
    	at com.google.testing.junit.testparameterinjector.junit5.TestParameterAnnotationMethodProcessor.validateConstructor(TestParameterAnnotationMethodProcessor.java:518)
    	at com.google.testing.junit.testparameterinjector.junit5.TestMethodProcessorList.lambda$validateConstructor$4(TestMethodProcessorList.java:134)
    	at com.google.common.collect.Iterators$6.transform(Iterators.java:829)
    	at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:52)
    	at com.google.common.collect.Iterators.tryFind(Iterators.java:780)
    	at com.google.common.collect.Iterables.tryFind(Iterables.java:708)
    	at com.google.common.collect.FluentIterable.firstMatch(FluentIterable.java:476)
    	at com.google.testing.junit.testparameterinjector.junit5.TestMethodProcessorList.validateConstructor(TestMethodProcessorList.java:135)
    	... 85 more
    
    opened by jbduncan 5
  • Can't use more than one `TestParameter` annotation with Android Instrumentation tests.

    Can't use more than one `TestParameter` annotation with Android Instrumentation tests.

    When I use only one property with TestParameter annotation tests works well. As soon as I add a 2nd property with TestParameter annotation then all tests fail.

    After some investigation I've found that androidx.test.runner.AndroidJUnitRunner.runnerArgs.tests contains incorrect list of test classes:

    • my.test.MyTestClass#testCheckSmth[boolParam1=false
    • boolParam2=false]

    And as soon as TestLoader.doCreateRunner() tries to create test class instance from string boolParam2=false] using reflection it fails later.

    It is possible that input parameters incorrectly parsed from test args bundle splitting my.test.MyTestClass#testCheckSmth[boolParam1=false,boolParam2=false] by coma.

    Test class sample:

    // This is instrumentation test, should run on device or emulator
    @RunWith(TestParameterInjector::class)
    class MyTestClass {
    
    	@TestParameter
    	var boolParam1 = false
    
    	@TestParameter
    	var boolParam2 = false
    
    	@Test
    	fun testCheckSmth() {
    	  // test body...
    	}
    }
    

    When I use the same sample with standard JUnit tests it works well.

    Test output:

    Starting 4 tests on Android_TV_720p_API_Q(AVD) - Q
    
    boolParam2=false] > [Android_TV_720p_API_Q(AVD) - Q] FAILED 
            java.lang.ClassNotFoundException: Invalid name: boolParam2=false]
            at java.lang.Class.classForName(Native Method)
    
    boolParam2=true] > [Android_TV_720p_API_Q(AVD) - Q] FAILED 
            java.lang.ClassNotFoundException: Invalid name: boolParam2=true]
            at java.lang.Class.classForName(Native Method)
    
    boolParam2=false] > [Android_TV_720p_API_Q(AVD) - Q] FAILED 
            java.lang.ClassNotFoundException: Invalid name: boolParam2=false]
            at java.lang.Class.classForName(Native Method)
    
    boolParam2=true] > [Android_TV_720p_API_Q(AVD) - Q] FAILED 
            java.lang.ClassNotFoundException: Invalid name: boolParam2=true]
            at java.lang.Class.classForName(Native Method)
    
    > Task :app:connectedDebugAndroidTest FAILED
    
    opened by ultraon 8
  • Integrate with RobolectricTestRunner

    Integrate with RobolectricTestRunner

    If we test an Android component(Activity, Fragment, Service...) with Robolectric, we will use RobolectricTestRunner as the test runner.

    And a test class only have a test runner. I also find a way to run a test class within multiple test runners, but I have no idea if it works with TestParameterInjector. https://bekce.github.io/junit-multiple-runwith-dependent-tests/

    Could you have a look about this topic? Is possible that using TestParameterInjector as a Rule?

    opened by AlanChiou 1
Releases(v1.0)
Owner
Google
Google ❤️ Open Source
Google
Arbitrary test data generator for parameterized tests in Java inspired by AutoFixture.

AutoParams AutoParams is an arbitrary test data generator for parameterized tests in Java inspired by AutoFixture. Sometimes setting all the test data

null 260 Jan 2, 2023
A BDD-style test runner for Java 8. Inspired by Jasmine, RSpec, and Cucumber.

Spectrum A colorful BDD-style test runner for Java Spectrum is inspired by the behavior-driven testing frameworks Jasmine and RSpec, bringing their ex

Greg Haskins 143 Nov 22, 2022
Randomized Testing (Core JUnit Runner, ANT, Maven)

RANDOMIZED TESTING ================== JUnit test runner and plugins for running JUnit tests with pseudo-randomness. See the following for more infor

null 167 Dec 26, 2022
A TestNG like dataprovider runner for JUnit with many additional features

junit-dataprovider Have a look to this repositories Wiki pages for documenation, usage examples and further information. Table of contents Home What i

TNG Technology Consulting GmbH 237 Sep 7, 2022
A powerful open source test automation platform for Web Apps, Mobile Apps, and APIs

A powerful open source test automation platform for Web Apps, Mobile Apps, and APIs. Build stable and reliable end-to-end tests @ DevOps speed.

Testsigma Technologies Inc 466 Dec 31, 2022
Yet another Java annotation-based command parsing library, with Dependency Injection inspired by Guice

Commander A universal java command parsing library Building This project uses Gradle. Clone this repository: git clone https://github.com/OctoPvP/Comm

OctoDev 4 Oct 2, 2022
Test Automation Made Simple

Karate Test Automation Made Simple. Karate is the only open-source tool to combine API test-automation, mocks, performance-testing and even UI automat

Intuit 6.5k Dec 28, 2022
Test Automation Made Simple

Karate Test Automation Made Simple. Karate is the only open-source tool to combine API test-automation, mocks, performance-testing and even UI automat

Karate Labs 6.5k Dec 31, 2022
A Java architecture test library, to specify and assert architecture rules in plain Java

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code. That is, ArchUnit can check dependencies between pa

TNG Technology Consulting GmbH 2.5k Jan 2, 2023
Never debug a test again: Detailed failure reports and hassle free assertions for Java tests - Power Asserts for Java

Scott Test Reporter for Maven and Gradle Get extremely detailed failure messages for your tests without assertion libraries, additional configuration

Dávid Csákvári 133 Nov 17, 2022
A sample repo to help you handle basic auth for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to handle basic auth for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - htt

null 12 Jul 13, 2022
A sample repo to help you run automation test in incognito mode in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to run automation test in incognito mode in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - htt

null 12 Jul 13, 2022
A sample repo to help you handle cookies for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to handle cookies for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - https:

null 13 Jul 13, 2022
A sample repo to help you set geolocation for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to set geolocation for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - https

null 12 Jul 13, 2022
A sample repo to help you capture JavaScript exception for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to capture JavaScript exception for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Wi

null 12 Jul 13, 2022
A sample repo to help you find an element by text for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to find an element by text for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows

null 12 Jul 13, 2022
A sample repo to help you emulate network conditions in Java-selenium automation test on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to emulate network conditions in Java-selenium automation test on LambdaTest Prerequisites Install and set environment variable for java. Windows

null 12 Jul 13, 2022
A library for setting up Java objects as test data.

Beanmother Beanmother helps to create various objects, simple and complex, super easily with fixtures for testing. It encourages developers to write m

Jaehyun Shin 113 Nov 7, 2022
PowerMock is a Java framework that allows you to unit test code normally regarded as untestable.

Writing unit tests can be hard and sometimes good design has to be sacrificed for the sole purpose of testability. Often testability corresponds to go

PowerMock 3.9k Dec 28, 2022