package org.easyb.listener; import java.util.Arrays; import java.util.List; import org.easyb.BehaviorStep; import org.easyb.domain.Behavior; import org.easyb.domain.Story; import org.easyb.util.BehaviorStepType; /** * this class prints data to the console related to running easyb stories and specifications. This * is a user facing class and thus, a lot of effort goes towards human readable messages that convey * precise information. note, there is a lot of conditional logic to determine various result * altering messages; that is, pending and ignored behaviors change the behavior of reporting * output. */ public class ConsoleReporterListener extends ResultsCollector { private long startTime; @Override public void startBehavior(final Behavior behavior) { super.startBehavior(behavior); System.out.println("Running " + behaviorName(behavior)); this.startTime = System.currentTimeMillis(); } private String behaviorName(final Behavior behavior) { return behavior.getPhrase() + " " + behavior.getTypeDescriptor() + " (" + behavior.getFile().getName() + ")"; } @Override public void stopBehavior(final BehaviorStep currentStep, final Behavior behavior) { final long endTime = System.currentTimeMillis(); printMetrics(behavior, this.startTime, new ResultsReporter(this.previousStep), endTime); } /** * this method returns a formatted string that contains the total scenarios run. if there were * ignored scenarios, the total number is determined by subtracting the ignored ones; thus, we * don't convey that an ignored scenario was "run" */ private String getScenariosRunMessage(final ResultsReporter results) { if(results.getIgnoredScenarioCount() > 0) { return "Scenarios run: (" + +(results.getScenarioCount() - results.getIgnoredScenarioCount()) + " of " + results.getScenarioCount() + ")"; } else { return "Scenarios run: " + results.getScenarioCount(); } } private void printMetrics(final Behavior behavior, final long startTime, final ResultsReporter results, final long endTime) { if(behavior instanceof Story) { System.out.println((results.getFailedScenarioCount() == 0 ? "" : "FAILURE ") + this.getScenariosRunMessage(results) + ", Failures: " + results.getFailedScenarioCount() + ", Pending: " + results.getPendingScenarioCount() + (results.getIgnoredScenarioCount() > 0 ? ", Ignored: " + results.getIgnoredScenarioCount() : "") + ", Time elapsed: " + (endTime - startTime) / 1000f + " sec\n"); System.out.println("#####################################################################################"); } else { System.out.println((results.getFailedSpecificationCount() == 0 ? "" : "FAILURE ") + "Specifications run: " + results.getSpecificationCount() + ", Failures: " + results.getFailedSpecificationCount() + ", Pending: " + results.getPendingSpecificationCount() + ", Time elapsed: " + (endTime - startTime) / 1000f + " sec"); } if(results.getFailedBehaviorCount() > 0) { handleFailurePrinting(results.getGenesisStep()); } } private static final List<BehaviorStepType> recurseErrorStepTypes = Arrays.asList(BehaviorStepType.SCENARIO, BehaviorStepType.GENESIS, BehaviorStepType.STORY, BehaviorStepType.SPECIFICATION, BehaviorStepType.EXECUTE, BehaviorStepType.AFTER, BehaviorStepType.AFTER_EACH, BehaviorStepType.BEFORE, BehaviorStepType.BEFORE_EACH); private void handleFailurePrinting(final BehaviorStep currentStep) { for(BehaviorStep step : currentStep.getChildSteps()) { if(recurseErrorStepTypes.contains(step.getStepType())) { handleFailurePrinting(step); } else { printFailureMessage(step); } } } private void printFailureMessage(final BehaviorStep istep) { if(istep.getResult() != null && istep.getResult().failed()) { System.out.println("\t" + istep.getParentStep().getStepType().type() + " \"" + istep.getParentStep().getName() + "\""); System.out.println("\tstep " + istep.getStepType().toString() + " \"" + istep.getName() + "\" -- " + (istep.getResult().cause() != null ? istep.getResult().cause().getMessage() : istep.getResult().description)); } } }