Skip to content

Support retry-on-failure for only the failing @Test cases #1392

@swhitty

Description

@swhitty

Motivation

xcodebuild supports the option -retry-tests-on-failure which can be passed to automatically retry tests that fail. Swift Testing is partially supported with this option, but all Swift Testing @Test are retried, even if they had already passed.

Consider the following tests;

struct SwiftTestingA {
  @Test
  func successA(){
    #expect(Bool(true))
  }

 @Test
  func failureA() {
    #expect(Bool(false))
  }
}

struct SwiftTestingB {
  @Test
  func successB() {
    #expect(Bool(true))
  }
}

final class XCTestA: XCTestCase {

  func testSuccess() {
    XCTAssertTrue(true)
  }

  func testFailure() {
    XCTAssertTrue(false)
  }
}

When executing with xcodebuild test ...

  • XCTestA.testSuccess() is executed and passes 1 time only (expected).
  • SwiftTestingA.success() is executed and passes 3 times (1 expected).
  • SwiftTestingB.success() is executed and passes 3 times (1 expected).
% xcodebuild test -scheme TestLibrary -retry-tests-on-failure

Test suite 'XCTestA' started
Test suite 'SwiftTestingB' started
Test suite 'SwiftTestingA' started
Test case 'SwiftTestingB/successB()' passed (0.000 seconds)
Test case 'SwiftTestingA/successA()' passed (0.000 seconds)
Test case 'XCTestA.testFailure()' failed (0.284 seconds)
Test case 'XCTestA.testFailure()' failed (0.001 seconds)
Test case 'XCTestA.testFailure()' failed (0.001 seconds)
Test case 'SwiftTestingA/failureA()' failed (0.000 seconds)
Test suite 'SwiftTestingB' started
Test suite 'SwiftTestingA' started
Test case 'SwiftTestingB/successB()' passed (0.000 seconds)
Test case 'SwiftTestingA/successA()' passed (0.000 seconds)
Test case 'SwiftTestingA/failureA()' failed (0.000 seconds)
Test suite 'SwiftTestingB' started
Test suite 'SwiftTestingA' started
Test case 'SwiftTestingA/successA()' passed (0.000 seconds)
Test case 'SwiftTestingB/successB()' passed (0.000 seconds)
Test case 'SwiftTestingA/failureA()' failed (0.000 seconds)
Test case 'XCTestA.testSuccess()' passed (0.001 seconds)

Proposed solution

With xcodebuild aside, it would be useful for swift test to natively support an option like -retry-tests-on-failure to automatically retry tests that fail;

% swift test -retry-tests-on-failure

◇ Suite SwiftTestingA started.
◇ Suite SwiftTestingB started.
✔ Test successA() passed after 0.001 seconds.
✔ Test successB() passed after 0.001 seconds.
✔ Suite SwiftTestingB passed after 0.001 seconds.
✘ Test failureA() recorded an issue at Tests.swift:17:5: Expectation failed: Bool(false)
✘ Test failureA() iteration: 1 failed after 0.001 seconds with 1 issue.
✘ Test failureA() recorded an issue at Tests.swift:17:5: Expectation failed: Bool(false)
✘ Test failureA() iteration: 2 failed after 0.001 seconds with 1 issue.
✘ Test failureA() recorded an issue at Tests.swift:17:5: Expectation failed: Bool(false)
✘ Test failureA() iteration: 3 failed after 0.001 seconds with 1 issue.
✘ Suite SwiftTestingA failed after 0.001 seconds with 3 issues.
✘ Test run with 3 tests failed after 0.001 seconds with 3 issues.

Tests that pass successA() / successB() would not be retried and would only be executed once.

While parametrized tests could potentially retry just the parameters that fail — the CLI output reports these as a single test so it may be fine to just retry all parameters if a single parameter fails.

Alternatives considered

No response

Additional information

https://forums.swift.org/t/retry-tests-on-failure-retries-test-that-have-already-passed/83031

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requesttriagedThis issue has undergone initial triage

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions