pl.hiber.testcase.runners.TestCaseRunner Maven / Gradle / Ivy
package pl.hiber.testcase.runners;
import org.junit.rules.RunRules;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;
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 pl.hiber.testcase.annotations.TestCase;
import pl.hiber.testcase.runners.inner.InnerTestCaseRunner;
import java.util.*;
/**
* Created 2014 by 4ib3r
* TestCaseRunner is simple runner which allows to run tests with defined test cases.
* Test case is defined by method with annotation {@link pl.hiber.testcase.annotations.TestCase}
* with minimum one parameter (test class and/or self class) eg.:
* {@code
@TestCase
public void testCase1(TestCaseRunnerOrderTest test) {
test.test1();
test.test2();
test.test3();
test.test4();
}}
This method only describe test's flow.
*/
public class TestCaseRunner extends ParentRunner {
/** Test cases list */
private List testCaseList;
/** Test instance */
private Object testInstance;
private Map otherTestInstances;
protected Object getTestInstance() {
return testInstance;
}
protected Map getOtherTestInstances() {
return otherTestInstances;
}
/** Constructor for run all test case's in test class */
public TestCaseRunner(Class> type) throws InitializationError {
super(type);
validateConstructorAndAnnotations(type);
otherTestInstances = new HashMap(1,1);
List testCaseMethods = getTestClass().getAnnotatedMethods(TestCase.class);
testCaseList = new ArrayList(testCaseMethods.size());
try {
testInstance = createTestInstance();
for(FrameworkMethod frameworkMethod : testCaseMethods) {
validate(frameworkMethod);
testCaseList.add(prepareInnerTestCaseRunner(type, frameworkMethod));
}
} catch (Throwable e) {
throw new InitializationError(e);
}
}
protected InnerTestCaseRunner prepareInnerTestCaseRunner(Class> type, FrameworkMethod frameworkMethod) throws InitializationError {
InnerTestCaseRunner innerTestCaseRunner = new InnerTestCaseRunner(type, frameworkMethod, testInstance, otherTestInstances);
innerTestCaseRunner.buildActionsList();
return innerTestCaseRunner;
}
/** Create test class instance */
protected Object createTestInstance() throws Exception {
return getTestClass().getOnlyConstructor().newInstance();
}
/** Test class constructor validation */
protected void validateConstructorAndAnnotations(Class> type) throws InitializationError {
if (type.getConstructors().length != 1) {
throw new InitializationError("Test class " + type.getName() + " must have only one public constructor");
}
RunWith runWith = type.getAnnotation(RunWith.class);
if (runWith != null && runWith.value() != TestCaseRunner.class) {
throw new InitializationError("Test class " + type.getName() + " must be annotated with @RunWith(TestCaseRunner.class)");
}
}
/** Methods validation */
private void validate(FrameworkMethod frameworkMethod) throws InitializationError {
List errors = new ArrayList();
validateTestCasePublicVoidMethod(frameworkMethod, errors);
if (!errors.isEmpty()) {
throw new InitializationError(errors);
}
}
/** Validation test case methods, all methods should have one or more parameters */
public void validateTestCasePublicVoidMethod(FrameworkMethod fMethod, List errors) {
fMethod.validatePublicVoid(false, errors);
/*if (fMethod.getMethod().getParameterTypes().length < 1) {
errors.add(new Exception("Method " + fMethod.getName() + " should have parameters"));
}*/
}
/** Simplified tests filtering */
@Override
public void filter(Filter filter) throws NoTestsRemainException {
Iterator runnerIterator = testCaseList.iterator();
while (runnerIterator.hasNext()) {
Runner runner = runnerIterator.next();
if (!filter.describe().contains(runner.getDescription().getDisplayName())) {
runnerIterator.remove();
}
}
}
/** Get children's, return test case's list */
@Override
protected List getChildren() {
return testCaseList;
}
/** Describe test case */
@Override
protected Description describeChild(Runner child) {
return child.getDescription();
}
/** Run one test case */
@Override
protected void runChild(Runner child, RunNotifier notifier) {
child.run(notifier);
}
/** Build test case run block, run before/after classes and apply rules */
@Override
protected Statement classBlock(final RunNotifier notifier) {
Statement statement = childrenInvoker(notifier);
statement = withBeforeClasses(statement);
statement = withAfterClasses(statement);
statement = withClassRules(statement);
return statement;
}
/** Apply rules */
private Statement withClassRules(Statement statement) {
List classRules = classRules();
return classRules.isEmpty() ? statement :
new RunRules(statement, classRules, getDescription());
}
}