From 72eff9b7754027bd2f9447917abc659a51e618bf Mon Sep 17 00:00:00 2001 From: CeeVeeR Date: Fri, 2 Oct 2026 05:12:37 +0200 Subject: [PATCH] feat: - Added ExpectedToFailUntilFixed marker and rule Ref.: https://github.com/VolmitSoftware/Iris/issues/1251 --- .../ExpectedToFailUntilFixedRuleTest.java | 81 +++++++++++++++++++ .../testsupport/ExpectedToFailUntilFixed.java | 12 +++ .../ExpectedToFailUntilFixedRule.java | 42 ++++++++++ 3 files changed, 135 insertions(+) create mode 100644 core/src/test/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRuleTest.java create mode 100644 core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixed.java create mode 100644 core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRule.java diff --git a/core/src/test/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRuleTest.java b/core/src/test/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRuleTest.java new file mode 100644 index 000000000..2f8bd6d53 --- /dev/null +++ b/core/src/test/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRuleTest.java @@ -0,0 +1,81 @@ +package art.arcane.iris.testsupport; + +import org.junit.AssumptionViolatedException; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.lang.annotation.Annotation; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +public class ExpectedToFailUntilFixedRuleTest { + private static final String KNOWN_BUG = "known bug"; + private static final String BUG_STILL_PRESENT = "bug still present"; + private static final String REMOVAL_REMINDER = "remove @ExpectedToFailUntilFixed: " + KNOWN_BUG; + private static final Statement PASSING = new Statement() { + @Override + public void evaluate() { + } + }; + + private final ExpectedToFailUntilFixedRule rule = new ExpectedToFailUntilFixedRule(); + private final AssertionError bugStillPresent = new AssertionError(BUG_STILL_PRESENT); + private final IllegalStateException crash = new IllegalStateException(BUG_STILL_PRESENT); + + @Test + public void doesAMarkedTestThatStillFailsGetReportedAsSkippedWithItsFailure() { + assertSame(bugStillPresent, assertThrows(AssumptionViolatedException.class, runMarked(failingWith(bugStillPresent))).getCause()); + } + + @Test + public void doesAMarkedTestThatPassesFailWithARemovalReminder() { + assertTrue(messageOfAssertionFailure(runMarked(PASSING)).contains(REMOVAL_REMINDER)); + } + + @Test + public void doesACrashInAMarkedTestStillFail() { + assertSame(crash, assertThrows(IllegalStateException.class, runMarked(failingWith(crash)))); + } + + @Test + public void doesAnUnmarkedFailingTestStillFail() { + assertSame(bugStillPresent, assertThrows(AssertionError.class, runUnmarked(failingWith(bugStillPresent)))); + } + + @ExpectedToFailUntilFixed(KNOWN_BUG) + private void markedTestTemplate() { + } + + private ThrowingRunnable runMarked(Statement test) { + return () -> rule.apply(test, describe(markerOfTemplate())).evaluate(); + } + + private ThrowingRunnable runUnmarked(Statement test) { + return () -> rule.apply(test, describe()).evaluate(); + } + + private ExpectedToFailUntilFixed markerOfTemplate() throws NoSuchMethodException { + return getClass().getDeclaredMethod("markedTestTemplate").getAnnotation(ExpectedToFailUntilFixed.class); + } + + private static String messageOfAssertionFailure(ThrowingRunnable test) { + return assertThrows(AssertionError.class, test).getMessage(); + } + + private static Description describe(Annotation... annotations) { + return Description.createTestDescription(ExpectedToFailUntilFixedRuleTest.class, "example", annotations); + } + + private static Statement failingWith(Throwable failure) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + throw failure; + } + }; + } +} diff --git a/core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixed.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixed.java new file mode 100644 index 000000000..78dd73a37 --- /dev/null +++ b/core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixed.java @@ -0,0 +1,12 @@ +package art.arcane.iris.testsupport; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ExpectedToFailUntilFixed { + String value(); +} diff --git a/core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRule.java b/core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRule.java new file mode 100644 index 000000000..182f1b979 --- /dev/null +++ b/core/src/testFixtures/java/art/arcane/iris/testsupport/ExpectedToFailUntilFixedRule.java @@ -0,0 +1,42 @@ +package art.arcane.iris.testsupport; + +import org.junit.AssumptionViolatedException; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +public final class ExpectedToFailUntilFixedRule implements TestRule { + @Override + public Statement apply(Statement test, Description description) { + ExpectedToFailUntilFixed marker = markerOf(description); + return marker == null ? test : new ExpectedFailure(test, marker.value()); + } + + private static ExpectedToFailUntilFixed markerOf(Description description) { + return description.getAnnotation(ExpectedToFailUntilFixed.class); + } + + private static final class ExpectedFailure extends Statement { + private final Statement test; + private final String reason; + + private ExpectedFailure(Statement test, String reason) { + this.test = test; + this.reason = reason; + } + + @Override + public void evaluate() throws Throwable { + try { + test.evaluate(); + } catch (AssertionError stillFailing) { + throw reportAsSkipped(stillFailing); + } + throw new AssertionError("Passes now, remove @ExpectedToFailUntilFixed: " + reason); + } + + private AssumptionViolatedException reportAsSkipped(AssertionError stillFailing) { + return new AssumptionViolatedException("Still failing until fixed: " + reason, stillFailing); + } + } +}