Skip to content

Commit d00b779

Browse files
authored
[ci] Automatically retry failed emulator tests. (#7997)
[Previously](#7963), we have used `retryCountOnTaskFailure` to retry some of our flaky test suites. However this is not a good solution for our MSBuild and emulator tests for 2 reasons: - Running each suite takes 30-60 minutes, so it would take a long time to retry the entire suite. - The suites are very flaky, and rerunning the entire suite would likely result in test(s) that were successful on the first run to fail on the second. We need a solution that only retries the specific test(s) that failed. Unfortunately nothing like that exists, so we'll once again have to roll our own solution, and we can reuse `dotnet-test-slicer` for this. This involves some trickery to make everything show up correctly in the AzDO UI: - Run the initial test suite - Run in a Powershell so we can ignore any test failures that would move the pipeline into `SucceededWithIssues` state - Do not automatically publish the test results, as they would contain test failures - Run `dotnet-test-slicer retry` - This creates a new `.runsettings` file that only contains the failed tests so `dotnet test` can run only them - It also rewrites the test results file of the initial run and removes any failed tests from so it can be published to AzDO - Publish the successful tests from the first run to AzDO - Run the retried tests - This time we can use normal `dotnet`, and any test failures can be automatically reported to AzDO Affected Test Suites: - MSBuild Emulator Tests
1 parent 475b912 commit d00b779

File tree

5 files changed

+44
-12
lines changed

5 files changed

+44
-12
lines changed

build-tools/automation/yaml-templates/install-dotnet-test-slicer.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
version: '0.1.0-alpha2'
2+
version: '0.1.0-alpha5'
33
condition: succeeded()
44
continueOnError: true
55

build-tools/automation/yaml-templates/run-msbuild-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/$(DotNetStableTargetFramework)/Xamarin.Android.Build.Tests.dll
4949
testFilter: ${{ parameters.testFilter }} $(ExcludedNUnitCategories)
5050
testRunTitle: Xamarin.Android.Build.Tests - ${{ parameters.testOS }}
51-
testResultsTitle: TestResult-MSBuildTests-${{ parameters.jobName }}
51+
retryFailedTests: false
5252

5353
- template: upload-results.yaml
5454
parameters:

build-tools/automation/yaml-templates/run-sliced-nunit-tests.yaml

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,55 @@ parameters:
22
testAssembly: # NUnit test assembly to run
33
testFilter: # Filter used to select tests (NUnit test selection language, not dotnet test filter language)
44
testRunTitle: # Title of the test run
5-
testResultsTitle: # Title used to construct test results file name
5+
retryFailedTests: true # Retry failed tests once
66

77
steps:
88
- pwsh: |
99
dotnet-test-slicer `
10+
slice `
1011
--test-assembly="${{ parameters.testAssembly }}" `
1112
--test-filter="${{ parameters.testFilter }}" `
1213
--slice-number=$(System.JobPositionInPhase) `
1314
--total-slices=$(System.TotalJobsInPhase) `
1415
--outfile="${{ parameters.testAssembly }}.runsettings"
1516
displayName: Slice unit tests
1617

17-
- template: run-nunit-tests.yaml
18-
parameters:
19-
useDotNet: true
20-
testRunTitle: ${{ parameters.testRunTitle }}-$(System.JobPositionInPhase)
21-
testAssembly: ${{ parameters.testAssembly }}
22-
dotNetTestExtraArgs: --settings "${{ parameters.testAssembly }}.runsettings"
23-
testResultsFile: ${{ parameters.testResultsTitle }}-$(System.JobPositionInPhase)-$(XA.Build.Configuration).xml
18+
- ${{ if eq(parameters.retryFailedTests, 'false') }}:
19+
# If we aren't using auto-retry logic, then this is just a simple template call
20+
- template: run-nunit-tests.yaml
21+
parameters:
22+
testRunTitle: ${{ parameters.testRunTitle }}-$(System.JobPositionInPhase)
23+
testAssembly: ${{ parameters.testAssembly }}
24+
dotNetTestExtraArgs: --settings "${{ parameters.testAssembly }}.runsettings"
25+
26+
- ${{ if eq(parameters.retryFailedTests, 'true') }}:
27+
# We need a custom dotnet test invocation here that does not trigger a task failure on failed tests
28+
- pwsh: |
29+
dotnet `
30+
test `
31+
${{ parameters.testAssembly }} `
32+
--settings "${{ parameters.testAssembly }}.runsettings" `
33+
--logger trx --results-directory $(Agent.TempDirectory) `
34+
-- NUnit.NumberOfTestWorkers=$(NUnit.NumberOfTestWorkers)
35+
displayName: Run tests
36+
ignoreLASTEXITCODE: true
37+
38+
- pwsh: |
39+
dotnet-test-slicer `
40+
retry `
41+
--trx="$(Agent.TempDirectory)" `
42+
--outfile="${{ parameters.testAssembly }}.runsettings"
43+
displayName: Look for failed tests
44+
45+
# dotnet-test-slicer removed the failed tests from our results file, so it's safe to publish it now
46+
- task: PublishTestResults@2
47+
inputs:
48+
testResultsFormat: VSTest
49+
testResultsFiles: $(Agent.TempDirectory)/*.trx
50+
testRunTitle: ${{ parameters.testRunTitle }}-$(System.JobPositionInPhase)
51+
52+
- template: run-nunit-tests.yaml
53+
parameters:
54+
testRunTitle: ${{ parameters.testRunTitle }}-$(System.JobPositionInPhase) (Auto-Retry)
55+
testAssembly: ${{ parameters.testAssembly }}
56+
dotNetTestExtraArgs: --settings "${{ parameters.testAssembly }}.runsettings"

build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ stages:
5353
testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/MSBuildDeviceIntegration/$(DotNetStableTargetFramework)/MSBuildDeviceIntegration.dll
5454
testFilter: cat != TimeZoneInfo & cat != Localization $(ExcludedNUnitCategories)
5555
testRunTitle: MSBuildDeviceIntegration On Device - macOS
56-
testResultsTitle: TestResult-MSBuildDeviceIntegration-${{ parameters.job_name }}
5756

5857
- template: start-stop-emulator.yaml
5958
parameters:

build-tools/automation/yaml-templates/start-stop-emulator.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ parameters:
55
avdApiLevel: # Device API level, like '30', required if 'specificImage' is 'true'
66
avdAbi: # Device ABI, like 'x86', required if 'specificImage' is 'true'
77
avdType: # Device AVD, like 'android-wear', required if 'specificImage' is 'true'
8-
launchTimeoutMin: 15 # Minutes to wait for the emulator to start
8+
launchTimeoutMin: 20 # Minutes to wait for the emulator to start
99
xaSourcePath: $(System.DefaultWorkingDirectory) # working directory
1010

1111
steps:

0 commit comments

Comments
 (0)