Closed sbernard31 closed 1 year ago
It looks like what you're after is class-level parameterization that is tracked in https://github.com/junit-team/junit5/issues/878.
@marcphilipp, :pray: thx for reply.
I tried to read the whole issue. If I well understand class-level parameterization does not exist yet ? right ?
The proposed design would be https://github.com/junit-team/junit5/issues/878#issuecomment-354544841.
So in my case it would looks like :
@ParameterizedContainer(name = ...)
@ValueSource(strings = { "param1", "param2", "param3"})
public class TestSuite {
@Parameter(0)
private String param;
private MyObjectToTest objectToTest;
@BeforeEach
public void start() {
objectToTest = new MyObjectToTest(param);
}
@AfterEach
public void stop() throws InterruptedException {
objectToTest.destroy();
}
@Test
public void test1() {
assertThat(objectToTest).isValid();
}
@Test
public void test2() {
assertThat(objectToTest).isOK();
}
It should fit my needs. :+1:
Ideally instead of having parameter as attribute I would prefer to get it as argument like this :sparkles: :
@ParameterizedContainer(name = ...)
@ValueSource(strings = { "param1", "param2", "param3"})
public class TestSuite {
@BeforeEach
@Parameterized
public void start(String param) {
objectToTest = new MyObjectToTest(param);
}
... ...
OR
@ParameterizedContainer(name = ...)
@ValueSource(strings = { "param1", "param2", "param3"})
public class TestSuite {
@BeforeEach
public void start(@Parameter(0) String param) {
objectToTest = new MyObjectToTest(param);
}
... ...
Sorry for the boring question but it is plan at short/mid term ? Do you know if someone is working on this currently ? Do you think this is something achievable for a new contributor ?
Reading #878, I find other work around, so I decide to list it here.
1) using CustomParameterResolver
as explain at https://stackoverflow.com/a/69265907/5088764
(Need to add CustomParameterResolver
and MappedParameterContext
)
@ExtendWith(CustomParameterResolver.class)
public class TestSuite {
@ParameterizedTest(name = "My custom name {}")
@ValueSource(strings = { "param1", "param2", "param3"})
@Retention(RetentionPolicy.RUNTIME)
private @interface TestAllParams {
}
private MyObjectToTest objectToTest;
@BeforeEach
public void start(String param) {
objectToTest = new MyObjectToTest(param);
}
@AfterEach
public void stop() throws InterruptedException {
objectToTest.destroy();
}
@TestAllParams
public void test1(String param) {
assertThat(objectToTest).isValid();
}
@TestAllParams
public void test2(String param) {
assertThat(objectToTest).isOK();
}
2) using TestFactory as explain at https://github.com/junit-team/junit5/issues/878#issuecomment-568879837
(no to add TestingUtils
class)
public class TestSuite {
@TestFactory
Stream<DynamicNode> runTests() throws Exception {
return TestingUtils.parameterizedClassTester("param={0}", Tests.class,
Stream.of(Arguments.of("param1"), Arguments.of("param2"), Arguments.of("param3")));
}
static class Tests {
private String param;
public TestSuite(String param){
this.param = param;
}
private MyObjectToTest objectToTest;
@BeforeEach
public void start() {
objectToTest = new MyObjectToTest(param);
}
@AfterEach
public void stop() throws InterruptedException {
objectToTest.destroy();
}
@Test
public void test1() {
assertThat(objectToTest).isValid();
}
@Test
public void test2() {
assertThat(objectToTest).isOK();
}
3) using abstract/interface + concrete class as explain at https://github.com/junit-team/junit5/issues/871#issuecomment-1330777589 (no need extra class)
public abstract class TestSuite {
public TestSuite1 extends TestSuite {
TestSuite1() {
super("param1")
}
}
public TestSuite2 extends TestSuite {
TestSuite2() {
super("param2")
}
}
public TestSuite3 extends TestSuite {
TestSuite3() {
super("param3")
}
}
public TestSuite(String param){
this.param = param;
}
private String param;
private MyObjectToTest objectToTest;
@BeforeEach
public void start() {
objectToTest = new MyObjectToTest(param);
}
@AfterEach
public void stop() throws InterruptedException {
objectToTest.destroy();
}
@Test
public void test1() {
assertThat(objectToTest).isValid();
}
@Test
public void test2() {
assertThat(objectToTest).isOK();
}
All of those workarounds have drawback but it could help waiting for class-level parameterization
If you would like us to be able to process this issue, please provide the requested information. If the information is not provided within the next 3 weeks, we will be unable to proceed and this issue will be closed.
please provide the requested information.
Maybe I totally missed something but I'm not sure what are requested information ?
Maybe I totally missed something but I'm not sure what are requested information ?
Never mind, we should have removed the "waiting-for-feedback" label after your previous comment.
Team decision: We'll take your feedback into consideration in the context of #878.
My need :
I have a class containing several tests. I have a
@BeforeEach
and@AfterEach
which setup and tear down each tests.Now I would like to parameterize test but I don't want to get param on test method but only on
@BeforeEach
method.Here is a very simplified example of code of what I would like to do : (In my real use case, my start() method is far more complicated with more than one object to initialize and more than 1 argument as parameter)
My solution for now :
I used the
CustomParameterResolver
way described atbut this does not reallly elegant as I need to add argument to test method too. This looks like :
Question ?
Do you think this feature request make sense ? Any advice to achieve this in a better / more elegant way ?