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
Allow to run some tests isolated #2142
Comments
Reminds me of the discussion we had in #1634 (comment) and the following comments. Do you have to set the |
It is actually stored in a
This is exactly what we are looking for. A way to run some tests that can change the environment separately from all tests that have read-only access to the environment. |
@pbludov What setting do you use for parallel execution of your top level classes? Do they run in parallel as well or sequentially? When they run sequentially, you could consider to move the test which alter the system state to a separate top level class in which you execute all methods sequentially. Another approach to this problem could be that all classes and tests annotated with ExecutionMode.SAME_THREAD are executed and completed before tests marked with ExecutionMode.CONCURRENT will start. |
The config is <properties>
<!-- execute top-level classes in parallel but methods in same thread -->
<configurationParameters>
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.classes.default = concurrent
junit.jupiter.execution.parallel.mode.default = same_thread
</configurationParameters>
</properties> The behavior I'm currently observing:
Did I understand correctly that if I explicitly mark all tests as either |
Currently not. I didn't make clear enough that this might be a possible way to implement this feature in JUnit instead of using ResourceLocks. |
It looks like we need this in Apache JMeter as well. Is there a way to understand the effective locks used for the test? For instance, what if I add an interface like the following @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
@ResourceLock(value = Resources.TIME_ZONE, mode = ResourceAccessMode.READ)
interface CommonReadLocks {
} then I make the sensitive tests to implement that interface and then add the relevant Would that work? I would expect that method-level annotations would override "inherited ones". So the engine should probably be able to schedule methods as appropriate. The sad thing is it is not clear how to cross-check if annotations work as expected. |
We could log them or send report entries for them. Would that help you?
In order to avoid deadlocks, locks are currently pulled up to the first node in the test tree that declares a lock. In your example that would mean that all implementations of |
Over at JUnitPioneer (@vlsi, @pbludov: you may want to check out our
While we arrived there independently of one another, our problem and analyses are identical and @pbludov suggested the same solution. I think this is worth looking into. |
@leonard84 had a similar use case recently, right? |
Yes, I'm currently adding parallel support to Spock and we have an extension @ConfineMetaClassChanges for tests that manipulate one or more meta classes in groovy, this is by its nature a global change potentially affecting all other tests. The extension automatically sets the So a way to mark a test/class to run in a global exclusive mode would be a nice solution for this kind of problems. A possible implementation would be that each test acquires either a |
I'd really like to see an official solution, so maybe I'm shooting myself in the foot, but there's a fairly straightforward way for us to solve this without onboard support:
|
It must be safe to use Pioneer's extensions in a test suite that is executed in parallel. This change enables that for all extensions except TempDirectory (see #227). It does that in various ways. # Resource locks For extensions touching global state (like default locales or environment variables), we've chosen the following approach: * the extension acquires a read/write lock to the global resource (this prevents extended tests from running in parallel) * we offer a `@Writes...` annotation that does the same thing, so users can annotate their tests that write to the same resource and prevent them from running in parallel with each other and with extended tests * we offer a `@Reads...` annotation that acquires read access to the same lock, so users can make sure such tests do not run in parallel with tests that write to the same resource (they can run in parallel with one another, though) # Verify, then modify Most extensions verify their configuration at some point. It helps with writing parallel tests for them if they do not change global state until the configuration is verified. That particularly applies to "store in beforeEach - restore in afterEach"-extensions! If they fail after "store", they will still "restore" and thus potentially create a race condition with other tests. # Testing To have a better chance to discover threading-related problems in our extensions, we parallelize our own tests (configured in `junit-platform.properties`). Ideally, we'd like to run them in parallel _across_ and _within_ top-level classes, but unfortunately, this leads to problems[1] when some test setups change global state (like the security manager) that other tests rely on. As we see it, the solution would be to force such tests onto a single thread, but Jupiter has no such feature, yet[2]. While a homegrown solution is possible[3], we wait for the discussion to resolve. We hence do not parallelize across top-level classes - just within. Closes: #131 Relates to #274 PR: #253 [1]: #253 (comment) [2]: junit-team/junit5#2142 [3]: junit-team/junit5#2142 (comment)
@leonard84 and I started working on an implementation today. We added an |
This commit introduces a new global resource lock that all test descriptors that are direct children of the engine descriptor acquire by default in READ mode. Using the `@Isolated` annotation in the Jupiter API causes the mode to be changed to READ_WRITE. Resolves #2142. Co-authored-by: Leonard Brünings <lord_damokles@gmx.net>
It must be safe to use Pioneer's extensions in a test suite that is executed in parallel. This change enables that for all extensions except TempDirectory (see #227). It does that in various ways. # Resource locks For extensions touching global state (like default locales or environment variables), we've chosen the following approach: * the extension acquires a read/write lock to the global resource (this prevents extended tests from running in parallel) * we offer a `@Writes...` annotation that does the same thing, so users can annotate their tests that write to the same resource and prevent them from running in parallel with each other and with extended tests * we offer a `@Reads...` annotation that acquires read access to the same lock, so users can make sure such tests do not run in parallel with tests that write to the same resource (they can run in parallel with one another, though) # Verify, then modify Most extensions verify their configuration at some point. It helps with writing parallel tests for them if they do not change global state until the configuration is verified. That particularly applies to "store in beforeEach - restore in afterEach"-extensions! If they fail after "store", they will still "restore" and thus potentially create a race condition with other tests. # Testing To have a better chance to discover threading-related problems in our extensions, we parallelize our own tests (configured in `junit-platform.properties`). Ideally, we'd like to run them in parallel _across_ and _within_ top-level classes, but unfortunately, this leads to problems[1] when some test setups change global state (like the security manager) that other tests rely on. As we see it, the solution would be to force such tests onto a single thread, but Jupiter has no such feature, yet[2]. While a homegrown solution is possible[3], we wait for the discussion to resolve. We hence do not parallelize across top-level classes - just within. Closes: #131 Relates to #274 PR: #253 [1]: junit-pioneer/junit-pioneer#253 (comment) [2]: junit-team/junit5#2142 [3]: junit-team/junit5#2142 (comment)
We have one test that changes the global state, for example
and hundreds of tests that reads the state:
After enabling parallel test execution our tests start to fail at random locations with messages like that:
[ERROR] message 0 expected:<...Annotation.java:17: [Annotation 'AnnotationAnnotation' have incorrect indentation level 2, expected level should be 0].> but was:<...Annotation.java:17: [Die Annotation 'AnnotationAnnotation' hat eine unerwartete Einrückungstiefe von 2 (erwartet: 0)].>
@Execution(ExecutionMode.SAME_THREAD)
for the testlocaleTest
won't help us, since the all other tests are able to run concurrent with every other test and withlocaleTest
too.This can be solved with
@ResourceLock
:but this is error prone, since adding a new Test without this annotation will produce a flaky tests which may fail.
It will be much better to mark some tests as "incompatible with parallel execution at all":
As a workaround, it is possible to turn such a test into Junit 4 test, which will be executed in other universe, isolated from all other.
The text was updated successfully, but these errors were encountered: