Skip to content

Commit

Permalink
Easier Data Driven Tests for Java
Browse files Browse the repository at this point in the history
  • Loading branch information
musketyr committed May 25, 2024
1 parent a8c44f7 commit dc01f01
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 8 deletions.
8 changes: 1 addition & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,12 @@ nexusPublishing {
subprojects { Project subproject ->
if (subproject.name == 'guide') return

apply plugin: 'java-library'
apply plugin: 'groovy'

targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8

config {
bintray {
name = subproject.name
githubRepo = "agorapulse/$rootProject.name"
}
}

test {
systemProperty 'TEST_RESOURCES_FOLDER', new File(subproject.projectDir, 'src/test/resources').canonicalPath
systemProperty 'user.timezone', 'UTC'
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ kordampVersion=0.46.0
nexusPluginVersion=1.0.0
version = 0.2.0-SNAPSHOT
groovyVersion = 2.5.4
junitVersion = 4.13
junitVersion = 5.10.2
spockVersion = 1.3-groovy-2.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.agorapulse.testing.where4j;

import com.agorapulse.testing.where4j.dsl.*;
import org.junit.jupiter.api.DynamicTest;

import java.util.Arrays;

public interface Expectations extends Iterable<DynamicTest> {

static Headers3 header(String nameA, String nameB, String nameC) {
return new Headers3(nameA, nameB, nameC);
}

static <A, B, C>Row3<A, B, C> row(A a, B b, C c) {
return new Row3<>(a, b, c);
}

@SafeVarargs
static <A, B, C> Where3<A, B, C> forEach(Headers3 headers, Row3<A, B, C> first, Row3<A, B, C> ... rest) {
return new Where3<>(headers, first, Arrays.asList(rest));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.agorapulse.testing.where4j.dsl;

@FunctionalInterface
public interface Assertion3<A, B, C> {

boolean verify(A a, B b, C c);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.agorapulse.testing.where4j.dsl;

import com.agorapulse.testing.where4j.Expectations;
import org.junit.jupiter.api.DynamicTest;

import java.util.Iterator;

class Expectations3<A, B, C> implements Expectations {

private final Where3<A, B, C> where;
private final String template;
private final Assertion3<A, B, C> verification;

Expectations3(Where3<A, B, C> where, String template, Assertion3<A, B, C> verification) {
this.where = where;
this.template = template;
this.verification = verification;
}

@Override
public Iterator<DynamicTest> iterator() {
return where.generateTests(template, verification);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.agorapulse.testing.where4j.dsl;

public class Headers3 {

private final String a;
private final String b;
private final String c;

public Headers3(String a, String b, String c) {
this.a = a;
this.b = b;
this.c = c;
}

public String getA() {
return a;
}

public String getB() {
return b;
}

public String getC() {
return c;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.agorapulse.testing.where4j.dsl;

public class Row3<A, B, C> {

private final A a;
private final B b;
private final C c;

public Row3(A a, B b, C c) {
this.a = a;
this.b = b;
this.c = c;
}

public A getA() {
return a;
}

public B getB() {
return b;
}

public C getC() {
return c;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.agorapulse.testing.where4j.dsl;

@FunctionalInterface
public interface Verifcation3<A, B, C> {

void verify(A a, B b, C c);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.agorapulse.testing.where4j.dsl;

import com.agorapulse.testing.where4j.Expectations;
import org.junit.jupiter.api.DynamicTest;
import org.opentest4j.AssertionFailedError;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

public class Where3<A, B , C> {

private final List<Row3<A, B, C>> data = new ArrayList<>();
private final Headers3 headers;

public Where3(Headers3 headers, Row3<A, B, C> first, Collection<Row3<A, B, C>> rest) {
this.headers = headers;

this.data.add(first);
this.data.addAll(rest);
}

public Expectations expect(String template, Assertion3<A, B, C> verification) {
return new Expectations3<>(this, template, verification);
}

public Expectations verify(String template, Verifcation3<A, B, C> verification) {
return new Expectations3<>(this, template, (a, b, c) -> {
verification.verify(a, b, c);
return true;
});
}

Iterator<DynamicTest> generateTests(String template, Assertion3<A, B, C> verification) {
return data.stream().map(row -> {
String title = template.replace("#" + headers.getA(), String.valueOf(row.getA()));
title = title.replace("#" + headers.getB(), String.valueOf(row.getB()));
title = title.replace("#" + headers.getC(), String.valueOf(row.getC()));
String finalTitle = title;
return DynamicTest.dynamicTest(
finalTitle,
() -> {
if (!verification.verify(row.getA(), row.getB(), row.getC())) {
throw new AssertionFailedError("Verification failed for " + finalTitle + " with values " + headers.getA() + "=" + row.getA() + ", " + headers.getB() + "=" + row.getB() + ", " + headers.getC() + "=" + row.getC());
}
}
);
}).iterator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.agorapulse.testing.where4j;

public class Calculator {

public int add(int a, int b) {
return a + b;
}

public int subtract(int a, int b) {
return a - b;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.agorapulse.testing.where4j;

import org.junit.jupiter.api.TestFactory;

import static com.agorapulse.testing.where4j.Expectations.*;
import static org.junit.jupiter.api.Assertions.*;

class ExpectationsTest {

@TestFactory
Expectations basicTestWithThreeVariablesAndExplicitEvaluation() {
Calculator calculator = new Calculator();

return forEach(
header("a", "b", "c"),
row(2, 3, 5),
row(3, 5, 8),
row(4, 7, 11)
).expect("#a + #b = #c", (a, b, c) ->
calculator.add(a, b) == c
);
}

@TestFactory
Expectations basicTestWithThreeVariablesAndExplicitEvaluationWithMultipleLines() {
Calculator calculator = new Calculator();

return forEach(
header("a", "b", "c"),
row(2, 3, 5),
row(3, 5, 8),
row(4, 7, 11)
).expect("#a + #b = #c", (a, b, c) ->
calculator.add(a, b) == c
&& calculator.subtract(c, a) == b
&& calculator.subtract(c, b) == a
);
}

@TestFactory
Expectations basicTestWithThreeVariablesAndAssertion() {
Calculator calculator = new Calculator();

return forEach(
header("a", "b", "c"),
row(2, 3, 5),
row(3, 5, 8),
row(4, 7, 11)
).verify("#a + #b = #c", (a, b, c) ->
assertEquals(c, calculator.add(a, b))
);
}

}
33 changes: 33 additions & 0 deletions libs/where4j/where4j.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2018-2021 Agorapulse.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
config {
publishing {
enabled = true
}
}

dependencies {
api "org.junit.jupiter:junit-jupiter-api:$junitVersion"

testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$junitVersion"
}

test {
useJUnitPlatform()
}

0 comments on commit dc01f01

Please sign in to comment.