junit-team / junit5

✅ The 5th major version of the programmer-friendly testing framework for Java and the JVM
https://junit.org
Other
6.23k stars 1.44k forks source link

Introduce mechanism to enable specific global extensions in JUnit Jupiter #3717

Open translatenix opened 4 months ago

translatenix commented 4 months ago

Enabling all global extensions on the class/module path with junit.jupiter.extensions.autodetection.enabled=true is asking for surprises (and potentially trouble).

Instead, I'd like to explicitly enable the global extensions that I want to use.

I imagine that I'd do this by setting junit.jupiter.extensions.autodetection.enabled=foo.bar.Baz,foo.bar.Qux or a similar property.

If the JUnit team is open to this idea, I'd be happy to discuss further and send a PR.

sbrannen commented 4 months ago

Thanks for the proposal, @translatenix.

We'll discuss it within the team during an upcoming team call and get back to you.

marcphilipp commented 3 months ago

Team decision: Introduce junit.jupiter.extensions.autodetection.include and junit.jupiter.extensions.autodetection.exclude configuration parameters with defaults of * and empty, respectively.

marcphilipp commented 3 months ago

Addendum: The new properties should support the same pattern matching syntax supported for other configuration parameters.

bjmi commented 3 months ago

One use case would be to enable org.mockito.junit.jupiter.MockitoExtension from org.mockito:mockito-junit-jupiter globally by default. This would activate strict stubbing then. https://github.com/mockito/mockito/issues/769.

dev-jonghoonpark commented 1 month ago

Can I Contribute?

sbrannen commented 1 month ago

Hi @dev-jonghoonpark,

Can I Contribute?

Yes, feel free to submit a PR for review.

dev-jonghoonpark commented 1 month ago

@marcphilipp

Team decision: Introduce junit.jupiter.extensions.autodetection.include and junit.jupiter.extensions.autodetection.exclude configuration parameters with defaults of * and empty, respectively.

It seems like junit.jupiter.extensions.autodetection.include and junit.jupiter.extensions.autodetection.exclude should be designed to accept more than one input, is that correct?

I think it should be able to accept multiple folders and multiple classes.

sbrannen commented 1 month ago

Yes, comma-separated entries with wildcard matching.

dev-jonghoonpark commented 1 month ago

hello.

I've been thinking about how to implement this feature, and I've come up with 2 approaches.

Basically, both approaches involve replacing the extension that is registered in registerAutoDetectedExtension method.


1st approach

https://github.com/junit-team/junit5/compare/main...dev-jonghoonpark:junit5-forked:implement-all-callbacks

Create an AutoDetectedExtension that implements all possible callbacks.

Let the AutoDetectedExtension contain the originalExtension and perform the callbacks when conditions are matched.

Disadvantages :

2nd approach

https://github.com/junit-team/junit5/compare/main...dev-jonghoonpark:junit5-forked:use-proxy

Use a proxy to intercept the callback function when it is executed and check the path. If it matches the conditions, perform the callback.

Disadvantages :


I'm going to try the first of the two approaches, what do you think? (Note that the above code is just written to check the approach, it's not the finished code).

If you have a better way, I'd love to hear about it, even if it's a completely different approach.

Thank you.

marcphilipp commented 2 weeks ago

@dev-jonghoonpark Thanks for looking into this and sorry for not getting back to you sooner!

Auto-registration of extensions is already implemented here: https://github.com/junit-team/junit5/blob/89a0201073efd12b0732ceaeba52c6d7d7029f3a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java#L78-L80

Therefore, all that should be needed is to implement filtering of the classes loaded via ServiceLoader based on the two new configuration parameters before calling registerAutoDetectedExtension: https://github.com/junit-team/junit5/blob/89a0201073efd12b0732ceaeba52c6d7d7029f3a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java#L85-L88

For the filtering, exclusions are already implemented in ClassNamePatternFilterUtils and you'll have to add support for inclusions.

Please let me know if you have any questions.