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

Truth seems to import JUnit 4, even on JUnit 5 #333

Open
jbduncan opened this issue Jul 6, 2017 · 43 comments
Open

Truth seems to import JUnit 4, even on JUnit 5 #333

jbduncan opened this issue Jul 6, 2017 · 43 comments
Labels
P3 not scheduled type=enhancement Make an existing feature better

Comments

@jbduncan
Copy link

jbduncan commented Jul 6, 2017

It occurs to me that the core/ subproject's pom.xml imports JUnit 4 as a non-test dependency. I think this is fine for projects that use JUnit 4 and Truth together for testing, but I'm a little concerned that for projects using JUnit 5 it will cause JUnit 4 to be unnecessarily downloaded and depended upon.

Are there any plans to move any parts of Truth which depend on JUnit 4 APIs into their own extensions?

@cpovirk
Copy link
Member

cpovirk commented Jul 7, 2017

Unfortunately, the parts of Truth that depend on JUnit 4 are basically all "all of them," since we throw ComparisonFailure.

There are at least a couple approaches we could take here:

  • Throw ComparisonFailure conditionally only if it's available at runtime.
  • Adopt the opentest4j types once they're finalized.

Overall, I'm not too concerned about a dependency on JUnit 4 in Truth, since it's a test framework. But if it's causing people trouble, we should reconsider.

@dimo414
Copy link
Contributor

dimo414 commented Jul 9, 2017

Throwing ComparisonFailure only if it's already on the classpath would be a silent regression for users not using JUnit4, so (as you say, assuming it's not causing real trouble) I think waiting for opentest4j makes the most sense.

@kashike
Copy link

kashike commented Nov 9, 2017

opentest4j 1.0.0 was released on September 10th.

@cpovirk
Copy link
Member

cpovirk commented Nov 9, 2017

Cool, thanks.

@Androbin
Copy link

Since #40 is merged, we can close this now.

@jbduncan
Copy link
Author

@Androbin Sorry, I'm unclear on how #40 is related to this issue. Would you kindly clarify things for me?

@Androbin
Copy link

Androbin commented Feb 12, 2018

Oops, I meant cashapp/misk#40 😁

@cpovirk
Copy link
Member

cpovirk commented Feb 12, 2018

Oh, thanks for the link:

Until this is resolved, we should be careful to use the @org.junit.jupiter.api.Test annotation and not @org.junit.Test by mistake.

That's a good downside for us to keep in mind. Inside Google, I think we're pretty much resigned to having JUnit 4 on our classpath, and people haven't started using JUnit 5 much. But externally, things are different.

This is still something we could consider doing someday. It's just not at the top of the list currently.

@Androbin
Copy link

Isn't there a way to search & replace "en masse" across the codebase?
Or is this simply not feasible?

@cpovirk
Copy link
Member

cpovirk commented Feb 12, 2018

We can do search and replace. My fears are:

  • Some people will be catching particular exception types, and their code will break. They ideally wouldn't be doing that, but we still have to clean them up inside Google, and others will have to fix it outside Google :\ Of course, the sooner we make the change, the better, so that the fallout is smaller.

  • We'd need to get the opentest4j exceptions working under GWT and Android [update: all the way back to Ice Cream Sandwich] -- which is probably straightforward but sometimes turns out not to be.

  • The opentest4j annotations still look possibly not officially finalized -- or maybe the docs just haven't been updated yet, since they're used in JUnit 5?

None of these are necessarily huge problems; there just didn't seem to be a big upside to eliminating the JUnit 4 dependency. The release of JUnit 5 may change that, and it calls attention to a larger problem with multiple @Test annotations.

@cpovirk
Copy link
Member

cpovirk commented Feb 13, 2018

Oh, and we should also check whether IDEs have begun supporting the opentest4j AssertionFailedError. I gather that they probably have, but I'd want to be sure. (e.g., I found this comment suggesting that IntelliJ has problems, but it seems hard to believe. I'd still want to verify.)

@childnode
Copy link

childnode commented Feb 13, 2018

@Androbin

Isn't there a way to search & replace "en masse" across the codebase?
Or is this simply not feasible?

just have a look what the gradle guys do with their codebase: gradle/gradle#4116 << tl;dr: auto converting and running junit 4 tests with junit 5 platform both vintage and converted https://github.com/gradle/gradle/pull/4116/files#diff-a5945fda2451f7bab0e91c578e8e7f2eR49 ff

BUT: this is just done for the gradle tests itself and not intended to be used for other projects neither as production code

THIS truth one has other impacts, but if you ask me: just deprecate Junit 4 support and branch for Junit 5 ;)

@cpovirk
Copy link
Member

cpovirk commented Sep 19, 2018

We should at least consider migrating to the new extensions before 1.0. My guess is that we'll ultimately not consider this to be a true 1.0 blocker, but I'll mark it for consideration.

@cpovirk cpovirk added this to the Release 1.0 milestone Sep 19, 2018
@cpovirk
Copy link
Member

cpovirk commented Sep 19, 2018

This might include eliminating TruthJUnit in favor of something on Truth itself.

Alternatively, it might include concluding that TruthJUnit is a weird name for a class that contains assume -- and then doing something about that.

@cpovirk
Copy link
Member

cpovirk commented Sep 21, 2018

Another thing that opentest4j offers is MultipleFailuresError, which would be nice for Expect.

@ptahchiev
Copy link

This issue is blocking me to migrate to JUnit5 :( I use google-compile testing framework which brings truth as transitive dependency and you guys have hard-coded junit4 classes in there (JUnitComparisonFailure)

@cpovirk
Copy link
Member

cpovirk commented Apr 10, 2019

My current thinking is that we won't fix this for 1.0 (which we're going to try to make our final release with breaking changes) because we can still theoretically fix it afterward by:

  • changing our calls to FailureStrategy.fail to pass an AssertionFailedError (a subtype of AssertionError)
  • making JUnit 4 an optional dependency that users can add if they want to use TruthJUnit
    I still hope to have a look at all that someday, but it's not imminent.

@cpovirk
Copy link
Member

cpovirk commented Apr 10, 2019

Oh, and I meant to add that, as part of opentest4j support, we'd also want to look for the opentest4j IncompleteExecutionException (and subtypes) in Expect.

@jbduncan
Copy link
Author

Sounds good to me @cpovirk! 👍

@raghsriniv raghsriniv added the P3 not scheduled label Jun 24, 2019
@netdpb netdpb added the type=enhancement Make an existing feature better label Oct 2, 2019
@ptahchiev
Copy link

Any updates on this? I'd really like to see you guys support JUnit5 so we can move the google-compile-testing to JUnit5 too.

copybara-service bot pushed a commit that referenced this issue Jan 23, 2021
… real this time.

This should *really* let users exclude the JUnit 4 dependency -- again, as long as they don't use Expect, ExpectFailure, or TruthJUnit (i.e., assume()).

This change makes the previously failing test procedure described in #333 (comment) pass.

RELNOTES=Made it possible for users to exclude our JUnit 4 dependency and still use standard Truth assertions -- *really* this time. (JUnit 4 is still required for some advanced features, like `Expect`, `ExpectFailure`, and `TruthJUnit.assume()`.)
PiperOrigin-RevId: 353318639
copybara-service bot pushed a commit that referenced this issue Jan 23, 2021
… real this time.

This should *really* let users exclude the JUnit 4 dependency -- again, as long as they don't use Expect, ExpectFailure, or TruthJUnit (i.e., assume()).

This change makes the previously failing test procedure described in #333 (comment) pass.

RELNOTES=Made it possible for users to exclude our JUnit 4 dependency and still use standard Truth assertions -- *really* this time. (JUnit 4 is still required for some advanced features, like `Expect`, `ExpectFailure`, and `TruthJUnit.assume()`.)
PiperOrigin-RevId: 353318639
copybara-service bot pushed a commit that referenced this issue Jan 23, 2021
… real this time.

This should *really* let users exclude the JUnit 4 dependency -- again, as long as they don't use Expect, ExpectFailure, or TruthJUnit (i.e., assume()).

This change makes the previously failing test procedure described in #333 (comment) pass.

RELNOTES=Made it possible for users to exclude our JUnit 4 dependency and still use standard Truth assertions -- *really* this time. (JUnit 4 is still required for some advanced features, like `Expect`, `ExpectFailure`, and `TruthJUnit.assume()`.)
PiperOrigin-RevId: 353416036
@cpovirk
Copy link
Member

cpovirk commented Jan 23, 2021

OK, 1.1.2 contains the fix (and another fix that I noticed I needed along the way...). Sorry for all the trouble.

It's still conceivable that something will go wrong in some case (InnerClasses?). But I have dealt with the one definite problem, which those following along at home may recognize as Java Puzzler 44 (as Martin Buchholz points out to me).

Please continue to let us know of new problems that the JUnit dependency causes. The ones I'm aware of:

@KevinMcT
Copy link

1.1.2 looks good 👍 @cpovirk. No more broken window spam when utilizing truth in projects with jupiter and excluding junit.

(Work with stolsvik, so ack from us)

@MariusVolkhart
Copy link

@cpovirk the ExpectFailure class extends from JUnitTestRule which extends JUnit 4's TestRule. So when excluding JUnit 4, code referencing ExpectFailure no longer works. This includes code using the expectFailureAbout factory method

@tbroyer
Copy link

tbroyer commented Feb 5, 2021

And that's, uh, expected: https://github.com/google/truth/releases/tag/release_1_1_2

(JUnit 4 is still required for some advanced features, like Expect, ExpectFailure, and TruthJUnit.assume().)

@MariusVolkhart
Copy link

🤦 missed that, thanks!

@cpovirk
Copy link
Member

cpovirk commented Feb 5, 2021

We don't have a clear plan for JUnit 5 at this point :(

I want to say that we ought to be able to extract the purely static version of ExpectFailure into a class with no JUnit dependency, but I'd have to confirm. And ideally, we'd want to get at least the beginnings of a long-term plan before copying things around.

In the meantime, copying and pasting the methods from ExpectFailure into your own codebase doesn't require too much duplication, so it may be a workable option (depending on licensing and other such questions).

@astubbs
Copy link

astubbs commented Jul 27, 2021

Related: Nicer way to support soft assertions (Expect.create junit4 Rule) in JUnit5? #893 (patch available)

@TWiStErRob
Copy link

@cpovirk is this still on hold?

@cpovirk
Copy link
Member

cpovirk commented Jan 24, 2022

Truth still declares a build dependency on JUnit:

truth/core/pom.xml

Lines 21 to 24 in ceecbd4

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>

As of Truth 1.1.2, you can exclude that dependency, and Truth will work at runtime. (It just won't throw a ComparisonFailure.)

That's as far as we're likely to take this for a long while, unfortunately.

@TWiStErRob
Copy link

If that's the case would it make sense to document how to use Truth with JUnit 5 with detail on what features are lost to that exclusion and how to get them back in JUnit 5? I really like how detailed https://truth.dev/comparison is, would love to see a similar page for JUnit 5.

@cpovirk
Copy link
Member

cpovirk commented Jan 24, 2022

It would :( Truth is very much on the back burner. I do hope to change that someday.

Offhand, I think you lose only ComparisonFailure and the "assertThat alternatives," which are Expect, ExpectFailure, and TruthJUnit.assume() (noted in the 1.1.2 page). We don't have alternatives for them at the moment, nor do I know enough JUnit 5 to confidently sketch what they would look like (though I'd expect it to be relatively straightforward).

@Sineaggi
Copy link

According to the junit 5 codebase, it looks like they use the AssertionFailedError from org.opentest4j. Their asserts take the form of org.opentest4j.AssertionFailedError: expected: <1> but was: <2>

copybara-service bot pushed a commit that referenced this issue Jul 23, 2022
…yReflection`.

This makes it possible to write a config that instructs Proguard to keep that constructor if it keeps the class.

I'm hoping that I don't need to explicitly instruct it to keep the class, since the class name appears as a literal argument to `Class.forName`. (I could just tell it to keep it "just to be safe," but then maybe we'd see problems with users who don't actually use Truth but end up with it at runtime anyway because it's somewhere in the transitive deps and we asked Proguard to keep it.)

(The reason we're using reflection in the first place is to support running without JUnit 4 on the classpath. See #333.)

RELNOTES=n/a
PiperOrigin-RevId: 462420279
copybara-service bot pushed a commit that referenced this issue Jul 23, 2022
…yReflection`.

This makes it possible to write a config that instructs Proguard to keep that constructor if it keeps the class.

I'm hoping that I don't need to explicitly instruct it to keep the class, since the class name appears as a literal argument to `Class.forName`. (I could just tell it to keep it "just to be safe," but then maybe we'd see problems with users who don't actually use Truth but end up with it at runtime anyway because it's somewhere in the transitive deps and we asked Proguard to keep it.)

(The reason we're using reflection in the first place is to support running without JUnit 4 on the classpath. See #333.)

RELNOTES=n/a
PiperOrigin-RevId: 462826082
cpovirk referenced this issue in google/flogger Nov 29, 2023
RELNOTES=Speed up the first `GoogleLogger` construction.
PiperOrigin-RevId: 586132513
lqiu96 added a commit to googleapis/sdk-platform-java that referenced this issue May 20, 2024
fixes #2728, attempt to remove Junit 4 support after migration.
Other than POM dependency migrate, changes include:
- package name changes
- Junit 5 syntax upgrades, e.g. `@Before` --> `@BeforeEach`, Replace
assertion methods
- remove public modifier on tests and test classes.
- Refactor JUnit 4 TemporaryFolder `@Rule` in
[ITGdch.java](https://github.com/googleapis/sdk-platform-java/pull/2757/files#diff-6ae7755a0b038e1a2febae2d27e36c762f6751b8c7db577421667069399884b4)
to JUnit 5 `@TempDir`
- Replace `@Test(timeout = 15000L)` in
[ITClientShutdown.java](https://github.com/googleapis/sdk-platform-java/pull/2757/files#diff-70d1df57471178a7a63302f82e4a4855ffbbd642ea67d92d501bd1f7008957ca)
with `@Timeout(15)`
- Update `@RunWith(Parameterized.class)` test in
[ITHttpAnnotation.java](https://github.com/googleapis/sdk-platform-java/pull/2757/files#diff-03d420650ecc9fe78ad4887761043c4fdceaa978f464ce30cfc4ed5f8be9b64d)
to `@ParameterizedTest` with `@MethodSource("data")`

~~Note: #2737 creates a new test class with JUnit4 syntax. Depending on
merging order, I will either update in this pr, or #2737.~~ Updated.


Due to truth library depending on junit 4 ([see
issue](google/truth#333)), junit 4 cannot be
completely removed, or will encounter `java.lang.ClassNotFoundException:
org.junit.runner.notification.RunListener` running tests with maven
surefire. To keep things cleaner, excluding the implicitly junit brought
in from truth and `junit-vintage-engine`. We could also do the reverse,
and make a comment if that's prefered.

---------

Co-authored-by: Burke Davison <40617934+burkedavison@users.noreply.github.com>
Co-authored-by: Lawrence Qiu <lawrenceqiu@google.com>
lqiu96 added a commit to googleapis/sdk-platform-java that referenced this issue May 22, 2024
fixes #2728, attempt to remove Junit 4 support after migration.
Other than POM dependency migrate, changes include:
- package name changes
- Junit 5 syntax upgrades, e.g. `@Before` --> `@BeforeEach`, Replace
assertion methods
- remove public modifier on tests and test classes.
- Refactor JUnit 4 TemporaryFolder `@Rule` in
[ITGdch.java](https://github.com/googleapis/sdk-platform-java/pull/2757/files#diff-6ae7755a0b038e1a2febae2d27e36c762f6751b8c7db577421667069399884b4)
to JUnit 5 `@TempDir`
- Replace `@Test(timeout = 15000L)` in
[ITClientShutdown.java](https://github.com/googleapis/sdk-platform-java/pull/2757/files#diff-70d1df57471178a7a63302f82e4a4855ffbbd642ea67d92d501bd1f7008957ca)
with `@Timeout(15)`
- Update `@RunWith(Parameterized.class)` test in
[ITHttpAnnotation.java](https://github.com/googleapis/sdk-platform-java/pull/2757/files#diff-03d420650ecc9fe78ad4887761043c4fdceaa978f464ce30cfc4ed5f8be9b64d)
to `@ParameterizedTest` with `@MethodSource("data")`

~~Note: #2737 creates a new test class with JUnit4 syntax. Depending on
merging order, I will either update in this pr, or #2737.~~ Updated.


Due to truth library depending on junit 4 ([see
issue](google/truth#333)), junit 4 cannot be
completely removed, or will encounter `java.lang.ClassNotFoundException:
org.junit.runner.notification.RunListener` running tests with maven
surefire. To keep things cleaner, excluding the implicitly junit brought
in from truth and `junit-vintage-engine`. We could also do the reverse,
and make a comment if that's prefered.

---------

Co-authored-by: Burke Davison <40617934+burkedavison@users.noreply.github.com>
Co-authored-by: Lawrence Qiu <lawrenceqiu@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 not scheduled type=enhancement Make an existing feature better
Projects
None yet
Development

No branches or pull requests