Skip to content

Commit db35d03

Browse files
authored
Migrate from XCTest to Swift Testing (#195)
Migrating `swift-distributed-tracing` from XCTest to Swift Testing ### Motivation Swift Testing is a modern alternative to XCTest. Swift Server Ecosystem packages should serve as reference implementations for modern Swift features and best practices. ### Modifications - 1-to-1 migration of test suites, tests, and assertions to Swift Testing syntax with XCTest import removed ### Result Successfully executes 57 tests with `swift test --disable-xctest`.
1 parent 94a0a92 commit db35d03

File tree

10 files changed

+300
-224
lines changed

10 files changed

+300
-224
lines changed

CONTRIBUTING.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,38 @@ We require that your commit messages match our template. The easiest way to do t
5656

5757
### Run CI checks locally
5858

59-
You can run the Github Actions workflows locally using [act](https://github.com/nektos/act). For detailed steps on how to do this please see [https://github.com/swiftlang/github-workflows?tab=readme-ov-file#running-workflows-locally](https://github.com/swiftlang/github-workflows?tab=readme-ov-file#running-workflows-locally).
59+
You can run the Github Actions workflows locally using
60+
[act](https://github.com/nektos/act). To run all the jobs that run on a pull
61+
request, use the following command:
62+
63+
```
64+
% act pull_request
65+
```
66+
67+
To run just a single job, use `workflow_call -j <job>`, and specify the inputs
68+
the job expects. For example, to run just shellcheck:
69+
70+
```
71+
% act workflow_call -j soundness --input shell_check_enabled=true
72+
```
73+
74+
To bind-mount the working directory to the container, rather than a copy, use
75+
`--bind`. For example, to run just the formatting, and have the results
76+
reflected in your working directory:
77+
78+
```
79+
% act --bind workflow_call -j soundness --input format_check_enabled=true
80+
```
81+
82+
If you'd like `act` to always run with certain flags, these can be be placed in
83+
an `.actrc` file either in the current working directory or your home
84+
directory, for example:
85+
86+
```
87+
--container-architecture=linux/amd64
88+
--remote-name upstream
89+
--action-offline-mode
90+
```
6091

6192
## How to contribute your work
6293

Tests/InMemoryTracingTests/InMemoryTracerTests.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
#if canImport(Testing)
15+
@_spi(Testing) import InMemoryTracing
1616
@_spi(Locking) import Instrumentation
1717
import Testing
1818
import Tracing
19-
@_spi(Testing) import InMemoryTracing
2019

2120
@Suite("InMemoryTracer")
2221
struct InMemoryTracerTests {
@@ -437,5 +436,3 @@ private final class MockClock {
437436
Instant(nanosecondsSinceEpoch: self._now)
438437
}
439438
}
440-
441-
#endif

Tests/InstrumentationTests/InstrumentTests.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import Foundation
1516
import Instrumentation
1617
import ServiceContextModule
17-
import XCTest
18+
import Testing
1819

19-
final class InstrumentTests: XCTestCase {
20-
func testMultiplexInvokesAllInstruments() {
20+
@Suite("MultiplexInstrument")
21+
struct InstrumentTests {
22+
@Test("MultiplexInstrument invokes all instruments")
23+
func multiplexInvokesAllInstruments() {
2124
let instrument = MultiplexInstrument([
2225
FirstFakeTracer(),
2326
SecondFakeTracer(),
@@ -26,15 +29,14 @@ final class InstrumentTests: XCTestCase {
2629
var context = ServiceContext.topLevel
2730
instrument.extract([String: String](), into: &context, using: DictionaryExtractor())
2831

29-
XCTAssertEqual(context[FirstFakeTracer.TraceIDKey.self], FirstFakeTracer.defaultTraceID)
30-
XCTAssertEqual(context[SecondFakeTracer.TraceIDKey.self], SecondFakeTracer.defaultTraceID)
32+
#expect(context[FirstFakeTracer.TraceIDKey.self] == FirstFakeTracer.defaultTraceID)
33+
#expect(context[SecondFakeTracer.TraceIDKey.self] == SecondFakeTracer.defaultTraceID)
3134

3235
var subsequentRequestHeaders = ["Accept": "application/json"]
3336
instrument.inject(context, into: &subsequentRequestHeaders, using: DictionaryInjector())
3437

35-
XCTAssertEqual(
36-
subsequentRequestHeaders,
37-
[
38+
#expect(
39+
subsequentRequestHeaders == [
3840
"Accept": "application/json",
3941
FirstFakeTracer.headerName: FirstFakeTracer.defaultTraceID,
4042
SecondFakeTracer.headerName: SecondFakeTracer.defaultTraceID,

Tests/TracingTests/ActorTracingTests.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,19 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import ServiceContextModule
16+
import Testing
1617
import Tracing
17-
import XCTest
1818

1919
@testable import Instrumentation
2020

2121
/// This is a compile-time test
22-
final class ActorTracingTests: XCTestCase {
23-
func test() {}
22+
@Suite("Actor Tracing Compatibility")
23+
struct ActorTracingTests {
24+
@Test("Compiles with actor isolation")
25+
func compilesWithActorIsolation() {
26+
// This test exists purely to verify that the code compiles
27+
// with Swift's strict concurrency checking
28+
}
2429
}
2530

2631
func work() async {}

Tests/TracingTests/DynamicTracepointTracerTests.swift

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import Foundation
1516
import ServiceContextModule
17+
import Testing
1618
import Tracing
17-
import XCTest
1819

1920
@testable import Instrumentation
2021

21-
final class DynamicTracepointTracerTests: XCTestCase {
22-
func test_adhoc_enableBySourceLoc() {
22+
@Suite("Dynamic Tracepoint Tracer Tests")
23+
struct DynamicTracepointTracerTests {
24+
@Test("Ad-hoc tracepoint enable by source location")
25+
func adhoc_enableBySourceLoc() {
2326
let tracer = DynamicTracepointTestTracer()
2427

2528
let fileID = #fileID
@@ -49,16 +52,17 @@ final class DynamicTracepointTracerTests: XCTestCase {
4952
}
5053
}
5154

52-
XCTAssertEqual(tracer.spans.count, 4)
55+
#expect(tracer.spans.count == 4)
5356

5457
for span in tracer.spans {
55-
XCTAssertEqual(span.context.traceID, "trace-id-fake-\(fileID)-\(fakeLine)")
58+
#expect(span.context.traceID == "trace-id-fake-\(fileID)-\(fakeLine)")
5659
}
57-
XCTAssertEqual(tracer.spans[0].context.spanID, "span-id-fake-\(fileID)-\(fakeLine)")
58-
XCTAssertEqual(tracer.spans[1].context.spanID, "span-id-fake-\(fileID)-\(fakeNextLine)")
60+
#expect(tracer.spans[0].context.spanID == "span-id-fake-\(fileID)-\(fakeLine)")
61+
#expect(tracer.spans[1].context.spanID == "span-id-fake-\(fileID)-\(fakeNextLine)")
5962
}
6063

61-
func test_adhoc_enableByFunction() {
64+
@Test("Ad-hoc tracepoint enable by function")
65+
func adhoc_enableByFunction() {
6266
let tracer = DynamicTracepointTestTracer()
6367

6468
let fileID = #fileID
@@ -70,12 +74,12 @@ final class DynamicTracepointTracerTests: XCTestCase {
7074
self.logic(fakeLine: 55, tracer: tracer)
7175
self.traceMeLogic(fakeLine: fakeLine, tracer: tracer)
7276

73-
XCTAssertEqual(tracer.spans.count, 2)
77+
#expect(tracer.spans.count == 2)
7478
for span in tracer.spans {
75-
XCTAssertEqual(span.context.traceID, "trace-id-fake-\(fileID)-\(fakeLine)")
79+
#expect(span.context.traceID == "trace-id-fake-\(fileID)-\(fakeLine)")
7680
}
77-
XCTAssertEqual(tracer.spans[0].context.spanID, "span-id-fake-\(fileID)-\(fakeLine)")
78-
XCTAssertEqual(tracer.spans[1].context.spanID, "span-id-fake-\(fileID)-\(fakeNextLine)")
81+
#expect(tracer.spans[0].context.spanID == "span-id-fake-\(fileID)-\(fakeLine)")
82+
#expect(tracer.spans[1].context.spanID == "span-id-fake-\(fileID)-\(fakeNextLine)")
7983
}
8084

8185
func logic(fakeLine: UInt, tracer: any Tracer) {

0 commit comments

Comments
 (0)