@Override
 public Void call() throws Exception {
   Stopwatch reportingStopwatch = Stopwatch.started();
   reportingTask.generateReports();
   LOGGER.debug("{} generated in {} ms", reportingTask.toString(), reportingStopwatch.stop());
   return null;
 }
  public TestOutcomes generateReportsForTestResultsFrom(final File sourceDirectory)
      throws IOException {

    Stopwatch stopwatch = Stopwatch.started();
    copyScreenshotsFrom(sourceDirectory);

    LOGGER.debug("Copied screenshots after {} ms", stopwatch.lapTime());

    TestOutcomes allTestOutcomes = loadTestOutcomesFrom(sourceDirectory);

    LOGGER.debug("Loaded test outcomes after {} ms", stopwatch.lapTime());

    generateReportsForTestResultsIn(allTestOutcomes);

    LOGGER.debug("Generated reports after {} ms", stopwatch.lapTime());

    return allTestOutcomes;
  }
  @Override
  public void evaluateFor(Actor actor) {
    Stopwatch stopwatch = new Stopwatch();

    stopwatch.start();
    do {
      try {
        consequenceThatMightTakeSomeTime.evaluateFor(actor);
        return;
      } catch (AssertionError assertionError) {
        caughtAssertionError = assertionError;
      } catch (RuntimeException runtimeException) {
        caughtRuntimeException = runtimeException;
      }
      pauseBeforeNextAttempt();
    } while (stopwatch.lapTime() < timeout);

    throwAnyCaughtErrors();
  }
  private void generateReportsFor(Collection<ReportingTask> reportingTasks) throws IOException {
    stopwatch.start();

    try {
      Reporter.generateReportsFor(reportingTasks);

      final List<Callable<Void>> partitions = Lists.newArrayList();
      for (ReportingTask reportingTask : reportingTasks) {
        partitions.add(new ReportExecutor(reportingTask));
      }

      final ExecutorService executorPool =
          Executors.newFixedThreadPool(NumberOfThreads.forIOOperations());
      for (Future<Void> executedTask : executorPool.invokeAll(partitions)) {
        executedTask.get();
      }
    } catch (Exception e) {
      LOGGER.error("Report generation failed", e);
    }

    LOGGER.debug("Test outcome reports generated in {} ms", stopwatch.stop());
  }
  public void generateReportsForTestResultsIn(TestOutcomes testOutcomes) throws IOException {

    Stopwatch stopwatch = Stopwatch.started();
    LOGGER.info("Generating test results for {} tests", testOutcomes.getTestCount());

    FreemarkerContext context =
        new FreemarkerContext(
            environmentVariables,
            requirements.getRequirementsService(),
            issueTracking,
            relativeLink);

    RequirementsOutcomes requirementsOutcomes =
        requirements.getRequirementsOutcomeFactory().buildRequirementsOutcomesFrom(testOutcomes);

    LOGGER.info(
        "{} requirements loaded after {} ms",
        requirementsOutcomes.getFlattenedRequirementCount(),
        stopwatch.lapTime());

    requirementsOutcomes = requirementsOutcomes.withoutUnrelatedRequirements();

    LOGGER.info(
        "{} related requirements found after {} ms",
        requirementsOutcomes.getFlattenedRequirementCount(),
        stopwatch.lapTime());

    List<String> knownRequirementReportNames =
        requirementReportNamesFrom(requirementsOutcomes, reportNameProvider);

    Set<ReportingTask> reportingTasks = new HashSet<>();

    reportingTasks.add(new CopyResourcesTask());
    reportingTasks.add(new CopyTestResultsTask());
    reportingTasks.add(
        new AggregateReportingTask(
            context,
            environmentVariables,
            requirements.getRequirementsService(),
            getOutputDirectory(),
            testOutcomes));
    reportingTasks.add(
        new TagTypeReportingTask(
            context, environmentVariables, getOutputDirectory(), reportNameProvider, testOutcomes));
    reportingTasks.addAll(
        tagReportsFor(testOutcomes)
            .using(
                context,
                environmentVariables,
                getOutputDirectory(),
                reportNameProvider,
                testOutcomes.getTags(),
                knownRequirementReportNames));

    reportingTasks.addAll(
        ResultReports.resultReportsFor(
            testOutcomes, context, environmentVariables, getOutputDirectory(), reportNameProvider));
    reportingTasks.addAll(
        RequirementsReports.requirementsReportsFor(
            context,
            environmentVariables,
            getOutputDirectory(),
            reportNameProvider,
            requirements.getRequirementsOutcomeFactory(),
            requirements.getRequirementsService(),
            relativeLink,
            testOutcomes,
            requirementsOutcomes));

    LOGGER.info("Starting generating reports: {} ms", stopwatch.lapTime());
    generateReportsFor(reportingTasks);

    LOGGER.info(
        "Finished generating test results for {} tests after {} ms",
        testOutcomes.getTestCount(),
        stopwatch.stop());
  }