@Override
  public void finished(boolean allStepsExecuted) {
    if (postProjectAnalysisTasks.length == 0) {
      return;
    }

    ProjectAnalysisImpl projectAnalysis = createProjectAnalysis(allStepsExecuted ? SUCCESS : FAILED);
    for (PostProjectAnalysisTask postProjectAnalysisTask : postProjectAnalysisTasks) {
      executeTask(projectAnalysis, postProjectAnalysisTask);
    }
  }
@Test
  @UseDataProvider("booleanValues")
  public void logStatistics_adds_statistics_to_end_of_task_log(boolean allStepsExecuted) {
    Map<String, Object> stats = new HashMap<>();
    for (int i = 0; i <= new Random().nextInt(10); i++) {
      stats.put("statKey_" + i, "statVal_" + i);
    }
    PostProjectAnalysisTask logStatisticsTask = mock(PostProjectAnalysisTask.class);
    when(logStatisticsTask.getDescription()).thenReturn("PT1");
    doAnswer(i -> {
      PostProjectAnalysisTask.Context context = i.getArgument(0);
      stats.forEach((k, v) -> context.getLogStatistics().add(k, v));
      return null;
    }).when(logStatisticsTask)
      .finished(any(PostProjectAnalysisTask.Context.class));

    new PostProjectAnalysisTasksExecutor(
      ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, new PostProjectAnalysisTask[] {logStatisticsTask})
        .finished(allStepsExecuted);

    verify(logStatisticsTask).finished(taskContextCaptor.capture());

    assertThat(logTester.logs()).hasSize(1);
    List<String> logs = logTester.logs(Level.INFO);
    assertThat(logs).hasSize(1);
    StringBuilder expectedLog = new StringBuilder("^PT1 ");
    stats.forEach((k, v) -> expectedLog.append("\\| " + k + "=" + v + " "));
    expectedLog.append("\\| status=SUCCESS \\| time=\\d+ms$");
    assertThat(logs.get(0)).matches(expectedLog.toString());
  }