Property-Based Matrix Testing in Java
Tags: java, test, pbt, junit
Published: 2021-04-13 14:12:20

---
title: Property-Based Matrix Testing in Java
published: true
description: Property-Based Matrix Testing in Java.
tags: ["java", "test", "pbt", "junit"]
cover_image: https://source.unsplash.com/EWLHA4T-mso
---

I've used a common approach for property-based matrix testing in *Java*. Using *JUnit's* [ParameterizedTest][1] and a [MethodSource][2] annotations to point to a method as an argument supplier that spits out a stream representing a matrix.

It's pretty straightforward, but the more parameter types we have in our matrix, the harder it is to read or write the method supplying them. :dizzy_face:

Let's take a look.</br>
First, these are the two types for our matrix, these should spit out 6 test cases:

```java
  enum Direction {
    INCOMING,
    OUTGOING
  }

  enum Status {
    SUCCESS,
    FAILURE,
    WAITING
  }
```

Implementing a matrix from these *Enums* with [JUnit's ParameterizedTest][1] and a [MethodSource][2]:

```java
  @ParameterizedTest
  @MethodSource("getArguments")
  void using_junit_parameterized_test_with_method_source(
      final Direction direction, final Status status) {
    assertTrue(true);
  }

  static Stream<Arguments> getArguments() {
    return Stream.of(Direction.values())
        .flatMap(d -> Stream.of(Status.values()).map(s -> arguments(d, s)));
  }
```

Adding members to the existing *Enums* will dynamically increase the matrix and, therefore, the number of tests performed; there's no need to modify the test code.

But, adding a third type to the matrix and the `getArguments` method will start losing its readability.

Lately, I discovered [JUnit Pioneer][3], which is a *JUnit 5 Extension Pack*. Using its [CartesianProductTest][4] and [CartesianEnumSource][5] annotations, we can implement the same matrix simply and elegantly: :smiley:

```java
  @CartesianProductTest
  @CartesianEnumSource(Direction.class)
  @CartesianEnumSource(Status.class)
  void using_junit_pioneer_cartesian_product_test_with_enum_source(
      final Direction direction, final Status status) {
    assertTrue(true);
  }
```

This will spit out the same matrix, only now, adding a third element is quite simple: add another [CartesianEnumSource][5] annotation.

You can find other types of sources beside *Enums*, in *JUnit Pioneer*'s [Documentation][6].

As demonstrated in [this repository][0], executing both matrix tests will print out:

```text
[INFO] '-- JUnit Jupiter [OK]
[INFO]   '-- Property Based Matrix Test [OK]
[INFO]     +-- using junit pioneer cartesian product test with enum source (Direction, Status) [OK]
[INFO]     | +-- [1] INCOMING, SUCCESS [OK]
[INFO]     | +-- [2] INCOMING, FAILURE [OK]
[INFO]     | +-- [3] INCOMING, WAITING [OK]
[INFO]     | +-- [4] OUTGOING, SUCCESS [OK]
[INFO]     | +-- [5] OUTGOING, FAILURE [OK]
[INFO]     | '-- [6] OUTGOING, WAITING [OK]
[INFO]     '-- using junit parameterized test with method source (Direction, Status) [OK]
[INFO]       +-- [1] INCOMING, SUCCESS [OK]
[INFO]       +-- [2] INCOMING, FAILURE [OK]
[INFO]       +-- [3] INCOMING, WAITING [OK]
[INFO]       +-- [4] OUTGOING, SUCCESS [OK]
[INFO]       +-- [5] OUTGOING, FAILURE [OK]
[INFO]       '-- [6] OUTGOING, WAITING [OK]
```

Check out the code for this tutorial in [Github][0].

[0]: https://github.com/TomerFi/property-based-matrix-testing-tutorial
[1]: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
[2]: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests-sources-MethodSource
[3]: https://junit-pioneer.org/
[4]: https://junit-pioneer.org/docs/cartesian-product/
[5]: https://junit-pioneer.org/docs/cartesian-product/#cartesianenumsource
[6]: https://junit-pioneer.org/docs/cartesian-product/#annotating-your-test-method