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

No one assigned

    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