From 226ecd8efc45e4540bba43f6c604e891b5a94689 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 27 Oct 2015 17:09:55 +0100 Subject: [PATCH] Saved code from current master --- junit-commons/build.gradle | 2 + .../junit/gen5/commons}/util/ObjectUtils.java | 2 +- .../gen5/commons}/util/Preconditions.java | 2 +- .../java/org/junit/gen5/console/Console.java | 4 +- .../java/org/junit/gen5/engine/Engine.java | 4 +- .../gen5/engine/EngineTestDescription.java | 9 - .../junit/gen5/engine}/TestDescriptor.java | 18 +- junit-launcher/build.gradle | 1 + .../org/junit/gen5/launcher/Launcher.java | 20 +- .../gen5/launcher/TestExecutionPlan.java | 21 +++ .../org/junit/gen5/launcher/TestPlan.java | 73 +++++++- .../gen5/launcher/TestPlanBuilderTests.java | 34 ++++ junit5-api/build.gradle | 2 + .../java/org/junit/gen5/api}/Assertions.java | 15 +- .../java/org/junit/gen5/api}/Assumptions.java | 7 +- .../java/org/junit/gen5/api}/Executable.java | 3 +- .../main/java/org/junit/gen5/api/Test.java | 15 ++ junit5-engine/build.gradle | 1 + .../gen5/engine/junit5/JUnit5Engine.java | 30 +-- .../junit5/JavaMethodTestDescription.java | 31 ---- .../engine/junit5/JavaTestDescriptor.java | 175 ++++++++++++++++++ .../junit5/JavaTestDescriptorTests.java | 98 ++++++++++ old-junit-core/build.gradle | 3 - ...ception.java => AssertionFailedError.java} | 26 ++- .../TestAbortedException.java | 4 + .../TestSkippedException.java | 7 +- .../{SampleTest.java => SampleTestCase.java} | 5 +- settings.gradle | 2 +- 28 files changed, 496 insertions(+), 118 deletions(-) create mode 100644 junit-commons/build.gradle rename {old-junit-core/src/main/java/org/junit/core => junit-commons/src/main/java/org/junit/gen5/commons}/util/ObjectUtils.java (94%) rename {old-junit-core/src/main/java/org/junit/core => junit-commons/src/main/java/org/junit/gen5/commons}/util/Preconditions.java (96%) delete mode 100644 junit-engine-api/src/main/java/org/junit/gen5/engine/EngineTestDescription.java rename {old-junit-core/src/main/java/org/junit/core => junit-engine-api/src/main/java/org/junit/gen5/engine}/TestDescriptor.java (68%) create mode 100644 junit-launcher/src/main/java/org/junit/gen5/launcher/TestExecutionPlan.java create mode 100644 junit-launcher/src/test/java/org/junit/gen5/launcher/TestPlanBuilderTests.java rename {old-junit-core/src/main/java/org/junit/core => junit5-api/src/main/java/org/junit/gen5/api}/Assertions.java (96%) rename {old-junit-core/src/main/java/org/junit/core => junit5-api/src/main/java/org/junit/gen5/api}/Assumptions.java (88%) rename {old-junit-core/src/main/java/org/junit/core => junit5-api/src/main/java/org/junit/gen5/api}/Executable.java (82%) delete mode 100644 junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaMethodTestDescription.java create mode 100644 junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaTestDescriptor.java create mode 100644 junit5-engine/src/test/java/org/junit/gen5/engine/junit5/JavaTestDescriptorTests.java delete mode 100644 old-junit-core/build.gradle rename open-test-alliance/src/main/java/org/opentestalliance/{AssertionFailedException.java => AssertionFailedError.java} (67%) rename sample-project/src/test/java/com/example/{SampleTest.java => SampleTestCase.java} (72%) diff --git a/junit-commons/build.gradle b/junit-commons/build.gradle new file mode 100644 index 00000000000..7d82dc72fbf --- /dev/null +++ b/junit-commons/build.gradle @@ -0,0 +1,2 @@ +dependencies { +} diff --git a/old-junit-core/src/main/java/org/junit/core/util/ObjectUtils.java b/junit-commons/src/main/java/org/junit/gen5/commons/util/ObjectUtils.java similarity index 94% rename from old-junit-core/src/main/java/org/junit/core/util/ObjectUtils.java rename to junit-commons/src/main/java/org/junit/gen5/commons/util/ObjectUtils.java index d3e01461b9d..41a41e68435 100644 --- a/old-junit-core/src/main/java/org/junit/core/util/ObjectUtils.java +++ b/junit-commons/src/main/java/org/junit/gen5/commons/util/ObjectUtils.java @@ -1,5 +1,5 @@ -package org.junit.core.util; +package org.junit.gen5.commons.util; import static java.util.Arrays.*; import static java.util.stream.Collectors.*; diff --git a/old-junit-core/src/main/java/org/junit/core/util/Preconditions.java b/junit-commons/src/main/java/org/junit/gen5/commons/util/Preconditions.java similarity index 96% rename from old-junit-core/src/main/java/org/junit/core/util/Preconditions.java rename to junit-commons/src/main/java/org/junit/gen5/commons/util/Preconditions.java index 87e70f94375..6c8020f56a6 100644 --- a/old-junit-core/src/main/java/org/junit/core/util/Preconditions.java +++ b/junit-commons/src/main/java/org/junit/gen5/commons/util/Preconditions.java @@ -1,5 +1,5 @@ -package org.junit.core.util; +package org.junit.gen5.commons.util; import java.util.function.Supplier; diff --git a/junit-console/src/main/java/org/junit/gen5/console/Console.java b/junit-console/src/main/java/org/junit/gen5/console/Console.java index a66891db709..3ec3252b2f8 100644 --- a/junit-console/src/main/java/org/junit/gen5/console/Console.java +++ b/junit-console/src/main/java/org/junit/gen5/console/Console.java @@ -1,7 +1,7 @@ package org.junit.gen5.console; import org.junit.gen5.launcher.Launcher; -import org.junit.gen5.launcher.TestPlan; +import org.junit.gen5.launcher.TestExecutionPlan; public class Console { @@ -12,7 +12,7 @@ public static void main(String[] args) throws Exception { Launcher launcher = new Launcher(); // TODO Launch parameters: Provide configuration - TestPlan testPlan = launcher.discoverTests(className); + TestExecutionPlan testPlan = launcher.discoverTests(className); // TODO Provide means to allow manipulation of test plan? launcher.execute(testPlan); diff --git a/junit-engine-api/src/main/java/org/junit/gen5/engine/Engine.java b/junit-engine-api/src/main/java/org/junit/gen5/engine/Engine.java index db0f0a367d0..457fdda9a8a 100644 --- a/junit-engine-api/src/main/java/org/junit/gen5/engine/Engine.java +++ b/junit-engine-api/src/main/java/org/junit/gen5/engine/Engine.java @@ -7,7 +7,7 @@ public interface Engine { String getId(); - List discoverTests(String className); + List discoverTests(String className); - void execute(List testDescriptions) throws Exception; + void execute(List testDescriptions) throws Exception; } diff --git a/junit-engine-api/src/main/java/org/junit/gen5/engine/EngineTestDescription.java b/junit-engine-api/src/main/java/org/junit/gen5/engine/EngineTestDescription.java deleted file mode 100644 index 4273c83fbdc..00000000000 --- a/junit-engine-api/src/main/java/org/junit/gen5/engine/EngineTestDescription.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.junit.gen5.engine; - -public interface EngineTestDescription { - - String getId(); - - String getDisplayName(); - -} diff --git a/old-junit-core/src/main/java/org/junit/core/TestDescriptor.java b/junit-engine-api/src/main/java/org/junit/gen5/engine/TestDescriptor.java similarity index 68% rename from old-junit-core/src/main/java/org/junit/core/TestDescriptor.java rename to junit-engine-api/src/main/java/org/junit/gen5/engine/TestDescriptor.java index b897879f7b2..f723c20e28a 100644 --- a/old-junit-core/src/main/java/org/junit/core/TestDescriptor.java +++ b/junit-engine-api/src/main/java/org/junit/gen5/engine/TestDescriptor.java @@ -1,5 +1,5 @@ -package org.junit.core; +package org.junit.gen5.engine; import java.util.List; @@ -9,21 +9,21 @@ */ public interface TestDescriptor { - String getEngineId(); - - String getTestId(); - /** * Get the unique identifier (UID) for the described test. * - *

Uniqueness must hold across an entire test plan, regardless of - * how many engines are used behind the scenes. + *

Uniqueness must be guaranteed across an entire test plan, + * regardless of how many engines are used behind the scenes. * - *

The UID is simply the concatenation of the {@linkplain #getEngineId engine ID} + *

The ID is simply the concatenation of the {@linkplain #getEngineId engine ID} * and the {@linkplain #getTestId test ID} separated by a colon ({@code ":"}) * — for example, {@code myEngine:test-description-unique-within-my-engine}. */ - String getUniqueId(); + String getId(); + + String getEngineId(); + + String getTestId(); String getDisplayName(); diff --git a/junit-launcher/build.gradle b/junit-launcher/build.gradle index f171b09be87..199e5e4a176 100644 --- a/junit-launcher/build.gradle +++ b/junit-launcher/build.gradle @@ -1,3 +1,4 @@ dependencies { compile(project(':junit-engine-api')) + testCompile('junit:junit:4.12') } diff --git a/junit-launcher/src/main/java/org/junit/gen5/launcher/Launcher.java b/junit-launcher/src/main/java/org/junit/gen5/launcher/Launcher.java index 904dcf374c0..fed0e3539b4 100644 --- a/junit-launcher/src/main/java/org/junit/gen5/launcher/Launcher.java +++ b/junit-launcher/src/main/java/org/junit/gen5/launcher/Launcher.java @@ -9,14 +9,14 @@ import java.util.stream.Collectors; import org.junit.gen5.engine.Engine; -import org.junit.gen5.engine.EngineTestDescription; +import org.junit.gen5.engine.TestDescriptor; public class Launcher { - private final Map> testDescriptionsByEngine = new LinkedHashMap<>(); + private final Map> testDescriptionsByEngine = new LinkedHashMap<>(); - public TestPlan discoverTests(String className) { - TestPlan testPlan = new TestPlan(); + public TestExecutionPlan discoverTests(String className) { + TestExecutionPlan testPlan = new TestExecutionPlan(); for (Engine engine : discoverEngines()) { testPlan.addTestIdentifiers(discoverTests(className, engine)); } @@ -24,9 +24,9 @@ public TestPlan discoverTests(String className) { } private Set discoverTests(String className, Engine engine) { - List discoveredTests = engine.discoverTests(className); + List discoveredTests = engine.discoverTests(className); - Map engineTestDescriptionsByTestId = new LinkedHashMap<>(); + Map engineTestDescriptionsByTestId = new LinkedHashMap<>(); discoveredTests.forEach(testDescription -> engineTestDescriptionsByTestId.put( new TestIdentifier(engine.getId(), testDescription.getId(), testDescription.getDisplayName()), testDescription)); @@ -36,14 +36,14 @@ private Set discoverTests(String className, Engine engine) { } // TODO no exceptions please - public void execute(TestPlan testPlan) throws Exception { + public void execute(TestExecutionPlan testPlan) throws Exception { for (Engine engine : discoverEngines()) { - Map engineTestDescriptions = testDescriptionsByEngine + Map engineTestDescriptions = testDescriptionsByEngine .get(engine.getId()); List testIdentifiers = testPlan.getTestIdentifiers(); List filtered = engineTestDescriptions.keySet().stream() .filter(testIdentifier -> testIdentifiers.contains(testIdentifier)).collect(Collectors.toList()); - List testDescriptions = new ArrayList<>(); + List testDescriptions = new ArrayList<>(); for (TestIdentifier testIdentifier : filtered) { testDescriptions.add(lookup(engine, testIdentifier)); } @@ -51,7 +51,7 @@ public void execute(TestPlan testPlan) throws Exception { } } - private EngineTestDescription lookup(Engine engine, TestIdentifier testIdentifier) { + private TestDescriptor lookup(Engine engine, TestIdentifier testIdentifier) { return testDescriptionsByEngine.get(engine.getId()).get(testIdentifier); } diff --git a/junit-launcher/src/main/java/org/junit/gen5/launcher/TestExecutionPlan.java b/junit-launcher/src/main/java/org/junit/gen5/launcher/TestExecutionPlan.java new file mode 100644 index 00000000000..ab6f2462f41 --- /dev/null +++ b/junit-launcher/src/main/java/org/junit/gen5/launcher/TestExecutionPlan.java @@ -0,0 +1,21 @@ +package org.junit.gen5.launcher; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +// TODO make immutable? +// TODO name? +public class TestExecutionPlan { + + private final List testIdentifiers = new LinkedList<>(); + + public List getTestIdentifiers() { + return testIdentifiers; + } + + public void addTestIdentifiers(Collection testDescriptions) { + this.testIdentifiers.addAll(testDescriptions); + } + +} diff --git a/junit-launcher/src/main/java/org/junit/gen5/launcher/TestPlan.java b/junit-launcher/src/main/java/org/junit/gen5/launcher/TestPlan.java index 3017393bbcf..b51f68138d1 100644 --- a/junit-launcher/src/main/java/org/junit/gen5/launcher/TestPlan.java +++ b/junit-launcher/src/main/java/org/junit/gen5/launcher/TestPlan.java @@ -1,20 +1,73 @@ + package org.junit.gen5.launcher; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.nio.file.Path; +import java.util.Map; -// TODO make immutable? -public class TestPlan { +/** + * @author Sam Brannen + * @since 5.0 + */ +public final class TestPlan { - private final List testIdentifiers = new LinkedList<>(); + private TestPlan() { + /* no-op */ + } - public List getTestIdentifiers() { - return testIdentifiers; + public static TestPlanBuilder builder() { + return new TestPlanBuilder(); } - public void addTestIdentifiers(Collection testDescriptions) { - this.testIdentifiers.addAll(testDescriptions); + public static final class TestPlanBuilder { + + private TestPlanBuilder() { + /* no-op */ + } + + public TestPlanBuilder configuration(Map parameters) { + return this; + } + + public TestPlanBuilder classes(Class... classes) { + return this; + } + + public TestPlanBuilder classNames(String... classNames) { + return this; + } + + public TestPlanBuilder packages(Package... packages) { + return this; + } + + public TestPlanBuilder packageNames(String... packageNames) { + return this; + } + + public TestPlanBuilder paths(Path... paths) { + return this; + } + + public TestPlanBuilder fileNames(String... fileNames) { + return this; + } + + public TestPlanBuilder descriptorIds(String... descriptorIds) { + return this; + } + + public TestPlanBuilder includePatterns(String... patterns) { + return this; + } + + public TestPlanBuilder excludePatterns(String... patterns) { + return this; + } + + public TestPlan build() { + return new TestPlan(); + } + } } diff --git a/junit-launcher/src/test/java/org/junit/gen5/launcher/TestPlanBuilderTests.java b/junit-launcher/src/test/java/org/junit/gen5/launcher/TestPlanBuilderTests.java new file mode 100644 index 00000000000..86a7cadade1 --- /dev/null +++ b/junit-launcher/src/test/java/org/junit/gen5/launcher/TestPlanBuilderTests.java @@ -0,0 +1,34 @@ + +package org.junit.gen5.launcher; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; + +import org.junit.Test; +import org.junit.gen5.launcher.TestPlan.TestPlanBuilder; + +/** + * Unit tests for {@link TestPlanBuilder}. + * + * @author Sam Brannen + * @since 5.0 + */ +public class TestPlanBuilderTests { + + @Test + public void testPlanBuilderDemo() { + @SuppressWarnings("serial") + TestPlan testPlan = TestPlan.builder() + .configuration(new HashMap(){{ + put("category", "smoke"); + }}) + .packageNames("org.example.service.impl") + .includePatterns("*Tests") + .descriptorIds("junit5:org.example.UserTests#fullname()") + .build(); + + assertThat(testPlan).isNotNull(); + } + +} diff --git a/junit5-api/build.gradle b/junit5-api/build.gradle index 7d82dc72fbf..096b8054fba 100644 --- a/junit5-api/build.gradle +++ b/junit5-api/build.gradle @@ -1,2 +1,4 @@ dependencies { + compile(project(':open-test-alliance')) + compile(project(':junit-commons')) } diff --git a/old-junit-core/src/main/java/org/junit/core/Assertions.java b/junit5-api/src/main/java/org/junit/gen5/api/Assertions.java similarity index 96% rename from old-junit-core/src/main/java/org/junit/core/Assertions.java rename to junit5-api/src/main/java/org/junit/gen5/api/Assertions.java index 6de6a2ca2b4..d4f8631f4fa 100644 --- a/old-junit-core/src/main/java/org/junit/core/Assertions.java +++ b/junit5-api/src/main/java/org/junit/gen5/api/Assertions.java @@ -1,11 +1,10 @@ - -package org.junit.core; +package org.junit.gen5.api; import java.util.function.BooleanSupplier; import java.util.function.Supplier; -import org.junit.core.util.ObjectUtils; -import org.opentestalliance.AssertionFailedException; +import org.junit.gen5.commons.util.ObjectUtils; +import org.opentestalliance.AssertionFailedError; /** * @author JUnit Community @@ -20,9 +19,9 @@ private Assertions() { public static void fail(String message) { if (message == null) { - throw new AssertionFailedException(); + throw new AssertionFailedError(); } - throw new AssertionFailedException(message); + throw new AssertionFailedError(message); } public static void fail(Supplier messageSupplier) { @@ -205,10 +204,10 @@ public static T expectThrows(Class expected, Executable else { String message = Assertions.format(expected.getName(), actual.getClass().getName(), "unexpected exception type thrown;"); - throw new AssertionFailedException(message, actual); + throw new AssertionFailedError(message, actual); } } - throw new AssertionFailedException( + throw new AssertionFailedError( String.format("expected %s to be thrown, but nothing was thrown", expected.getName())); } diff --git a/old-junit-core/src/main/java/org/junit/core/Assumptions.java b/junit5-api/src/main/java/org/junit/gen5/api/Assumptions.java similarity index 88% rename from old-junit-core/src/main/java/org/junit/core/Assumptions.java rename to junit5-api/src/main/java/org/junit/gen5/api/Assumptions.java index 51c4b66e9e9..9583744a325 100644 --- a/old-junit-core/src/main/java/org/junit/core/Assumptions.java +++ b/junit5-api/src/main/java/org/junit/gen5/api/Assumptions.java @@ -1,5 +1,4 @@ - -package org.junit.core; +package org.junit.gen5.api; import org.opentestalliance.TestAbortedException; @@ -30,6 +29,10 @@ public static void assumingThat(boolean condition, Executable executable) { try { executable.execute(); } + catch (AssertionError | RuntimeException e) { + // rethrow + throw e; + } catch (Throwable e) { // TODO Don't wrap Throwables such as OutOfMemoryError, etc. throw new RuntimeException("Wrapped exception thrown from Executable", e); diff --git a/old-junit-core/src/main/java/org/junit/core/Executable.java b/junit5-api/src/main/java/org/junit/gen5/api/Executable.java similarity index 82% rename from old-junit-core/src/main/java/org/junit/core/Executable.java rename to junit5-api/src/main/java/org/junit/gen5/api/Executable.java index 8ed49f4c44e..c78206ce1db 100644 --- a/old-junit-core/src/main/java/org/junit/core/Executable.java +++ b/junit5-api/src/main/java/org/junit/gen5/api/Executable.java @@ -1,5 +1,4 @@ - -package org.junit.core; +package org.junit.gen5.api; /** * @author Sam Brannen diff --git a/junit5-api/src/main/java/org/junit/gen5/api/Test.java b/junit5-api/src/main/java/org/junit/gen5/api/Test.java index e9109ea5b4f..185d2570ddd 100644 --- a/junit5-api/src/main/java/org/junit/gen5/api/Test.java +++ b/junit5-api/src/main/java/org/junit/gen5/api/Test.java @@ -1,5 +1,20 @@ package org.junit.gen5.api; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Sam Brannen + * @since 5.0 + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented public @interface Test { + String name() default ""; + } diff --git a/junit5-engine/build.gradle b/junit5-engine/build.gradle index 971d98c789a..3931d613612 100644 --- a/junit5-engine/build.gradle +++ b/junit5-engine/build.gradle @@ -1,4 +1,5 @@ dependencies { compile(project(':junit-engine-api')) compile(project(':junit5-api')) + testCompile("junit:junit:4.12") } diff --git a/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JUnit5Engine.java b/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JUnit5Engine.java index 3c8aad0f5ed..81ff1739f29 100644 --- a/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JUnit5Engine.java +++ b/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JUnit5Engine.java @@ -2,44 +2,44 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.gen5.engine.Engine; -import org.junit.gen5.engine.EngineTestDescription; +import org.junit.gen5.engine.TestDescriptor; public class JUnit5Engine implements Engine { private static final String JUNIT5_ENGINE_ID = "junit5"; @Override - public List discoverTests(String className) { - return Arrays. asList(new JavaMethodTestDescription(className, "failingTest"), - new JavaMethodTestDescription(className, "succeedingTest")); + public List discoverTests(String className) { + // TODO implement this + return Collections.emptyList(); +// return Arrays. asList(new JavaTestDescriptor(className, "failingTest"), +// new JavaTestDescriptor(className, "succeedingTest")); } @Override - public void execute(List testDescriptions) throws Exception { - for (EngineTestDescription testDescription : testDescriptions) { + public void execute(List testDescriptions) throws Exception { + for (TestDescriptor testDescription : testDescriptions) { execute(testDescription); } } - private void execute(EngineTestDescription testDescription) throws Exception { - if (testDescription instanceof JavaMethodTestDescription) { - JavaMethodTestDescription javaMethodTestDescription = (JavaMethodTestDescription) testDescription; - String className = javaMethodTestDescription.getClassName(); - // TODO use correct classloader - Class testClass = Class.forName(className); + private void execute(TestDescriptor testDescription) throws Exception { + if (testDescription instanceof JavaTestDescriptor) { + JavaTestDescriptor javaTestDescription = (JavaTestDescriptor) testDescription; + Class testClass = javaTestDescription.getTestClass(); Constructor constructor = testClass.getDeclaredConstructor(); constructor.setAccessible(true); Object testInstance = constructor.newInstance(); - Method method = testClass.getDeclaredMethod(javaMethodTestDescription.getMethodName()); + Method method = javaTestDescription.getTestMethod(); method.setAccessible(true); try { method.invoke(testInstance); } catch (Exception e) { - System.out.println("Test failed: " + javaMethodTestDescription.getMethodName()); + System.out.println("Test failed: " + method.getName()); e.printStackTrace(System.out); } } diff --git a/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaMethodTestDescription.java b/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaMethodTestDescription.java deleted file mode 100644 index 6329370744c..00000000000 --- a/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaMethodTestDescription.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.junit.gen5.engine.junit5; - -import org.junit.gen5.engine.EngineTestDescription; - -public class JavaMethodTestDescription implements EngineTestDescription { - - private final String className; - private final String methodName; - - public JavaMethodTestDescription(String className, String methodName) { - this.className = className; - this.methodName = methodName; - } - - public String getClassName() { - return className; - } - - public String getMethodName() { - return methodName; - } - - public String getId() { - return getClassName() + ":" + getMethodName(); - } - - public String getDisplayName() { - return getClassName() + ":" + getMethodName(); - } - -} diff --git a/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaTestDescriptor.java b/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaTestDescriptor.java new file mode 100644 index 00000000000..e952196f44e --- /dev/null +++ b/junit5-engine/src/main/java/org/junit/gen5/engine/junit5/JavaTestDescriptor.java @@ -0,0 +1,175 @@ + +package org.junit.gen5.engine.junit5; + +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; +import static org.junit.gen5.commons.util.ObjectUtils.nullSafeToString; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.gen5.api.Test; +import org.junit.gen5.commons.util.ObjectUtils; +import org.junit.gen5.commons.util.Preconditions; +import org.junit.gen5.engine.TestDescriptor; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * {@link TestDescriptor} for tests based on Java classes and methods. + * + *

The pattern of the {@link #getTestId test ID} takes the form of + * {fully qualified class name}#{method name}({comma separated list + * of method parameter types}), where each method parameter type is + * a fully qualified class name or a primitive type. For example, + * {@code org.example.MyTests#test()} references the {@code test()} method + * in the {@code org.example.MyTests} class that does not accept parameters. + * Similarly, {@code org.example.MyTests#test(java.lang.String, java.math.BigDecimal)} + * references the {@code test()} method in the {@code org.example.MyTests} + * class that requires a {@code String} and {@code BigDecimal} as parameters. + * + * @author Sam Brannen + * @since 5.0 + */ +@Data +@EqualsAndHashCode +public class JavaTestDescriptor implements TestDescriptor { + + // The following pattern only supports descriptors for test methods. + // TODO Support descriptors for test classes. + // TODO Decide if we want to support descriptors for packages. + private static final Pattern UID_PATTERN = Pattern.compile("^(.+):(.+)#(.+)\\((.*)\\)$"); + + + private final String id; + + private final String engineId; + + private final String testId; + + private final String displayName; + + private final TestDescriptor parent; + + private final List children; + + private final Class testClass; + + private final Method testMethod; + + private final boolean dynamic; + + + public JavaTestDescriptor(String engineId, Method testMethod) { + this(engineId, null, testMethod, false, null, null); + } + + public JavaTestDescriptor(String engineId, Class testClass, Method testMethod) { + this(engineId, testClass, testMethod, false, null, null); + } + + public JavaTestDescriptor(String engineId, Class testClass, Method testMethod, boolean dynamic, + TestDescriptor parent, List children) { + + Preconditions.notEmpty(engineId, "engineId must not be null or empty"); + if (testMethod == null) { + Preconditions.notNull(testClass, "testClass must not be null"); + } else { + Preconditions.notNull(testMethod, "testMethod must not be null"); + testClass = testMethod.getDeclaringClass(); + } + + this.testClass = testClass; + this.testMethod = testMethod; + this.dynamic = dynamic; + this.displayName = determineDisplayName(testClass, testMethod); + this.parent = parent; + this.children = (children != null ? unmodifiableList(children) : emptyList()); + this.engineId = engineId; + this.testId = createTestId(testClass, testMethod); + this.id = this.engineId + ":" + this.testId; + } + + + @Override + public boolean isRoot() { + return (getParent() == null); + } + + @Override + public boolean isNode() { + return !isLeaf(); + } + + @Override + public boolean isLeaf() { + return getChildren().isEmpty(); + } + + public static JavaTestDescriptor from(final String uid) throws Exception { + Preconditions.notNull(uid, "TestDescriptor UID must not be null"); + + Matcher matcher = UID_PATTERN.matcher(uid); + Preconditions.condition(matcher.matches(), () -> + String.format("Invalid format for %s UID: %s", JavaTestDescriptor.class.getSimpleName(), uid)); + + // TODO Validate contents of matched groups. + String engineId = matcher.group(1); + String className = matcher.group(2); + String methodName = matcher.group(3); + String methodParameters = matcher.group(4); + + Class clazz = loadClass(className); + + System.out.println("DEBUG - method params: " + methodParameters); + + List> paramTypeList = new ArrayList<>(); + for (String type : methodParameters.split(",")) { + type = type.trim(); + if (!type.isEmpty()) { + paramTypeList.add(loadClass(type)); + } + } + + Class[] parameterTypes = paramTypeList.toArray(new Class[paramTypeList.size()]); + Method method = clazz.getDeclaredMethod(methodName, parameterTypes); + + return new JavaTestDescriptor(engineId, clazz, method); + } + + private static Class loadClass(String name) { + try { + // TODO Add support for primitive types and arrays. + return JavaTestDescriptor.class.getClassLoader().loadClass(name); + } + catch (ClassNotFoundException e) { + throw new IllegalStateException("Failed to load class with name '" + name + "'."); + } + } + + private static String createTestId(Class testClass, Method testMethod) { + return (testMethod != null ? String.format("%s#%s(%s)", testClass.getName(), testMethod.getName(), + nullSafeToString(testMethod.getParameterTypes())) : testClass.getName()); + } + + private static String determineDisplayName(Class testClass, Method testMethod) { + if (testMethod != null) { + Test test = testMethod.getAnnotation(Test.class); + if (test != null) { + String customName = test.name(); + if (!ObjectUtils.isEmpty(customName)) { + return customName; + } + } + return testMethod.getName(); + } + else { + return testClass.getSimpleName(); + } + } + +} diff --git a/junit5-engine/src/test/java/org/junit/gen5/engine/junit5/JavaTestDescriptorTests.java b/junit5-engine/src/test/java/org/junit/gen5/engine/junit5/JavaTestDescriptorTests.java new file mode 100644 index 00000000000..d12bf3a30df --- /dev/null +++ b/junit5-engine/src/test/java/org/junit/gen5/engine/junit5/JavaTestDescriptorTests.java @@ -0,0 +1,98 @@ + +package org.junit.gen5.engine.junit5; + +import static org.junit.gen5.api.Assertions.*; + +import java.lang.reflect.Method; +import java.math.BigDecimal; + +import org.junit.gen5.api.Test; + +/** + * Unit tests for {@link JavaTestDescriptor}. + * + * @author Sam Brannen + * @since 5.0 + */ +public class JavaTestDescriptorTests { + + private static final String JUNIT_5_ENGINE_ID = "junit5"; + + private static final String TEST_METHOD_ID = JavaTestDescriptorTests.class.getName() + "#test()"; + private static final String TEST_METHOD_UID = JUNIT_5_ENGINE_ID + ":" + TEST_METHOD_ID; + + private static final String TEST_METHOD_STRING_BIGDECIMAL_ID = JavaTestDescriptorTests.class.getName() + + "#test(java.lang.String, java.math.BigDecimal)"; + private static final String TEST_METHOD_STRING_BIGDECIMAL_UID = JUNIT_5_ENGINE_ID + ":" + TEST_METHOD_STRING_BIGDECIMAL_ID; + + + @org.junit.Test + public void constructFromMethod() throws Exception { + Method testMethod = getClass().getDeclaredMethod("test"); + JavaTestDescriptor descriptor = new JavaTestDescriptor(JUNIT_5_ENGINE_ID, testMethod); + + System.out.println("DEBUG - " + descriptor); + assertEqual(JUNIT_5_ENGINE_ID, descriptor.getEngineId()); + assertEqual(TEST_METHOD_ID, descriptor.getTestId()); + assertEqual(TEST_METHOD_UID, descriptor.getId()); + assertEqual(getClass(), descriptor.getTestClass()); + assertEqual(testMethod, descriptor.getTestMethod()); + assertEqual("test", descriptor.getDisplayName(), "display name:"); + } + + @org.junit.Test + public void constructFromMethodWithCustomDisplayName() throws Exception { + Method testMethod = getClass().getDeclaredMethod("foo"); + JavaTestDescriptor descriptor = new JavaTestDescriptor(JUNIT_5_ENGINE_ID, testMethod); + + System.out.println("DEBUG - " + descriptor); + assertEqual(JUNIT_5_ENGINE_ID, descriptor.getEngineId()); + assertEqual(getClass(), descriptor.getTestClass()); + assertEqual(testMethod, descriptor.getTestMethod()); + assertEqual("custom test name", descriptor.getDisplayName(), "display name:"); + } + + @org.junit.Test + public void constructFromMethodWithParameters() throws Exception { + Method testMethod = getClass().getDeclaredMethod("test", String.class, BigDecimal.class); + JavaTestDescriptor descriptor = new JavaTestDescriptor(JUNIT_5_ENGINE_ID, testMethod); + + System.out.println("DEBUG - " + descriptor); + assertEqual(JUNIT_5_ENGINE_ID, descriptor.getEngineId()); + assertEqual(TEST_METHOD_STRING_BIGDECIMAL_ID, descriptor.getTestId()); + assertEqual(TEST_METHOD_STRING_BIGDECIMAL_UID, descriptor.getId()); + assertEqual(getClass(), descriptor.getTestClass()); + assertEqual(testMethod, descriptor.getTestMethod()); + assertEqual("test", descriptor.getDisplayName(), "display name:"); + } + + @org.junit.Test + public void fromTestDescriptorIdForMethod() throws Exception { + JavaTestDescriptor descriptor = JavaTestDescriptor.from(TEST_METHOD_UID); + assertNotNull(descriptor, "descriptor:"); + assertEqual("test", descriptor.getDisplayName(), "display name:"); + assertEqual(JavaTestDescriptorTests.class, descriptor.getTestClass()); + assertEqual(JavaTestDescriptorTests.class.getDeclaredMethod("test"), descriptor.getTestMethod()); + } + + @org.junit.Test + public void fromTestDescriptorIdForMethodWithParameters() throws Exception { + JavaTestDescriptor descriptor = JavaTestDescriptor.from(TEST_METHOD_STRING_BIGDECIMAL_UID); + assertNotNull(descriptor, "descriptor:"); + assertEqual("test", descriptor.getDisplayName(), "display name:"); + assertEqual(getClass(), descriptor.getTestClass()); + assertEqual(getClass().getDeclaredMethod("test", String.class, BigDecimal.class), descriptor.getTestMethod()); + } + + + void test() { + } + + void test(String txt, BigDecimal sum) { + } + + @Test(name = "custom test name") + void foo() { + } + +} diff --git a/old-junit-core/build.gradle b/old-junit-core/build.gradle deleted file mode 100644 index 2ce1a93fe35..00000000000 --- a/old-junit-core/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - compile(project(':open-test-alliance')) -} diff --git a/open-test-alliance/src/main/java/org/opentestalliance/AssertionFailedException.java b/open-test-alliance/src/main/java/org/opentestalliance/AssertionFailedError.java similarity index 67% rename from open-test-alliance/src/main/java/org/opentestalliance/AssertionFailedException.java rename to open-test-alliance/src/main/java/org/opentestalliance/AssertionFailedError.java index a7c7343600a..5df6f1a06e4 100644 --- a/open-test-alliance/src/main/java/org/opentestalliance/AssertionFailedException.java +++ b/open-test-alliance/src/main/java/org/opentestalliance/AssertionFailedError.java @@ -20,53 +20,59 @@ * @author Sam Brannen * @since 1.0 */ -public class AssertionFailedException extends AssertionError { +public class AssertionFailedError extends AssertionError { private static final long serialVersionUID = 3170879295749989795L; + /** + * Undefined object, used to differentiate between a {@code null} + * default value and a user-supplied {@code null} value. + */ private static final Object UNDEFINED = new Object(); + private final Object expected; private final Object actual; - public AssertionFailedException() { + + public AssertionFailedError() { this((String) null); } - public AssertionFailedException(String message) { + public AssertionFailedError(String message) { this(message, UNDEFINED, UNDEFINED); } - public AssertionFailedException(String message, Object expected, Object actual) { + public AssertionFailedError(String message, Object expected, Object actual) { super(message); this.expected = expected; this.actual = actual; } - public AssertionFailedException(String message, Throwable cause) { + public AssertionFailedError(String message, Throwable cause) { this(message, UNDEFINED, UNDEFINED, cause); } - public AssertionFailedException(String message, Object expected, Object actual, Throwable cause) { + public AssertionFailedError(String message, Object expected, Object actual, Throwable cause) { super(message, cause); this.expected = expected; this.actual = actual; } - public boolean isExpectedValueDefined() { + public boolean isExpectedDefined() { return (this.expected != UNDEFINED); } - public boolean isActualValueDefined() { + public boolean isActualDefined() { return (this.actual != UNDEFINED); } - public Object getExpectedValue() { + public Object getExpected() { return (this.expected == UNDEFINED ? null : this.expected); } - public Object getActualValue() { + public Object getActual() { return (this.actual == UNDEFINED ? null : this.actual); } diff --git a/open-test-alliance/src/main/java/org/opentestalliance/TestAbortedException.java b/open-test-alliance/src/main/java/org/opentestalliance/TestAbortedException.java index ddfdbc2e408..e96f6875921 100644 --- a/open-test-alliance/src/main/java/org/opentestalliance/TestAbortedException.java +++ b/open-test-alliance/src/main/java/org/opentestalliance/TestAbortedException.java @@ -17,6 +17,9 @@ package org.opentestalliance; /** + * {@link RuntimeException} used to indicate that a test was aborted, either + * prior to or during execution. + * * @author Sam Brannen * @since 1.0 */ @@ -24,6 +27,7 @@ public class TestAbortedException extends RuntimeException { private static final long serialVersionUID = -5277362515874754471L; + public TestAbortedException() { } diff --git a/open-test-alliance/src/main/java/org/opentestalliance/TestSkippedException.java b/open-test-alliance/src/main/java/org/opentestalliance/TestSkippedException.java index a1f1a8ea821..99db74be2b9 100644 --- a/open-test-alliance/src/main/java/org/opentestalliance/TestSkippedException.java +++ b/open-test-alliance/src/main/java/org/opentestalliance/TestSkippedException.java @@ -17,13 +17,18 @@ package org.opentestalliance; /** + * Specialization of {@link TestAbortedException}, used to indicate that a + * test was aborted prior to execution (i.e., skipped or + * ignored). + * * @author Sam Brannen * @since 1.0 */ -public class TestSkippedException extends RuntimeException { +public class TestSkippedException extends TestAbortedException { private static final long serialVersionUID = -2632738154006239247L; + public TestSkippedException() { } diff --git a/sample-project/src/test/java/com/example/SampleTest.java b/sample-project/src/test/java/com/example/SampleTestCase.java similarity index 72% rename from sample-project/src/test/java/com/example/SampleTest.java rename to sample-project/src/test/java/com/example/SampleTestCase.java index 5ee4be0a3a0..1e6d50af2d3 100644 --- a/sample-project/src/test/java/com/example/SampleTest.java +++ b/sample-project/src/test/java/com/example/SampleTestCase.java @@ -2,7 +2,10 @@ import org.junit.gen5.api.Test; -class SampleTest { +/** + * Named *TestCase so Gradle will not try to run it. + */ +class SampleTestCase { @Test void failingTest() { diff --git a/settings.gradle b/settings.gradle index e4d1c8005d5..404dd243b47 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,6 @@ rootProject.name = "junit-lambda" +include "junit-commons" include "junit-console" include "junit-engine-api" include "junit-launcher" @@ -8,7 +9,6 @@ include "junit4-engine" include "junit5-api" include "junit5-engine" include "open-test-alliance" -include "old-junit-core" include "sample-extension" include "sample-project"