@@ -59,27 +59,20 @@ public IApiClient WithDefaultCredentials()
5959 return this ;
6060 }
6161
62- public async Task < string > MarkTestCasesCompleted ( int testRunId , IEnumerable < TestResultParent > testCases , DateTime completedDate , CancellationToken cancellationToken )
63- {
64- string requestBody = GetTestCasesAsCompleted ( testCases , completedDate ) ;
65-
66- return await SendAsync ( new HttpMethod ( "PATCH" ) , $ "/{ testRunId } /results", requestBody , cancellationToken ) . ConfigureAwait ( false ) ;
67- }
68-
6962 public async Task < int > AddTestRun ( TestRun testRun , CancellationToken cancellationToken )
7063 {
71- string requestBody = new Dictionary < string , object >
72- {
73- { "name" , testRun . Name } ,
74- { "build" , new Dictionary < string , object > { { "id" , testRun . BuildId } } } ,
75- { "startedDate" , testRun . StartedDate . ToString ( _dateFormatString ) } ,
76- { "isAutomated" , true }
64+ string requestBody = new Dictionary < string , object >
65+ {
66+ { "name" , testRun . Name } ,
67+ { "build" , new Dictionary < string , object > { { "id" , testRun . BuildId } } } ,
68+ { "startedDate" , testRun . StartedDate . ToString ( _dateFormatString ) } ,
69+ { "isAutomated" , true }
7770 } . ToJson ( ) ;
7871
7972 string responseString = await SendAsync ( HttpMethod . Post , null , requestBody , cancellationToken ) . ConfigureAwait ( false ) ;
8073 using ( StringReader reader = new StringReader ( responseString ) )
8174 {
82- JsonObject response = JsonDeserializer . Deserialize ( reader ) as JsonObject ;
75+ JsonObject response = JsonDeserializer . Deserialize ( reader ) as JsonObject ;
8376 return response . ValueAsInt ( "id" ) ;
8477 }
8578 }
@@ -108,13 +101,13 @@ public async Task<int[]> AddTestCases(int testRunId, string[] testCaseNames, Dat
108101 {
109102 Dictionary < string , object > properties = new Dictionary < string , object >
110103 {
111- { "testCaseTitle" , x } ,
112- { "automatedTestName" , x } ,
113- { "resultGroupType" , "generic" } ,
114- { "outcome" , "Passed" } , // Start with a passed outcome initially
115- { "state" , "InProgress" } ,
116- { "startedDate" , startedDate . ToString ( _dateFormatString ) } ,
117- { "automatedTestType" , "UnitTest" } ,
104+ { "testCaseTitle" , x } ,
105+ { "automatedTestName" , x } ,
106+ { "resultGroupType" , "generic" } ,
107+ { "outcome" , "Passed" } , // Start with a passed outcome initially
108+ { "state" , "InProgress" } ,
109+ { "startedDate" , startedDate . ToString ( _dateFormatString ) } ,
110+ { "automatedTestType" , "UnitTest" } ,
118111 { "automatedTestTypeId" , "13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" } // This is used in the sample response and also appears in web searches
119112 } ;
120113 if ( ! string . IsNullOrEmpty ( source ) )
@@ -145,18 +138,17 @@ public async Task<int[]> AddTestCases(int testRunId, string[] testCaseNames, Dat
145138 }
146139 }
147140
148- public async Task MarkTestRunCompleted ( int testRunId , DateTime startedDate , DateTime completedDate , CancellationToken cancellationToken )
141+ public async Task MarkTestRunCompleted ( int testRunId , bool aborted , DateTime completedDate , CancellationToken cancellationToken )
149142 {
150143 // Mark the overall test run as completed
151144 string requestBody = $@ "{{
152- ""state"": ""Completed"",
153- ""startedDate"": ""{ startedDate . ToString ( _dateFormatString ) } "",
145+ ""state"": ""{ ( aborted ? "Aborted" : "Completed" ) } "",
154146 ""completedDate"": ""{ completedDate . ToString ( _dateFormatString ) } ""
155147 }}" ;
156148
157149 await SendAsync ( new HttpMethod ( "PATCH" ) , $ "/{ testRunId } ", requestBody , cancellationToken ) . ConfigureAwait ( false ) ;
158- }
159-
150+ }
151+
160152 protected Dictionary < string , object > GetTestResultProperties ( ITestResult testResult )
161153 {
162154 // https://docs.microsoft.com/en-us/rest/api/azure/devops/test/results/list?view=azure-devops-rest-6.0#testcaseresult
@@ -184,47 +176,48 @@ protected Dictionary<string, object> GetTestResultProperties(ITestResult testRes
184176 }
185177
186178 Dictionary < string , object > properties = new Dictionary < string , object >
187- {
179+ {
188180 { "outcome" , testOutcome } ,
189181 { "computerName" , testResult . ComputerName } ,
190182 { "runBy" , new Dictionary < string , object > { { "displayName" , BuildRequestedFor } } }
191183 } ;
192184
193185 AddAdditionalTestResultProperties ( testResult , properties ) ;
194186
195- if ( testResult . Outcome == TestOutcome . Passed || testResult . Outcome == TestOutcome . Failed )
196- {
197- long duration = Convert . ToInt64 ( testResult . Duration . TotalMilliseconds ) ;
198- properties . Add ( "durationInMs" , duration . ToString ( CultureInfo . InvariantCulture ) ) ;
199-
200- string errorStackTrace = testResult . ErrorStackTrace ;
201- if ( ! string . IsNullOrEmpty ( errorStackTrace ) )
202- {
203- properties . Add ( "stackTrace" , errorStackTrace ) ;
204- }
205-
206- string errorMessage = testResult . ErrorMessage ;
207-
208- if ( ! string . IsNullOrEmpty ( errorMessage ) )
209- {
210- properties . Add ( "errorMessage" , errorMessage ) ;
211- }
212- }
213- else
214- {
215- // Handle output type skip, NotFound and None
187+ if ( testResult . Outcome == TestOutcome . Passed || testResult . Outcome == TestOutcome . Failed )
188+ {
189+ properties . Add ( "startedDate" , testResult . StartTime . ToString ( _dateFormatString ) ) ;
190+ properties . Add ( "completedDate" , testResult . EndTime . ToString ( _dateFormatString ) ) ;
191+
192+ long duration = Convert . ToInt64 ( testResult . Duration . TotalMilliseconds ) ;
193+ properties . Add ( "durationInMs" , duration . ToString ( CultureInfo . InvariantCulture ) ) ;
194+
195+ string errorStackTrace = testResult . ErrorStackTrace ;
196+ if ( ! string . IsNullOrEmpty ( errorStackTrace ) )
197+ {
198+ properties . Add ( "stackTrace" , errorStackTrace ) ;
199+ }
200+
201+ string errorMessage = testResult . ErrorMessage ;
202+
203+ if ( ! string . IsNullOrEmpty ( errorMessage ) )
204+ {
205+ properties . Add ( "errorMessage" , errorMessage ) ;
206+ }
207+ }
208+ else
209+ {
210+ // Handle output type skip, NotFound and None
216211 }
217212
218213 return properties ;
219214 }
220215
221- internal abstract string GetTestCasesAsCompleted ( IEnumerable < TestResultParent > testCases , DateTime completedDate ) ;
222-
223216 internal abstract string GetTestResults (
224217 Dictionary < string , TestResultParent > testCaseTestResults ,
225218 IEnumerable < IGrouping < string , ITestResult > > testResultsByParent ,
226- DateTime completedDate ) ;
227-
219+ DateTime completedDate ) ;
220+
228221 internal virtual void AddAdditionalTestResultProperties ( ITestResult testResult , Dictionary < string , object > properties )
229222 {
230223 }
0 commit comments