/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jdave.junit4;
import java.lang.reflect.Modifier;
import jdave.IStringComparisonFailure;
import jdave.Specification;
import jdave.runner.SpecRunner;
import jdave.tools.SpecdoxRunner;
import junit.framework.ComparisonFailure;
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.notification.RunNotifier;
/**
* The JDaveRunner is a JUnit4 test runner implementation for JDave
* specifications. Just tag your JDave specification class with the
* <code>@RunWith(JDaveRunner.class)</code> annotation and you're good to go!
*
* @author Lasse Koskela
*/
public class JDaveRunner extends Runner implements Filterable {
private final Class<? extends Specification<?>> spec;
private final Description description;
private Filter filter;
@SuppressWarnings("unchecked")
public JDaveRunner(final Class<?> testClass) {
if (Specification.class.isAssignableFrom(testClass)) {
spec = (Class<? extends Specification<?>>) testClass;
} else if (isAContext(testClass)) {
spec = (Class<? extends Specification<?>>) testClass.getDeclaringClass();
} else {
throw new IllegalArgumentException("Testclass is not a Specification or a Context: "
+ testClass);
}
Specification.setStringComparisonFailure(new IStringComparisonFailure() {
public void fail(final String message, final String expected, final String actual) {
throw new ComparisonFailure(message, expected, actual);
}
});
description = DescriptionFactory.create(this.spec);
}
private boolean isAContext(final Class<?> contextClass) {
final boolean isMemberClass = contextClass.isMemberClass();
if (!isMemberClass) {
return false;
}
final boolean isStatic = Modifier.isStatic(contextClass.getModifiers());
if (isStatic) {
return false;
}
final Class<?> declaringClass = contextClass.getDeclaringClass();
final boolean declaringClassIsASpecification = Specification.class
.isAssignableFrom(declaringClass);
return declaringClassIsASpecification;
}
@Override
public Description getDescription() {
return description;
}
@Override
public void run(final RunNotifier notifier) {
new SpecRunner().run(spec, new JDaveCallback(notifier, filter));
new SpecdoxRunner().generate(spec);
}
public void filter(final Filter filter) {
this.filter = filter;
}
}