@@ -176,14 +176,67 @@ private static string Indent(IReadOnlyCollection<TestResultMessage> messages)
176176 $ "{ Environment . NewLine } { indent } ",
177177 messages . SelectMany ( m =>
178178 m . Text . Split ( new string [ ] { "\r " , "\n " } , StringSplitOptions . None )
179- . Where ( x => ! string . IsNullOrWhiteSpace ( x ) )
180- . Select ( x => x . Trim ( ) ) ) ) ;
179+ . Where ( x => ! string . IsNullOrWhiteSpace ( x ) )
180+ . Select ( x => x . Trim ( ) ) ) ) ;
181181 }
182182
183- private XElement CreateTestSuitesElement (
184- List < TestResultInfo > results ,
185- TestRunConfiguration runConfiguration ,
186- List < TestMessageInfo > messages )
183+ private static IEnumerable < XElement > CreatePropertyElement ( string name , params string [ ] values )
184+ {
185+ if ( string . IsNullOrWhiteSpace ( name ) )
186+ {
187+ throw new ArgumentException ( "message" , nameof ( name ) ) ;
188+ }
189+
190+ foreach ( var value in values )
191+ {
192+ yield return new XElement (
193+ "property" ,
194+ new XAttribute ( "name" , name ) ,
195+ new XAttribute ( "value" , value ) ) ;
196+ }
197+ }
198+
199+ private static XElement CreatePropertyElement ( Trait trait )
200+ {
201+ return CreatePropertyElement ( trait . Name , trait . Value ) . Single ( ) ;
202+ }
203+
204+ private static XElement CreatePropertiesElement ( TestResultInfo result )
205+ {
206+ var propertyElements = new HashSet < XNode > ( result . Traits . Select ( CreatePropertyElement ) ) ;
207+
208+ #pragma warning disable CS0618 // Type or member is obsolete
209+
210+ // Required since TestCase.Properties is a superset of TestCase.Traits
211+ // Unfortunately not all NUnit properties are available as traits
212+ var traitProperties = result . Properties ;
213+
214+ #pragma warning restore CS0618 // Type or member is obsolete
215+
216+ foreach ( var traitProperty in traitProperties )
217+ {
218+ if ( traitProperty . Key != "CustomProperty" )
219+ {
220+ continue ;
221+ }
222+
223+ var propertyDef = traitProperty . Value as string [ ] ;
224+ if ( propertyDef == null || propertyDef . Length != 2 )
225+ {
226+ continue ;
227+ }
228+
229+ var propertyElement = CreatePropertyElement ( propertyDef [ 0 ] , propertyDef [ 1 ] ) ;
230+ foreach ( var element in propertyElement )
231+ {
232+ propertyElements . Add ( element ) ;
233+ }
234+ }
235+
236+ return propertyElements . Any ( ) ? new XElement ( "properties" , propertyElements . Distinct ( ) ) : null ;
237+ }
238+
239+ private XElement CreateTestSuitesElement ( List < TestResultInfo > results , TestRunConfiguration runConfiguration , List < TestMessageInfo > messages )
187240 {
188241 var assemblies = results . Select ( x => x . AssemblyPath ) . Distinct ( ) . ToList ( ) ;
189242 var testsuiteElements = assemblies
@@ -266,9 +319,7 @@ private XElement CreateTestCaseElement(TestResultInfo result)
266319
267320 // Ensure time value is never zero because gitlab treats 0 like its null. 0.1 micro
268321 // seconds should be low enough it won't interfere with anyone monitoring test duration.
269- testcaseElement . SetAttributeValue (
270- "time" ,
271- Math . Max ( 0.0000001f , result . Duration . TotalSeconds ) . ToString ( "0.0000000" , CultureInfo . InvariantCulture ) ) ;
322+ testcaseElement . SetAttributeValue ( "time" , Math . Max ( 0.0000001f , result . Duration . TotalSeconds ) . ToString ( "0.0000000" , CultureInfo . InvariantCulture ) ) ;
272323
273324 if ( result . Outcome == TestOutcome . Failed )
274325 {
@@ -343,6 +394,8 @@ private XElement CreateTestCaseElement(TestResultInfo result)
343394 testcaseElement . Add ( new XElement ( "system-err" , new XCData ( stdErr . ToString ( ) ) ) ) ;
344395 }
345396
397+ testcaseElement . Add ( CreatePropertiesElement ( result ) ) ;
398+
346399 return testcaseElement ;
347400 }
348401
0 commit comments