-
Notifications
You must be signed in to change notification settings - Fork 8
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
Is it possible to set a different Test key for each dynamic test iteration? #59
Comments
It's tricky, but it works: package xyz;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.util.List;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
class DynTest {
@TestFactory
List<DynamicTest> something() {
return List.of(
dynamicTest("token$1", () -> {
// ...
}),
dynamicTest("token$2", () -> {
// ...
}),
dynamicTest("token$3", () -> {
// ...
})
);
}
} Custom package xyz;
import app.getxray.xray.junit.customjunitxml.DefaultXrayTestMetadataReader;
import java.util.Optional;
import org.junit.platform.launcher.TestIdentifier;
public class CustomTestMetadataReader extends DefaultXrayTestMetadataReader {
@Override
public Optional<String> getKey(TestIdentifier testIdentifier) {
var token = testIdentifier.getDisplayName();
if (Consts.TOKEN_TO_KEY.containsKey(token)) {
return Optional.of(Consts.TOKEN_TO_KEY.get(token));
}
return super.getKey(testIdentifier);
}
@Override
public Optional<String> getSummary(TestIdentifier testIdentifier) {
var token = testIdentifier.getDisplayName();
if (Consts.TOKEN_TO_SUMMARY.containsKey(token)) {
return Optional.of(Consts.TOKEN_TO_SUMMARY.get(token));
}
return super.getSummary(testIdentifier);
}
@Override
public Optional<String> getDescription(TestIdentifier testIdentifier) {
var token = testIdentifier.getDisplayName();
if (Consts.TOKEN_TO_DESCRIPTION.containsKey(token)) {
return Optional.of(Consts.TOKEN_TO_DESCRIPTION.get(token));
}
return super.getDescription(testIdentifier);
}
} Key/summary/description definitions for dynamic tests: package xyz;
import java.util.Map;
public class Consts {
public static final Map<String, String> TOKEN_TO_KEY = Map.ofEntries(
Map.entry("token$1", "ABC-100"),
Map.entry("token$2", "ABC-200"),
Map.entry("token$3", "ABC-300")
);
public static final Map<String, String> TOKEN_TO_SUMMARY = Map.ofEntries(
Map.entry("token$1", "Summary 1"),
Map.entry("token$2", "Summary 2"),
Map.entry("token$3", "Summary 3")
);
public static final Map<String, String> TOKEN_TO_DESCRIPTION = Map.ofEntries(
Map.entry("token$1", "description 1"),
Map.entry("token$2", "description 2"),
Map.entry("token$3", "description 3")
);
}
|
If you really need to set the key/summary/description from the test method, you can do something like this: package xyz;
import java.util.HashMap;
import java.util.Map;
public class Consts {
public static final Map<String, String> TOKEN_TO_KEY = new HashMap<>();
public static final Map<String, String> TOKEN_TO_SUMMARY = new HashMap<>();
public static final Map<String, String> TOKEN_TO_DESCRIPTION = new HashMap<>();
} package xyz;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.util.List;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
class DynTest {
@TestFactory
List<DynamicTest> something() {
return List.of(
dynamicTest("token$1", () -> {
Consts.TOKEN_TO_KEY.put("token$1", "ABC-100");
Consts.TOKEN_TO_SUMMARY.put("token$1", "Summary 1");
Consts.TOKEN_TO_DESCRIPTION.put("token$1", "description 1");
// ...
}),
dynamicTest("token$2", () -> {
Consts.TOKEN_TO_KEY.put("token$2", "ABC-200");
Consts.TOKEN_TO_SUMMARY.put("token$2", "Summary 2");
Consts.TOKEN_TO_DESCRIPTION.put("token$2", "description 2");
// ...
}),
dynamicTest("token$3", () -> {
Consts.TOKEN_TO_KEY.put("token$3", "ABC-300");
Consts.TOKEN_TO_SUMMARY.put("token$3", "Summary 3");
Consts.TOKEN_TO_DESCRIPTION.put("token$3", "description 3");
// ...
})
);
}
} |
Oh wait... CustomTestMetadataReader.java package xyz;
import app.getxray.xray.junit.customjunitxml.DefaultXrayTestMetadataReader;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Optional;
import org.junit.platform.engine.support.descriptor.UriSource;
import org.junit.platform.launcher.TestIdentifier;
public class CustomTestMetadataReader extends DefaultXrayTestMetadataReader {
@Override
public Optional<String> getKey(TestIdentifier testIdentifier) {
var keyFromUriOpt = readQueryValue(testIdentifier, "key");
if (keyFromUriOpt.isPresent()) {
return keyFromUriOpt;
}
return super.getKey(testIdentifier);
}
@Override
public Optional<String> getSummary(TestIdentifier testIdentifier) {
var summaryFromUriOpt = readQueryValue(testIdentifier, "summary");
if (summaryFromUriOpt.isPresent()) {
return summaryFromUriOpt;
}
return super.getSummary(testIdentifier);
}
@Override
public Optional<String> getDescription(TestIdentifier testIdentifier) {
var descriptionFromUriOpt = readQueryValue(testIdentifier, "description");
if (descriptionFromUriOpt.isPresent()) {
return descriptionFromUriOpt;
}
return super.getDescription(testIdentifier);
}
private static Optional<String> readQueryValue(TestIdentifier testIdentifier, String key) {
return testIdentifier.getSource()
.filter(source -> source instanceof UriSource)
.map(source -> (UriSource) source)
.map(UriSource::getUri)
.map(URI::getQuery)
.stream()
.map(query -> query.split("&"))
.flatMap(Arrays::stream)
.filter(query -> query.startsWith(key + "="))
.map(query -> query.substring(key.length() + 1))
.map(value -> URLDecoder.decode(value, StandardCharsets.UTF_8))
.findFirst();
}
} DynTest.java package xyz;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
class DynTest {
@TestFactory
List<DynamicTest> something() {
return List.of(
dynamicTest("Test 1",
testToURI(DynTest.class, "something/test1", "ABC-100", "Summary 1", "Description 1"), () -> {
// ...
}),
dynamicTest("Test 2",
testToURI(DynTest.class, "something/test2", "ABC-200", "Summary 2", "Description 2"), () -> {
// ...
}),
dynamicTest("Test 3",
testToURI(DynTest.class, "something/test3", "ABC-300", "Summary 3", "Description 3"), () -> {
// ...
})
);
}
public static URI testToURI(Class<?> testClass, String testMethod, String key, String summary,
String description) {
return URI.create("test://" + testClass.getName() + "/" + testMethod
+ "?key=" + URLEncoder.encode(key, StandardCharsets.UTF_8)
+ "&summary=" + URLEncoder.encode(summary, StandardCharsets.UTF_8)
+ "&description=" + URLEncoder.encode(description, StandardCharsets.UTF_8));
}
} Output report: <?xml version="1.0" encoding="UTF-8"?>
<testsuite name="JUnit Jupiter" tests="3" skipped="0" failures="0" errors="0" time="0" hostname="XXXXXX" timestamp="XXXXXX">
<properties>
<!-- ... -->
</properties>
<testcase name="something" classname="xyz.DynTest" time="0" started-at="XXXXXX" finished-at="XXXXXX">
<system-out><![CDATA[
unique-id: [engine:junit-jupiter]/[class:xyz.DynTest]/[test-factory:something()]/[dynamic-test:#2]
display-name: Test 2
]]></system-out>
<properties>
<property name="test_key" value="ABC-200"/>
<property name="test_description"><![CDATA[Description 2]]></property>
<property name="test_summary" value="Summary 2"/>
<property name="_dummy_" value=""/>
</properties>
</testcase>
<testcase name="something" classname="xyz.DynTest" time="0" started-at="XXXXXX" finished-at="XXXXXX">
<system-out><![CDATA[
unique-id: [engine:junit-jupiter]/[class:xyz.DynTest]/[test-factory:something()]/[dynamic-test:#3]
display-name: Test 3
]]></system-out>
<properties>
<property name="test_key" value="ABC-300"/>
<property name="test_description"><![CDATA[Description 3]]></property>
<property name="test_summary" value="Summary 3"/>
<property name="_dummy_" value=""/>
</properties>
</testcase>
<testcase name="something" classname="xyz.DynTest" time="0" started-at="XXXXXX" finished-at="XXXXXX">
<system-out><![CDATA[
unique-id: [engine:junit-jupiter]/[class:xyz.DynTest]/[test-factory:something()]/[dynamic-test:#1]
display-name: Test 1
]]></system-out>
<properties>
<property name="test_key" value="ABC-100"/>
<property name="test_description"><![CDATA[Description 1]]></property>
<property name="test_summary" value="Summary 1"/>
<property name="_dummy_" value=""/>
</properties>
</testcase>
<system-out><![CDATA[
unique-id: [engine:junit-jupiter]
display-name: JUnit Jupiter
]]></system-out>
</testsuite>
In this example test metadata like key/summary/description is passed in the TestSource (see UriSource). |
BTW. |
Thanks for the input @mk868 . I don't have a strong opinion on this but I think the last approach you suggest could be feasible, as long as we keep it simple for anyone that doesn't wish all this level of customization. Do you want to prepare a PR? |
Given a dynamic test like the below I can't see how it's possible to use an annotation and have a unique key for each iteration:
Is there any workaround or solution, perhaps a way to set the key in the test body?
Thanks
The text was updated successfully, but these errors were encountered: