For teams that prefer _per-class_ test instance lifecycle semantics, in order to prevent such teams from having to copy-n-paste @TestInstance(Lifecycle.PER_CLASS) across the code base, it would be beneficial to introduce a configuration flag (e.g., system property) that allows the default test instance lifecycle semantics to be set on a per-project basis (e.g., for a build).
Switching the default semantics would remain an opt-in decision but would be considerably less intrusive with the configuration flag.
See https://github.com/junit-team/junit5/issues/419#issuecomment-312001083 for background information.
In addition, we could introduce support for setting ConfigurationParameters via a properties file (e.g., a junit.properties file in the root of the classpath). This would allow such configuration to be contained in the project itself (and checked into a VCS) as opposed to having to set such a flag in the build script as well as in the IDE (perhaps on a per test run basis).
junit.jupiter.testinstance.lifecycle.default configuration parameter for setting default test instance lifecycle semantics.org.junit.jupiter.engine.Constants.TestInstance.Lifecycle, ignoring case.INFO message if the test instance lifecycle mode has been set via the configuration parameter.@TestInstance.Strong +1 for this one and not only from a Kotlin developer perspective, to me @TestInstance(Lifecycle.PER_CLASS) makes sense as the default behavior in Java as well. Since it seems not possible to set that as the default in JUnit 5, being able to set such default globally would be super useful.
Since this issue has been postponed to 5.1 backlog (I can understand there is some concern introducing a different mode of execution of the tests based on configuration), I was wondering if we could find a better alternative solution.
For example, can't we turn this issue into enabling automatically PER_CLASS on classes with non-static methods annotated with @BeforeAll and @AfterAll rather than just failing in such case?
For example, can't we turn this issue into enabling automatically
PER_CLASSon classes with non-static methods annotated with@BeforeAlland@AfterAllrather than just failing in such case?
That's certainly an interesting idea.
But I'm concerned that it would come as a surprise to developers who simply forgot to type static but meant to.
@junit-team/junit-lambda What do the rest of you think?
it would come as a surprise to developers
I agree - I think feature switches that change the default behavior should be specified explicitly.
Ok, I understand.
Is supporting @TestInstance(Lifecycle.PER_CLASS) at package level something we could consider?
I still think making it the default for test classes _written in Kotlin_ would be a clear rule and solve your problem...
@junit-team/junit-committers Thoughts?
@marcphilipp I guess I missed your proposal, but indeed that would be even better, so big +1 for that !!!
The code for detecting Kotlin classes is straightforward and does not need any dependencies:
private static boolean isKotlinClass(Class<?> clazz) {
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
if (annotation.annotationType().getName().equals("kotlin.Metadata")) {
return true;
}
}
return false;
}
I still think making it the default for test classes written in Kotlin would be a clear rule and solve your problem...
@junit-team/junit-committers Thoughts?
I think you meant to address the "JUnit Lambda" team. 😛
In any case, I don't have a problem with making it the default for _classes written in Kotlin_.
Kotlin developers could always explicitly revert back to per-method semantics if desired.
@sdeleuze, thanks for the isKotlinClass() snippet!
FYI: I just created #991 to enable per-class lifecycle semantics by default for Kotlin test classes.
Test classes written in the Kotlin programming language are now executed with
@TestInstance(Lifecycle.PER_CLASS)semantics by default.
I read this in the release notes and was kind of surprised by this change. One of the things that I like about Junit over TestNG is that each test it executed in its own instance of the test. I don't want state to be shared between tests. I write a lot of my unit tests in Kotlin and this change would probably break many of my tests. Not only that but if a user were to go through and convert their Java tests to Kotlin they would end up seeing different results which could lead to quite a bit of confusion.
Is there some reason why this should be the default for kotlin? Personally, I don't think this is the right decision.
https://martinfowler.com/bliki/JunitNewInstance.html
I would personally be fine with this being configurable but having this be the default for junit RC2 is enough to prevent me from moving my tests forward to this release.
Just so everyone is on the same page, this is what it looks like to use PER_METHOD with @BeforeAll/@AfterAll from Kotlin:
@TestInstance(PER_METHOD)
class SimpleKotlinTestCase {
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
println("beforeAll")
}
@JvmStatic
@AfterAll
fun afterAll() {
println("afterAll")
}
}
@BeforeEach
fun beforeEach(testInfo: TestInfo) {
println("beforeEach: " + testInfo)
}
@AfterEach
fun afterEach(testInfo: TestInfo) {
println("afterEach: " + testInfo)
}
@Test
fun firstTest() {
println("firstTest")
}
@Test
fun secondTest() {
println("secondTest")
}
}
Having to declare the companion object and using @JvmStatic did strike us as ugly and non-obvious, thus the change in #991.
It would be great to get a representative survey of all users who use Jupiter with Kotlin. Otherwise, it's very hard to decide this trade-off. Any ideas?
@sdeleuze Did I state your main concerns with using PER_CLASS correctly or did I miss something?
@marcphilipp Yes
If you prefer making it configurable via a global config or a static field, that's would be also fine to me and would be appreciated by a lot of users including non Kotlin ones IMO. What would be a pain would be to specify @TestInstance(PER_CLASS) on each tests.
On the other hand, it's only 4 additional lines, and using @BeforeAll/@AfterAll is not something you need in every test. So, we could solve it with additional documentation on how to use @BeforeAll/@AfterAll with Kotlin in the User Guide. 🤔
If you prefer making it configurable via a global config or a static field, that's would be also fine to me and would be appreciated by a lot of users including non Kotlin ones IMO. What would be a pain would be to specify
@TestInstance(PER_CLASS)on each tests.
How would the static field approach work?
I 100% expect that this is what I would need to do in order to correctly use @BeforeAll and @AfterAll in kotlin given what I know of the language.
The problem with kotlin is that if you don't do this then you end up with lots of code like this:
class `Some class with a nice name` {
lateinit val someList : MutableList<Int>
@BeforeEach
fun beforeEach() {
someList = mutableListOf(30)
}
@Test
fun `test that modifies someList`() {
// Change some list somehow
}
}
VS
The far simpler:
class `Some class with a nice name` {
val someList = mutableListOf(30)
@Test
fun `test that modifies someList`() {
// Change some list somehow
}
}
Having to put lateinit everywhere becomes quite a bit of an annoyance after a while.
You could do something like mockito where they have a config switch that they put in a resource file:
https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable
If you want to enable the mocking of final classes then they expect you to put:
in a file in: src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
If we decide to go that route, we could introduce a general mechanism for reading default ConfigurationParameters from a Properties file, e.g. junit-platform-config.properties (on the classpath).
This file could look like this:
junit.extensions.autodetection.enabled = true
junit.testinstance.lifecycle.default = PER_CLASS
We could read the file when building LauncherConfigurationParameters. Any property passed explicitly to LauncherDiscoveryRequestBuilder (e.g. from an IDE) would override those from the file.
@junit-team/junit-lambda Thoughts?
Well I'm not @Team - however I will take the chance to chime in.
As I said in #991:
I myself would prefer a code based solution - i.e. Declare a static
variable TEST_LIFECYCLE; If doesn't exist the default JUnit semantics
exist; if does exist the declared semantics are used. I would make the
semantics per test runner launch.
I'm always troubled by config files because people often forget to look
there. At least the code based approach has slight better visibility.
Cheers
Mark
On Tue, Aug 1, 2017 at 2:03 PM, Marc Philipp notifications@github.com
wrote:
If we decide to go that route we could introduce a general mechanism for
reading default ConfigurationParameters from a Properties file, e.g.
junit-platform-config.properties.This file could look like this:
junit.extensions.autodetection.enabled = true
junit.testinstance.lifecycle.default = PER_CLASSWe could read the file when building LauncherConfigurationParameters. Any
property passed explicitly to LauncherDiscoveryRequestBuilder (e.g. from
an IDE) would override those from the file.@junit-team/junit-lambda
https://github.com/orgs/junit-team/teams/junit-lambda Thoughts?—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/junit-team/junit5/issues/905#issuecomment-319449357,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAImZsXPDHsb50kD5Aj1wUFXMyrqhhN1ks5sT2hYgaJpZM4OJj_E
.
--
[image: headshot-square-300x300]
http://www.flickr.com/photos/36331075@N00/9674877046/ Mark Levison | 1
(877) 248-8277 | Twitter https://twitter.com/mlevison | LinkedIn
http://ca.linkedin.com/in/marklevison | Facebook
https://www.facebook.com/agilepainrelief
Certified ScrumMaster Training: Vancouver
http://agilepainrelief.com/courses/vancouver | Edmonton
http://agilepainrelief.com/courses/edmonton | Ottawa
http://agilepainrelief.com/courses/ottawa | Montreal
http://agilepainrelief.com/courses/montreal | Toronto
http://agilepainrelief.com/courses/toronto
Certified Product Owner & Private Training also available ~ Our Training
Schedule http://agilepainrelief.com/courses/certified-scrum-agile-training
Agile Pain Relief Consulting http://agilepainrelief.com/ | Notes from a
Tool User http://agilepainrelief.com/notesfromatooluser
Proud Sponsor of Agile Tour Gatineau Ottawa http://goagiletour.ca/ and Agile
Coach Camp Canada http://agilecoachcampcanada.wordpress.com/
@mlevison Can you please sketch that out in a bit more detail?
On Tue, Aug 1, 2017 at 2:07 PM, Marc Philipp notifications@github.com
wrote:
@mlevison https://github.com/mlevison Can you please sketch that out in
a bit more detail?
​Here's a quick stab:
public enum TestLifeCycle { PER_INSTANCE, PER_CLASS }
@TEST_LIFE_CYCLE
static final ​TestLifeCycle VAR_NAME_DOESNT_MATTER = PER_CLASS;
If the runner finds this initialized more than once it throws an exception.
I cringe at using a global variable, however it seems marginally better
than a config file. Both seem better than a different default for Kotlin.
Cheers
Mark
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/junit-team/junit5/issues/905#issuecomment-319450480,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAImZvHgC2fW4r0MrT7M7ONXbsi19J3-ks5sT2lMgaJpZM4OJj_E
.
--
[image: headshot-square-300x300]
http://www.flickr.com/photos/36331075@N00/9674877046/ Mark Levison | 1
(877) 248-8277 | Twitter https://twitter.com/mlevison | LinkedIn
http://ca.linkedin.com/in/marklevison | Facebook
https://www.facebook.com/agilepainrelief
Certified ScrumMaster Training: Vancouver
http://agilepainrelief.com/courses/vancouver | Edmonton
http://agilepainrelief.com/courses/edmonton | Ottawa
http://agilepainrelief.com/courses/ottawa | Montreal
http://agilepainrelief.com/courses/montreal | Toronto
http://agilepainrelief.com/courses/toronto
Certified Product Owner & Private Training also available ~ Our Training
Schedule http://agilepainrelief.com/courses/certified-scrum-agile-training
Agile Pain Relief Consulting http://agilepainrelief.com/ | Notes from a
Tool User http://agilepainrelief.com/notesfromatooluser
Proud Sponsor of Agile Tour Gatineau Ottawa http://goagiletour.ca/ and Agile
Coach Camp Canada http://agilecoachcampcanada.wordpress.com/
Please don't make this a global setting. People writing or reading a test won't remember to look for the global setting (this will be particularly bad in large codebases). In addition, it will be difficult to find a way to set global settings that will work in IDEs and build tools.
Ok. So without judgement, let's enumerate the options
I consider the Static Variable to be a close relative of the Properties
file.
Are there any options we're not considering?
Cheers
Mark
On Tue, Aug 1, 2017 at 7:40 PM, Kevin Cooney notifications@github.com
wrote:
Please don't make this a global setting. People writing or reading a test
won't remember to look for the global setting (this will be particularly
bad in large codebases). In addition, it will be difficult to find a way to
set global settings that will work in IDEs and build tools.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/junit-team/junit5/issues/905#issuecomment-319526923,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAImZppS3MhkuHBREaWByFYlYMN8fZ6jks5sT7d4gaJpZM4OJj_E
.
--
[image: headshot-square-300x300]
http://www.flickr.com/photos/36331075@N00/9674877046/ Mark Levison | 1
(877) 248-8277 | Twitter https://twitter.com/mlevison | LinkedIn
http://ca.linkedin.com/in/marklevison | Facebook
https://www.facebook.com/agilepainrelief
Certified ScrumMaster Training: Vancouver
http://agilepainrelief.com/courses/vancouver | Edmonton
http://agilepainrelief.com/courses/edmonton | Ottawa
http://agilepainrelief.com/courses/ottawa | Montreal
http://agilepainrelief.com/courses/montreal | Toronto
http://agilepainrelief.com/courses/toronto
Certified Product Owner & Private Training also available ~ Our Training
Schedule http://agilepainrelief.com/courses/certified-scrum-agile-training
Agile Pain Relief Consulting http://agilepainrelief.com/ | Notes from a
Tool User http://agilepainrelief.com/notesfromatooluser
Proud Sponsor of Agile Tour Gatineau Ottawa http://goagiletour.ca/ and Agile
Coach Camp Canada http://agilecoachcampcanada.wordpress.com/
Hi everybody,
I'm on vacation and in a hurry, so please excuse the _brevity_ of my response (and don't take offense at choppy answers).
I think the "static field" is a bad idea: we already have a dedicated annotation for this feature.
It's a no-brainer to create dedicated _composed annotations_ like @TestInstancePerClass or @TestInstancePerMethod, but I fail to see how this is any better than the already supported @TestInstance(PER_CLASS) and @TestInstance(PER_METHOD) (with static imports for ...Lifecycle.*).
Regarding having different default semantics per programming language, I have to agree that this is probably not the best idea.
Allowing @TestInstance to be declared on a _package_ is something that I consider a viable addition to the current programming model.
Having a global properties file (in the classpath) to back JUnit's configuration parameters is something I have been pushing for for almost two years now. So I am obviously in favor of that option.
In summary, sensible defaults that are consistent across programming models should be a must.
Providing convenient ways to override the test instance lifecycle semantics for a package (and its subpackages) or for an entire project should not be cumbersome.
Please don't make this a global setting. People writing or reading a test won't remember to look for the global setting (this will be particularly bad in large codebases).
Documenting the default behavior and logging a user-configured _global_ value address this issue.
If users don't read the documentation _and_ ignore log output, that's their problem.
In addition, it will be difficult to find a way to set global settings that will work in IDEs and build tools.
A global properties file in the classpath solves this problem elegantly.
If you prefer making it configurable via a global config or a static field, that's would be also fine to me and would be appreciated by a lot of users including non Kotlin ones IMO. What would be a pain would be to specify
@TestInstance(PER_CLASS)on each tests.
Just to reiterate: I don't see how having to declare a static field with some special name in a test class is any better, shorter, or more intuitive than annotating a test class with @TestInstance(PER_CLASS). Plus, the annotation declaration is _intuitively_ inherited within test class hierarchies as well as from implemented test interfaces.
On Wed, Aug 2, 2017 at 3:51 PM, Sam Brannen notifications@github.com
wrote:
If you prefer making it configurable via a global config or a static
field, that's would be also fine to me and would be appreciated by a lot of
users including non Kotlin ones IMO. What would be a pain would be to
specify @TestInstance(PER_CLASS) on each tests.Just to reiterate: I don't see how having to declare a static field with
some special name in a test class is any better, shorter, or more intuitive
than annotating a test class with @TestInstance(PER_CLASS). Plus, the
annotation declaration is intuitively inherited within test class
hierarchies as well as from implemented test interfaces.
​The only reason was people have to remember to set ​
@TestInstance(PER_CLASS). - at this stage I don't think any of the
solutions are ideal.
What has bothered me - most of JUnit 5 can be learned by reading a trivial
amount of documentation and mimicking what you see elsewhere. I like this
about JUnit 5 - simple to learn.
This is one of those features where we just to rely on people reading the
documentation.
Must run and be a parent
Cheers
Mark
Just to put a timeline on this issue. A consensus should be reached before 5.0.0 is released. After that, changing the way kotlin tests behave will be a breaking change and (if following semver) would require a 6.0.0 release before it could be changed safely.
If users don't read the documentation and ignore log output, that's their problem.
Some users learn better by example and by searching for answers than by reading a guide. Users might see an example test in StackOverflow or in a blog, try it in their project, and it might fail if their project as a global setting specifying all tests use "Lifecycle.PER_CLASS". Even if you log something, novice users might not realize that their test isn't passing because of something called Lifecycle.
So the first problem is that you should be able to understand a test by reading the code of the test. A global setting to set the default lifecycle violates this.
The second problem is that with Lifecycle.PER_CLASS you have to be very careful to not share state between test methods. You end up having to put code in @BeforeEach methods to assign fields, when with a "normal" Java class would assign the field at declaration time (and make the field final).
I wonder if we should think about this in a different way. The issue for Kotlin users is that @AfterAll and @BeforeAll methods must be static. This has been something that many users of JUnit4 have been complaining about, too. The problem is we still want most tests to use the per-instance strategy.
Could we use parameter resolvers to solve this? Perhaps if your class has constructor with a parameter annotated with @PerClass, the JUnit will create it once per run of the test class, using the default constructor of the class (in Kotlin, the primary constructor). That class can have _non-static_ methods annotated with @BeforeAll, @AfterAll, @BeforeEach or @AfterEach:
class SimpleKotlinTestCase constructor(@PerClass db: Database) {
class Database {
@BeforeAll fun createDatabase() {
}
@AfterAll fun dropDatabase() {
}
@BeforeEach fun clearDatabase() {
}
fun insert(id: Int, account: Account) {
}
}
@Test
fun insertAccount() {
val account = ...
db.insert(1, account);
...
}
}
Perhaps instead of adding an annotation to the constructor parameter, the class that is passed in could have a class-level annotation (that might make more sense, since often these classes will be shared).
I guess this is a matter of taste but PER_CLASS is the behavior a lot of developers want and most developers I know are not aware that JUnit instantiate class per test and already ensure that not shared state is shared in their test class fields.
If enabling this mode for Kotlin by default is a blocker for some of you, providing a configuration flag will allow everybody to use the behavior they like + make Kotlin developer happy, no need to introduce nested classes for that IMO, that not much less verbose than the companion object thing.
I'm a fan of this suggestion:
https://github.com/junit-team/junit5/issues/905#issuecomment-320170677
This would need to be documented well but once you read it it's pretty clear.
The companion object route should still work for people that want to go that route.
To me this suggestion should be a distinct feature (so different issue), is not more or less appealing than the companion object one, and does not help for Kotlin developers that want PER_CLASS by default which will make sense for most people IMO so it does not prevent to provide a flag to change the default mode.
@sbrannen
Having a global properties file (in the classpath) to back
JUnit's configuration parameters is something I
have been pushing for for almost two years now.
Is there an Issue tracking this? If not, I think we should create it and discuss that aspect of this proposal there.
Is there general consensus from the team that the current implementation of having kotlin code by default use the PER_CLASS configuration should be reverted so it is the same as Java code?
If there is not consensus not should we move that particular decision to a new thread? This thread seems to be particular to adding some sort of global configuration, not about the specifics of the behaviour of kotlin.
@sdeleuze wrote:
does not help for Kotlin developers that want PER_CLASS by default
Some users want PER_INSTANCE for Kotlin by default (@JLLeitschuh for example).
@sbrannen wrote:
Regarding having different default semantics per programming language, I have to agree that this is
probably not the best idea.
I agree. It's one thing to not expect that PER_INSTANCE is the default for JUnit. It's another thing to lean that and later get bitten because you didn't realize that JUnit has a different default for Kotlin.
@sbrannen wrote:
Allowing @TestInstance to be declared on a package is something that I consider a viable addition
to the current programming model.
It appears that Java will only initialize Package objects when first loading a class from the package (see https://github.com/junit-team/junit4/pull/1423#issuecomment-284252612). That might be a problem.
@JLLeitschuh
Is there general consensus from the team that the current implementation of having kotlin code by
default use the PER_CLASS configuration should be reverted so it is the same as Java code?
I would agree on this, but I'm on the JUnit4 team, not the JUnit5 team, so it's not really my call :-)
I worry we will probably not get a resolution on this in the 5.0.0 time frame. There have been discussions for years in the JUnit4 project about globally changing behavior, and we haven't been able to get to a resolution.
I suggest
TestInstance as Java testsCan't we consider just supporting @TestInstance at package level since it would not introduce a new mechanism, just extend existing one?
Can't we consider just supporting @TestInstance at package level since it would not introduce a new mechanism, just extend existing one?
Supporting annotations on the package level would actually mean introducing a new mechanism.
I worry we will probably not get a resolution on this in the 5.0.0 time frame. There have been discussions for years in the JUnit4 project about globally changing behavior, and we haven't been able to get to a resolution.
There's no need to worry. Since Eclipse has just pushed back on the Oxygen service release they will include JUnit 5 support, we've changed our plan to have another RC to be released on August 24, and GA on September 6. The lack of progress comes from the whole JUnit 5 team currently being on vacation. 😉
Is there general consensus from the team that the current implementation of having kotlin code by
default use the PER_CLASS configuration should be reverted so it is the same as Java code?
Yes, there is a consensus within the team. The decision to change the default for Kotlin was done overly hasty on my part. I will create a separate issue to revert this change. EDIT: #1002
As far as this issue is concerned, we still plan to add a configuration parameter to change the behavior globally. The mechanisms to change behavior globally is already in place, we'll just have to read another parameter in the Jupiter engine. Reading default config parameter values from a file on the classpath is a different issue and will probably not make it into 5.0. I will also create another issue for the config file targeting 5.1. EDIT: #1003
Thanks for the update, @marcphilipp
Hope you had a relaxing vacation
we'll just have to read another parameter in the Jupiter engine
Sorry, I am sadly not very familiar with the Jupiter engine code. What does changing this mean for the typical user of JUnit?
AFAIK, @marcphilipp is unreachable for about two weeks starting.... about 15 minutes ago. 😉
Sorry, I am sadly not very familiar with the Jupiter engine code. What does changing this mean for the typical user of JUnit?
The JUnit Platform provides first-class support for what we call "configuration parameters". ConfigurationParameters can be supplied to the Launcher or via JVM system properties, and config params can be read by any TestEngine.
At the moment, JUnit Jupiter supports two such config params.
junit.conditions.deactivatejunit.extensions.autodetection.enabledNote, however, that both of these were renamed just a few minutes ago in #1004.
To answer your question, _this change_ means that a user can set the junit.jupiter.testinstance.lifecycle.default configuration parameter to PER_CLASS to change the default for the current TestPlan execution, and that would apply to any test class executed with the JUnit Jupiter test engine.
Updated _Deliverables_.
_in progress_
Updated _Related Issues_
@sbrannen thanks for the explanation
I'm not to trilled with the idea of specifying the lifecycle semantics via a system property. That would likely lead to the possibility the setting being different when tests are run via a build tool vs when debugging in an IDE. Using a config file stored as a Java resource would be preferable. Regardless, a warning in the docs might be a good idea.
@JLLeitschuh FYI: I created #1006 to track my proposal in https://github.com/junit-team/junit5/issues/905#issuecomment-320170677
FYI: for anyone interested in the progress on this issue...
Here's the code: https://github.com/junit-team/junit5/commit/a916e47e2c2b1cfedff83e570cce912726d7ef11
All that's left is documentation.
In a Gradle project like https://github.com/sdeleuze/spring-kotlin-functional, what would be the recommended way to change the default to PER_CLASS with this improvement?
Is there a way to set the configuration parameter at Gradle level? Or should I set a system property?
Hi @sdeleuze,
Unfortunately there is currently no native support for setting a _configuration parameter_ via the console launcher, Maven Surefire plugin, or Gradle plugin.
Thus, the only option from the build perspective is to set a system property.
For the JUnit Platform Gradle Plugin, you can achieve that as discussed here: https://github.com/junit-team/junit5/issues/475#issuecomment-242038043.
@sdeleuze,
FYI: I raised #1015 to address the lacking support for setting configuration parameters with the Gradle plugin.
Resolved in master in commit f750c85946939119d05966c65fc81ce68444b2b9.
How does that constant work when running tests in IntelliJ? Will IntelliJ pickup that the gradle plugin has that default configured?
How does that constant work when running tests in IntelliJ?
Unless IntelliJ provides explicit support for setting _configuration parameters_ to pass to the JUnit Platform Launcher (and I don't think it does yet), your only option (currently) is to set the configuration parameter as a JVM system property for the run configuration in IDEA (or whatever it's called in IDEA -- "run configuration" is the term in Eclipse).
Will IntelliJ pickup that the gradle plugin has that default configured?
Nope. There's currently no explicit support for setting configuration parameters in the Gradle plugin (although there _is_ a work-around). That will be addressed in #1015.
However, the best (i.e., the only _robust_) solution is the use of the JUnit Platform _configuration file_ which I'll be committing soon in conjunction with #1003. 😉
@sdeleuze,
In Gradle project like https://github.com/sdeleuze/spring-kotlin-functional, what would be the recommanded way to change the default to PER_CLASS with this improvement? Is there a way to set the configuration parameter at Gradle level ? Or should I set a system property ?
Now that I've resolved #1003, you can give the _configuration file_ approach a try against the latest snapshots.
If you do try it out, please let us know how it works for you.
Cheers
@sbrannen Works as expected, and seems a good outcome, thanks !!! https://github.com/sdeleuze/spring-kotlin-functional/commit/7aef2209231760d539fffe50ddf7e6ca30b05560
Works as expected, and seems a good outcome, thanks !!! sdeleuze/spring-kotlin-functional@7aef220
Cool!
Thanks for letting us know.
Most helpful comment
Some users learn better by example and by searching for answers than by reading a guide. Users might see an example test in StackOverflow or in a blog, try it in their project, and it might fail if their project as a global setting specifying all tests use "Lifecycle.PER_CLASS". Even if you log something, novice users might not realize that their test isn't passing because of something called Lifecycle.
So the first problem is that you should be able to understand a test by reading the code of the test. A global setting to set the default lifecycle violates this.
The second problem is that with
Lifecycle.PER_CLASSyou have to be very careful to not share state between test methods. You end up having to put code in@BeforeEachmethods to assign fields, when with a "normal" Java class would assign the field at declaration time (and make the field final).I wonder if we should think about this in a different way. The issue for Kotlin users is that
@AfterAlland@BeforeAllmethods must be static. This has been something that many users of JUnit4 have been complaining about, too. The problem is we still want most tests to use the per-instance strategy.Could we use parameter resolvers to solve this? Perhaps if your class has constructor with a parameter annotated with
@PerClass, the JUnit will create it once per run of the test class, using the default constructor of the class (in Kotlin, the primary constructor). That class can have _non-static_ methods annotated with@BeforeAll,@AfterAll,@BeforeEachor@AfterEach:Perhaps instead of adding an annotation to the constructor parameter, the class that is passed in could have a class-level annotation (that might make more sense, since often these classes will be shared).