2222import io .qameta .allure .SeverityLevel ;
2323import io .qameta .allure .model .FixtureResult ;
2424import io .qameta .allure .model .Label ;
25+ import io .qameta .allure .model .Parameter ;
2526import io .qameta .allure .model .Stage ;
2627import io .qameta .allure .model .Status ;
2728import io .qameta .allure .model .StatusDetails ;
8990})
9091public class AllureJunitPlatform implements TestExecutionListener {
9192
93+ public static final String ALLURE_PARAMETER = "allure.parameter" ;
94+ public static final String ALLURE_PARAMETER_VALUE_KEY = "value" ;
95+ public static final String ALLURE_PARAMETER_MODE_KEY = "mode" ;
96+ public static final String ALLURE_PARAMETER_EXCLUDED_KEY = "excluded" ;
97+
9298 public static final String ALLURE_FIXTURE = "allure.fixture" ;
9399 public static final String PREPARE = "prepare" ;
94100 public static final String TEAR_DOWN = "tear_down" ;
95101 public static final String EVENT_START = "start" ;
96102 public static final String EVENT_STOP = "stop" ;
97103 public static final String EVENT_FAILURE = "failure" ;
104+
98105 public static final String JUNIT_PLATFORM_UNIQUE_ID = "junit.platform.uniqueid" ;
99106 private static final Logger LOGGER = LoggerFactory .getLogger (AllureJunitPlatform .class );
100107 private static final String STDOUT = "stdout" ;
@@ -188,40 +195,17 @@ public void executionSkipped(final TestIdentifier testIdentifier,
188195 );
189196 }
190197
191- @ SuppressWarnings ({"ReturnCount" , "PMD.NcssCount" })
198+ @ SuppressWarnings ({"ReturnCount" , "PMD.NcssCount" , "CyclomaticComplexity" })
192199 @ Override
193200 public void reportingEntryPublished (final TestIdentifier testIdentifier ,
194201 final ReportEntry entry ) {
195202 final Map <String , String > keyValuePairs = entry .getKeyValuePairs ();
196203 if (keyValuePairs .containsKey (ALLURE_FIXTURE )) {
197- final String type = keyValuePairs .get (ALLURE_FIXTURE );
198- final String event = keyValuePairs .get ("event" );
199-
200- // skip for invalid events
201- if (Objects .isNull (type ) || Objects .isNull (event )) {
202- return ;
203- }
204-
205- switch (event ) {
206- case EVENT_START :
207- final Optional <String > maybeParent = containers .get (testIdentifier );
208- if (!maybeParent .isPresent ()) {
209- return ;
210- }
211- final String parentUuid = maybeParent .get ();
212- startFixture (parentUuid , type , keyValuePairs );
213- return ;
214- case EVENT_FAILURE :
215- failFixture (keyValuePairs );
216- resetContext (testIdentifier );
217- return ;
218- case EVENT_STOP :
219- stopFixture (keyValuePairs );
220- resetContext (testIdentifier );
221- return ;
222- default :
223- break ;
224- }
204+ processFixtureEvent (testIdentifier , keyValuePairs );
205+ return ;
206+ }
207+ if (keyValuePairs .containsKey (ALLURE_PARAMETER )) {
208+ processParameterEvent (keyValuePairs );
225209 return ;
226210 }
227211
@@ -236,6 +220,63 @@ public void reportingEntryPublished(final TestIdentifier testIdentifier,
236220
237221 }
238222
223+ private void processParameterEvent (final Map <String , String > keyValuePairs ) {
224+ final String name = keyValuePairs .get (ALLURE_PARAMETER );
225+ final String value = keyValuePairs .get (ALLURE_PARAMETER_VALUE_KEY );
226+
227+ final Parameter parameter = ResultsUtils .createParameter (name , value );
228+ if (keyValuePairs .containsKey (ALLURE_PARAMETER_MODE_KEY )) {
229+ final String modeString = keyValuePairs .get (ALLURE_PARAMETER_MODE_KEY );
230+ Stream .of (Parameter .Mode .values ())
231+ .filter (mode -> mode .name ().equalsIgnoreCase (modeString ))
232+ .findAny ()
233+ .ifPresent (parameter ::setMode );
234+ }
235+ if (keyValuePairs .containsKey (ALLURE_PARAMETER_EXCLUDED_KEY )) {
236+ final String excludedString = keyValuePairs .get (ALLURE_PARAMETER_EXCLUDED_KEY );
237+ Optional .ofNullable (excludedString )
238+ .map (Boolean ::parseBoolean )
239+ .ifPresent (parameter ::setExcluded );
240+ }
241+
242+ getLifecycle ().updateTestCase (tr -> tr .getParameters ()
243+ .add (parameter )
244+ );
245+ }
246+
247+ @ SuppressWarnings ({"ReturnCount" })
248+ private void processFixtureEvent (final TestIdentifier testIdentifier ,
249+ final Map <String , String > keyValuePairs ) {
250+ final String type = keyValuePairs .get (ALLURE_FIXTURE );
251+ final String event = keyValuePairs .get ("event" );
252+
253+ // skip for invalid events
254+ if (Objects .isNull (type ) || Objects .isNull (event )) {
255+ return ;
256+ }
257+
258+ switch (event ) {
259+ case EVENT_START :
260+ final Optional <String > maybeParent = containers .get (testIdentifier );
261+ if (!maybeParent .isPresent ()) {
262+ return ;
263+ }
264+ final String parentUuid = maybeParent .get ();
265+ startFixture (parentUuid , type , keyValuePairs );
266+ return ;
267+ case EVENT_FAILURE :
268+ failFixture (keyValuePairs );
269+ resetContext (testIdentifier );
270+ return ;
271+ case EVENT_STOP :
272+ stopFixture (keyValuePairs );
273+ resetContext (testIdentifier );
274+ return ;
275+ default :
276+ break ;
277+ }
278+ }
279+
239280 private void resetContext (final TestIdentifier testIdentifier ) {
240281 // in case of fixtures that reported within a test we need to return current
241282 // test case uuid to allure thread local storage
@@ -362,13 +403,38 @@ private void startTestCase(final TestIdentifier testIdentifier) {
362403 final Optional <Class <?>> testClass = testSource
363404 .flatMap (AllureJunitPlatformUtils ::getTestClass );
364405
406+ final boolean testTemplate = "test-template-invocation"
407+ .equals (testIdentifier .getUniqueIdObject ().getLastSegment ().getType ());
408+
409+ final Optional <TestIdentifier > maybeParent = Optional .of (testPlanStorage )
410+ .map (ThreadLocal ::get )
411+ .flatMap (tp -> tp .getParent (testIdentifier ));
412+
365413 final TestResult result = new TestResult ()
366414 .setUuid (uuid )
367- .setName (testIdentifier .getDisplayName ())
415+ .setName (testTemplate && maybeParent .isPresent ()
416+ ? maybeParent .get ().getDisplayName () + " " + testIdentifier .getDisplayName ()
417+ : testIdentifier .getDisplayName ()
418+ )
368419 .setLabels (getTags (testIdentifier ))
420+ .setTestCaseId (testTemplate
421+ ? maybeParent .map (TestIdentifier ::getUniqueId )
422+ .orElseGet (testIdentifier ::getUniqueId )
423+ : testIdentifier .getUniqueId ()
424+ )
369425 .setHistoryId (getHistoryId (testIdentifier ))
370426 .setStage (Stage .RUNNING );
371427
428+ if (testTemplate ) {
429+ // history id is ignored in Allure TestOps, so we add a hidden parameter
430+ // to make sure different results are not considered as retries
431+ result .getParameters ().add (new Parameter ()
432+ .setMode (Parameter .Mode .HIDDEN )
433+ .setName ("UniqueId" )
434+ .setValue (testIdentifier .getUniqueId ())
435+ );
436+ }
437+
372438 result .getLabels ().addAll (getProvidedLabels ());
373439
374440 result .getLabels ().add (getJUnitPlatformUniqueId (testIdentifier ));
0 commit comments