package org.easyb.junit;
import org.easyb.Configuration;
import org.easyb.domain.Behavior;
import org.easyb.listener.ExecutionListener;
import org.easyb.listener.ListenerBuilder;
import org.easyb.listener.ListenerFactory;
import org.easyb.listener.ResultsAmalgamator;
import org.easyb.report.HtmlReportWriter;
import org.easyb.report.ReportWriter;
import org.easyb.report.TxtSpecificationReportWriter;
import org.easyb.report.TxtStoryReportWriter;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.easyb.BehaviorRunner.getBehaviors;
import static org.easyb.junit.RunProperties.isEclipse;
import static org.easyb.junit.RunProperties.isIDEA;
import static org.junit.runner.Description.createSuiteDescription;
public class EasybJUnitRunner extends Runner {
private final RunNotifierReplay runNotifierReplay = new RunNotifierReplay(); //needed for timing?
private final DescriptionCreator descriptionCreator;
private Description description;
private List<Behavior> behaviors;
private final EasybSuite suite;
private JunitExecutionListenerRegistry listenerRegistry;
private Configuration configuration;
public EasybJUnitRunner(Class<? extends EasybSuite> testClass) throws Exception {
suite = testClass.newInstance();
descriptionCreator = new DescriptionCreator(suite.baseDir());
listenerRegistry = new JunitExecutionListenerRegistry();
configuration = new Configuration(getFilePaths(), getReports(suite));
ListenerFactory.registerBuilder(new ListenerBuilder() {
public ExecutionListener get() {
return listenerRegistry;
}
});
}
public Description getDescription() {
if (description == null) {
description = createSuiteDescription(suite.description());
if (isEclipse() || isIDEA() )
executeBehaviors(runNotifierReplay);
}
return description;
}
private void executeBehaviors(RunNotifier notifier) {
for (Behavior behavior : behaviors()) {
Description behaviorDescription = descriptionCreator.create(behavior);
description.addChild(behaviorDescription);
executeBehavior(behavior, behaviorDescription, notifier);
}
ListenerFactory.notifyTestingCompleted();
final ResultsAmalgamator resultsAmalgamator = new ResultsAmalgamator(behaviors);
for (final ReportWriter report : configuration.getConfiguredReports()) {
report.writeReport(resultsAmalgamator);
}
}
private void executeBehavior(Behavior behavior, Description behaviorDescription, RunNotifier notifier) {
final JUnitExecutionListener listener = new JUnitExecutionListener(behaviorDescription, notifier);
listenerRegistry.registerListener(listener);
try {
behavior.execute();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
listenerRegistry.unregisterListener(listener);
}
}
public void run(RunNotifier notifier) {
if (isEclipse() || isIDEA())
runNotifierReplay.replay(notifier, suite.trackTime());
else
executeBehaviors(notifier);
}
private List<Behavior> behaviors() {
return behaviors != null ? behaviors : (behaviors = getBehaviors(getFilePaths()));
}
private String[] getFilePaths() {
List<String> filePaths = new ArrayList<String>();
listFiles(suite.searchDir(), filePaths);
return filePaths.toArray(new String[filePaths.size()]);
}
private void listFiles(File dir, List<String> files) {
//check whether this is a valid directory at all
File[] filesInDirectory = dir.listFiles();
if (filesInDirectory != null) {
for (File file : filesInDirectory) {
if (file.isDirectory()) {
listFiles(file, files);
} else if (isBehavior(file)) {
files.add(file.getAbsolutePath());
}
}
} else {
System.err.println("Could not find any behaviour/story files in " + dir + ", maybe IDE prefix (working dir) is wrong?");
}
}
private boolean isBehavior(File file) {
return file.getName().endsWith(".story") || file.getName().endsWith(".specification");
}
private List<ReportWriter> getReports(EasybSuite suite) {
if(!suite.generateReports()){
return new ArrayList<ReportWriter>();
}
String reportsDir = suite.reportsDir().getPath();
File html = new File(reportsDir, "html");
html.mkdirs();
File plain = new File(reportsDir, "plain");
plain.mkdirs();
List<ReportWriter> reports = new ArrayList<ReportWriter>();
reports.add(new HtmlReportWriter(html.getAbsolutePath() + "/easyb.html"));
reports.add(new TxtStoryReportWriter(plain.getAbsolutePath() + "/easyb-stories.txt"));
reports.add(new TxtSpecificationReportWriter(plain.getAbsolutePath() + "/easyb-specifications.txt"));
return reports;
}
}