44using System . Linq ;
55using System . Text ;
66using Allure . Net . Commons ;
7+ using Allure . Net . Commons . Attributes ;
78using Allure . Net . Commons . Functions ;
9+ using Allure . Net . Commons . Sdk ;
810using Allure . Net . Commons . TestPlan ;
9- using Allure . NUnit . Attributes ;
1011using NUnit . Framework ;
1112using NUnit . Framework . Interfaces ;
1213using NUnit . Framework . Internal ;
@@ -120,7 +121,8 @@ internal static TestResult CreateTestResult(ITest test)
120121 ..ModelFunctions . EnumerateGlobalLabels ( ) ,
121122 ]
122123 } ;
123- UpdateTestDataFromAllureAttributes ( test , testResult ) ;
124+ ApplyLegacyAllureAttributes ( test , testResult ) ;
125+ ApplyAllureAttributes ( test , testResult ) ;
124126 AddTestParametersFromNUnit ( test , testResult ) ;
125127 SetIdentifiers ( test , testResult ) ;
126128 return testResult ;
@@ -262,40 +264,37 @@ static void SetLegacyIdentifiers(ITest test, TestResult testResult)
262264
263265 static void AddTestParametersFromNUnit ( ITest test , TestResult testResult )
264266 {
265- var arguments = CollectNUnitArguments ( test ) ;
267+ var parameters = test . Method . MethodInfo . GetParameters ( ) ;
268+ var arguments = test . Arguments ;
266269 var formatters = AllureLifecycle . TypeFormatters ;
267- foreach ( var ( name , value ) in arguments )
268- {
269- testResult . parameters . Add ( new ( )
270- {
271- name = name ,
272- value = FormatFunctions . Format ( value , formatters )
273- } ) ;
274- }
270+
271+ testResult . parameters . AddRange (
272+ ModelFunctions . CreateParameters ( parameters , arguments , formatters )
273+ ) ;
275274 }
276275
277- static IEnumerable < ( string , object ) > CollectNUnitArguments ( ITest test ) =>
278- test . Method . MethodInfo . GetParameters ( )
279- . Select ( p => p . Name )
280- . Zip (
281- test . Arguments ,
282- ( n , v ) => ( n , v )
283- ) ;
276+ static void ApplyAllureAttributes ( ITest test , TestResult testResult )
277+ {
278+ var testFixtureClass = GetTestFixture ( test ) . TypeInfo . Type ;
279+
280+ AllureApiAttribute . ApplyTypeAttributes ( testFixtureClass , testResult ) ;
281+ AllureApiAttribute . ApplyMethodAttributes ( test . Method . MethodInfo , testResult ) ;
282+ }
284283
285- static void UpdateTestDataFromAllureAttributes ( ITest test , TestResult testResult )
284+ static void ApplyLegacyAllureAttributes ( ITest test , TestResult testResult )
286285 {
287286 foreach ( var attribute in IterateAllAllureAttribites ( test ) )
288287 {
289288 attribute . UpdateTestResult ( testResult ) ;
290289 }
291290 }
292291
293- static IEnumerable < AllureTestCaseAttribute > IterateAllAllureAttribites ( ITest test ) =>
292+ static IEnumerable < Attributes . AllureTestCaseAttribute > IterateAllAllureAttribites ( ITest test ) =>
294293 test . Method
295- . GetCustomAttributes < AllureTestCaseAttribute > ( true )
294+ . GetCustomAttributes < Attributes . AllureTestCaseAttribute > ( true )
296295 . Concat (
297296 GetTestFixture ( test )
298- . GetCustomAttributes < AllureTestCaseAttribute > ( true )
297+ . GetCustomAttributes < Attributes . AllureTestCaseAttribute > ( true )
299298 ) ;
300299
301300 static string GetNamespace ( string classFullName )
@@ -309,6 +308,14 @@ static string GetNamespace(string classFullName)
309308 ) ;
310309 }
311310
311+ static string ResolveSubSuite ( TestFixture testFixture )
312+ => AllureApiAttribute
313+ . GetTypeAttributes ( testFixture . TypeInfo . Type )
314+ . OfType < AllureNameAttribute > ( )
315+ . LastOrDefault ( )
316+ ? . Name
317+ ?? GetClassName ( testFixture . FullName ) ;
318+
312319 static string GetClassName ( string classFullName )
313320 {
314321 var lastDotIndex = StripTypeArgs ( classFullName ) ? . LastIndexOf ( '.' ) ?? - 1 ;
@@ -349,39 +356,66 @@ static TestFixture GetTestFixture(ITest test)
349356
350357 internal static void ApplyDefaultSuiteHierarchy ( ITest test )
351358 {
352- var testClassFullName = GetTestFixture ( test ) . FullName ;
359+ var testFixture = GetTestFixture ( test ) ;
360+ var testClassFullName = testFixture . FullName ;
353361 var assemblyName = test . TypeInfo ? . Assembly ? . GetName ( ) . Name ;
354362 var @namespace = GetNamespace ( testClassFullName ) ;
355- var className = GetClassName ( testClassFullName ) ;
363+ var subSuite = ResolveSubSuite ( testFixture ) ;
356364
357365 AllureLifecycle . UpdateTestCase (
358366 testResult => ModelFunctions . EnsureSuites (
359367 testResult ,
360368 assemblyName ,
361369 @namespace ,
362- className
370+ subSuite
363371 )
364372 ) ;
365373 }
366374
367375 private void UpdateTestDataFromNUnitProperties ( )
368376 {
369- foreach ( var p in GetTestProperties ( PropertyNames . Description ) )
377+ this . ApplyNUnitDescriptions ( ) ;
378+ this . ApplyNUnitAuthors ( ) ;
379+ this . ApplyNUnitCategories ( ) ;
380+ }
381+
382+ void ApplyNUnitDescriptions ( )
383+ {
384+ bool hasDescription = false ;
385+ AllureLifecycle . UpdateTestCase ( ( tr ) =>
370386 {
371- AllureLifecycle . UpdateTestCase ( x => x . description += $ "{ p } \n "
372- ) ;
387+ hasDescription = tr . description is not null || tr . descriptionHtml is not null ;
388+ } ) ;
389+
390+ if ( hasDescription )
391+ {
392+ // If a description is provided via the Allure API,
393+ // NUnit descriptions are ignored.
394+ return ;
373395 }
374396
375- foreach ( var p in GetTestProperties ( PropertyNames . Author ) )
397+ foreach ( var p in EnumerateTestProperties ( PropertyNames . Description ) )
376398 {
377- AllureLifecycle . UpdateTestCase ( x => x . labels . Add ( Label . Owner ( p ) )
378- ) ;
399+ AllureLifecycle . UpdateTestCase ( x =>
400+ x . description = string . IsNullOrEmpty ( x . description )
401+ ? p
402+ : $ "{ x . description } \n \n { p } ") ;
379403 }
404+ }
380405
381- foreach ( var p in GetTestProperties ( PropertyNames . Category ) )
406+ void ApplyNUnitAuthors ( )
407+ {
408+ foreach ( var p in EnumerateTestProperties ( PropertyNames . Author ) )
382409 {
383- AllureLifecycle . UpdateTestCase ( x => x . labels . Add ( Label . Tag ( p ) )
384- ) ;
410+ AllureLifecycle . UpdateTestCase ( x => x . labels . Add ( Label . Owner ( p ) ) ) ;
411+ }
412+ }
413+
414+ void ApplyNUnitCategories ( )
415+ {
416+ foreach ( var p in EnumerateTestProperties ( PropertyNames . Category ) )
417+ {
418+ AllureLifecycle . UpdateTestCase ( x => x . labels . Add ( Label . Tag ( p ) ) ) ;
385419 }
386420 }
387421
@@ -402,30 +436,32 @@ private void AddConsoleOutputAttachment()
402436 }
403437 }
404438
405- private IEnumerable < string > GetTestProperties ( string name )
439+ IEnumerable < string > EnumerateTestProperties ( string name )
406440 {
407- var list = new List < string > ( ) ;
408- var currentTest = _test ;
409- while ( currentTest . GetType ( ) != typeof ( TestSuite )
410- && currentTest . GetType ( ) != typeof ( TestAssembly ) )
441+ var propertyContainers = EnumeratePropertyContainers ( ) . Reverse ( ) ;
442+ foreach ( var obj in propertyContainers )
411443 {
412- if ( currentTest . Properties . ContainsKey ( name ) )
444+ if ( obj . Properties . ContainsKey ( name ) )
413445 {
414- if ( currentTest . Properties [ name ] . Count > 0 )
446+ for ( var i = 0 ; i < obj . Properties [ name ] . Count ; i ++ )
415447 {
416- for ( var i = 0 ; i < currentTest . Properties [ name ] . Count ; i ++ )
417- {
418- list . Add (
419- currentTest . Properties [ name ] [ i ] . ToString ( )
420- ) ;
421- }
448+ yield return obj . Properties [ name ] [ i ] . ToString ( ) ;
422449 }
423450 }
451+ }
452+ }
424453
425- currentTest = currentTest . Parent ;
454+ IEnumerable < ITest > EnumeratePropertyContainers ( )
455+ {
456+ for ( var test = this . _test ; ShouldContinue ( test ) ; test = test . Parent )
457+ {
458+ yield return test ;
426459 }
427460
428- return list ;
461+ static bool ShouldContinue ( ITest test )
462+ => test is not null
463+ && test . GetType ( ) != typeof ( TestSuite )
464+ && test . GetType ( ) != typeof ( TestAssembly ) ;
429465 }
430466
431467 private string ContainerId => $ "tc-{ _test . Id } ";
0 commit comments