1
1
using System ;
2
2
using System . Collections . Concurrent ;
3
+ using System . Linq ;
4
+ using Allure . Net . Commons ;
5
+ using NUnit . Allure . Attributes ;
3
6
using NUnit . Framework ;
4
7
using NUnit . Framework . Interfaces ;
5
8
using NUnit . Framework . Internal ;
@@ -20,50 +23,96 @@ public AllureNUnitAttribute()
20
23
{
21
24
}
22
25
23
- public void BeforeTest ( ITest test )
24
- {
25
- var helper = new AllureNUnitHelper ( test ) ;
26
- _allureNUnitHelper . AddOrUpdate (
27
- test . Id ,
28
- helper ,
29
- ( key , existing ) => helper
30
- ) ;
31
-
32
- if ( test . IsSuite )
33
- {
34
- helper . SaveOneTimeResultToContext ( ) ;
35
- StepsHelper . StopFixture ( ) ;
36
- }
37
- else
26
+ public void BeforeTest ( ITest test ) =>
27
+ RunHookInRestoredAllureContext ( test , ( ) =>
38
28
{
39
- helper . StartTestContainer ( ) ;
40
- helper . AddOneTimeSetupResult ( ) ;
41
- helper . StartTestCase ( ) ;
42
- }
43
- }
29
+ var helper = new AllureNUnitHelper ( test ) ;
30
+ _allureNUnitHelper . AddOrUpdate (
31
+ test . Id ,
32
+ helper ,
33
+ ( key , existing ) => helper
34
+ ) ;
44
35
45
- public void AfterTest ( ITest test )
46
- {
47
- if ( _allureNUnitHelper . TryGetValue ( test . Id , out var helper ) )
48
- {
49
36
if ( ! test . IsSuite )
50
37
{
51
- helper . StopTestCase ( ) ;
38
+ helper . StartTestContainer ( ) ; // A container for SetUp/TearDown methods
39
+ helper . StartTestCase ( ) ;
52
40
}
41
+ } ) ;
53
42
54
- helper . StopTestContainer ( ) ;
55
- }
56
- }
43
+ public void AfterTest ( ITest test ) =>
44
+ RunHookInRestoredAllureContext ( test , ( ) =>
45
+ {
46
+ if ( _allureNUnitHelper . TryGetValue ( test . Id , out var helper ) )
47
+ {
48
+ if ( ! test . IsSuite )
49
+ {
50
+ helper . StopTestCase ( ) ;
51
+ helper . StopTestContainer ( ) ;
52
+ }
53
+ else if ( IsSuiteWithNoAfterFixtures ( test ) )
54
+ {
55
+ // If a test fixture contains a OneTimeTearDown method
56
+ // with the [AllureAfter] attribute, the corresponding
57
+ // container is closed in StopContainerAspect instead.
58
+ helper . StopTestContainer ( ) ;
59
+ }
60
+ }
61
+ } ) ;
57
62
58
63
public ActionTargets Targets =>
59
64
ActionTargets . Test | ActionTargets . Suite ;
60
65
61
66
public void ApplyToContext ( TestExecutionContext context )
62
67
{
63
68
var test = context . CurrentTest ;
64
- var helper = new AllureNUnitHelper ( test ) ;
65
- helper . StartTestContainer ( ) ;
66
- StepsHelper . StartBeforeFixture ( $ "fr- { test . Id } " ) ;
69
+ // A container for OneTimeSetUp/OneTimeTearDown methods.
70
+ new AllureNUnitHelper ( test ) . StartTestContainer ( ) ;
71
+ CaptureGlobalAllureContext ( test ) ;
67
72
}
73
+
74
+ static bool IsSuiteWithNoAfterFixtures ( ITest test ) =>
75
+ test is TestSuite suite && ! suite . OneTimeTearDownMethods . Any (
76
+ m => IsDefined ( m . MethodInfo , typeof ( AllureAfterAttribute ) )
77
+ ) ;
78
+
79
+ #region Allure context manipulation
80
+
81
+ /*
82
+ * The methods this region are to make sure the AllureContext
83
+ * flows into setup/teardown/test methods correctly. This is needed
84
+ * because NUnit might spread hooks of this class and user's code
85
+ * across unrelated threads, hiding changes made to the allure context
86
+ * in, say, BeforeTest from, say, a one-time tear down method.
87
+ */
88
+
89
+ static void RunHookInRestoredAllureContext ( ITest test , Action action )
90
+ {
91
+ RestoreAssociatedAllureContext ( test ) ;
92
+ try
93
+ {
94
+ action ( ) ;
95
+ }
96
+ finally
97
+ {
98
+ CaptureGlobalAllureContext ( test ) ;
99
+ }
100
+ }
101
+
102
+ static void CaptureGlobalAllureContext ( ITest test ) =>
103
+ test . Properties . Set ( ALLURE_CONTEXT_KEY , AllureLifecycle . Instance . Context ) ;
104
+
105
+ static void RestoreAssociatedAllureContext ( ITest test ) =>
106
+ AllureLifecycle . Instance . RestoreContext (
107
+ GetAssociatedAllureContext ( test )
108
+ ) ;
109
+
110
+ static AllureContext GetAssociatedAllureContext ( ITest test ) =>
111
+ ( AllureContext ) test . Properties . Get ( ALLURE_CONTEXT_KEY )
112
+ ?? GetAssociatedAllureContext ( test . Parent ) ;
113
+
114
+ const string ALLURE_CONTEXT_KEY = "AllureContext" ;
115
+
116
+ #endregion
68
117
}
69
118
}
0 commit comments