forked from phoedos/pmd
Extract test framework into own sub-module
This commit is contained in:
24
pmd-test/pom.xml
Normal file
24
pmd-test/pom.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>pmd-test</artifactId>
|
||||
<name>PMD Test Framework</name>
|
||||
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd-aggregate</artifactId>
|
||||
<version>5.1.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.testframework;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.cpd.SourceCode;
|
||||
import net.sourceforge.pmd.cpd.TokenEntry;
|
||||
import net.sourceforge.pmd.cpd.Tokenizer;
|
||||
import net.sourceforge.pmd.cpd.Tokens;
|
||||
|
||||
/**
|
||||
* @author Romain PELISSE, belaran@gmail.com
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractTokenizerTest {
|
||||
|
||||
protected int expectedTokenCount;
|
||||
protected Tokenizer tokenizer;
|
||||
protected SourceCode sourceCode;
|
||||
|
||||
public abstract void buildTokenizer();
|
||||
|
||||
public abstract String getSampleCode();
|
||||
|
||||
protected void tokenizeTest() throws IOException {
|
||||
Tokens tokens = new Tokens();
|
||||
tokenizer.tokenize(sourceCode, tokens);
|
||||
List<TokenEntry> entries = tokens.getTokens();
|
||||
assertEquals(expectedTokenCount,entries.size());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* 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.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runner.manipulation.Filter;
|
||||
import org.junit.runner.manipulation.Filterable;
|
||||
import org.junit.runner.manipulation.NoTestsRemainException;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||
import org.junit.runners.model.InitializationError;
|
||||
import org.junit.runners.model.TestClass;
|
||||
|
||||
/**
|
||||
* A test runner for rule tests. Unlike {@link SimpleAggregatorTst.CustomXmlTestClassMethodsRunner}
|
||||
* it also reports the successful executed tests and allows to selectively execute single test cases
|
||||
* (it is {@link Filterable}).
|
||||
* <p>
|
||||
* In order to use it, you'll need to subclass {@link SimpleAggregatorTst} and annotate your test
|
||||
* class with RunWith:
|
||||
* <pre>
|
||||
* {@code @}RunWith(PMDTestRunner.class)
|
||||
* public class MyRuleSetTest extends SimpleAggregatorTst {
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public class PMDTestRunner extends Runner implements Filterable {
|
||||
private final Description desc;
|
||||
private final Class<? extends SimpleAggregatorTst> klass;
|
||||
private final List<TestDescriptor> allTests = new ArrayList<TestDescriptor>();
|
||||
private BlockJUnit4ClassRunner chainedRunner;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PMDTestRunner} for the given test class.
|
||||
* @param klass the test class that is under test
|
||||
* @throws InitializationError any error
|
||||
*/
|
||||
public PMDTestRunner(final Class<? extends SimpleAggregatorTst> klass) throws InitializationError {
|
||||
this.klass = klass;
|
||||
|
||||
desc = Description.createSuiteDescription(klass);
|
||||
configureRuleTests();
|
||||
configureUnitTests();
|
||||
}
|
||||
|
||||
private void configureRuleTests() throws InitializationError {
|
||||
Description root = Description.createSuiteDescription("Rule Tests");
|
||||
try {
|
||||
SimpleAggregatorTst test = createTestClass();
|
||||
test.setUp();
|
||||
|
||||
List<Rule> rules = new ArrayList<Rule>(test.getRules());
|
||||
Collections.sort(rules, new Comparator<Rule>() {
|
||||
@Override
|
||||
public int compare(Rule o1, Rule o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
for (Rule r : rules) {
|
||||
Description ruleDescription = Description.createSuiteDescription(r.getName());
|
||||
root.addChild(ruleDescription);
|
||||
|
||||
TestDescriptor[] ruleTests = test.extractTestsFromXml(r);
|
||||
for (TestDescriptor t : ruleTests) {
|
||||
Description d = createTestDescription(t);
|
||||
ruleDescription.addChild(d);
|
||||
allTests.add(t);
|
||||
}
|
||||
}
|
||||
if (!root.getChildren().isEmpty()) {
|
||||
desc.addChild(root);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new InitializationError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private SimpleAggregatorTst createTestClass() {
|
||||
try {
|
||||
return klass.getConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void configureUnitTests() throws InitializationError {
|
||||
TestClass tclass = new TestClass(klass);
|
||||
if (!tclass.getAnnotatedMethods(Test.class).isEmpty()) {
|
||||
Description unitTests = Description.createSuiteDescription("Unit tests");
|
||||
chainedRunner = new BlockJUnit4ClassRunner(klass);
|
||||
for (Description d : chainedRunner.getDescription().getChildren()) {
|
||||
unitTests.addChild(d);
|
||||
}
|
||||
desc.addChild(unitTests);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description getDescription() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(RunNotifier notifier) {
|
||||
SimpleAggregatorTst test = createTestClass();
|
||||
boolean regressionTestMode = TestDescriptor.inRegressionTestMode();
|
||||
|
||||
for (TestDescriptor t : allTests) {
|
||||
Description d = createTestDescription(t);
|
||||
notifier.fireTestStarted(d);
|
||||
try {
|
||||
if (!regressionTestMode || t.isRegressionTest()) {
|
||||
test.runTest(t);
|
||||
} else {
|
||||
notifier.fireTestIgnored(d);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
notifier.fireTestFailure(new Failure(d, e));
|
||||
} finally {
|
||||
notifier.fireTestFinished(d);
|
||||
}
|
||||
}
|
||||
if (chainedRunner != null) {
|
||||
chainedRunner.run(notifier);
|
||||
}
|
||||
}
|
||||
|
||||
private Description createTestDescription(TestDescriptor t) {
|
||||
String d = t.getDescription().replaceAll("\n|\r", " ");
|
||||
return Description.createTestDescription(klass, t.getRule().getName() + "::" + t.getNumberInDocument() + " " + d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(Filter filter) throws NoTestsRemainException {
|
||||
Iterator<TestDescriptor> it = allTests.iterator();
|
||||
while (it.hasNext()) {
|
||||
TestDescriptor t = it.next();
|
||||
Description testDesc = createTestDescription(t);
|
||||
if (filter.shouldRun(testDesc)) {
|
||||
try {
|
||||
filter.apply(t);
|
||||
} catch (NoTestsRemainException e) {
|
||||
it.remove();
|
||||
}
|
||||
} else {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
boolean chainIsEmpty = false;
|
||||
try {
|
||||
if (chainedRunner != null) {
|
||||
chainedRunner.filter(filter);
|
||||
} else {
|
||||
chainIsEmpty = true;
|
||||
}
|
||||
} catch (NoTestsRemainException e) {
|
||||
chainIsEmpty = true;
|
||||
}
|
||||
|
||||
if (allTests.isEmpty() && chainIsEmpty) {
|
||||
throw new NoTestsRemainException();
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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.List;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Standard methods for (simple) testcases.
|
||||
*/
|
||||
@RunWith(PMDTestRunner.class)
|
||||
public abstract class SimpleAggregatorTst extends RuleTst {
|
||||
|
||||
/**
|
||||
* Configure the rule tests to be executed. Implement this method in
|
||||
* subclasses by calling adRule.
|
||||
*
|
||||
* @see #addRule(String, String)
|
||||
*/
|
||||
protected void setUp() {
|
||||
// empty, to be overridden
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a set of tests defined in an XML test-data file for a rule. The file
|
||||
* should be ./xml/RuleName.xml relative to the test-class. The format is
|
||||
* defined in test-data.xsd.
|
||||
*/
|
||||
public void runTests(Rule rule) {
|
||||
runTests(extractTestsFromXml(rule));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a set of tests defined in a XML test-data file. The file should be
|
||||
* ./xml/[testsFileName].xml relative to the test-class. The format is
|
||||
* defined in test-data.xsd.
|
||||
*/
|
||||
public void runTests(Rule rule, String testsFileName) {
|
||||
runTests(extractTestsFromXml(rule, testsFileName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a set of tests of a certain sourceType.
|
||||
*/
|
||||
public void runTests(TestDescriptor[] tests) {
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
runTest(tests[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Rule> rules = new ArrayList<Rule>();
|
||||
|
||||
/**
|
||||
* Add new XML tests associated with the rule to the test suite. This should
|
||||
* be called from the setup method.
|
||||
*/
|
||||
protected void addRule(String ruleSet, String ruleName) {
|
||||
rules.add(findRule(ruleSet, ruleName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all configured rules.
|
||||
*
|
||||
* @return all configured rules.
|
||||
*/
|
||||
protected List<Rule> getRules() {
|
||||
return rules;
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.testframework;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
|
||||
public class StreamUtil {
|
||||
|
||||
public static String toString(InputStream in) {
|
||||
if (in == null) {
|
||||
throw new NullPointerException("no input stream given");
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
try {
|
||||
while ((c = in.read()) != -1) {
|
||||
sb.append((char) c);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 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.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.lang.LanguageVersion;
|
||||
|
||||
import org.junit.Ignore;
|
||||
|
||||
/**
|
||||
* Stores the information required to run a complete test.
|
||||
*/
|
||||
@Ignore("this is not a unit test")
|
||||
public class TestDescriptor {
|
||||
private Rule rule;
|
||||
private Properties properties;
|
||||
private String description;
|
||||
private int numberOfProblemsExpected;
|
||||
private List<String> expectedMessages = new ArrayList<String>();
|
||||
private List<Integer> expectedLineNumbers = new ArrayList<Integer>();
|
||||
private String code;
|
||||
private LanguageVersion languageVersion;
|
||||
private boolean reinitializeRule = true; //default, avoids unintentional mixing of state between test cases
|
||||
private boolean isRegressionTest = true;
|
||||
private int numberInDocument = -1;
|
||||
|
||||
// Empty descriptor added to please mvn surefire plugin
|
||||
public TestDescriptor() {
|
||||
|
||||
}
|
||||
|
||||
public TestDescriptor(String code, String description, int numberOfProblemsExpected, Rule rule) {
|
||||
this(code, description, numberOfProblemsExpected, rule, RuleTst.DEFAULT_LANGUAGE_VERSION);
|
||||
}
|
||||
|
||||
public TestDescriptor(String code, String description, int numberOfProblemsExpected, Rule rule, LanguageVersion languageVersion) {
|
||||
this.rule = rule;
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.numberOfProblemsExpected = numberOfProblemsExpected;
|
||||
this.languageVersion = languageVersion;
|
||||
}
|
||||
|
||||
public int getNumberInDocument() {
|
||||
return numberInDocument;
|
||||
}
|
||||
|
||||
public void setNumberInDocument(int numberInDocument) {
|
||||
this.numberInDocument = numberInDocument;
|
||||
}
|
||||
|
||||
public void setExpectedMessages(List<String> messages) {
|
||||
expectedMessages.clear();
|
||||
expectedMessages.addAll(messages);
|
||||
}
|
||||
|
||||
public List<String> getExpectedMessages() {
|
||||
return expectedMessages;
|
||||
}
|
||||
|
||||
public void setExpectedLineNumbers(List<Integer> expectedLineNumbers) {
|
||||
this.expectedLineNumbers.clear();
|
||||
this.expectedLineNumbers.addAll(expectedLineNumbers);
|
||||
}
|
||||
|
||||
public List<Integer> getExpectedLineNumbers() {
|
||||
return expectedLineNumbers;
|
||||
}
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public LanguageVersion getLanguageVersion() {
|
||||
return languageVersion;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public int getNumberOfProblemsExpected() {
|
||||
return numberOfProblemsExpected;
|
||||
}
|
||||
|
||||
public Rule getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
public boolean getReinitializeRule() {
|
||||
return reinitializeRule;
|
||||
}
|
||||
|
||||
public void setReinitializeRule(boolean reinitializeRule) {
|
||||
this.reinitializeRule = reinitializeRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we are testing for regression problems only.
|
||||
* Return value is based on the system property "pmd.regress".
|
||||
*
|
||||
* @return <code>false</code> if system property "pmd.regress" is set to <code>false</code>, <code>true</code> otherwise
|
||||
*/
|
||||
public static boolean inRegressionTestMode() {
|
||||
boolean inRegressionMode = true; // default
|
||||
try {
|
||||
//get the "pmd.regress" System property
|
||||
String property = System.getProperty("pmd.regress");
|
||||
if (property != null) {
|
||||
inRegressionMode = Boolean.parseBoolean(property);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
|
||||
return inRegressionMode;
|
||||
}
|
||||
|
||||
public boolean isRegressionTest() {
|
||||
return isRegressionTest;
|
||||
}
|
||||
|
||||
public void setRegressionTest(boolean isRegressionTest) {
|
||||
this.isRegressionTest = isRegressionTest;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user