1package net.serenitybdd.cucumber.suiteslicing;2import net.serenitybdd.cucumber.util.BigDecimalAverageCollector;3import net.thucydides.core.util.Inflector;4import org.slf4j.Logger;5import org.slf4j.LoggerFactory;6import java.math.BigDecimal;7import java.net.URI;8import java.nio.file.FileSystem;9import java.nio.file.FileSystemAlreadyExistsException;10import java.nio.file.FileSystems;11import java.nio.file.Files;12import java.nio.file.Path;13import java.nio.file.Paths;14import java.util.Collections;15import java.util.List;16import java.util.Optional;17import static com.google.common.collect.Lists.newArrayList;18import static java.util.stream.Collectors.toList;19public class MultiRunTestStatistics implements TestStatistics {20 private final List<TestScenarioResults> results = newArrayList();21 static Logger LOGGER = LoggerFactory.getLogger(MultiRunTestStatistics.class);22 public static MultiRunTestStatistics fromRelativePath(String basePath) {23 MultiRunTestStatistics multiRunTestStatistics = new MultiRunTestStatistics();24 try {25 URI uri = MultiRunTestStatistics.class.getResource(basePath).toURI();26 Path resultsPath;27 LOGGER.info("Loading results from {}", uri);28 if (uri.getScheme().equals("jar")) {29 FileSystem fileSystem;30 try {31 fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap());32 } catch (FileSystemAlreadyExistsException e) {33 fileSystem = FileSystems.getFileSystem(uri);34 }35 resultsPath = fileSystem.getPath(basePath);36 } else {37 resultsPath = Paths.get(uri);38 }39 Files.walk(resultsPath).filter(path -> Files.isRegularFile(path)).forEach(file -> {40 LOGGER.debug("Aggregating results from {}", file.getFileName());41 multiRunTestStatistics.addStatistics(SingleRunTestStatistics.fromFileName(basePath + "/" + file.getFileName()));42 });43 } catch (Exception e) {44 throw new RuntimeException(String.format("could not open scenario results from %s", basePath), e);45 }46 return multiRunTestStatistics;47 }48 @Override49 public BigDecimal scenarioWeightFor(String feature, String scenario) {50 return records().stream()51 .filter(record -> record.feature.equals(feature) && record.scenario.equals(scenario))52 .map(TestScenarioResult::duration)53 .findFirst()54 .orElseGet(() -> average(feature, scenario));55 }56 @Override57 public List<TestScenarioResult> records() {58 return results.stream().map(TestScenarioResults::average).collect(toList());59 }60 private void addStatistics(TestStatistics statistics) {61 statistics.records().forEach(record -> {62 Optional<TestScenarioResults> existingResult = results.stream().filter(existing -> existing.scenarioKey.equals(record.scenarioKey)).findFirst();63 if (existingResult.isPresent()) {64 existingResult.get().addDuration(record.duration);65 } else {66 results.add(TestScenarioResults.create(record));67 }68 });69 }70 private BigDecimal averageDuration() {71 return records().stream().map(TestScenarioResult::duration).collect(BigDecimalAverageCollector.create());72 }73 private BigDecimal average(String feature, String scenario) {74 LOGGER.warn("Returning average weighting of {} due to non-match of {} -> {}", averageDuration(), feature, scenario);75 return averageDuration();76 }77 public String toString() {78 return Inflector.getInstance().kebabCase(this.getClass().getSimpleName());79 }80}...