All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.serenitybdd.junit5.ParameterizedTestsOutcomeAggregator Maven / Gradle / Ivy

There is a newer version: 4.2.9
Show newest version
package net.serenitybdd.junit5;

import net.thucydides.model.domain.*;
import net.thucydides.core.steps.BaseStepListener;
import net.thucydides.core.steps.StepEventBus;
import net.thucydides.model.util.Inflector;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.params.ParameterizedTest;

import java.util.*;
import java.util.stream.Collectors;

public class ParameterizedTestsOutcomeAggregator {

    private final List allTestOutcomes;

    public ParameterizedTestsOutcomeAggregator() {
        BaseStepListener baseStepListener = StepEventBus.getParallelEventBus().getBaseStepListener();
        allTestOutcomes = baseStepListener.getTestOutcomes();
    }

    public ParameterizedTestsOutcomeAggregator(BaseStepListener baseStepListener) {
        allTestOutcomes = baseStepListener.getTestOutcomes();
    }

    public ParameterizedTestsOutcomeAggregator(List testOutcomes) {
        allTestOutcomes = testOutcomes;
    }

    public List aggregateTestOutcomesByTestMethods() {
        List allOutcomes = getTestOutcomesForAllParameterSets();

        if (allOutcomes.isEmpty()) {
            return new ArrayList<>();
        } else {
            return aggregatedScenarioOutcomes(allOutcomes);
        }
    }

    private synchronized List aggregatedScenarioOutcomes(List allOutcomes) {

        Map scenarioOutcomes = new HashMap<>();

        for(int testOutcomeNumber = 0; testOutcomeNumber < allOutcomes.size(); testOutcomeNumber++) {
            TestOutcome testOutcome = allOutcomes.get(testOutcomeNumber);
            final String normalizedMethodName = normalizedMethodName(testOutcome);

            TestOutcome scenarioOutcome = scenarioOutcomeFor(normalizedMethodName, testOutcome, scenarioOutcomes);
            recordTestOutcomeAsSteps(testOutcome, scenarioOutcome);
            scenarioOutcome.setContext(testOutcome.getContext());

            if (testOutcome.isManual()) {
                scenarioOutcome = scenarioOutcome.setToManual();
            }

            if (testOutcome.isDataDriven()) {
                updateResultsForAnyExternalFailures(testOutcome, scenarioOutcomes.get(normalizedMethodName));
                if(scenarioOutcome.getDataTable() != null) {
                    List scenarioRows = scenarioOutcome.getDataTable().getRows();
                    List outcomeRows = testOutcome.getDataTable().getRows();
                    for (DataTableRow row : outcomeRows) {
                        if (!containRow(scenarioRows, row)) {
                            scenarioOutcome.addRow(row);
                        }
                    }
                } else {
                    scenarioOutcome.addDataFrom(testOutcome.getDataTable());
                }
                scenarioOutcome.updateDataTableResult(testOutcomeNumber, testOutcome.getResult());
                if (testOutcome.getTestOutlineName() != null) {
                    scenarioOutcome.setTitle(testOutcome.getTestOutlineName());
                } else {
                    scenarioOutcome.setTitle(Inflector.getInstance().humanize(testOutcome.getMethodName()));
                }
            }
        }

        List aggregatedScenarioOutcomes = new ArrayList<>();
        aggregatedScenarioOutcomes.addAll(scenarioOutcomes.values());
        return aggregatedScenarioOutcomes;

    }

    private boolean containRow(List scenarioRows, DataTableRow expectedRow) {
        return scenarioRows.stream().anyMatch( row -> row.equalsIgnoringTheResult(expectedRow));
    }

    private void recordTestOutcomeAsSteps(TestOutcome testOutcome, TestOutcome scenarioOutcome) {
        final String name = alternativeMethodName(testOutcome);
        TestStep nestedStep = TestStep.forStepCalled(name).withResult(testOutcome.getResult());
        List testSteps = testOutcome.getTestSteps();

        if (testOutcome.getTestFailureCause() != null) {
            nestedStep.failedWith(testOutcome.getTestFailureCause().getOriginalCause());
        }

        if (!testSteps.isEmpty()) {
            for (TestStep nextStep : testSteps) {
                nextStep.setDescription(normalizeTestStepDescription(nextStep.getDescription(),
                        scenarioOutcome.getTestSteps().size() + 1));
                nestedStep.addChildStep(nextStep);
                nestedStep.setDuration(nextStep.getDuration() + nestedStep.getDuration());
            }
        }

        if (nestedStep.getDuration() == 0) {
            nestedStep.setDuration(testOutcome.getDuration());
        }

        scenarioOutcome.recordStep(nestedStep);
    }

    private TestOutcome scenarioOutcomeFor(String normalizedMethodName, TestOutcome testOutcome, Map scenarioOutcomes) {
        if (!scenarioOutcomes.containsKey(normalizedMethodName)) {
            TestOutcome scenarioOutcome = createScenarioOutcome(testOutcome);
            scenarioOutcomes.put(normalizedMethodName, scenarioOutcome);
        }
        return scenarioOutcomes.get(normalizedMethodName);
    }

    private void updateResultsForAnyExternalFailures(TestOutcome testOutcome, TestOutcome scenarioOutcome) {
        if (rowResultsAreInconsistantWithOverallResult(testOutcome)) {
            testOutcome.getDataTable().getRows().get(0).updateResult(testOutcome.getResult());
            //TODO
            //scenarioOutcome.addFailingStepAsSibling(new AssertionError(testOutcome.getTestFailureMessage()));
        }
    }

    private boolean rowResultsAreInconsistantWithOverallResult(TestOutcome testOutcome) {
        TestResult overallRowResult = overallResultFrom(testOutcome.getDataTable().getRows());
        return (testOutcome.isError() || testOutcome.isFailure() || testOutcome.isCompromised())
                && (!testOutcome.getDataTable().getRows().isEmpty())
                && (testOutcome.getResult() != overallRowResult);
    }

    private TestResult overallResultFrom(List rows) {

        List resultsOfEachRow = rows.stream()
                .map(DataTableRow::getResult)
                .collect(Collectors.toList());

        return TestResultList.overallResultFrom(resultsOfEachRow);
    }

    private String normalizeTestStepDescription(String description, int index) {
        return StringUtils.replace(description, "[1]", "[" + index + "]");
    }

    private TestOutcome createScenarioOutcome(TestOutcome parameterizedOutcome) {
        TestOutcome testOutcome = TestOutcome.forTest(baseMethodName(parameterizedOutcome),
                parameterizedOutcome.getTestCase());

        return testOutcome;
    }

    private String baseMethodName(TestOutcome testOutcome) {
        return testOutcome.getName(); //Updated the baseMethodName so that we can effectively handle display names, display name generators, and methods without JUnit custom display names.
    }

    private String normalizedMethodName(TestOutcome testOutcome) {
        return testOutcome.isDataDriven() ? testOutcome.getMethodName() : testOutcome.getName();
    }

    private String alternativeMethodName(TestOutcome testOutcome) {
        // Any parameterized test name attributes overrides the qualified name
        if (hasParameterizedTestName(testOutcome)) {
            return testOutcome.getTitle();
        }

        Optional qualifier = testOutcome.getQualifier();
        if (qualifier != null && qualifier.isPresent()) {
            return testOutcome.getTitle(false) + " " + testOutcome.getQualifier().get();
        } else {
            return testOutcome.getTitle();
        }
    }

    private boolean hasParameterizedTestName(TestOutcome testOutcome) {
        if (testOutcome.getTestCase() == null) {
            return false;
        }
        String parameterizedTestName = Arrays.stream(testOutcome.getTestCase().getDeclaredMethods())
                .filter(method -> method.getName().equals(testOutcome.getMethodName()))
                .filter(method -> method.isAnnotationPresent(ParameterizedTest.class))
                .map(method -> method.getAnnotation(ParameterizedTest.class).name())
                .findFirst()
                .orElse("");

        return (!parameterizedTestName.isEmpty());
    }

    public List getTestOutcomesForAllParameterSets() {
        List testOutcomes = new ArrayList<>();
        for (TestOutcome testOutcome : allTestOutcomes) {
            testOutcomes.add(withParentStepsMerged(testOutcome));
        }
        return testOutcomes;
    }

    private static TestOutcome withParentStepsMerged(TestOutcome testOutcome) {
        if ( (testOutcome.getTestSteps().size() == 1) && testOutcome.getTestSteps().get(0).getDescription().startsWith("Example ") ){
            // Give the example a title based on the data used for this example
            String testStepQualifier = testOutcome.getTestSteps().get(0).getDescription().replaceAll("Example \\d+:","");
            List childSteps = testOutcome.getTestSteps().get(0).getChildren();
            return testOutcome.withQualifier(testStepQualifier).withSteps(childSteps);
        } else {
            return testOutcome;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy