-
Notifications
You must be signed in to change notification settings - Fork 453
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
Replace JUnit 4 by JUnit 5 #2988
Conversation
didn't we have that earlier and moved away from it? Anybody remembers the reasons? @mrieser ? One reason may be that we want to wean people away from inheritance. I can see that it will be plausible for tests but not elsewhere, but if people see it a lot, even in tests, they will start using it elsewhere as well. But these are just arguments, not a decision. |
I think we discussed it several times, including this issue: #1354. I am leaning more towards hard switching from junit 4 to 5. The problem with the soft switch (using But the hard switch may be painful, so maybe we could do it gradually for some contribs (as an intermediate solution between the global hard and soft switch). |
Please do not take my comment as a voice against this PR. I just wanted to give a broader context. |
Thanks for your comments! Have a look at However, I do see a drawback: Both the rule and the extension hold information that is test case specific. They get their data somehow "magically". With inheritance, it's much more explicit. So the But because of the easier refactoring, I would vote for the extension. |
Thanks. I think I did not read this PR carefully (or somehow missed the last commit). I like the approach with the extension. If it is as you say that IntelliJ converts everything but rules, then the migration seems quite straightforward. |
# Conflicts: # contribs/application/src/test/java/org/matsim/application/options/ShpOptionsTest.java # matsim/src/test/java/org/matsim/analysis/ScoreStatsControlerListenerTest.java # matsim/src/test/java/org/matsim/analysis/TripsAndLegsWriterTest.java # matsim/src/test/java/org/matsim/core/config/ReflectiveConfigGroupTest.java
It wasn't that easy as expected, but I made some progress. ToDos are:
Fortunately, there are some automatic migration tools which are better than the built in ones of IntelliJ: https://docs.openrewrite.org/recipes/java/testing/junit5/ |
Probably we used inheritance with JUnit 3 several years ago, but replaced it with the
Haha, I should use that reasoning to get rid of Dependency Injection, I always preferred the hard-coded dependencies in the constructors, it made it easier to follow the trail of usages. 😉 (I got used to DI in the mean time, but it was a long way...) I would prefer the extension over inheritance for the tests. Thanks for cleaning up the code and getting rid of the old stuff! |
Yes, DI is indeed magic. But normally if I inject class A into B, A has no information about B. And getting rid of constructors is a very strong argument. |
I think I'm done with the migration. Some last remarks:
Could you also check the pom files and some random test classes? |
Why we need it? The ID cache is a global variable. Without resetting it, some state will leak from one test to another. This often leads to non-deterministic results (e.g. when iterating over ID sets or map keys).
This looks interesting, because it means that it should work also in IDEs.
Some time ago I removed lots of static variables/fields from our tests. Maybe I removed (almost) all, but some new have been added in the meantime? Anyway, if there is a fixture that is shared, I suggest we make it non-static and keep on resetting the cache. |
I looked at the build results and started wondering: Do we have builds that show that before removing "auto-reset" we have a failure, and after removing it, the build is green? |
Yes, right now, all builds are green and auto reset is removed. The build before, I switched to the JUnit 5 Extension and got a red build.
Even with non-static fixtures there are problems. Take the test class |
Hm, it's not green apparently. I tried to find the root cause and it looks like that the assertion, which fails, compares an id which is randomly chosen. When I run the tests of the freightreceiver contrib locally, I everything works fine (even 10times in a row) |
The build before is red because it got cancelled: https://github.com/matsim-org/matsim-libs/actions/runs/7197145936.
That's the point. The tests are flaky, sometimes they pass, sometimes not. It all depends whether, for instance, you run one test or many. There are also differences in the order of test execution (e.g. OS, IDE vs mvn). I think the authors of the tests write them in a way that they work fine when run in the IDE for a given mvn module (e.g. contrib). That is why there is a high chance of not running into problems when running locally.
The fixture is a non-static field. That means it is created for each test (6 times in this class).
The problem is with static fields - they are created only once, so there is a risk of transferring some state from one test to another. |
I did now. There are lots of failures. One can reproduce them locally.
I don't think so. Because it's a class field, it gets created once. The same problems applies for The call hierarchy of Junit5 is:
|
Please have a look here: https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-instance-lifecycle.
|
I think the problem is that in junit 4, In junit 5, |
Thanks for sharing this and clarifying my miss understanding.
You are right. I switched to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice to switch to Junit 5. 🚀
I really like that it a full transition (no interim state where we support both). Thanks a lot for making the effort of adapting the test code to the jUnit5 style (e.g. non-public test methods), so when writing new tests we have good patterns to base on. 🥇
With this PR, JUnit 4 should be replaced by JUnit 5. Testcases that don't use the
@Rule
annotation can automatically be converted by IntelliJ. We need another logic for theMatsimTestUtils
.It's main purpose is to provide functions to get the input and output directories. This data is collected by the
starting()
andfinished()
methods. JUnit 5 provides the same logic via@BeforeEach
and@AfterEach
.So my proposition is the following: Instead of having a rule field, classes which use the
MatsimTestUtils
inherit the functionality from an abstract parent test class. It provides the same functionality.I implemented this for two example test classes.
Closes #1354.