You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Introduce extension API for expression language evaluation in display names #1154
I have found that it would be useful if you could use argument fields as a part of parametrized test name. Right now, when using just {0} as described in docs, it results in injecting into a test name string in form of ClassName(fieldName1=fieldValue1, fieldName2=fieldValue2, ...). But that doesn't seen readable at all especially then you have a class with more than just few fields. Now I would like to be able to use some semantics as {0.name} or {0}.name to use just name field of class used as test method argument, so I can write test name as follows:
@BeerTestclassBeerConversionServiceTest {
@AutowiredprivateBeerConversionServicebeerConversionService;
privatestaticStream<Arguments> createBeers() {
returnStream.of(
Arguments.of(newBeer(...), 25L),
Arguments.of(newBeer(...), 50L)
);
}
@DisplayName("Get alcohol content of a beer in mg")
@ParameterizedTest(name = "Alcohol content of {0.name} should be equal to {1}")
@MethodSource("createBeers")
voidgetAlcInMg(Beerbeer, longmg) {
Assertions.assertEquals(beerConversionService.getAlcInMg(beer), mg);
}
}
This would give users possibility to keep test names simple, yet still descriptive, as they could reference objects passed as arguments and use only parts of them which identifies test cases.
I didn't look into the source code so I cannot tell which approach would be easier to implement but I would guess that {0.name} seems more reasonable.
Deliverables
Introduce an SPI (similar to what has been proposed above) and provide a SpEL-based and/or OGNL-based implementation.
I agree that this would be useful. Implementation-wise it might be a rabbit hole, though. We should probably check for getters first. If there are none, we could try to find a field traversing the class hierarchy upward.
I agree that this would be useful. Implementation-wise it might be a rabbit hole, though. We should probably check for getters first. If there are none, we could try to find a field traversing the class hierarchy upward.
@junit-team/junit-lambda Thoughts?
accessor method: name()
getter method: getName()
field named name (local and then traversing the hierarchy)
Mustache may be a nice addition but I agree with Mark that if it's going to be used it should be provided as some kind of extension because it will be used by rather small amount of users.
But will we need anything apart of this simple usecase? If not, additional dependecy seems a bit unnecessary.
Based on the discussions here, I think it's already starting to get a bit out of hand.
As soon as we support one level of expressions, people will want more, and then they'll want additional features that the JUnit Team should not be implementing (due to scope).
So, in order to avoid feature creep, my proposal is to go back to the original plan (from the JUnit Lambda prototype phase) to add an extension for plugging in a custom expression language.
In summary, I believe it would be better to design a new extension API that receives the String displayName and a Map<String,Object> expressionContextMap and then allow people to pick between Mustache, SpEL, etc.
changed the title [-]Add support for using argument fields in parametrized test names[/-][+]Introduce extension API for expression language evaluation in display names[/+]on Aug 11, 2020
Based on #4293 (review), @sbrannen and I did a bit of brainstorming today. Based on our discussion, here's a more concrete proposal to be discussed with the entire team.
Introduce a ServiceLoader-based ExpressionLanguage interface in junit-jupiter-api in junit-platform-commons
Add @ExpressionLanguage("mustache") annotation so it can be set per class or method
Add junit.jupiter.expression-language.default configuration parameter so it can be set globally
Expose via ExtensionContext.getExpressionLanguage(String id) : Optional<ExpressionLanguage> andExtensionContext.getDefaultExpressionLanguage() : Optional<ExpressionLanguage>
In junit-jupiter-params, get the default expression language, parse the template, and evaluate the expression if the new nameExpr attribute is set
Handle case where expression language is set but @ParameterizedTest(name = ...) isn't configured to generate the same default name as before
Activity
marcphilipp commentedon Nov 11, 2017
I agree that this would be useful. Implementation-wise it might be a rabbit hole, though. We should probably check for getters first. If there are none, we could try to find a field traversing the class hierarchy upward.
@junit-team/junit-lambda Thoughts?
vikaskumar89 commentedon Nov 17, 2017
hi @marcphilipp may i please work on this?
marcphilipp commentedon Nov 17, 2017
Sure!
sbrannen commentedon Nov 17, 2017
name()getName()name(local and then traversing the hierarchy)DcortezMeleth commentedon Nov 17, 2017
Seems like a good idea.
sormuras commentedon Nov 17, 2017
How about supporting
{{ mustache }}notation? We could include this library here https://github.com/spullara/mustache.javamarcphilipp commentedon Nov 17, 2017
I was also wondering about that. If we do, it needs to be an extension, though. Moreover, I'm not sure we need everything mustache has to offer. 🤔
DcortezMeleth commentedon Nov 17, 2017
Mustache may be a nice addition but I agree with Mark that if it's going to be used it should be provided as some kind of extension because it will be used by rather small amount of users.
But will we need anything apart of this simple usecase? If not, additional dependecy seems a bit unnecessary.
marcphilipp commentedon Nov 17, 2017
Do we want to support things like
{0.manufacturer.owner.name}?sbrannen commentedon Nov 18, 2017
Based on the discussions here, I think it's already starting to get a bit out of hand.
As soon as we support one level of expressions, people will want more, and then they'll want additional features that the JUnit Team should not be implementing (due to scope).
So, in order to avoid feature creep, my proposal is to go back to the original plan (from the JUnit Lambda prototype phase) to add an extension for plugging in a custom expression language.
See also:
In summary, I believe it would be better to design a new extension API that receives the
String displayNameand aMap<String,Object> expressionContextMapand then allow people to pick between Mustache, SpEL, etc.sbrannen commentedon Nov 18, 2017
For example...
"Owner: {0.manufacturer.owner.name}"."Owner: #{#0.manufacturer.owner.name}"or"Owner: #{#beer.manufacturer.owner.name}".22 remaining items
[-]Add support for using argument fields in parametrized test names[/-][+]Introduce extension API for expression language evaluation in display names[/+]stale commentedon Jun 19, 2022
jean-andre-gauthier commentedon Dec 20, 2024
Hi @marcphilipp , as discussed over slack I'm currently working on preparing a spike PR for this. Please feel free to assign me the issue
marcphilipp commentedon Feb 7, 2025
Based on #4293 (review), @sbrannen and I did a bit of brainstorming today. Based on our discussion, here's a more concrete proposal to be discussed with the entire team.
ServiceLoader-basedExpressionLanguageinterfacein junit-jupiter-apiin junit-platform-commonsAdd@ExpressionLanguage("mustache")annotation so it can be set per class or methodjunit.jupiter.expression-language.defaultconfiguration parameter so it can be set globallyExtensionContext.getExpressionLanguage(String id) : Optional<ExpressionLanguage>andExtensionContext.getDefaultExpressionLanguage() : Optional<ExpressionLanguage>nameExprattribute is setHandle case where expression language is set but@ParameterizedTest(name = ...)isn't configured to generate the same default name as beforeAPI
Example
marcphilipp commentedon Feb 28, 2025
Team decision: Explore the above proposal and re-evaluate after seeing a prototype in action.