diff --git a/src/main/java/com/nordstrom/automation/junit/AtomicTest.java b/src/main/java/com/nordstrom/automation/junit/AtomicTest.java index ff3e34a..ed4fa14 100644 --- a/src/main/java/com/nordstrom/automation/junit/AtomicTest.java +++ b/src/main/java/com/nordstrom/automation/junit/AtomicTest.java @@ -1,18 +1,8 @@ package com.nordstrom.automation.junit; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.junit.After; import org.junit.AfterClass; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.theories.Theory; @@ -20,6 +10,14 @@ import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.TestClass; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * This class represents an atomic JUnit test, which is composed of a core {@link Test @Test} method and * the configuration methods that run with it ({@link Before @Before}, {@link org.junit.After @After}, @@ -33,10 +31,10 @@ public class AtomicTest { private FrameworkMethod identity; private final List particles; private Throwable thrown; - + private static final Pattern PARAM = Pattern.compile("[(\\[]"); private static final List> TEST_TYPES = Arrays.asList(Test.class, Theory.class); - + public AtomicTest(Description description) { this.runner = Run.getThreadRunner(); this.description = description; @@ -46,7 +44,7 @@ public AtomicTest(Description description) { /** * Get the runner for this atomic test. - * + * * @return {@code BlockJUnit4ClassRunner} object */ public Object getRunner() { @@ -55,13 +53,13 @@ public Object getRunner() { /** * Get the description for this atomic test. - * + * * @return {@link Description} object */ public Description getDescription() { return description; } - + /** * Set the "identity" method for this atomic test - the core {@link Test @Test} method. */ @@ -72,16 +70,16 @@ void setIdentity(FrameworkMethod method) { /** * Get the "identity" method for this atomic test - the core {@link Test @Test} method. - * + * * @return core method associated with this atomic test (may be {@code null}) */ public FrameworkMethod getIdentity() { return identity; } - + /** * Get the "particle" methods of which this atomic test is composed. - * + * * @return list of methods that compose this atomic test (may be empty) */ public List getParticles() { @@ -90,82 +88,82 @@ public List getParticles() { /** * Determine if this atomic test includes configuration methods. - * + * * @return {@code true} if this atomic test includes configuration; otherwise {@code false} */ public boolean hasConfiguration() { return (particles.size() > 1); } - + /** * Set the exception for this atomic test. - * + * * @param thrown exception for this atomic test */ void setThrowable(Throwable thrown) { this.thrown = thrown; } - + /** * Get the exception for this atomic test. - * + * * @return exception for this atomic test; {@code null} if test finished normally */ public Throwable getThrowable() { return thrown; } - + /** * Determine if this atomic test includes the specified method. - * + * * @param method method object * @return {@code true} if this atomic test includes the specified method; otherwise {@code false} */ public boolean includes(FrameworkMethod method) { return particles.contains(method); } - + /** * Determine if this atomic test represents a "theory" method permutation. - * + * * @return {@code true} if this atomic test represents a permutation; otherwise {@code false} */ public boolean isTheory() { return isTheory(description); } - + /** * Determine if the specified description represents a "theory" method permutation. - * + * * @param description JUnit method description * @return {@code true} if the specified description represents a permutation; otherwise {@code false} */ public static boolean isTheory(Description description) { return DescribeChild.isPermutation(description); } - + /** * Determine if this atomic test represents a test method. - * - * @return {@code true} if this atomic test represents a test method; otherwise {@code false} + * + * @return {@code true} if this atomic test represents a test method; otherwise {@code false} */ public boolean isTest() { return isTest(description); } - + /** * Determine if the specified description represents a test method. - * + * * @param description JUnit description object - * @return {@code true} if description represents a test method; otherwise {@code false} + * @return {@code true} if description represents a test method; otherwise {@code false} */ public static boolean isTest(Description description) { return (getTestAnnotation(description) != null); } - + /** * Get the annotation that marks the specified description as a test method. - * + * * @param description JUnit description object * @return if description represents a test method, the {@link Test} or {@link Theory} annotation; * otherwise {@code null} @@ -176,7 +174,7 @@ public static Annotation getTestAnnotation(Description description) { } return null; } - + /** * {@inheritDoc} */ @@ -205,10 +203,10 @@ public boolean equals(Object o) { public int hashCode() { return description.hashCode(); } - + /** * Get the "particle" method for this atomic test. - * + * * @param runner JUnit test runner * @param description JUnit method description * @return list of "particle" methods (may be empty) @@ -216,31 +214,39 @@ public int hashCode() { private List getParticles(Object runner, Description description) { List particles = new ArrayList<>(); if (isTest(description)) { - TestClass testClass = LifecycleHooks.getTestClassOf(runner); - - String methodName = description.getMethodName(); - Matcher matcher = PARAM.matcher(methodName); - if (matcher.find()) { - methodName = methodName.substring(0, matcher.start()); - } - + TestClass testClass = LifecycleHooks.getTestClassOf(runner); String descriptionMethodName = description.getMethodName(); FrameworkMethod identity = null; + // Try exact match first for (FrameworkMethod method : testClass.getAnnotatedMethods()) { - if (method.getName().equals(methodName)) { + if (descriptionMethodName.equals(method.getName())) { identity = method; break; } } - + // Fall back to parameter stripping if needed + if (identity == null) { + String fallbackMethodName = descriptionMethodName; + Matcher matcher = PARAM.matcher(fallbackMethodName); + if (matcher.find()) { + fallbackMethodName = fallbackMethodName.substring(0, matcher.start()); + } + for (FrameworkMethod method : testClass.getAnnotatedMethods()) { + if (method.getName().equals(fallbackMethodName)) { + identity = method; + break; + } + } + } if (identity != null) { particles.add(identity); particles.addAll(testClass.getAnnotatedMethods(Before.class)); particles.addAll(testClass.getAnnotatedMethods(After.class)); } else { - throw new IllegalStateException("Identity method not found"); + throw new IllegalStateException( + "Identity method not found for: " + descriptionMethodName + ); } } - return particles; } }