forked from phoedos/pmd
Create a new JUnit test runner to execute rule tests
This runner now also supports Before, After, and (JUnit) Rules.
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.testframework;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.internal.runners.statements.RunAfters;
|
||||
import org.junit.internal.runners.statements.RunBefores;
|
||||
import org.junit.rules.RunRules;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.junit.runners.ParentRunner;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
import org.junit.runners.model.InitializationError;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
|
||||
/**
|
||||
* A JUnit Runner, that executes all declared rule tests in the class.
|
||||
* It supports Before and After methods as well as TestRules.
|
||||
*
|
||||
* @author Andreas Dangel
|
||||
*/
|
||||
public class RuleTestRunner extends ParentRunner<TestDescriptor> {
|
||||
private ConcurrentHashMap<TestDescriptor, Description> testDescriptions = new ConcurrentHashMap<>();
|
||||
private final SimpleAggregatorTst instance;
|
||||
|
||||
public RuleTestRunner(Class<?> testClass) throws InitializationError {
|
||||
super(testClass);
|
||||
instance = createTestClass();
|
||||
instance.setUp();
|
||||
}
|
||||
|
||||
protected Description describeChild(TestDescriptor testCase) {
|
||||
Description description = testDescriptions.get(testCase);
|
||||
if (description == null) {
|
||||
description = Description.createTestDescription(getTestClass().getJavaClass(),
|
||||
testCase.getRule().getName() + "::"
|
||||
+ testCase.getNumberInDocument() + " "
|
||||
+ testCase.getDescription().replaceAll("\n|\r", " "));
|
||||
testDescriptions.putIfAbsent(testCase, description);
|
||||
}
|
||||
return description;
|
||||
};
|
||||
|
||||
@Override
|
||||
protected List<TestDescriptor> getChildren() {
|
||||
List<Rule> rules = new ArrayList<>(instance.getRules());
|
||||
Collections.sort(rules, new Comparator<Rule>() {
|
||||
@Override
|
||||
public int compare(Rule o1, Rule o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
List<TestDescriptor> tests = new LinkedList<>();
|
||||
for (Rule r : rules) {
|
||||
TestDescriptor[] ruleTests = instance.extractTestsFromXml(r);
|
||||
for (TestDescriptor t : ruleTests) {
|
||||
tests.add(t);
|
||||
}
|
||||
}
|
||||
|
||||
return tests;
|
||||
}
|
||||
|
||||
private SimpleAggregatorTst createTestClass() throws InitializationError {
|
||||
try {
|
||||
return (SimpleAggregatorTst)getTestClass().getOnlyConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new InitializationError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runChild(TestDescriptor testCase, RunNotifier notifier) {
|
||||
Description description = describeChild(testCase);
|
||||
if (isIgnored(testCase)) {
|
||||
notifier.fireTestIgnored(description);
|
||||
} else {
|
||||
runLeaf(ruleTestBlock(testCase), description, notifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the actual test case. If there are Before, After, or TestRules present,
|
||||
* they are executed accordingly.
|
||||
*
|
||||
* @param testCase the PMD rule test case to be executed
|
||||
* @return a single statement which includes any rules, if present.
|
||||
*/
|
||||
private Statement ruleTestBlock(final TestDescriptor testCase) {
|
||||
Statement statement = new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
instance.runTest(testCase);
|
||||
}
|
||||
};
|
||||
statement = withBefores(testCase, statement);
|
||||
statement = withAfters(testCase, statement);
|
||||
statement = withRules(testCase, statement);
|
||||
return statement;
|
||||
}
|
||||
|
||||
private Statement withBefores(final TestDescriptor testCase, Statement statement) {
|
||||
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(Before.class);
|
||||
return befores.isEmpty() ? statement : new RunBefores(statement, befores, instance);
|
||||
}
|
||||
|
||||
private Statement withAfters(final TestDescriptor testCase, Statement statement) {
|
||||
List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(After.class);
|
||||
return afters.isEmpty() ? statement : new RunAfters(statement, afters, instance);
|
||||
}
|
||||
|
||||
private Statement withRules(final TestDescriptor testCase, Statement statement) {
|
||||
List<TestRule> testRules = getTestClass().getAnnotatedFieldValues(instance, org.junit.Rule.class, TestRule.class);
|
||||
return testRules.isEmpty() ? statement : new RunRules(statement, testRules, describeChild(testCase));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isIgnored(TestDescriptor child) {
|
||||
return TestDescriptor.inRegressionTestMode() && !child.isRegressionTest();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user