Summary
This is a concrete proposal for a flaky test management system that can be provided by test platform with a cooperation with test frameworks.
Goals:
- Have a native experience for managing flaky tests.
- We don't want to lose coverage from those tests by completely ignoring them forever.
- We want to have a way to track whether or not a test became stable.
Background and Motivation
Flaky tests are part of every big project that people need to deal with it. Today, there is no good way to manage and track flaky tests, and different efforts and approaches are getting invented by individual teams. None of the approaches that exist today is very ideal as well.
Proposed Feature
The test platform should have the knowledge of a test being known to be flaky. Such tests should be run, but shouldn't fail the test run. For that, such tests will have "inconclusive" result. But there we have two different kind of "inconclusive" results. First is "passed inconclusive", second is "failed inconclusive".
How this is going to work
Individual test frameworks who want to support this feature will:
- Ship their own attribute, let's say it's named FlakyTestAttribute or InconclusiveResultAttribute (that's a choice for the individual test frameworks to make)
- Have a way to let MTP know that the test is marked as such.
- MTP reporting provides a way to get the results of such tests.
- Because of backcompat concerns for TRX, we might need a different way.
- This could be a simple json file that doesn't have the full test reporting capabilities. The json will just have two arrays, one for "inconclusive passed" and the other for "inconclusive failed" and the new json file format won't be concerned about all other kind of tests, and won't be concerned by attachments, display names, duration, traits, ....
- The info needed might be just the TestUid and FQN.
This allows users to track how their flaky tests performs without fully skipping them, and also by keeping them running in the same process as the other tests.
People can then build their system that deals with those json files.
Taking this a step further
There are two additional ways to take this a step further.
-
Manage a flaky info storage on Azure DevOps.
- We could use Azure DevOps to store information about those flaky tests and have an easy way to do queries like "tests that haven't failed in the past X runs" or "tests that haven't failed in the past X days" or "tests with failure rate >= X%" or "tests with failure rate <= X%", ...
-
Specify a specific flakiness reason.
-
This is about having specific failure(s) to be considered "inconclusive failed".
-
Let's say:
[FlakyTest(nameof(IsTimeout))]
public void MyTest() { ... }
public static void IsTimeout(Exception testFailureException)
=> testFailureException.Message.Contains("Timed out");
-
In the above scenario, we could have 3 outcomes:
- Test is passing -> Consider as "inconclusive passed".
- Test is failing matching the known flakiness reason (e.g, timeout check in example) -> Consider as "inconclusive failed".
- Test is failing with an unknown reason -> Consider as "failed" and fail the test run.
-
Why is this nice?
- This allows users to still run their flaky tests without failing CI much for "known reasons" that users acknowledged. But still fail in case it's a different failure. That way, the test coverage isn't fully lost, and regressions can still be captured by those tests. So we get the best of everything, CI stability and capturing new potential regressions.
-
The way how the "is known flakiness reason" is implemented will be up to the test frameworks. The test platform should provide some way for the test framework to hook the implementation. The right API shape for this might require some experimentation with implementation.
Additional notes
As of today, repos could have their own custom "quarantine" system. The way this works is that tests are by default "unquarantined", and with the existence of a specific test property (via attribute), the test is marked as "quarantined".
Repos could then setup the necessary infrastructure to have two CI pipelines, one that's required and runs only quarantined tests, and another that's not required and runs only unquarantined tests.
This has down sides:
- The detection for whether or not a test is stable cannot be reliable when quarantined tests are isolated from other tests.
- It's extra infrastructure that people have to maintain and potentially duplicate across repos.
Note that the above system is implemented by aspnetcore repo already, but isn't reliable IMO.
Summary
This is a concrete proposal for a flaky test management system that can be provided by test platform with a cooperation with test frameworks.
Goals:
Background and Motivation
Flaky tests are part of every big project that people need to deal with it. Today, there is no good way to manage and track flaky tests, and different efforts and approaches are getting invented by individual teams. None of the approaches that exist today is very ideal as well.
Proposed Feature
The test platform should have the knowledge of a test being known to be flaky. Such tests should be run, but shouldn't fail the test run. For that, such tests will have "inconclusive" result. But there we have two different kind of "inconclusive" results. First is "passed inconclusive", second is "failed inconclusive".
How this is going to work
Individual test frameworks who want to support this feature will:
This allows users to track how their flaky tests performs without fully skipping them, and also by keeping them running in the same process as the other tests.
People can then build their system that deals with those json files.
Taking this a step further
There are two additional ways to take this a step further.
Manage a flaky info storage on Azure DevOps.
Specify a specific flakiness reason.
This is about having specific failure(s) to be considered "inconclusive failed".
Let's say:
In the above scenario, we could have 3 outcomes:
Why is this nice?
The way how the "is known flakiness reason" is implemented will be up to the test frameworks. The test platform should provide some way for the test framework to hook the implementation. The right API shape for this might require some experimentation with implementation.
Additional notes
As of today, repos could have their own custom "quarantine" system. The way this works is that tests are by default "unquarantined", and with the existence of a specific test property (via attribute), the test is marked as "quarantined".
Repos could then setup the necessary infrastructure to have two CI pipelines, one that's required and runs only quarantined tests, and another that's not required and runs only unquarantined tests.
This has down sides:
Note that the above system is implemented by aspnetcore repo already, but isn't reliable IMO.