Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JUnit5 support for the existing soft-assertions support (Expect.create JUnit4 Rule) #893

Open
astubbs opened this issue Jul 27, 2021 · 5 comments
Labels
P3 not scheduled type=addition A new feature

Comments

@astubbs
Copy link

astubbs commented Jul 27, 2021

From a purely JUnit5 perspective, am I missing something?

I made this wrapper around the core Expect function:

    public class ThingyThing {
        public static void softly(final SoftAssertions softly) throws Throwable {
            Expect expect = Expect.create();
            expect.apply(new Statement() {
                @Override
                public void evaluate() throws Throwable {
                        softly.apply(expect);
                }
            }, Description.EMPTY)
                    .evaluate();
        }

        public interface SoftAssertions{
            void apply(final Expect expect);
        }
    }

Used like:

        ThingyThing.softly(expector -> {
            expector.that(1).isEqualTo(2);
            expector.that(-1).isGreaterThan(0);
        });

Outputs:

2 expectations failed:
  1. expected: 2
     but was : 1
     	at io.<snip>.ThingTest.lambda$testRemit$0(ThingTest.java:113)
     
  2. expected to be greater than: 0
     but was                    : -1
     	at io.<snip>.ThingTest.lambda$testRemit$0(ThingTest.java:114)

P.s. amazing framework BTW - beautiful. Especially for chained custom objects. Amazing. Wish I'd found it sooner.

@astubbs astubbs changed the title Nicer way to support soft assertions (Expect.create) in JUnit5? Nicer way to support soft assertions (Expect.create junit4 Rule) in JUnit5? Jul 27, 2021
@cpovirk
Copy link
Member

cpovirk commented Jul 27, 2021

Thanks. As you've seen, JUnit 5 is a giant TODO for us, one that we're unlikely to carve off time for in the near future :(

I can say one slightly encouraging thing, which is that your proposal looks useful even to non-JUnit-5 users. (Maybe we've even heard requests for it from such users? I can't seem to find any offhand, though.) Then I can say one more discouraging thing, which is that we have had a proposal open inside Google for something like this for a couple years, and we haven't acted on it. Now, that proposal was more about adding context to a group of assertions:

try (TruthContext ctx = Truth.addFailureMessage("foo %s", bar)) {
  ...
}

If we take into account that such a feature could support all of...

  • context to add to failure messages
  • Expect-style failure collection for...
    • users of JUnit 5 (and other non-JUnit-4 frameworks)
    • users of any framework who simply want to group assertions at a smaller scope than a whole test

...then that provides at least a little more motivation.

Still probably not a big priority for us, given that Truth itself continues not to be a big priority for us, sadly.

@cpovirk cpovirk added P3 not scheduled type=addition A new feature labels Jul 27, 2021
@ephemient
Copy link

ephemient commented Aug 17, 2021

I created PR #706 over a year ago which enables

@Test
public void test(StandardSubjectBuilder expect) {
  expect.that(1).isEqualTo(2);
  expect.that(-1).isGreaterThan(0);
}

in JUnit 5. I think that makes sense if you're actually using JUnit 5, but if you want to use it in any test framework, then your ThingyThing seems reasonable.

@astubbs
Copy link
Author

astubbs commented Sep 2, 2021

@ephemient that seems great! Perhaps the two could be merged to enable both options...

@cpovirk have you seen #706 ?

@ddaeyeonkim
Copy link

ddaeyeonkim commented Oct 1, 2021

My solution Inspired by ThingyThing.

class ExpectExtension : BeforeEachCallback, AfterEachCallback, InvocationInterceptor,
                        ParameterResolver {

    private var _expect: Expect? = null

    val expect: Expect
        get() = _expect!!

    override fun beforeEach(context: ExtensionContext) {
        _expect = Expect.create()
    }

    override fun interceptTestMethod(
        invocation: InvocationInterceptor.Invocation<Void>,
        invocationContext: ReflectiveInvocationContext<Method>,
        extensionContext: ExtensionContext
    ) {
        _expect?.apply(
            object : Statement() {
                override fun evaluate() {
                    invocation.proceed()
                }
            },
            Description.EMPTY,
        )?.evaluate()
    }

    override fun afterEach(context: ExtensionContext) {
        _expect = null
    }

    override fun supportsParameter(
        parameterContext: ParameterContext,
        extensionContext: ExtensionContext
    ): Boolean {
        val paramType = parameterContext.parameter.type
        return paramType is Type && paramType == Expect::class.java
    }

    override fun resolveParameter(
        parameterContext: ParameterContext,
        extensionContext: ExtensionContext
    ): Any {
        return expect
    }
}

A.

@Test
@ExtendWith(ExpectExtension::class)
fun test(expect: Expect) {
    expect.that<Int>(1).isEqualTo(2)
    expect.that<Int>(1).isEqualTo(3)
    expect.that<Int>(1).isEqualTo(4)
}

B.

@JvmField
@RegisterExtension
val extension = ExpectExtension()

@Test
fun test2() {
    extension.expect.that<Int>(1).isEqualTo(2)
    extension.expect.that<Int>(1).isEqualTo(3)
    extension.expect.that<Int>(1).isEqualTo(4)
}

@Test
fun test3(expect: Expect) {
    expect.that<Int>(1).isEqualTo(2)
    expect.that<Int>(1).isEqualTo(3)
    expect.that<Int>(1).isEqualTo(4)
}

I look forward to any form of Expect Extension for JUnit5 being added in the future!

@cpovirk
Copy link
Member

cpovirk commented Oct 19, 2021

As belatedly noted on #894, anything that we label as P3 has no timeline for being reviewed :( We hope to eventually schedule some more time for Truth (especially for features that could work well in Kotlin, like this one), but there are no plans yet.

(Another thing we should do: Figure out if this feature request and #266 represent different requests or if they could be merged.)

@cpovirk cpovirk changed the title Nicer way to support soft assertions (Expect.create junit4 Rule) in JUnit5? JUnit5 support for the existing soft-assertions support (Expect.create JUnit4 Rule) Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 not scheduled type=addition A new feature
Projects
None yet
Development

No branches or pull requests

4 participants