Replies: 5 comments 15 replies
-
|
First of all, thanks for reaching out! I think TableTest looks very useful. There is quite a bit of overlap with regular
We can certainly discuss it! Please note that we're currently very busy with the upcoming 6.0 release so it will take even longer than usual. I'll add it to our discussion backlog. |
Beta Was this translation helpful? Give feedback.
-
Hi @nchaugen, just FYI, on top of the work at #4219, I'm also creating a I'd be happy to get your feedback there, too, in case you find it useful 🙂 |
Beta Was this translation helpful? Give feedback.
-
|
Sorry this took some time, but I have finally had a chance to look into the new ConversionSupport to see how it would work with TableTest. This post turned rather long, so TLDR:
Long versionI like that it is possible to override the provided built-in converters. In many situations I like to use constants like TODAY, TOMORROW, YESTERDAY as argument values to represent LocalDates to improve readability. I found that when adding the following custom converter it took precedence over the built-in public class StringToLocalDateConverter implements Converter<String, LocalDate> {
@Override
public boolean canConvert(ConversionContext context) {
return LocalDate.class.isAssignableFrom(context.targetType().getType()) ;
}
@Override
public LocalDate convert(@Nullable String source, ConversionContext context) throws ConversionException {
return switch (source) {
case null -> null;
case "TODAY" -> LocalDate.now();
case "TOMORROW" -> LocalDate.now().plusDays(1);
case "YESTERDAY" -> LocalDate.now().minusDays(1);
default -> LocalDate.parse(source);
};
}
}I also like that it is possible to convert from other types than String. This allows the ArgumentsProvider to serve other types to the converters. For example for TableTest there is a parser that parses the table syntax and captures collection values as collection types before conversion starts. That means there are not only strings to convert, but also However, for complex values there could also be source types like Firstly, TableTest will recurse through the source value, and for each level compare the source type at that level with the target type of the parameter. For example, if the parsed source value is
Now Secondly, when invoking custom converters (factory methods in TableTest's case), TableTest will do the same for the converter parameter, allowing multiple converters to work together to do the total conversion. If the parsed source value is This means you could have the same public static StudentGrades parseStudentGrades(
Map<String, Grades> input
) {
// ...
}
public static Grades parseGrades(List<Integer> input) {
// ...
}I think this strategy for converting complex types reduces the work for developers providing custom converters and also makes the converters reusable in more situations. However I don't know if this kind of functionality is within the scope of ConversionSupport. Finally there are two (smaller) things that I think the framework could do to help developers implement custom converters:
public abstract class TypeConverter<S, T> implements Converter<S, T> {
private final Class<T> targetClass;
protected TypeConverter(Class<T> targetClass) {
this.targetClass = targetClass;
}
@Override
public boolean canConvert(ConversionContext context) {
return targetClass.isAssignableFrom(context.targetType().getType());
}
}Alternatively there could be a helper method on ConversionContext to ease implementation of public boolean isTargetTypeAssignableTo(Class<?> converterTarget) {
return converterTarget != null && converterTarget.isAssignableFrom(this.targetType().getType());
}This concludes my thoughts so far. |
Beta Was this translation helpful? Give feedback.
-
|
One additional comment: I think there is a use case for converters that are local to the test class, in addition to the global ServiceLoader converters. The local ones should take precedence over the global ones. This would allow test developers to add converters for a particular test case, without having to worry about affecting other tests. |
Beta Was this translation helpful? Give feedback.
-
|
Copied from TableTest.java#L65-L69: @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@ParameterizedTest
@ArgumentsSource(TableArgumentsProvider.class)
public @interface TableTest {
...This implementation choice makes usages of An @ParameterizedClass
@TableSource("""
Fruit | Quantity
apple | 23
banana | 42
""")
record FruitTests(String fruit, int quantity) {
@Test
void test() {
assertFruit(fruit);
assertQuantity(quantity);
}
@Test
void anotherTest() {
// ...
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
First off all, thank you @junit-team for your great work in developing and maintaining JUnit.
I am a long-time fan of using tables to drive tests, ever since being introduced to Ward Cunningham’s Fit Framework 20 years ago.
Having used Spock Framework for table-driven testing in recent projects, I found that not all Java and Kotlin developers got comfortable with the Groovy-ness of it.
Based on this experience, plus some ideas for how to further improve support for table-driven testing, I set out to create an alternative based on JUnit.
The result is TableTest. I also wrote a couple of short blog posts that introduce table-driven testing and TableTest, and I created a plugin for IntelliJ IDEA to help with auto formatting, colouring and syntax.
I have received good feedback from people who have looked into it and started using it in their projects.
One question I get is if it would be possible to make TableTest built-in to JUnit. Personally I would love that as it would make table-driven testing available to a lot of programmers.
So I wanted to ask your thoughts on this. If you think it is worth looking into, I would be happy to discuss how we could approach it, and also to do the necessary adaptations if we decide to move forward.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions