4
4
using System . Diagnostics ;
5
5
using System . IO ;
6
6
using System . Linq ;
7
+ using System . Threading ;
7
8
using System . Threading . Tasks ;
8
9
using System . Xml . Linq ;
9
10
using Xunit ;
@@ -12,54 +13,76 @@ namespace Tests.IntegrationTests
12
13
{
13
14
public record Invocation ( object [ ] InjectedParameters ) ;
14
15
15
- public record TestResult ( string TestName , string Outcome , string Message , ImmutableList < Invocation > Invocations ) ;
16
+ public record TestResult ( string TestName , string Outcome , string Message , string Output ) ;
16
17
17
18
public abstract class TestSuiteFixture : IAsyncLifetime
18
19
{
20
+ private static readonly SemaphoreSlim Lock = new ( 1 , 1 ) ;
21
+
19
22
private readonly string _currentDirectory = Directory . GetCurrentDirectory ( ) ;
20
23
private readonly string _testReportFileName ;
21
- private readonly string _testSuiteName ;
22
24
23
25
public TestSuiteFixture ( string testSuiteName )
24
26
{
27
+ TestSuiteName = testSuiteName ;
25
28
_testReportFileName = Path . Combine ( _currentDirectory , $ "test_result_{ testSuiteName } _{ DateTime . UtcNow . Ticks } .trx") ;
26
- _testSuiteName = testSuiteName ;
27
29
}
28
30
31
+ public string TestSuiteName { get ; }
32
+
29
33
public ImmutableList < TestResult > TestResults { get ; private set ; } = default ! ;
30
34
35
+ public IReadOnlyDictionary < string , string > TestNameToTestResult { get ; private set ; } = default ! ;
36
+
37
+ public string TestReport { get ; private set ; } = default ! ;
38
+
31
39
public async Task InitializeAsync ( )
32
40
{
33
- var currentProjectDir = Enumerable
34
- . Range ( 0 , 3 )
35
- . Aggregate ( new DirectoryInfo ( _currentDirectory ) , ( acc , _ ) => acc . Parent ! ) ;
36
- var integrationProjectDir = Path . Combine ( currentProjectDir . FullName , "samples" , _testSuiteName ) ;
41
+ await Lock . WaitAsync ( ) ;
37
42
38
- var testProcess = Process . Start ( new ProcessStartInfo
43
+ try
39
44
{
40
- FileName = "dotnet" ,
41
- Arguments = $ "test { integrationProjectDir } --logger \" trx;LogFileName={ _testReportFileName } \" ",
42
- RedirectStandardOutput = true ,
43
- RedirectStandardError = true ,
44
- } ) ;
45
-
46
- var standardOutput = await testProcess ! . StandardOutput . ReadToEndAsync ( ) ;
47
- var standardError = await testProcess ! . StandardError . ReadToEndAsync ( ) ;
48
-
49
- var testReport = File . ReadAllText ( _testReportFileName ) ;
50
-
51
- var testResults =
52
- from descendent in XElement . Parse ( testReport ) . Descendants ( )
53
- where descendent . Name . LocalName == "UnitTestResult"
54
- select ElementToTestResult ( descendent ) ;
55
-
56
- TestResults = testResults . ToImmutableList ( ) ;
45
+ var currentProjectDir = Enumerable
46
+ . Range ( 0 , 3 )
47
+ . Aggregate ( new DirectoryInfo ( _currentDirectory ) , ( acc , _ ) => acc . Parent ! ) ;
48
+ var integrationProjectDir = Path . Combine ( currentProjectDir . FullName , "samples" , TestSuiteName ) ;
49
+
50
+ var testProcess = Process . Start ( new ProcessStartInfo
51
+ {
52
+ FileName = "dotnet" ,
53
+ Arguments = $ "test { integrationProjectDir } --logger \" trx;LogFileName={ _testReportFileName } \" ",
54
+ RedirectStandardOutput = true ,
55
+ RedirectStandardError = true ,
56
+ } ) ;
57
+
58
+ var standardOutput = await testProcess ! . StandardOutput . ReadToEndAsync ( ) ;
59
+ var standardError = await testProcess ! . StandardError . ReadToEndAsync ( ) ;
60
+
61
+ TestReport = await File . ReadAllTextAsync ( _testReportFileName ) ;
62
+
63
+ var testResults =
64
+ from descendent in XElement . Parse ( TestReport ) . Descendants ( )
65
+ where descendent . Name . LocalName == "UnitTestResult"
66
+ select ElementToTestResult ( descendent ) ;
67
+
68
+ TestResults = testResults . ToImmutableList ( ) ;
69
+
70
+ TestNameToTestResult = TestResults
71
+ . OrderBy ( x => x . TestName )
72
+ . GroupBy ( x => x . TestName . Contains ( '(' ) ? x . TestName [ ..x . TestName . IndexOf ( '(' ) ] : x . TestName )
73
+ . SelectMany ( g => g . Select ( ( x , i ) => ( TestName : $ "{ g . Key } _{ i } ", TestResult : x ) ) )
74
+ . ToDictionary (
75
+ x => x . TestName ,
76
+ x => string . Join ( "\n " , $ "Outcome: { x . TestResult . Outcome } ", "" , "Output:" , "" , x . TestResult . Output ) ) ;
77
+ }
78
+ finally
79
+ {
80
+ Lock . Release ( ) ;
81
+ }
57
82
}
58
83
59
84
public Task DisposeAsync ( ) => Task . CompletedTask ;
60
85
61
- public TestResult FindTestResult ( string testName ) => TestResults . Single ( x => x . TestName == testName ) ;
62
-
63
86
private static TestResult ElementToTestResult ( XElement element )
64
87
{
65
88
var attributes = element . Attributes ( ) ;
@@ -69,11 +92,20 @@ from desc in element.Descendants()
69
92
where desc . Name . LocalName . Contains ( "Message" )
70
93
select desc . Value ) . SingleOrDefault ( ) ;
71
94
95
+ var output = (
96
+ from desc in element . Descendants ( )
97
+ where desc . Name . LocalName . Contains ( "Output" )
98
+ select desc . Value ) . SingleOrDefault ( ) ;
99
+ if ( output ? . Contains ( " at " ) is true )
100
+ {
101
+ output = output [ ..output . IndexOf ( " at " ) ] ; // Scrub the stacktrace with local paths 😅
102
+ }
103
+
72
104
return new TestResult (
73
105
attributes . Single ( a => a . Name . LocalName . Contains ( "testName" ) ) . Value . Split ( '.' ) . Last ( ) ,
74
106
attributes . Single ( a => a . Name . LocalName . Contains ( "outcome" ) ) . Value ,
75
107
message ! ,
76
- new List < Invocation > ( ) . ToImmutableList ( ) ) ;
108
+ output ! ) ;
77
109
}
78
110
}
79
111
}
0 commit comments