Junit5: Rename JUnit 5 base packages and modules

Created on 28 May 2016  ยท  59Comments  ยท  Source: junit-team/junit5

Status Quo

The base package for JUnit 5 is currently org.junit.gen5; however, this tightly couples current and future releases to the number 5, which would seem illogical for later major releases such as JUnit 6, 7, etc., especially if later major releases wish to build on the stable Launcher and TestEngine APIs which are not specific to the JUnit 5 programming and extension models.

JUnit 4 Base Packages

  • org.junit
  • org.junit.experimental
  • org.junit.internal
  • org.junit.matchers
  • org.junit.rules
  • org.junit.runner
  • org.junit.runners
  • org.junit.validator

    JUnit 5 Base Packages (currently)

  • org.junit.gen5.api

  • org.junit.gen5.commons
  • org.junit.gen5.console
  • org.junit.gen5.engine
  • org.junit.gen5.engine.junit4
  • org.junit.gen5.engine.junit5
  • org.junit.gen5.gradle
  • org.junit.gen5.junit4.runner
  • org.junit.gen5.launcher
  • org.junit.gen5.surefire

Proposals

Proposal A

Replace gen5 with something else, for example a code name such as delta, lambda, etc.

  • org.junit.delta: _delta_ signifies major changes with regard to previous generations of JUnit
  • org.junit.jade: _jade_ is a green gemstone, hinting at green bars for successful tests
  • org.junit.jupiter: _Jupiter_ is the fifth planet from the sun
  • org.junit.lambda: _lambda_ signifies the move to Java 8 and was the original code name for JUnit 5

Proposal B

Retain org.junit as a base package for _platform_ modules, ensuring that there are no conflicts with packages used in JUnit 4, and include version numbers in package names only where applicable.

Names in parentheses are proposed module names (i.e., artifact IDs).

JUnit Platform - 5th Generation

  • org.junit.gen5.commons --> org.junit.commons (junit-commons)
  • org.junit.gen5.console --> org.junit.console (junit-console)
  • org.junit.gen5.launcher --> org.junit.launcher (junit-launcher)
  • org.junit.gen5.engine --> org.junit.engine (junit-engine)
  • org.junit.gen5.gradle --> org.junit.gradle (junit-gradle-plugin)
  • org.junit.gen5.surefire --> org.junit.surefire (junit-surefire-provider)

    JUnit 4 & JUnit 5 - Interoperability

  • org.junit.gen5.engine.junit4 --> org.junit.engine.junit4 (junit4-engine)

  • org.junit.gen5.junit4.runner --> org.junit.runners.junit5 (junit5-runner)

    JUnit 5 - APIs and Implementation

  • org.junit.gen5.api --> org.junit.api.junit5 (junit5-api)

  • org.junit.gen5.engine.junit5 --> org.junit.engine.junit5 (junit5-engine)

    Proposal C

Introduce the concept of a _JUnit Platform_ upon which any testing framework (e.g, JUnit 4/5/6, Groovy, Kotlin, etc.) can build. Make the separation between platform modules and programming models visually distinct, both in terms of packages and artifact IDs.

Introduce a _code name_ for the JUnit 3 and JUnit 4 programming models (e.g., legacy, vintage, retro, classic).

Introduce a _code name_ for the JUnit 5 programming model (e.g., lambda, delta, jade, jupiter).

Names in parentheses are proposed module names (i.e., artifact IDs).

JUnit Platform

  • org.junit.gen5.commons --> org.junit.platform.commons (junit-platform-commons)
  • org.junit.gen5.launcher --> org.junit.platform.launcher (junit-platform-launcher)
  • org.junit.gen5.engine --> org.junit.platform.engine (junit-platform-engine)
  • org.junit.gen5.console --> org.junit.platform.console (junit-platform-console)
  • org.junit.gen5.junit4.runner --> org.junit.platform.runner (junit-platform-runner)
  • org.junit.gen5.gradle --> org.junit.platform.gradle.plugin (junit-platform-gradle-plugin)
  • org.junit.gen5.surefire --> org.junit.platform.surefire (junit-platform-surefire-provider)

    JUnit 3 & JUnit 4

  • org.junit.gen5.engine.junit4 --> org.junit.vintage.engine (junit-vintage-engine)

    JUnit 5

  • org.junit.gen5.api --> org.junit.lambda.api (junit-lambda-api)

  • org.junit.gen5.engine.junit5 --> org.junit.lambda.engine (junit-lambda-engine)

... or:

  • org.junit.gen5.api --> org.junit.jupiter.api (junit-jupiter-api)
  • org.junit.gen5.engine.junit5 --> org.junit.jupiter.engine (junit-jupiter-engine)

... or:

  • org.junit.gen5.api --> org.junit.jade.api (junit-jade-api)
  • org.junit.gen5.engine.junit5 --> org.junit.jade.engine (junit-jade-engine)

Deliverables

  • [x] Decide on new names for base packages used in all 5th generation modules.
  • [x] Rename all packages and modules throughout the framework as appropriate.
task

Most helpful comment

Applying KISS principle just keep org.junit since a major release doesn't mean rename the base package. e.g springframework is not going to be org.springframework5 in the next generation. Build tools are the best place to manage version avoiding the redundancy in base packages.

All 59 comments

@sbrannen Is there any particular reason for proposing that the base package be renamed org.junit.delta rather than, say, org.junit.epsilon? It would make sense to me to go for epsilon, since it's the 5th letter in the Greek alphabet (for gen5), compared to delta which is the 4th letter (which I'd associate with JUnit 4).

What about just going with org.junit5?

@olivergierke I'm under the impression that @sbrannen wants to avoid that to reduce an explicit dependency on the number 5, which may confuse users of Launcher and TestEngine in the future.

Applying KISS principle just keep org.junit since a major release doesn't mean rename the base package. e.g springframework is not going to be org.springframework5 in the next generation. Build tools are the best place to manage version avoiding the redundancy in base packages.

Okay, I'm starting to think less favourably of my idea for org.junit.epsilon now. I'm also feeling ambivalent about org.junit.delta, because on one hand it sounds "cool", but on the other hand I associate it with the number 4. How about naming after something that doesn't have any ordering, like org.junit.moebius?

org.junit.extension? Or simply org.junit to be "expected"

Is moving to another domain an option? http://junit.io seems to be free. Then it may be simply io.junit.

@jbduncan,

Is there any particular reason for proposing that the base package be renamed org.junit.delta rather than, say, org.junit.epsilon?

I positively _knew_ somebody would ask that. ๐Ÿ˜‰

We actually thought about "epsilon" since it's the 5th letter of the Greek alphabet, but we decided against it for the following reasons:

  1. it's longer and more difficult to type
  2. it doesn't convey anything like "delta" does (i.e., in the sense of change, new horizons, etc.)

@olivergierke,

What about just going with org.junit5?

That's a very good question!

We in fact discussed that idea within the team. It's obviously considerably shorter than org.junit.gen5 and easy to type/remember; however, it still carries the number _5_ along with it, and we are aiming to avoid including any reference to "5" in the base package name for things that are not related to the JUnit 5 programming and extension models. For example, the Launcher and TestEngine APIs should remain stable over time and backwards compatible. So in that sense we don't feel that the package name should tie them to JUnit 5.

Perhaps more importantly, we would strongly like to avoid splitting completely from org.junit as the very base package. In other words, we would like to build on org.junit.

@eddumelendez,

Applying KISS principle just keep org.junit since a major release doesn't mean rename the base package. e.g springframework is not going to be org.springframework5 in the next generation. Build tools are the best place to manage version avoiding the redundancy in base packages.

I totally understand where you're coming from with that, and believe me: we _wish_ it were that simple with JUnit.

Regarding a framework like Spring, you are of course correct: Spring will not reinvent itself completely on top of a nested package name. And more importantly, it doesn't need to: Nobody is going to deploy their web application with Spring Framework 4.3 and 5.0 in the classpath.

But JUnit is a totally different story: it's a testing framework, and people _do_ execute tests in the same suite against different versions of JUnit. In fact, the Spring Framework does exactly that: to this day, there are both JUnit 3.8 and JUnit 4.12 based tests running side by side in Spring's test suite. The reason that's not a problem is that JUnit 3 and JUnit 4 have completely different programming models (with completely different base packages) and therefore completely different discovery mechanisms.

The JUnit Team realized this early on and made certain from the start that it will be possible to run JUnit 3.8, JUnit 4.12, and JUnit 5.0 based tests all within the same suite. And... we also want to make the same possible for future versions of JUnit (e.g., 6, 7, etc.).

Long story, short: we cannot simply reuse org.junit as the base package (at least not for JUnit 5 specific APIs like @Test). For certain things we will have to introduce base packages specific to JUnit 5 and/or the 5th generation of the framework.

Now... what I've just written is to help explain to people where we are coming from. Having said that, I do actually agree with you to an extent, and I'll provide more details in a follow-up proposal. ๐Ÿ˜‰

@jbduncan,

How about naming after something that doesn't have any ordering, like org.junit.moebius?

The JUnit Team has also discussed that idea.

"moebius" sounds pretty cool.

Along those lines, we brainstormed a bit and came up with the following. The names in parentheses follow the logic of _i18n_.

  • catalyst (c6t)
  • delta
  • metamorphosis (m11s)
  • evolution (e7n)

So if people come up with other _cool_ ideas, post them here!

@rmannibucau,

org.junit.extension?

One of the key features of JUnit 5 is its dedicated Extension model. So we wouldn't want to use anything as a base package name that would be confusing in different contexts.

@c00ler,

Is moving to another domain an option? http://junit.io seems to be free. Then it may be simply io.junit.

I personally think io.junit seems pretty cool. ๐Ÿ‘

But... as I mentioned previously, we would like to avoid splitting completely from org.junit as the very base package.

That doesn't mean it's a 100% no-go, but for the time being the JUnit Team is shying away from switching to a different domain name.

@sbrannen .extension was intended to reference Extension

like io.junit but still thing v5 shouldnt break v < 5 standard package so org.junit sounds the best to me and I didn't find any real reason preventing it. For not compatible features (@Test) a sub package defining the feature or specificity is far better than any "new" "vx" or other arbitrary naming IMO.

Everybody,

I have overhauled the description of this issue and introduced a separate proposal (_Proposal B_).

Feedback is welcome!

@junit-team/junit-lambda, your input is also welcome. ๐Ÿ˜‰

can't org.junit.api.junit5 be org.junit.api? otherwise looks better :)

What bothers me most regarding Proposal B is that JUnit 4 will be maintained for quite some time and will introduce new packages (e.g. a current pull request adds the org.junit.function package). So we would have to be really careful not to cause any problems there.

In addition, I've had the feedback from multiple people who like having a new base package because it makes it very easy to distinguish between "old" JUnit 4 classes and "new" JUnit 5 classes in code.

can't org.junit.api.junit5 be org.junit.api?

I thought about that, but then we'd run into the same problem with JUnit 6 (assuming it has a different programming model). So having api there would allow for org.junit.api.junit5, org.junit.api.junit6, org.junit.api.junit7, etc.

@sbrannen weird to use .junit5 in JUnit 6 then or would it be shaded and both supported? conflicts should be rare IMO so better to avoid the version IMHO

BTW using a different TLD, such as io.junit is not a 100% no-go for me.

What about "org.junit.five" ?

@marcphilipp,

You raise some very valid points there!

A base package name that helps to distinguish the _old_ from the _new_ at a quick glance is certainly beneficial.

In addition, the introduction of a new org.junit.function package in JUnit 4.13 also makes things a bit scary as we move forward. If the two teams coordinate, we should be able to avoid issues, but if something gets overlooked... that could lead to serious issues with the classpath.

With the latter in mind, maybe it's _safest_ and _cleanest_ to go the new TLD route.

Let's mull it over a bit.

As long as you ship org.junit* packages with version=5.x its fine from my perspective. At build time you only should have one junit api on your path and at runtime you leverage OSGi metadata (proper package versioning).

However, if you look for a package name for launcher etc. apis, some suggestions:

  • org.junit.pentagon (nice release name for junit5 anyway). And you can make nice logos with it.

io.junit .. well yes its a hip TLD.. but seriously? junit went from "junit" to "org.junit" in the past which still confuses people. Also, whats next? junit6 moving to "coffee.junit" TLD?

Will keep thinking.

Good idea to draw people in via the tweet btw. Got me into this, too.

@tonit, you say that at build time one should only have one junit api on the classpath, but I highly doubt it's that simple for everyone. I know for instance that the Guava team use both JUnit 3 and 4, I think at least partially because JUnit 4 has features which can't be emulated with GWT, which is one of the platforms that Guava targets.

I don't know anything about OSGi (other than how it fulfils the same role as the upcoming Java 9 Modules system, I think?), so I don't really understand your suggestion for the JUnit team regarding that.

I vote for org.junit5

I currently think it makes most sense to put all the JUnit 5-specific stuff under org.junit.gen5 (or an equivalent name like @tonit's suggestion org.junit.pentagon), and to put all the stuff which is intended to be stable and backwards-compatible, like Launcher and TestEngine, in the org.junit.delta package suggested in Proposal A.

This seems to me to mostly avoid the issue with Proposal B, where adding new packages to JUnit 4 could cause package name conflicts with JUnit 5, which would inadvertently hurt users who want to use JUnit 4 and 5 together (and maybe even users like Guava who currently use both JUnit 3 and 4 and may want to use JUnit 5 as well in the future).

Similar to changing the base to io.junit reminds me of the Jackson change from codehaus to fasterxml. I actually prefer the difference, because if I find it to be a benefit as it is obvious if a class is using an outdated api I want to move off of.

See http://stackoverflow.com/questions/30782706/org-codehaus-jackson-versus-com-fasterxml-jackson-core

@sbrannen I like Proposal B

  • try using versionless packages/classes
  • pack version specific stuff in version specific package (org.junit.api.junit5).
  • put version in className for specific implementations (org.junit.launcher.Junit5EngineExecutionListener)

If it's really needed to choose a package prefix, why not go for org.junit.lambda, since this was the original project name and is also an indicator for the required language level. The idea of modernising the API to reflect the Java 8 language features will be visible with such a naming. It's not containing any version number, so it may be used in future versions too.

+1 for org.junit.lambda although I still can't shake the feeling that JUnit 5 is going to be an awkward upgrade for many users. As a user, what I really want to do is change <version>4.12</version> to <version>5.0</version> and have new features available to me see what classes and methods have been deprecated.

Most of my tests consist of @Test annotations, calls to Assert and the occasional @Rule. I'd love to upgrade to 5.0, change nothing in my tests then start using lambda style assertions and new annotations.

Maybe prefixing only the new stuff can be an option to retain backwards compatibility.

UPDATE

I have overhauled the description of this issue and introduced a third proposal (_Proposal C_) which incorporates feedback provided thus far and takes a different approach to the aforementioned issues. Namely, Proposal C introduces the concept of a _JUnit Platform_ and simultaneously avoids any references to version numbers in package and artifact names by introducing _code names_ for the various programming models supported in different generations of JUnit.

Feedback is welcome!

@junit-team/junit-lambda, the _Proposal C_ is a direct result of our discussion earlier this morning.

@junit-team/junit-committers, your feedback would also be appreciated.

I'm thinking to the "nio" package introduced in the JDK.
java.io is the original package for IO but we all know the java.nio package as new generation of IO utilities.

Why not apply the same concept by replacing gen5 by something like ng => org.junit.ng?

@gdrouet,

The JUnit team naturally considered something like this, but there will always be a _next_ or _new_ generation. Thus such a naming convention wouldn't make sense for subsequent versions of the framework, since their only options would be to call themselves _newer_, _newest_, etc.

Also, "ng" is in direct conflict with _TestNG_. So that's a no-go in terms of naming. ๐Ÿ˜‰

@philwebb said

As a user, what I really want to do is change
4.12 to 5.0
and have new features available to me see what classes
and methods have been deprecated.

Junit 5 doesn't contain any classes from JUnit 4.12 or 3.8.1. So you could have the JUnit 5 jars and the 4.12 jars on the classpath at the same time (in fact you would need to do this if your project uses 4.12 classes or annotations and you wanted to try out the 5.0 extensions in new tests).

I personally think some users will find this confusing

I don't think think the packages should contain numbers. You could imagine having a large release that you would consider a 6.0 release that would involve changes or additions in packages introduced in JUnit Lambda.

I like option C. I really dislike option B.

_Edit: What I don't like about option B is it would be hard to avoid package name conflicts and hard for users to understand which Jar contains which classes._

As for package names, I don't like the name "lambda". Other than the assertion API I don't think there is any features that take advantage of lambdas.

I like the name "jade". Jade is green, and tests should be green.

In fact, since this new release doesn't contain JUnit 4.12 classes, and since it has so many features that support integration tests in addition to unit tests, I've been pushing for naming the project JUnit Jade (or JUnit J@de) and making it a 1.0 release.

I rather like Proposal C as well. I also quite like @kcooney's suggestion for "JUnit Jade" and the imagery it evokes for me. However, if the JUnit team decides to go down this route, care will be needed because apparently Jade is a trademark.

@kcooney, thanks for chiming in!

For what it's worth, the JUnit 5 programming model currently supports lambdas in Assertions, in Assumptions, and more importantly for registering dynamic tests.

And I foresee more lambda related features over time.

So _JUnit Lambda_ is rather fitting in that regard. Now, I'm not saying it's my favorite code name thus far; I'm just saying it's palatable. ๐Ÿ˜‰

Though, _Jade_ also sounds rather cool, and I like the association with _green_. So I'll add it to the proposals. However, if it's trademarked within the software industry that could naturally be problematic.

Didn't realize Jade was trademarked. Sigh

We could go with "JUnit J@de" as the project name (the @ being a nod to having behavior specified via annotations) and "jade" for the package name.

After reading the comment by @sbrannen I also think "lambda" would be a fine package name.

@jbduncan 'epsilon' should be avoided in my opinion because of the math connotation of being very small, i.e. almost zero :)

While we all seem to more or less agree that using 'gen5' within all package names was not a very fortunate idea I still think the original intention behind it has a lot of merit.
I believe it to be important to convey to the larger community that the JUnit lambda effort represents the fifth generation of JUnit, i.e. something newer than the current fourth generation.
The larger community consists at least of hundreds of thousands of developers, both senior and junior ones while the discussion here is taking place among an 'elitist' group of experts. It is certainly appropriate that we discuss some finer points of maintainability and backwards and forwards compatibility issues but in the end we should strive for a very clear message to the general public. In my opinion this message should include a strong reference to the number 5 for the new programming model.

Having read through all the comments I still think the original gen5 was the best choice.

Anyway, keep in mind that any renaming of base packages will break the API promises already made for the Alpha release 4 months ago, e.g.

package org.junit.gen5.api;

@API(Stable)
public @interface Test {
}
public @interface API {
    /**
     * Indicates the level of stability of an API element.
     */
    enum Usage {
        /**
         * Intended for features that will not be changed in a backwards-
         * incompatible way in the current major version.
         */
        Stable
    }

}

I haven't seen a suggestion that feels good enough to make up for breaking the promises.

One more point: Renaming the base package should for consistency reasons also entail a renaming of the github repository. Again.

Anyway, keep in mind that any renaming of base packages will break the API promises already made for the Alpha release 4 months ago, e.g.

IMHO this promise will not take effect before shipping a GA release. Nevertheless, some people will be impacted by this change. But I think it's better to do it now rather than after shipping M1.

Renaming the base package should for consistency reasons also entail a renaming of the github repository. Again.

Unfortunately, yes. We will try to go about this as careful as possible. However, I think we should not worry too much about such short-term inconveniences but rather focus on what provides us with the most flexibility in the long term.

@marcphilipp pointed out that the current JUnit5 Runner is in fact not related to the JUnit 5 programming model but rather to the _Platform_ in general.

I have therefore updated _Proposal C_ accordingly with regard to the junit-platform-runner.

I think @mmerdes has brought up the most important point: "in the end we should strive for a very clear message to the general public. In my opinion this message should include a strong reference to the number 5 for the new programming model."

If the name won't communicate a FORWARD progression from JUnit 4 to whatever comes afterwards in an OBVIOUS WAY you'll confuse the heck out of the ordinary user. I don't see how this is possible without "5" in the name. And a confused user will not move from JUnit 4 to JUnit Something because "What the heck do I care about Something".

Spare yourself and the community the confusion and stick with JUnit 5.

@jlink I suspect an ordinary user would be more confused by a "JUnit 5.0" that didn't Iinclude the JUnit classes they already know and use.

To be clear I don't think JUnit Lambda should be released with the older JUnit classes. Users can use the new code to write new-style tests without upgrading to their existing tests (this is important, because the 4.11 upgrade was particularly painful due to the required Hamcrest upgrade, so some people are likely stuck on 4.10).

@kcooney What do you mean by "a "JUnit 5.0" that (doesn't include) the JUnit classes they already know and use"? Are you implying JUnit 5 contains JUnit 4 classes? Regardless, I'm struggling to understand the point you're trying to make - could you clarify, please?

@JUnit friends - Iโ€™m a small sponsor and silent observer for the past 8ish mths.

Two thoughts:

  • Normal people (assuming Iโ€™m normal) will expect the next version of JUnit to have a number i.e. 5.
  • Normal people will also assume that they can run their existing tests in parallel with the new JUnit 5 features.

Cheers
Mark

@jbduncan the release we are trying to name doesn't include any of the classes released in JUnit 4.12. That is why I think users would be confused if we named it JUnit 5.0.

_Edit:_ in fact, it's possible that JUnit 4.13 would be released in the same timeframe.

As for making it near that whatever we are talking about is the "next generation" of JUnit we can simply say that it is the next generation of JUnit.

p.s. I personally consider JUnit 4 the second generation of JUnit, which happened to be released in version 4.0. The changes between 1.0 and 3.8.1 were incremental.

@kevin et al. Running a Scrum class replying from my phone. Please excuse
brevity.

Pretend I have 4-5000 JUnit 4 tests. How do I move to modern, more elegant
JUnit next world.

I had assumed this would an embrace and extend. If I'm correct, and I might
have misunderstood, the current model forces people to change all of their
tests at once. That would seem to put off JUnit lambada adoption.

Cheers
Mark

@mlevison that concern is very near and dear to my heart because at my company we have several orders of magnitude more tests than that.

If you wanted to keep the old tests as-is but start writing some new tests as "JUnit Lambda" tests then you would need to include the JUnit Lambda jars in your classpath _in addition to_ the JUnit 4.x jar you are using today. There should be no change your existing tests, but you would need to change the way your build system runs your tests to use the new JUnit platform classes.

@kcooney thank you for helping me understand. While I get it, this causes
all sorts of strange questions.

Can existing tests use me assertions? ...

Naming is even harder now.

Back to Scrum class.
Mark

@kcooney thank you for helping me understand. While I get it, this causes all sorts of strange questions.

Can existing tests use me assertions? ...

Me == new.

I.e Can Junit4 tests running in the new world use new assertions? Can new tests use old assertions (ugh)?

โ€ฆ.more mix and match concerns come up.

Cheers

Mark - back to bookkeeping (less fun than JUnit or Scrum :-)

@mlevison that's a bit off topic. Would you mind raising a new issue?

@mlevison, although it's off topic, here are some quick answers to your questions regarding compatibility.

  • It shouldn't matter what assertion library you use: JUnit 4, JUnit 5, AssertJ, etc.
  • On the other hand, _assumptions_ from JUnit 4 and JUnit 5 are incompatible.

    • With JUnit 4 you must use Assume.*; with JUnit 5 you must use Assumptions.*.

    • On a positive note, since JUnit 5's assumption support builds on the Open Test Alliance, that support will compatible with any framework that also builds on the OTA.

Closing this issue since all deliverables have been pushed to master.

Documentation changes will be addressed in #345.

Was this page helpful?
0 / 5 - 0 ratings