diff --git a/allure-hamcrest/build.gradle.kts b/allure-hamcrest/build.gradle.kts new file mode 100644 index 000000000..3907ff9a9 --- /dev/null +++ b/allure-hamcrest/build.gradle.kts @@ -0,0 +1,32 @@ +description = "Allure Hamcrest Assertions Integration" + +val agent: Configuration by configurations.creating + +dependencies { + agent("org.aspectj:aspectjweaver") + api(project(":allure-java-commons")) + compileOnly("org.aspectj:aspectjrt") + implementation("org.hamcrest:hamcrest") + testAnnotationProcessor(project(":allure-descriptions-javadoc")) + testImplementation("org.junit.jupiter:junit-jupiter-api") + testImplementation("org.junit.jupiter:junit-jupiter-params") + testImplementation("org.assertj:assertj-core") + testImplementation("org.slf4j:slf4j-simple") + testImplementation(project(":allure-java-commons-test")) + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") +} + +tasks.jar { + manifest { + attributes(mapOf( + "Automatic-Module-Name" to "io.qameta.allure.hamcrest" + )) + } +} + +tasks.test { + useJUnitPlatform() + doFirst { + jvmArgs("-javaagent:${agent.singleFile}") + } +} \ No newline at end of file diff --git a/allure-hamcrest/src/main/java/io/qameta/allure/hamcrest/AllureHamcrestAssert.java b/allure-hamcrest/src/main/java/io/qameta/allure/hamcrest/AllureHamcrestAssert.java new file mode 100644 index 000000000..cf836d8f1 --- /dev/null +++ b/allure-hamcrest/src/main/java/io/qameta/allure/hamcrest/AllureHamcrestAssert.java @@ -0,0 +1,129 @@ +/* + * Copyright 2021 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.hamcrest; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.AfterReturning; +import io.qameta.allure.Allure; +import io.qameta.allure.AllureLifecycle; +import io.qameta.allure.model.Status; +import io.qameta.allure.model.StepResult; +import io.qameta.allure.util.ObjectUtils; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; + +import java.util.UUID; + +import static io.qameta.allure.util.ResultsUtils.getStatus; + +/** + *

+ * Aspect "interceptor" for automatic logging to the Allure report. + *

+ *

+ * This aspect should work for all asserts that are in the Hamcrest library, since they all go through a single method + * to start the comparison. + *

+ *

+ * In addition to the standard comparisons that are already in the Hamcrest library, this aspect should work correctly + * with custom matchers if developers correctly implemented the describeMismatch and / or describeMismatchSafely + * methods in the TypeSafeMatcher class. + *

+ * + * @author a-simeshin (Simeshin Artem) + * @see org.hamcrest.TypeSafeMatcher + */ +@Aspect +@SuppressWarnings("all") +public class AllureHamcrestAssert { + + private static InheritableThreadLocal lifecycle = new InheritableThreadLocal() { + @Override + protected AllureLifecycle initialValue() { + return Allure.getLifecycle(); + } + }; + + public static AllureLifecycle getLifecycle() { + return lifecycle.get(); + } + + @Pointcut("execution(void org.hamcrest.MatcherAssert.**(..))") + public void initAssertThat() { + } + + /** + *

+ * assertThat(String comment, Object actual, Matcher expected) - one and only one central entry point for all + * asserts. Based on this rule, you only need to log a method with three arguments. + *

+ *

+ * Even if there is no comment as the first argument, an empty string will be passed as the first argument. + *

+ *

+ * For example assertThat(value123.get(), is(equalTo("value123"))) will be proxied to the metod + * assertThat("", value123.get(), is(equalTo("value123"))) + *

+ * + * @param joinPoint - entry point with args and method name + */ + @Before("initAssertThat()") + public void catchAndStartStep(final JoinPoint joinPoint) { + if (joinPoint.getArgs().length == 3) { + final String reason = (String) joinPoint.getArgs()[0]; + final String actual = ObjectUtils.toString(joinPoint.getArgs()[1]); + final StringDescription description = new StringDescription(); + final String expecting = description.appendText("assert \"") + .appendText(actual) + .appendText("\" ") + .appendDescriptionOf((Matcher) joinPoint.getArgs()[2]) + .toString(); + + getLifecycle().startStep( + UUID.randomUUID().toString(), + new StepResult() + .setName(reason.isEmpty() ? expecting : expecting + " | " + reason) + .setDescription("Hamcrest assert") + .setStatus(Status.PASSED) + ); + } + } + + @AfterThrowing(pointcut = "initAssertThat()", throwing = "e") + public void stepFailed(final Throwable e) { + getLifecycle().updateStep(s -> s.setStatus(getStatus(e).orElse(Status.BROKEN))); + getLifecycle().stopStep(); + } + + @AfterReturning(pointcut = "initAssertThat()") + public void stepStop() { + getLifecycle().updateStep(s -> s.setStatus(Status.PASSED)); + getLifecycle().stopStep(); + } + + /** + * For tests only. + * + * @param allure allure lifecycle to set + */ + public static void setLifecycle(final AllureLifecycle allure) { + lifecycle.set(allure); + } +} diff --git a/allure-hamcrest/src/main/resources/META-INF/aop-ajc.xml b/allure-hamcrest/src/main/resources/META-INF/aop-ajc.xml new file mode 100644 index 000000000..5a9f73e6c --- /dev/null +++ b/allure-hamcrest/src/main/resources/META-INF/aop-ajc.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestAssertionNameContainsReasonTest.java b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestAssertionNameContainsReasonTest.java new file mode 100644 index 000000000..6086258f9 --- /dev/null +++ b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestAssertionNameContainsReasonTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021 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.hamcrest; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalToIgnoringCase; + +/** + * This tests should cover cases when reason string exists in assertion. + */ +@SuppressWarnings("all") +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +public class AllureHamcrestAssertionNameContainsReasonTest { + + @Test + void hamcrestAssertNameWithComment() { + final TestResult testResult = runWithinTestContext( + () -> assertThat( + "Business always likes something weird", + "TheBiscuit", + equalToIgnoringCase("thebiscuit") + ), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly("assert \"TheBiscuit\" a string equal to \"thebiscuit\" ignoring case | Business always likes something weird"); + } + + @Test + void hamcrestAssertNameWoComment() { + final TestResult testResult = runWithinTestContext( + () -> assertThat( + "TheBiscuit", + equalToIgnoringCase("thebiscuit") + ), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly("assert \"TheBiscuit\" a string equal to \"thebiscuit\" ignoring case"); + } +} diff --git a/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestCollectionsMatchersTest.java b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestCollectionsMatchersTest.java new file mode 100644 index 000000000..805b593c4 --- /dev/null +++ b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestCollectionsMatchersTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2021 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.hamcrest; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import org.assertj.core.api.Assertions; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +/** + * All tests should cover http://hamcrest.org/JavaHamcrest/tutorial "Collections" section + * + *
  • array
  • + *
  • hasEntry
  • + *
  • hasKey
  • + *
  • hasValue
  • + *
  • hasItem
  • + *
  • hasItems
  • + *
  • hasItemInArray
  • + *
    + */ +@SuppressWarnings("all") +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +public class AllureHamcrestCollectionsMatchersTest { + + @Test + void hamcrestAssertNameForArrayMatchers() { + final TestResult testResult = runWithinTestContext( + () -> assertThat(new Integer[]{1,2,3}, is(array(equalTo(1), equalTo(2), equalTo(3)))), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly("assert \"[1, 2, 3]\" is [<1>, <2>, <3>]"); + } + + private static Stream mapTestCases() { + HashMap map = new HashMap(); + map.put("key1", 1); + map.put("key2", 2); + map.put("key3", 3); + + return Stream.of( + Arguments.of( + map, hasEntry(equalTo("key1"), equalTo(1)), + "assert \"{key1=1, key2=2, key3=3}\" map containing [\"key1\"-><1>]" + ), + Arguments.of( + map, hasKey(equalTo("key2")), + "assert \"{key1=1, key2=2, key3=3}\" map containing [\"key2\"->ANYTHING]" + ), + Arguments.of( + map, hasValue(equalTo(3)), + "assert \"{key1=1, key2=2, key3=3}\" map containing [ANYTHING-><3>]" + ) + ); + } + + @ParameterizedTest + @MethodSource("mapTestCases") + void hamcrestAssertNameForMapMatchers(Map actual, Matcher matcher, String expectedName) { + final TestResult testResult = runWithinTestContext( + () -> assertThat(actual, matcher), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly(expectedName); + } + + private static Stream iterableTestCases() { + List list = Arrays.asList("val1", "val2", "val3"); + + return Stream.of( + Arguments.of( + list, hasItem(equalTo("key1")), + "assert \"[val1, val2, val3]\" a collection containing \"key1\"" + ), + Arguments.of( + list, hasItems(startsWith("v"), endsWith("l2")), + "assert \"[val1, val2, val3]\" (a collection containing a string starting with \"v\" and a collection containing a string ending with \"l2\")" + ), + Arguments.of( + list, hasItemInArray(Arrays.asList("val1", "val2")), + "assert \"[val1, val2, val3]\" an array containing <[val1, val2]>" + ) + ); + } + + @ParameterizedTest + @MethodSource("iterableTestCases") + void hamcrestAssertNameForIterableMatchers(Iterable actual, Matcher matcher, String expectedName) { + final TestResult testResult = runWithinTestContext( + () -> assertThat(actual, matcher), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly(expectedName); + } +} diff --git a/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestLogicalMatchersTest.java b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestLogicalMatchersTest.java new file mode 100644 index 000000000..f2c810425 --- /dev/null +++ b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestLogicalMatchersTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2021 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.hamcrest; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import org.assertj.core.api.Assertions; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +/** + * All tests should cover http://hamcrest.org/JavaHamcrest/tutorial "Logical" section + * + *
  • allOf
  • + *
  • anyOf
  • + *
  • not
  • + *
    + */ +@SuppressWarnings("all") +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +public class AllureHamcrestLogicalMatchersTest { + + private static Stream testCases() { + return Stream.of( + Arguments.of( + "thebiscuit", allOf(startsWith("the"), containsString("biscuit")), + "assert \"thebiscuit\" (a string starting with \"the\" and a string containing \"biscuit\")" + ), + Arguments.of( + "thebiscuit", anyOf(startsWith("the"), containsString("test")), + "assert \"thebiscuit\" (a string starting with \"the\" or a string containing \"test\")" + ), + Arguments.of( + "test", is(not(anyOf(startsWith("the"), containsString("biscuit")))), + "assert \"test\" is not (a string starting with \"the\" or a string containing \"biscuit\")" + ) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void hamcrestAssertNameForLogicalMatchers(String actual, Matcher matcher, String expectedName) { + final TestResult testResult = runWithinTestContext( + () -> assertThat(actual, matcher), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly(expectedName); + } +} diff --git a/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestNumberMatchersTest.java b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestNumberMatchersTest.java new file mode 100644 index 000000000..c6d43e44c --- /dev/null +++ b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestNumberMatchersTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 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.hamcrest; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import org.assertj.core.api.Assertions; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +/** + * All tests should cover http://hamcrest.org/JavaHamcrest/tutorial "Number" section + * + *
  • closeTo
  • + *
  • greaterThan
  • + *
  • greaterThanOrEqualTo
  • + *
  • lessThan
  • + *
  • lessThanOrEqualTo
  • + *
    + */ +@SuppressWarnings("all") +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +public class AllureHamcrestNumberMatchersTest { + + private static Stream testCases() { + return Stream.of( + Arguments.of( + 0.434d, is(closeTo(0.41d, 0.45d)), + "assert \"0.434\" is a numeric value within <0.45> of <0.41>" + ), + Arguments.of( + 0.434d, is(greaterThan(0.41d)), + "assert \"0.434\" is a value greater than <0.41>" + ), + Arguments.of( + 0.434d, is(greaterThanOrEqualTo(0.41d)), + "assert \"0.434\" is a value equal to or greater than <0.41>" + ), + Arguments.of( + 0.41d, is(lessThan(0.434d)), + "assert \"0.41\" is a value less than <0.434>" + ), + Arguments.of( + 0.41d, is(lessThanOrEqualTo(0.434d)), + "assert \"0.41\" is a value less than or equal to <0.434>" + ) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void hamcrestAssertNameForNumberMatchers(double actual, Matcher matcher, String expectedName) { + final TestResult testResult = runWithinTestContext( + () -> assertThat(actual, matcher), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly(expectedName); + } +} diff --git a/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestObjectMatchersTest.java b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestObjectMatchersTest.java new file mode 100644 index 000000000..3b0170d24 --- /dev/null +++ b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestObjectMatchersTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2021 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.hamcrest; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import org.assertj.core.api.Assertions; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.stream.Stream; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +/** + * All tests should cover http://hamcrest.org/JavaHamcrest/tutorial "Object" section + * + *
  • equalTo
  • + *
  • hasToString
  • + *
  • instanceOf
  • + *
  • isCompatibleType in new version typeCompatibleWith
  • + *
  • notNullValue
  • + *
  • nullValue
  • + *
  • sameInstance
  • + *
    + */ +@SuppressWarnings("all") +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +public class AllureHamcrestObjectMatchersTest { + + private static Stream testCases() { + final String testVal = "test_test"; + + return Stream.of( + Arguments.of( + "thebiscuit", is(equalTo("thebiscuit")), + "assert \"thebiscuit\" is \"thebiscuit\"" + ), + Arguments.of( + true, hasToString("TRUE"), + "assert \"true\" with toString() \"TRUE\"" + ), + Arguments.of( + Arrays.asList("key1", "key2"), instanceOf(Iterable.class), + "assert \"[key1, key2]\" an instance of java.lang.Iterable" + ), + Arguments.of( + Integer.class, typeCompatibleWith(Number.class), + "assert \"class java.lang.Integer\" type < java.lang.Number" + ), + Arguments.of( + "test", is(notNullValue()), + "assert \"test\" is not null" + ), + Arguments.of( + "test", is(not(nullValue())), + "assert \"test\" is not null" + ), + Arguments.of( + testVal, is(sameInstance(testVal)), + "assert \"test_test\" is sameInstance(\"test_test\")" + ) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void hamcrestAssertNameForObjectMatchers(Object actual, Matcher matcher, String expectedName) { + final TestResult testResult = runWithinTestContext( + () -> assertThat(actual, matcher), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly(expectedName); + } +} diff --git a/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestTextMatchersTest.java b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestTextMatchersTest.java new file mode 100644 index 000000000..ec401a53b --- /dev/null +++ b/allure-hamcrest/src/test/java/io/qameta/allure/hamcrest/AllureHamcrestTextMatchersTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2021 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.hamcrest; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import org.assertj.core.api.Assertions; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.TestInstance; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +/** + * All tests should cover http://hamcrest.org/JavaHamcrest/tutorial "Text" section + * + *
  • equalToIgnoringCase
  • + *
  • equalToIgnoringWhiteSpace(deprecated) - suggesting in code to use equalToCompressingWhiteSpace
  • + *
  • containsString
  • + *
  • endsWith
  • + *
  • startsWith
  • + *
    + */ +@SuppressWarnings("all") +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +public class AllureHamcrestTextMatchersTest { + + private static Stream testCases() { + return Stream.of( + Arguments.of( + "thebiscuit", equalToIgnoringCase("TheBiscuit"), + "assert \"thebiscuit\" a string equal to \"TheBiscuit\" ignoring case" + ), + Arguments.of( + "The Biscuit", equalToIgnoringWhiteSpace("TheBiscuit"), + "assert \"The Biscuit\" a string equal to \"TheBiscuit\" compressing white space" + ), + Arguments.of( + "The Biscuit", equalToCompressingWhiteSpace("TheBiscuit"), + "assert \"The Biscuit\" a string equal to \"TheBiscuit\" compressing white space" + ), + Arguments.of( + "The Biscuit", containsString("TheBiscuit"), + "assert \"The Biscuit\" a string containing \"TheBiscuit\"" + ), + Arguments.of( + "The Biscuit", endsWith("Biscuit"), + "assert \"The Biscuit\" a string ending with \"Biscuit\"" + ), + Arguments.of( + "The Biscuit", startsWith("Biscuit"), + "assert \"The Biscuit\" a string starting with \"Biscuit\"" + ) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void hamcrestAssertNameForTextMatchers(String actual, Matcher matcher, String expectedName) { + final TestResult testResult = runWithinTestContext( + () -> assertThat(actual, matcher), + AllureHamcrestAssert::setLifecycle + ).getTestResults().get(0); + + Assertions.assertThat(testResult.getSteps()) + .flatExtracting(StepResult::getName) + .containsExactly(expectedName); + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 56f72db2c..c39bbf257 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -141,6 +141,7 @@ configure(libs) { dependency("commons-io:commons-io:2.11.0") dependency("io.github.benas:random-beans:3.9.0") dependency("io.github.glytching:junit-extensions:2.4.0") + dependency("org.hamcrest:hamcrest:2.2") dependency("org.apache.commons:commons-lang3:3.12.0") dependency("org.apache.httpcomponents:httpclient:4.5.13") dependency("org.aspectj:aspectjrt:1.9.7") diff --git a/settings.gradle.kts b/settings.gradle.kts index 34c483a40..f0b8302ea 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,6 +11,7 @@ include("allure-cucumber4-jvm") include("allure-cucumber5-jvm") include("allure-cucumber6-jvm") include("allure-descriptions-javadoc") +include("allure-hamcrest") include("allure-httpclient") include("allure-java-commons") include("allure-java-commons-test")