Skip to content

Fix method name matching in getParticles() #143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 58 additions & 52 deletions src/main/java/com/nordstrom/automation/junit/AtomicTest.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
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;
import org.junit.runner.Description;
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},
Expand All @@ -33,10 +31,10 @@ public class AtomicTest {
private FrameworkMethod identity;
private final List<FrameworkMethod> particles;
private Throwable thrown;

private static final Pattern PARAM = Pattern.compile("[(\\[]");
private static final List<Class<? extends Annotation>> TEST_TYPES = Arrays.asList(Test.class, Theory.class);

public AtomicTest(Description description) {
this.runner = Run.getThreadRunner();
this.description = description;
Expand All @@ -46,7 +44,7 @@ public AtomicTest(Description description) {

/**
* Get the runner for this atomic test.
*
*
* @return {@code BlockJUnit4ClassRunner} object
*/
public Object getRunner() {
Expand All @@ -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 &#64;Test} method.
*/
Expand All @@ -72,16 +70,16 @@ void setIdentity(FrameworkMethod method) {

/**
* Get the "identity" method for this atomic test - the core {@link Test &#64;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<FrameworkMethod> getParticles() {
Expand All @@ -90,82 +88,82 @@ public List<FrameworkMethod> 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}
Expand All @@ -176,7 +174,7 @@ public static Annotation getTestAnnotation(Description description) {
}
return null;
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -205,42 +203,50 @@ 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)
*/
private List<FrameworkMethod> getParticles(Object runner, Description description) {
List<FrameworkMethod> 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;
}
}