File: OrganizingTests.md

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (147 lines) | stat: -rw-r--r-- 4,838 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Organizing test functions with suite types

<!--
This source file is part of the Swift.org open source project

Copyright (c) 2023-2024 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
-->

Organize tests into test suites.

## Overview

When working with a large selection of test functions, it can be helpful to
organize them into test suites.

A test function can be added to a test suite in one of two ways:

@Comment{ * By placing it in the same file as other test functions. }
* By placing it in a Swift type.
* By placing it in a Swift type and annotating that type with the `@Suite`
   attribute.

The `@Suite` attribute isn't required for the testing library to recognize that
a type contains test functions, but adding it allows customization of a test
suite's appearance in the IDE and at the command line. If a trait such as
``Trait/tags(_:)`` or ``Trait/disabled(_:sourceLocation:)`` is applied to a test
suite, it's automatically inherited by the tests contained in the suite.

In addition to containing test functions and any other members that a Swift type
might contain, test suite types can also contain additional test suites nested
within them. To add a nested test suite type, simply declare an additional type
within the scope of the outer test suite type.

By default, tests contained within a suite run in parallel with each other.
For more information about test parallelization, see <doc:Parallelization>.

### Customize a suite's name

To customize a test suite's name, supply a string literal as an argument to the
`@Suite` attribute:

```swift
@Suite("Food truck tests") struct FoodTruckTests {
  @Test func foodTruckExists() { ... }
}
```

To further customize the appearance and behavior of a test function, use
[traits](doc:Traits) such as ``Trait/tags(_:)``.

## Test functions in test suite types

If a type contains a test function declared as an instance method (that is,
without either the `static` or `class` keyword), the testing library calls
that test function at runtime by initializing an instance of the type, then
calling the test function on that instance. If a test suite type contains
multiple test functions declared as instance methods, each one is called on a
distinct instance of the type. Therefore, the following test suite and test
function:

```swift
@Suite struct FoodTruckTests {
  @Test func foodTruckExists() { ... }
}
```

Are equivalent to:

```swift
@Suite struct FoodTruckTests {
  func foodTruckExists() { ... }

  @Test static func staticFoodTruckExists() {
    let instance = FoodTruckTests()
    instance.foodTruckExists()
  }
}
```

### Constraints on test suite types

When using a type as a test suite, it's subject to some constraints that are
not otherwise applied to Swift types.

#### An initializer may be required

If a type contains test functions declared as instance methods, it must be
possible to initialize an instance of the type with a zero-argument initializer.
The initializer may be any combination of:

- implicit or explicit
- synchronous or asynchronous
- throwing or non-throwing
- `private`, `fileprivate`, `internal`, `package`, or `public`

For example:

```swift
@Suite struct FoodTruckTests {
  var batteryLevel = 100

  @Test func foodTruckExists() { ... } // ✅ OK: The type has an implicit init().
}

@Suite struct CashRegisterTests {
  private init(cashOnHand: Decimal = 0.0) async throws { ... }

  @Test func calculateSalesTax() { ... } // ✅ OK: The type has a callable init().
}

struct MenuTests {
  var foods: [Food]
  var prices: [Food: Decimal]

  @Test static func specialOfTheDay() { ... } // ✅ OK: The function is static.
  @Test func orderAllFoods() { ... } // ❌ ERROR: The suite type requires init().
}
```

The compiler emits an error when presented with a test suite that doesn't
meet this requirement.

### Test suite types must always be available

Although `@available` can be applied to a test function to limit its
availability at runtime, a test suite type (and any types that contain it) must
_not_ be annotated with the `@available` attribute:

```swift
@Suite struct FoodTruckTests { ... } // ✅ OK: The type is always available.

@available(macOS 11.0, *) // ❌ ERROR: The suite type must always be available.
@Suite struct CashRegisterTests { ... }

@available(macOS 11.0, *) struct MenuItemTests { // ❌ ERROR: The suite type's
                                                 // containing type must always
                                                 // be available too.
  @Suite struct BurgerTests { ... }
}
```

The compiler emits an error when presented with a test suite that doesn't
meet this requirement.