package restx.tests;
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.InitializationError;
import org.junit.runners.model.Statement;
import restx.specs.RestxSpec;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import static java.lang.String.format;
/**
* A runner which can be used to run a set of specs as JUnit tests.
*
* Example of use:
*
* <code>
* \@RunWith(RestxSpecTestsRunner.class)
* \@FindSpecsIn("specs/city")
* public class CitySpecTest { }
* </code>
*
* or
*
* <code>
* \@RunWith(RestxSpecTestsRunner.class)
* public class CitySpecTest extends RestxSpecTests {
* public CitySpecTest() {
* super(new RestxSpecRule(), RestxSpecTests.findSpecsIn("specs/city"));
* }
* }
* </code>
*/
public class RestxSpecTestsRunner extends ParentRunner<RestxSpec> {
private final RestxSpecTests tests;
/**
* Constructs a new {@code RestxSpecTestsRunner} that will run {@code @TestClass}
*/
public RestxSpecTestsRunner(Class<?> testClass) throws InitializationError, IllegalAccessException,
InvocationTargetException, InstantiationException, NoSuchFieldException, IOException {
super(testClass);
FindSpecsIn findSpecsIn = getTestClass().getJavaClass().getAnnotation(FindSpecsIn.class);
if (findSpecsIn != null) {
tests = new RestxSpecTests(new RestxSpecRule(findSpecsIn.withRouterPath()), RestxSpecTests.findSpecsIn(findSpecsIn.value()));
} else {
Object o = getTestClass().getOnlyConstructor().newInstance();
if (!(o instanceof RestxSpecTests)) {
throw new IllegalArgumentException(
format("Test class %s must either be annotated with FindSpecsIn" +
" or extend RestxSpecTests " +
"to be run with RestxSpecTestsRunner.",
getTestClass().getJavaClass().getName()));
}
tests = (RestxSpecTests) o;
}
}
@Override
protected List<RestxSpec> getChildren() {
return tests.getSpecs();
}
@Override
protected Description describeChild(RestxSpec child) {
return Description.createTestDescription(getTestClass().getJavaClass(), child.getTitle());
}
@Override
protected List<TestRule> classRules() {
List<TestRule> rules = super.classRules();
rules.add(tests.getRule());
return rules;
}
@Override
protected void runChild(final RestxSpec restxSpec, RunNotifier notifier) {
Description description = describeChild(restxSpec);
runLeaf(new Statement() {
@Override
public void evaluate() throws Throwable {
tests.getRule().runTest(restxSpec);
}
}, description, notifier);
}
}