Skip to content

Commit

Permalink
AssertJ soft assertions tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Achitheus committed Dec 30, 2023
1 parent 4ad3f29 commit e5c1899
Show file tree
Hide file tree
Showing 8 changed files with 428 additions and 0 deletions.
2 changes: 2 additions & 0 deletions allure-assertj/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ dependencies {
testImplementation(project(":allure-java-commons-test"))
testImplementation(project(":allure-junit-platform"))
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.junit.vintage:junit-vintage-engine")
testImplementation("org.junit.jupiter:junit-jupiter-params")
}

tasks.jar {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.assertj;

import io.qameta.allure.test.AllureFeatures;
import org.assertj.core.api.AutoCloseableSoftAssertions;
import org.assertj.core.api.SoftAssertions;
import org.assertj.core.api.StandardSoftAssertionsProvider;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.function.Consumer;

import static io.qameta.allure.assertj.util.SoftAssertionsUtils.eraseCollectedErrors;

/**
* @author Achitheus (Yury Yurchenko).
*/
public class SoftAssertionsBasicApproachesTest {

@AllureFeatures.Steps
@DisplayName("Check hardcoded soft assertions object")
@ParameterizedTest(name = "[{index}]: {arguments}")
@MethodSource(value = "io.qameta.allure.assertj.util.SoftAssertionsTestsProvider#softAssertionsTests")
void tests(String testName, Consumer<StandardSoftAssertionsProvider> test) {
SoftAssertions softly = new SoftAssertions();
test.accept(softly);
}

@AllureFeatures.Steps
@DisplayName("Check autocloseable soft assertions")
@ParameterizedTest(name = "[{index}]: {arguments}")
@MethodSource(value = "io.qameta.allure.assertj.util.SoftAssertionsTestsProvider#softAssertionsTests")
void autocloseableTests(String testName, Consumer<StandardSoftAssertionsProvider> test) {
try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
test.accept(softly);
eraseCollectedErrors(softly);
}
}

@AllureFeatures.Steps
@DisplayName("Check SoftAssertions.assertSoftly() method")
@ParameterizedTest(name = "[{index}]: {arguments}")
@MethodSource(value = "io.qameta.allure.assertj.util.SoftAssertionsTestsProvider#softAssertionsTests")
void assertSoftlyMethodTests(String testName, Consumer<StandardSoftAssertionsProvider> test) {
SoftAssertions.assertSoftly(softly -> {
test.accept(softly);
eraseCollectedErrors(softly);
});
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.assertj;

import io.qameta.allure.test.AllureFeatures;
import org.assertj.core.api.JUnitSoftAssertions;
import org.assertj.core.api.StandardSoftAssertionsProvider;
import org.junit.Rule;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.function.Consumer;

import static io.qameta.allure.assertj.util.SoftAssertionsUtils.eraseCollectedErrors;

/**
* @author Achitheus (Yury Yurchenko).
*/
public class SoftAssertionsJUnit4RuleTest {

@Rule
public final JUnitSoftAssertions softly = new JUnitSoftAssertions();

@AllureFeatures.Steps
@DisplayName("Check JUnit4 Rule soft assertions")
@ParameterizedTest(name = "[{index}]: {arguments}")
@MethodSource(value = "io.qameta.allure.assertj.util.SoftAssertionsTestsProvider#softAssertionsTests")
public void tests(String testName, Consumer<StandardSoftAssertionsProvider> test) {
test.accept(softly);
eraseCollectedErrors(softly);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.assertj;

import io.qameta.allure.test.AllureFeatures;
import org.assertj.core.api.SoftAssertions;
import org.assertj.core.api.StandardSoftAssertionsProvider;
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions;
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.function.Consumer;

import static io.qameta.allure.assertj.util.SoftAssertionsUtils.eraseCollectedErrors;

/**
* @author Achitheus (Yury Yurchenko).
*/
@ExtendWith(SoftAssertionsExtension.class)
public class SoftAssertionsJUnit5ExtensionTest {

@InjectSoftAssertions
private SoftAssertions softly;

@AllureFeatures.Steps
@DisplayName("Check soft assertions obj injected as field by JUnit5 extension")
@ParameterizedTest(name = "[{index}]: {arguments}")
@MethodSource(value = "io.qameta.allure.assertj.util.SoftAssertionsTestsProvider#softAssertionsTests")
void fieldInjectionTests(String testName, Consumer<StandardSoftAssertionsProvider> test) {
test.accept(softly);
eraseCollectedErrors(softly);
}

@AllureFeatures.Steps
@DisplayName("Check soft assertions obj injected as parameter by JUnit5 extension")
@ParameterizedTest(name = "[{index}]: {arguments}")
@MethodSource(value = "io.qameta.allure.assertj.util.SoftAssertionsTestsProvider#softAssertionsTests")
void parameterInjectionTests(String testName, Consumer<StandardSoftAssertionsProvider> test, SoftAssertions softly) {
test.accept(softly);
eraseCollectedErrors(softly);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.assertj.util;

import java.lang.reflect.Method;
import java.util.function.Consumer;

public class ReflectionUtils {

public static <T> Consumer<T> staticMethodAsConsumer(Method m) {
return param -> {
try {
m.invoke(null, param);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.assertj.util;

import io.qameta.allure.Allure;
import io.qameta.allure.Step;
import io.qameta.allure.aspects.StepsAspects;
import io.qameta.allure.assertj.AllureAspectJ;
import io.qameta.allure.model.StepResult;
import io.qameta.allure.model.TestResult;
import io.qameta.allure.test.AllureResults;
import junit.framework.AssertionFailedError;
import org.assertj.core.api.StandardSoftAssertionsProvider;
import org.junit.jupiter.params.provider.Arguments;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import static io.qameta.allure.Allure.step;
import static io.qameta.allure.assertj.util.ReflectionUtils.staticMethodAsConsumer;
import static io.qameta.allure.assertj.util.StringsUtils.humanReadableMethodOrClassName;
import static io.qameta.allure.model.Status.FAILED;
import static io.qameta.allure.model.Status.PASSED;
import static io.qameta.allure.test.RunUtils.runWithinTestContext;
import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Achitheus (Yury Yurchenko).
*/
@SuppressWarnings("unused")
public class SoftAssertionsTestsProvider {
public static final Logger LOGGER = LoggerFactory.getLogger(SoftAssertionsTestsProvider.class);

public static Stream<Arguments> softAssertionsTests() {
return Arrays.stream(SoftAssertionsTestsProvider.class.getDeclaredMethods())
.filter(method -> {
Class<?>[] paramTypeArray = method.getParameterTypes();
return !method.getName().contains("$")
&& paramTypeArray.length == 1
&& paramTypeArray[0] == StandardSoftAssertionsProvider.class;
})
.peek(method -> method.setAccessible(true))
.map(method -> Arguments.of(humanReadableMethodOrClassName(method.getName()), staticMethodAsConsumer(method)));
}

private static void afterAssertionErrorCollectedCallbackShouldWork(StandardSoftAssertionsProvider softly) {
final AllureResults results = runWithinTestContext(() -> {
step("Allure.step()", () -> {
annotationStep(() -> {});
annotationStep(() -> {});
annotationStep(() -> {
step("Allure.step()");
step("Allure.step()", () -> {
annotationStep(() -> {});
annotationStep(() -> softly.collectAssertionError(new AssertionFailedError("hellow")));
});
});
annotationStep(() -> {});
});
}, AllureAspectJ::setLifecycle, Allure::setLifecycle, StepsAspects::setLifecycle);
assertThat(results.getTestResults())
.flatExtracting(TestResult::getSteps)
.extracting(StepResult::getStatus)
.containsExactly(FAILED);
assertThat(results.getTestResults())
.flatExtracting(TestResult::getSteps)
.flatExtracting(StepResult::getSteps)
.extracting(StepResult::getStatus)
.containsExactly(PASSED, PASSED, FAILED, PASSED);
assertThat(softly.assertionErrorsCollected()).hasSize(1);
}

private static void customMethodStepShouldBeFailed(StandardSoftAssertionsProvider softly) {
final AllureResults results = runWithinTestContext(() -> {
List<String> notebookList = List.of("Tests string 0", "Tests string 1");
step("Allure.step()", () -> {
softly.assertThatList(notebookList)
.hasSize(1_000_000)
.containsAnyOf("Passed", "Tests string 0");
});
step("Allure.step()", () -> {
softly.assertThatList(notebookList)
.hasSize(2)
.containsExactly("failed", "nope", "its failed");
});
}, AllureAspectJ::setLifecycle, Allure::setLifecycle);
assertThat(results.getTestResults())
.flatExtracting(TestResult::getSteps)
.extracting(StepResult::getStatus)
.containsExactly(FAILED, FAILED);
assertThat(results.getTestResults())
.flatExtracting(TestResult::getSteps)
.flatExtracting(StepResult::getSteps)
.extracting(StepResult::getStatus)
.containsExactly(PASSED, FAILED, PASSED,
PASSED, PASSED, FAILED);
assertThat(softly.assertionErrorsCollected()).hasSize(2);
}

private static void severalMiddleStepsShouldBeFailed(StandardSoftAssertionsProvider softly) {
final AllureResults results = runWithinTestContext(() -> {
softly.assertThat("Some test string")
.as("%s description passed", "awesome")
.containsAnyOf("passed", "blahblah", "me te")
.containsOnlyDigits()
.doesNotContainIgnoringCase("passed")
.startsWith("failed")
.containsPattern(".+ test .+")
.endsWith("failed");
}, AllureAspectJ::setLifecycle);
assertThat(results.getTestResults())
.flatExtracting(TestResult::getSteps)
.extracting(StepResult::getStatus)
.containsExactly(PASSED, PASSED, PASSED, FAILED, PASSED, FAILED, PASSED, FAILED);
assertThat(softly.assertionErrorsCollected()).hasSize(3);
}

@Step("@Step")
public static void annotationStep(Runnable runnable) {
runnable.run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.assertj.util;

import org.assertj.core.api.DefaultAssertionErrorCollector;

import java.lang.reflect.Field;
import java.util.List;

/**
* @author Achitheus (Yury Yurchenko)
*/
@SuppressWarnings("unchecked")
public class SoftAssertionsUtils {

public static void eraseCollectedErrors(DefaultAssertionErrorCollector softAssertions) {
try {
Field errorListField = DefaultAssertionErrorCollector.class.getDeclaredField("collectedAssertionErrors");
errorListField.setAccessible(true);
List<AssertionError> errorList = (List<AssertionError>) errorListField.get(softAssertions.getDelegate().orElse(softAssertions));
errorList.clear();
} catch (ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
}
}
Loading

0 comments on commit e5c1899

Please sign in to comment.