Are @BeforeEach/All the most unambiguous names? #163

Open
nicolaiparlog opened this Issue Feb 23, 2016 · 16 comments

Projects

None yet
@nicolaiparlog
Contributor

Yesterday, at Objektforum, @jlink invited us to bike-shed so here we go. :)

I think @BeforeAll and @BeforeEach are somewhat ambiguous. While grammar is on your side, the difference in detail might be overlooked by many developers, the vast majority of which speak English as a second language.

This might be aggravated when only one of the annotations is used. Without the juxtaposition "all vs each" a developer might have to look up when the annotation triggers the method's execution or, worse, assume the wrong interpretation.

My proposal is @BeforeFirst,@BeforeEach (and @AfterEach, @AfterLast). I generally like them but I see the drawback that they start talking about order, which JUnit eschews on purpose and with success.

@schauder
Contributor

Took me some time time to see the ambiguity. Maybe because I'm a long time user (like probably all of those discussing here), but I find @BeforeFirst even more amiguous. What if "first" doesn't get executed, because it gets skipped? Or we execute only a single testmethod out of N ... The name @BeforeFirst seem to suggest it wouldn't get executed in these cases.

@nicolaiparlog
Contributor

Good points against first/last. But would you agree (tentatively at least) that developers might not easily spot the difference between all/each? I'm sure someone else will come up with a better alternative if need be.

Btw, there are other testing frameworks using the exact same words (Jasmine, RSpec) so there is precedence.

@schauder
Contributor

I have no idea if anybody ever had a problem with the meaning of Each/All in this context. I most certainly never had, and I never noticed anybody having that problem.

Of course that might be, because most of the time where this could come up, is when I explain how this kind of stuff works and then I explain both in short succession, so the potential confusion is already fixed before it could surface.

@marcphilipp
Member

I would rather keep Each/All following @schauder's arguments.

@junit-team/junit-lambda What do you think?

@sbrannen
Contributor

I am in favor of maintaining the status quo, simply because no one has proposed names that are better suited to the task at hand.

@ggcrjdev

I thought about the annotations names and maybe names like @PreTest/@PostTest rather than @BeforeEach/@AfterEach and @PreBundle/@PostBundle rather than @BeforeAll/@AfterAll could be better.
Note: The term bundle I use to represent a set of ests in a class or package.

@sbrannen
Contributor

We have intentionally avoided names like @PreTest simply because that implies that such a method executes before an @Test method; however, it may be the case that an @BeforeEach method is executed before an @Step method in a scenario test.

Thus, we aim to keep the common annotation names generic in order to avoid an unnecessary proliferation of annotations.

In addition, the term bundle does not seem applicable in a programming model for tests.

@jillesvangurp

I agree the names are fine. A bigger concern for me are the semantics: when do these things actually run and how? Junit currently requires these methods to be static, which I think is a needless complication inherited from the junit3 days. I recall having a issues with junit 4 a long time ago where we were doing some expensive cleanup in BeforeAll annotated methods where to our surprise the methods executed right after the test suite initialized before any of the tests in any of the test classes had actually run. Since the whole point was doing some expensive database cleanup in between test classes, this sort of got us stuck for a while. This makes for a bit awkward semantics. Junit5 might be a nice opportunity to clean that up.

As I understand it the reasoning for requiring static methods has to do with not allowing people to share state between methods in a unit test. This is valid for unit tests but kind of impractical for scenario or integration tests where you might actually have valid reasons for this. Since the name is changing with junit5 in any case, this might be a good opportunity to drop that requirement.

For reference, TestNg has BeforeSuite, AfterSuite, BeforeClass, AfterClass, BeforeMethod, and AfterMethod annotations that you put on non static methods.

@sbrannen
Contributor
sbrannen commented Jun 9, 2016

@jillesvangurp,

Scenario tests should address your concerns.

Please see the discussion in #48 for details.

@jillesvangurp

@sbrannen I responded to that issue earlier. To be honest, I don't think the annotations proposed there are anywhere near good enough yet compared to things, especially if BDD style testing is what you want. Frankly, I think it all looks a bit too verbose and too limited to me in the current form. I'm not sure if it is a fixable problem given Java's semantics.

I'm not that much into BDD myself but I do need to write integration tests with sane before and after semantics, which is why I brought this up because I think it is an area where junit can improve.

@sbrannen
Contributor

@jillesvangurp, oops... I didn't reread the comments in #48. So I didn't realize you'd already participated in that discussion.

To be honest, I don't think the annotations proposed there are anywhere near good enough yet compared to things

Compared to what things?

In any case, the decision as to whether or not @BeforeAll and @AfterAll should be able to be applied to non-static methods is not related to this issue. This issue only applies to the names of such annotations. So let's stay on topic here. 😉

If you'd like to discuss scenario tests, please do that in #48.

If you'd like to make a separate proposal to support @BeforeAll and @AfterAll on non-static methods, outside the scope of scenario tests, please create a new issue to address that.

Cheers!

@littleclay

While I get it and haven't been personally tripped up by this, I did recognize the ambiguous nature here. What if you changed @BeforeAll and @AfterAll to something like @First and @Last to capture the idea they run only once at the very beginning and end. I was also thinking of something like @BeforeAny but couldn't think of a good after version that wasn't more ambiguous :-)

@jbduncan
Contributor

I had the idea of replacing (Before|After)All with @BeforeStart and @AfterEnd, but after thinking about it, I realise this may be even more ambiguous than the status quo. After all, what part of the test cycle would 'Start' and 'End' refer to? Before/after each method; each class; or all tests?

What does everyone else think of this idea?

@smoyer64
Contributor

I was going to make an extension that provided @BeforeSuite and @AfterSuite. I thought those names were descriptive enough when placed compared the the existing annotations.

@ondrejlerch

I also suggest to use naming like in TestNG: BeforeClass, AfterClass, BeforeMethod and AfterMethod.

In my point of view, that is the most descriptive and least ambiguous.

I am also missing @BeforeSuite and @AfterSuite in Junit 5 and I think that this functionality should be added to Junit 5.

Taken to the extreme, do you want to rename @BeforeSuite and @AfterSuite to @BeforeBeforeAll and @AfterAfterAll to be according to new naming convention? :-)

I also think that there should not be any static restriction on the methods.

Let's make Junit 5 the best java testing framework in all aspects.

@mlevison
Contributor

Something that makes the naming a lot more obvious write a trivial sample test with all the different @Before/@After annotations. Put at @Test etc in between, a little effort on the formatting and the output will show elegantly which annotation does what. When I'm running a technical course (ie CSD) I get participants to do this for JUnit 4 and NUnit. I ask them to compare and discuss which model they prefer.

Cheers
Mark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment