-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Support DiscoverySelectors.selectMethod(String)
without declaring parameters
#3940
Comments
DiscoverySelectors.html#selectMethod(java.lang.String)
without declaring parametersDiscoverySelectors.selectMethod(java.lang.String)
without declaring parameters?
Hi @stdedos, It seems you ignored the following when creating this issue.
Thus, have you tried this yourself? The reason I'm asking is that we would be grateful if people tried things before asking if something works. Otherwise, such issues waste people's time. In any case, if I recall correctly, If you leave off the parameter types, it's the same as specifying
Well, if it selected more than one method, that would be wrong, since its contract is to select a single method. Having said that, we do actually have some fuzzy logic for selecting a method by fully-qualified name with So, I suppose we could consider introducing support similar to that for Would that suit your needs? |
No, not really 😅 (PS: "edit" my OP)
Yes, I have. I have called
From the exception it seems like it, yes 😅
I don't mind even if it was I don't see a more "generic" way to match parameters (from my limited understanding, hence the question), and I cannot have automation helping me on this one (like e.g. an IDE action that introspects the code and outputs the appropriate format). |
DiscoverySelectors.selectMethod(java.lang.String)
without declaring parameters?DiscoverySelectors.selectMethod(String)
without declaring parameters
OK. Thanks for letting us know. For the record, your original title and wording of the description made it sound like you were asking a simple "how does this work?" question rather than making a proposal. In the future, it would be helpful if you pointed out that you had already tried it and were proposing an enhancement.
I imagine we could introduce something like one of the following (likely also with
The Thoughts? |
I have never used JUnit "from the developer's viewpoint" (only for running/writing tests). I "guessed" that you should have some more versatile methods that do not require specifying everything. I understand there might be valid reasons why callers must define everything (e.g., maybe it's trivial for an IDE using So yes, this began as a "probing question" in Matrix, moved here, and evolved into an accepted enhancement proposal 🎉
In my case, I want to use user input to it - I cannot think how to use the
would select it? That looks amazing 😍 I would consider whether auto-surrounding with Will anything else be supported? Note that I am not trying to blow up the scope - the smallest, fastest, "more aligned to the project's goals". Please consider writing (all) the usage examples you can think of in the documentation (and/or test them) 🙏 |
Normally, people need to be able to select all test methods within a test class via one of the I don't recall anyone ever having asked for the ability to select multiple methods based on a single "input" (for example, a pattern). Though, I can see how that could be useful.
Well, we have not yet officially "accepted" it (hence no milestone assignment), but we are certainly open to exploring the possibilities. 😉
If we go with any sort of official "pattern" support, that would almost certainly delegate to the
Thanks for brainstorming! Those are certainly some interesting ideas.
Regarding that, I don't foresee how that would be possible. We'd have to have a
That remains to be seen. I'll add a follow-up comment to address some of my concerns about implementation details.
Understood.
Yes, we would definitely document example usage. |
After putting a bit more thought into it, I have some concerns about the above proposal. A It's up to a So, by the time a test engine processes a To support predicates/patterns while simultaneously ensuring that a That might work, but it would mean that this feature would only work for Java methods. In other words, it would not be a generic "select methods by pattern" feature that could be used for other programming languages or other use cases. Thus, in order to provide generic support for selecting potentially multiple methods based on a pattern or predicate, I think we might need to introduce a new type of But... a new type of In other words, if we introduce a new |
I see. At least I would hope that every half-decent IDE can provide a "Copy Reference" action (though it seems to not focus on arguments) - so fqdn would be fine. I wonder if a minified but unique FQDN would work for "less manual typing": e.g.
If it looks like a full development work rather than "patchwork", then of course please weight cost/benefits 🙏 It seems we are using |
Yes, I think most modern IDEs provide that functionality.
That would require scanning of the classpath to find candidate classes, which I still think would be a no-go (at least as a first-class feature in JUnit).
To provide generic support suitable for use with different test engines and programming languages, it might turn out to be "full development work"; however, if you wanted to implement it yourself, it turns out it's not that hard. I'll demonstrate in a subsequent comment. |
Luckily the factory methods in Along those lines, I spiked a custom implementation of Given the following test class... package example;
class ExampleTestCase {
@Test
void aardvark() {
}
@Test
void anaconda() {
}
@Test
void bat() {
}
@Test
void cat() {
}
} ... and the following ... import java.lang.reflect.Method;
import java.util.function.Predicate;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.PreconditionViolationException;
import org.junit.platform.commons.support.HierarchyTraversalMode;
import org.junit.platform.commons.support.ReflectionSupport;
import org.junit.platform.commons.util.ReflectionUtils;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.engine.discovery.MethodSelector;
import org.junit.platform.testkit.engine.EngineTestKit;
import org.junit.platform.testkit.engine.Event;
class SelectMethodsByPatternTests {
@Test
void verifyAllJupiterEvents() {
EngineTestKit.engine("junit-jupiter")//
.selectors(selectMethods("example.ExampleTestCase#(aa.+|bat)"))//
.execute()//
.testEvents()//
.finished()//
.stream()//
.map(Event::getTestDescriptor)//
.map(TestDescriptor::getDisplayName)//
.sorted()
.forEach(System.err::println);
}
public static MethodSelector[] selectMethods(String fullyQualifiedMethodNamePattern) {
String[] methodParts = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodNamePattern);
String className = methodParts[0];
Class<?> javaClass = ReflectionSupport.tryToLoadClass(className)//
.getOrThrow(
cause -> new PreconditionViolationException("Could not load class with name: " + className, cause));
String methodNamePattern = methodParts[1];
Predicate<Method> predicate = method -> method.getName().matches(methodNamePattern);
return ReflectionSupport.streamMethods(javaClass, predicate, HierarchyTraversalMode.TOP_DOWN)//
.map(method -> DiscoverySelectors.selectMethod(javaClass, method))
.toArray(MethodSelector[]::new);
}
} Running that runs/prints the following to the console, thanks to the custom selector:
Using
etc. |
Given how simple this looks, I wonder if I should spike a layer, that would "do what I want it to do", and use that as an input to the current API instead 🤔 |
YES! That's certainly a viable option and perhaps what the team may end up recommending in the end. 😉 In any case, this is flagged for "team discussion", and we'll discuss it in the coming weeks. But... beware: |
WDYM? 😅 Worst-case, I can just ... copy-paste the code and use it, right? 😕 (or idk what the issue is, and I am "answering" a different question in my head) |
That means that we reserve the right to change and/or remove any functionality whenever we deem it appropriate.
In other words, it's "use at your own risk", as the Javadoc states.
It of course depends on how you you plan to use it, based on the license, but I am not a lawyer and cannot give advice about licenses, etc. In any case, you can literally just split the input string as you see fit -- for example, using |
I am planning to ... not distribute it. So I should be good, right? 😅 (I heard the IANAL 👌)
Keeping these in mind 👍 |
It seems that I can spike off your spike, and more or less get the result I want. Thank you for your continuous support! Now, if I could spike something "crazy" for (of course, I'd be additionally interesting to compare implementations performance-wise 😅) |
btw, two questions:
|
Hello there! Can I use https://junit.org/junit5/docs/current/api/org.junit.platform.engine/org/junit/platform/engine/discovery/DiscoverySelectors.html#selectMethod(java.lang.String) and "skip" declaring parameters that my
fqdn#method
may or may not take?It is a manual orchestration, that makes declaring the parameters very tedious.
I don't mind it if it happens to match more than one method.
The text was updated successfully, but these errors were encountered: