package org.easyb; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ExecutorService; import org.easyb.domain.Behavior; import org.easyb.domain.BehaviorFactory; import org.easyb.domain.GroovyShellConfiguration; import org.easyb.listener.*; import org.easyb.report.ReportWriter; public class BehaviorRunner { private Configuration configuration; private ResultsAmalgamator resultsAmalgamator; public BehaviorRunner(final Configuration configuration, final ListenerBuilder... listeners) { this.configuration = configuration; for (ListenerBuilder lb : listeners) { ListenerFactory.registerBuilder(lb); } } /** * @param args the command line arguments * usage is: * <p/> * java BehaviorRunner my/path/to/spec/MyStory.groovy -txtstory ./reports/story-report.txt * <p/> * You don't need to pass in the file name for the report either-- if no * path is present, then the runner will create a report in the current directory * with a default filename following this convention: * easyb-<type>-report.<format> (for reports of either story or specification) * easyb-report.<format> (for reports that contain both) * <p/> * Multiple specifications can be passed in on the command line * <p/> * java BehaviorRunner my/path/to/spec/MyStory.groovy my/path/to/spec/AnotherStory.groovy */ public static void main(final String[] args) { final Configuration configuration = new ConsoleConfigurator().configure(args); //noinspection ConstantConditions if (configuration != null) { final BehaviorRunner runner = new BehaviorRunner(configuration); try { boolean success = runner.runBehaviors(getBehaviors(configuration.getFilePaths(), configuration)); //the Ant task assumes a return code from the easyb process to //determine error or not if (!success) { System.exit(-1); } } catch (Throwable exception) { System.err.println("There was an error running your easyb story or specification"); exception.printStackTrace(System.err); System.exit(-1); } } System.exit(0); } /** * @param behaviors collection of files that contain the specifications * @return success indicator * @throws Exception if unable to write report file */ public boolean runBehaviors(List<Behavior> behaviors) throws Exception { boolean wasSuccessful = true; executeBehaviors(behaviors); ListenerFactory.notifyTestingCompleted(); resultsAmalgamator = new ResultsAmalgamator(behaviors); // this is hideous - no, THIS IS JAVA! ;-) System.out.println(String.format("%d total behavior%s ran with %s failure%s", resultsAmalgamator.getResultsReporter().getBehaviorCount(), resultsAmalgamator.getResultsReporter().getBehaviorCount() == 1 ? "" : "s", resultsAmalgamator.getResultsReporter().getFailedBehaviorCount() == 0 ? "no" : ("" + resultsAmalgamator.getResultsReporter().getFailedBehaviorCount()) , resultsAmalgamator.getResultsReporter().getFailedBehaviorCount() ==1 ? "" : "s")); for (final ReportWriter report : configuration.getConfiguredReports()) { report.writeReport(resultsAmalgamator); } if (resultsAmalgamator.failuresDetected()) { wasSuccessful = false; } return wasSuccessful; } private void executeBehaviors(List<Behavior> behaviors) throws Exception { if (this.configuration.isParallel()) { ExecutorService executor = configuration.getExecutor(); List<RunnableBehavior> executedBehaviors = new ArrayList<RunnableBehavior>(); for (final Behavior behavior : behaviors) { RunnableBehavior task = new RunnableBehavior(behavior); executedBehaviors.add(task); executor.execute(task); } executor.shutdown(); executor.awaitTermination(60, SECONDS); //TODO: add this to genesys? for (RunnableBehavior each : executedBehaviors) { if (each.isFailed()) { throw each.getFailure(); } } } else { for (final Behavior behavior : behaviors) { behavior.execute(); } } } public static List<Behavior> getBehaviors(final GroovyShellConfiguration groovyShellConfiguration, final String[] paths, Configuration config) { List<Behavior> behaviors = new ArrayList<Behavior>(); for (final String path : paths) { behaviors.add(BehaviorFactory.createBehavior(groovyShellConfiguration, new File(path), config)); } return Collections.unmodifiableList(behaviors); } public static List<Behavior> getBehaviors(final GroovyShellConfiguration groovyShellConfiguration, final String[] paths) { return getBehaviors(groovyShellConfiguration, paths, null); } /** * @param paths locations of the specifications to be loaded * @return collection of files where the only element is the file of the spec to be run */ public static List<Behavior> getBehaviors(final String[] paths) { return getBehaviors(BehaviorFactory.DEFAULT_GROOVY_SHELL_CONFIG, paths); } /** * @param paths locations of the specifications to be loaded * @param config configuration * @return collection of files where the only element is the file of the spec to be run */ public static List<Behavior> getBehaviors(final String[] paths, Configuration config) { return getBehaviors(BehaviorFactory.DEFAULT_GROOVY_SHELL_CONFIG, paths, config); } }