Skip to content

Commit d14f43f

Browse files
authored
Migrate from XCTest to Swift Testing (#229)
* Remove processing of Vocabs resource from package manifest * Convert ModelsTests from XCTest to Swift Testing * Convert GenerationTests from XCTest to Swift Testing * Convert most of TokenizersTests from XCTest to Swift Testing * Convert FactoryTests from XCTest to Swift Testing * Fix test names for NormalizerTests * Reorganize RoBERTa tests * Inline SQuAD dataset into BertTokenizerTests * Convert TokenizerTests from XCTest to Swift Testing * Convert ConfigTests from XCTest to Swift Testing * Move config-specific tests from HubTests to ConfigTests * Migrate HubTests from XCTest to Swift Testing Fix race condition in moveDownloadedFile Pass hubApiForTests to AutoTokenizer.from calls Consolidate BERT uncased tests Conditionalize integration tests on HF_TOKEN * Revert "Migrate HubTests from XCTest to Swift Testing" This reverts commit 63eef12b1f3899a89dd7e0e376687fefd2f3f091. * Run tokenizer tests in serial * Consolidate references to google-bert/bert-base-uncased to avoid race conditions in tests * Consolidate references to phi and gemma to avoid race conditions in tests * Consolidate references to deepseek-ai/DeepSeek-R1-Distill-Qwen-7B to avoid race conditions in tests * Remove .serialized trait from tokenizer tests * Swap in google-bert/bert-base-chinese for applyTemplateError test
1 parent 58b40bc commit d14f43f

19 files changed

+1380
-1463
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ let package = Package(
3636
.testTarget(name: "GenerationTests", dependencies: ["Generation"]),
3737
.testTarget(name: "HubTests", dependencies: ["Hub", .product(name: "Jinja", package: "Jinja")], swiftSettings: swiftSettings),
3838
.testTarget(name: "ModelsTests", dependencies: ["Models", "Hub"], resources: [.process("Resources")]),
39-
.testTarget(name: "TokenizersTests", dependencies: ["Tokenizers", "Models", "Hub"], resources: [.process("Resources"), .process("Vocabs")]),
39+
.testTarget(name: "TokenizersTests", dependencies: ["Tokenizers", "Models", "Hub"], resources: [.process("Resources")]),
4040
]
4141
)

Tests/GenerationTests/LogitsWarperTests.swift

Lines changed: 69 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,150 +6,155 @@
66

77
#if canImport(CoreML)
88
import CoreML
9-
import XCTest
10-
119
@testable import Generation
10+
import Testing
1211

13-
final class LogitsWarperTests: XCTestCase {
12+
@Suite("Logits Warper Tests")
13+
struct LogitsWarperTests {
1414
private let accuracy: Float = 0.00001
1515

16-
func testTemperatureLogitsWarper() {
16+
@Test("Temperature logits warper functionality")
17+
func temperatureLogitsWarper() {
1718
let result1 = TemperatureLogitsWarper(temperature: 0.0)([], [])
18-
XCTAssertTrue(result1.indices.isEmpty)
19-
XCTAssertTrue(result1.logits.isEmpty)
19+
#expect(result1.indices.isEmpty)
20+
#expect(result1.logits.isEmpty)
2021

2122
let result2 = TemperatureLogitsWarper(temperature: 1.0)([], [])
22-
XCTAssertTrue(result2.indices.isEmpty)
23-
XCTAssertTrue(result2.logits.isEmpty)
23+
#expect(result2.indices.isEmpty)
24+
#expect(result2.logits.isEmpty)
2425

2526
let result3 = TemperatureLogitsWarper(temperature: 1.0)([0, 1], [2.0, 1.0])
26-
XCTAssertEqual(result3.indices, [0, 1])
27-
XCTAssertEqual(result3.logits, [2.0, 1.0], accuracy: accuracy)
27+
#expect(result3.indices == [0, 1])
28+
#expect(isClose(result3.logits, [2.0, 1.0], accuracy: accuracy))
2829

2930
let result4 = TemperatureLogitsWarper(temperature: 2.0)([0, 1], [2.0, 1.0])
30-
XCTAssertEqual(result4.indices, [0, 1])
31-
XCTAssertEqual(result4.logits, [1.0, 0.5], accuracy: accuracy)
31+
#expect(result4.indices == [0, 1])
32+
#expect(isClose(result4.logits, [1.0, 0.5], accuracy: accuracy))
3233

3334
let result5 = TemperatureLogitsWarper(temperature: 0.5)([0, 1], [2.0, 1.0])
34-
XCTAssertEqual(result5.indices, [0, 1])
35-
XCTAssertEqual(result5.logits, [4.0, 2.0], accuracy: accuracy)
35+
#expect(result5.indices == [0, 1])
36+
#expect(isClose(result5.logits, [4.0, 2.0], accuracy: accuracy))
3637

3738
let result6 = TemperatureLogitsWarper(temperature: 0.5)([200, 100], [2.0, 1.0])
38-
XCTAssertEqual(result6.indices, [200, 100])
39-
XCTAssertEqual(result6.logits, [4.0, 2.0], accuracy: accuracy)
39+
#expect(result6.indices == [200, 100])
40+
#expect(isClose(result6.logits, [4.0, 2.0], accuracy: accuracy))
4041
}
4142

42-
func testTopKLogitsWarper() {
43+
@Test("Top-K logits warper functionality")
44+
func topKLogitsWarper() {
4345
let result1 = TopKLogitsWarper(k: 0)([], [])
44-
XCTAssertTrue(result1.indices.isEmpty)
45-
XCTAssertTrue(result1.logits.isEmpty)
46+
#expect(result1.indices.isEmpty)
47+
#expect(result1.logits.isEmpty)
4648

4749
let result2 = TopKLogitsWarper(k: 3)([], [])
48-
XCTAssertTrue(result2.indices.isEmpty)
49-
XCTAssertTrue(result2.logits.isEmpty)
50+
#expect(result2.indices.isEmpty)
51+
#expect(result2.logits.isEmpty)
5052

5153
let result3 = TopKLogitsWarper(k: 3)([0, 1], [2.0, 1.0])
52-
XCTAssertEqual(result3.indices, [0, 1])
53-
XCTAssertEqual(result3.logits, [2.0, 1.0], accuracy: accuracy)
54+
#expect(result3.indices == [0, 1])
55+
#expect(isClose(result3.logits, [2.0, 1.0], accuracy: accuracy))
5456

5557
let result4 = TopKLogitsWarper(k: 3)([0, 1, 2], [2.0, 1.0, 3.0])
56-
XCTAssertEqual(result4.indices, [2, 0, 1])
57-
XCTAssertEqual(result4.logits, [3.0, 2.0, 1.0], accuracy: accuracy)
58+
#expect(result4.indices == [2, 0, 1])
59+
#expect(isClose(result4.logits, [3.0, 2.0, 1.0], accuracy: accuracy))
5860

5961
let result5 = TopKLogitsWarper(k: 4)([0, 1, 2, 3, 4, 5], [2.0, 1.0, 3.0, -1.0, 123.0, 0.0])
60-
XCTAssertEqual(result5.indices, [4, 2, 0, 1])
61-
XCTAssertEqual(result5.logits, [123.0, 3.0, 2.0, 1.0], accuracy: accuracy)
62+
#expect(result5.indices == [4, 2, 0, 1])
63+
#expect(isClose(result5.logits, [123.0, 3.0, 2.0, 1.0], accuracy: accuracy))
6264

6365
let result6 = TopKLogitsWarper(k: 3)([10, 1, 52], [2.0, 1.0, 3.0])
64-
XCTAssertEqual(result6.indices, [52, 10, 1])
65-
XCTAssertEqual(result6.logits, [3.0, 2.0, 1.0], accuracy: accuracy)
66+
#expect(result6.indices == [52, 10, 1])
67+
#expect(isClose(result6.logits, [3.0, 2.0, 1.0], accuracy: accuracy))
6668
}
6769

68-
func testTopPLogitsWarper() {
70+
@Test("Top-P logits warper functionality")
71+
func topPLogitsWarper() {
6972
let result1 = TopPLogitsWarper(p: 0.99)([], [])
70-
XCTAssertTrue(result1.indices.isEmpty)
71-
XCTAssertTrue(result1.logits.isEmpty)
73+
#expect(result1.indices.isEmpty)
74+
#expect(result1.logits.isEmpty)
7275

7376
let logits = (0..<10).map { Float($0) }
7477
let indices = Array(logits.indices)
7578
let result2 = TopPLogitsWarper(p: 0.99)(indices, logits)
76-
XCTAssertEqual(result2.indices, [9, 8, 7, 6, 5])
77-
XCTAssertEqual(result2.logits, [9.0, 8.0, 7.0, 6.0, 5.0], accuracy: accuracy)
79+
#expect(result2.indices == [9, 8, 7, 6, 5])
80+
#expect(isClose(result2.logits, [9.0, 8.0, 7.0, 6.0, 5.0], accuracy: accuracy))
7881

7982
let result3 = TopPLogitsWarper(p: 0.95)(indices, logits)
80-
XCTAssertEqual(result3.indices, [9, 8, 7])
81-
XCTAssertEqual(result3.logits, [9.0, 8.0, 7.0], accuracy: accuracy)
83+
#expect(result3.indices == [9, 8, 7])
84+
#expect(isClose(result3.logits, [9.0, 8.0, 7.0], accuracy: accuracy))
8285

8386
let result4 = TopPLogitsWarper(p: 0.6321493)(indices, logits)
84-
XCTAssertEqual(result4.indices, [9, 8])
85-
XCTAssertEqual(result4.logits, [9.0, 8.0], accuracy: accuracy)
87+
#expect(result4.indices == [9, 8])
88+
#expect(isClose(result4.logits, [9.0, 8.0], accuracy: accuracy))
8689

8790
let result5 = TopPLogitsWarper(p: 0.95)([3, 1, 8], [0, 1, 2])
88-
XCTAssertEqual(result5.indices, [8, 1, 3])
89-
XCTAssertEqual(result5.logits, [2, 1, 0], accuracy: accuracy)
91+
#expect(result5.indices == [8, 1, 3])
92+
#expect(isClose(result5.logits, [2, 1, 0], accuracy: accuracy))
9093
}
9194

92-
func testRepetitionPenaltyWarper() {
95+
@Test("Repetition penalty warper functionality")
96+
func repetitionPenaltyWarper() {
9397
let indices = Array(0..<10)
9498
let logits = indices.map { Float($0) }
9599

96100
let result1 = RepetitionPenaltyWarper(penalty: 1.0)(indices, logits)
97-
XCTAssertEqual(result1.indices, indices)
98-
XCTAssertEqual(result1.logits, logits, accuracy: accuracy)
101+
#expect(result1.indices == indices)
102+
#expect(isClose(result1.logits, logits, accuracy: accuracy))
99103

100104
let result2 = RepetitionPenaltyWarper(penalty: 3.75)(indices, logits)
101-
XCTAssertEqual(result2.indices, indices)
105+
#expect(result2.indices == indices)
102106
let logits2 = indices.map { Float($0) / 3.75 }
103-
XCTAssertEqual(result2.logits, logits2, accuracy: accuracy)
107+
#expect(isClose(result2.logits, logits2, accuracy: accuracy))
104108

105109
let result3 = RepetitionPenaltyWarper(penalty: 0.75)([0, 1, 2], [0.8108, 0.9954, 0.0119])
106-
XCTAssertEqual(result3.indices, [0, 1, 2])
107-
XCTAssertEqual(result3.logits, [1.0811, 1.3272, 0.0158], accuracy: 1e-4)
110+
#expect(result3.indices == [0, 1, 2])
111+
#expect(isClose(result3.logits, [1.0811, 1.3272, 0.0158], accuracy: 1e-4))
108112

109113
let result4 = RepetitionPenaltyWarper(penalty: 1.11)([2, 3, 4], [0.5029, 0.8694, 0.4765, 0.9967, 0.4190, 0.9158])
110-
XCTAssertEqual(result4.indices, [2, 3, 4])
111-
XCTAssertEqual(result4.logits, [0.5029, 0.8694, 0.4293, 0.8980, 0.3775, 0.9158], accuracy: 1e-4)
114+
#expect(result4.indices == [2, 3, 4])
115+
#expect(isClose(result4.logits, [0.5029, 0.8694, 0.4293, 0.8980, 0.3775, 0.9158], accuracy: 1e-4))
112116

113117
let result5 = RepetitionPenaltyWarper(penalty: 0.9)([0, 1, 2], [-0.7433, -0.4738, -0.2966])
114-
XCTAssertEqual(result5.indices, [0, 1, 2])
115-
XCTAssertEqual(result5.logits, [-0.6690, -0.4264, -0.2669], accuracy: 1e-4)
118+
#expect(result5.indices == [0, 1, 2])
119+
#expect(isClose(result5.logits, [-0.6690, -0.4264, -0.2669], accuracy: 1e-4))
116120

117121
let result6 = RepetitionPenaltyWarper(penalty: 1.125)([3, 1, 2], [0.1674, 0.6431, 0.6780, 0.2755])
118-
XCTAssertEqual(result6.indices, [3, 1, 2])
119-
XCTAssertEqual(result6.logits, [0.1674, 0.5716, 0.6026, 0.2449], accuracy: 1e-4)
122+
#expect(result6.indices == [3, 1, 2])
123+
#expect(isClose(result6.logits, [0.1674, 0.5716, 0.6026, 0.2449], accuracy: 1e-4))
120124
}
121125

122-
func testLogitsProcessor() {
126+
@Test("Logits processor functionality")
127+
func logitsProcessor() {
123128
let processor1 = LogitsProcessor(logitsWarpers: [])
124129
let result1 = processor1([])
125-
XCTAssertTrue(result1.indices.isEmpty)
126-
XCTAssertTrue(result1.logits.isEmpty)
130+
#expect(result1.indices.isEmpty)
131+
#expect(result1.logits.isEmpty)
127132

128133
let processor2 = LogitsProcessor(logitsWarpers: [])
129134
let result2 = processor2([2.0, 1.0])
130-
XCTAssertEqual(result2.indices, [0, 1])
131-
XCTAssertEqual(result2.logits, [2.0, 1.0], accuracy: accuracy)
135+
#expect(result2.indices == [0, 1])
136+
#expect(isClose(result2.logits, [2.0, 1.0], accuracy: accuracy))
132137

133138
let processor3 = LogitsProcessor(
134139
logitsWarpers: [TopKLogitsWarper(k: 3)]
135140
)
136141
let result3 = processor3([2.0, 1.0, 3.0, -5.0])
137-
XCTAssertEqual(result3.indices, [2, 0, 1])
138-
XCTAssertEqual(result3.logits, [3.0, 2.0, 1.0], accuracy: accuracy)
142+
#expect(result3.indices == [2, 0, 1])
143+
#expect(isClose(result3.logits, [3.0, 2.0, 1.0], accuracy: accuracy))
139144

140145
let processor4 = LogitsProcessor(
141146
logitsWarpers: [TopKLogitsWarper(k: 3), TopPLogitsWarper(p: 0.99)]
142147
)
143148
let result4 = processor4([2.0, 1.0, 3.0, -5.0, -23.0, 12.5])
144-
XCTAssertEqual(result4.indices, [5])
145-
XCTAssertEqual(result4.logits, [12.5], accuracy: accuracy)
149+
#expect(result4.indices == [5])
150+
#expect(isClose(result4.logits, [12.5], accuracy: accuracy))
146151

147152
let processor5 = LogitsProcessor(
148153
logitsWarpers: [TopKLogitsWarper(k: 4), TopPLogitsWarper(p: 0.99)]
149154
)
150155
let result5 = processor5([2.0, 1.0, 3.0, -5.0, -3.0, 4.5])
151-
XCTAssertEqual(result5.indices, [5, 2, 0, 1])
152-
XCTAssertEqual(result5.logits, [4.5, 3.0, 2.0, 1.0], accuracy: accuracy)
156+
#expect(result5.indices == [5, 2, 0, 1])
157+
#expect(isClose(result5.logits, [4.5, 3.0, 2.0, 1.0], accuracy: accuracy))
153158
}
154159
}
155160
#endif // canImport(CoreML)

Tests/GenerationTests/MathTests.swift

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,54 @@
66

77
#if canImport(CoreML)
88
import CoreML
9-
import XCTest
10-
119
@testable import Generation
10+
import Testing
1211

13-
final class MathTests: XCTestCase {
12+
@Suite("Math Tests")
13+
struct MathTests {
1414
private let accuracy: Float = 0.00001
1515

16-
func testCumsum() {
17-
XCTAssertTrue(Math.cumsum([]).isEmpty)
18-
XCTAssertEqual(Math.cumsum([1]), [1])
19-
XCTAssertEqual(Math.cumsum([1, 2, 3, 4]), [1, 3, 6, 10])
16+
@Test("Cumulative sum functionality")
17+
func cumsum() {
18+
#expect(Math.cumsum([]).isEmpty)
19+
#expect(Math.cumsum([1]) == [1])
20+
#expect(Math.cumsum([1, 2, 3, 4]) == [1, 3, 6, 10])
2021
}
2122

22-
func testArgMax() throws {
23+
@Test("Argmax functionality")
24+
func argmax() throws {
2325
let result1 = Math.argmax([3.0, 4.0, 1.0, 2.0] as [Float], count: 4)
24-
XCTAssertEqual(result1.0, 1)
25-
XCTAssertEqual(result1.1, 4.0)
26+
#expect(result1.0 == 1)
27+
#expect(result1.1 == 4.0)
2628

2729
let result2 = Math.argmax32([3.0, 4.0, 1.0, 2.0], count: 4)
28-
XCTAssertEqual(result2.0, 1)
29-
XCTAssertEqual(result2.1, 4.0)
30+
#expect(result2.0 == 1)
31+
#expect(result2.1 == 4.0)
3032

3133
let result3 = Math.argmax([3.0, 4.0, 1.0, 2.0] as [Double], count: 4)
32-
XCTAssertEqual(result3.0, 1)
33-
XCTAssertEqual(result3.1, 4.0)
34+
#expect(result3.0 == 1)
35+
#expect(result3.1 == 4.0)
3436

3537
let result4 = try Math.argmax32(MLMultiArray([3.0, 4.0, 1.0, 2.0] as [Float]))
36-
XCTAssertEqual(result4.0, 1)
37-
XCTAssertEqual(result4.1, 4.0)
38+
#expect(result4.0 == 1)
39+
#expect(result4.1 == 4.0)
3840

3941
let result5 = try Math.argmax(MLMultiArray([3.0, 4.0, 1.0, 2.0] as [Double]))
40-
XCTAssertEqual(result5.0, 1)
41-
XCTAssertEqual(result5.1, 4.0)
42+
#expect(result5.0 == 1)
43+
#expect(result5.1 == 4.0)
4244

4345
let result6 = Math.argmax(MLShapedArray(scalars: [3.0, 4.0, 1.0, 2.0] as [Float], shape: [4]))
44-
XCTAssertEqual(result6.0, 1)
45-
XCTAssertEqual(result6.1, 4.0)
46+
#expect(result6.0 == 1)
47+
#expect(result6.1 == 4.0)
4648
}
4749

48-
func testSoftmax() {
49-
XCTAssertEqual(Math.softmax([]), [])
50+
@Test("Softmax functionality")
51+
func softmax() {
52+
#expect(Math.softmax([]) == [])
5053

5154
let result1 = Math.softmax([3.0, 4.0, 1.0, 2.0])
52-
XCTAssertEqual(result1, [0.23688284, 0.6439143, 0.032058604, 0.08714432], accuracy: accuracy)
53-
XCTAssertEqual(result1.reduce(0, +), 1.0, accuracy: accuracy)
55+
#expect(isClose(result1, [0.23688284, 0.6439143, 0.032058604, 0.08714432], accuracy: accuracy))
56+
#expect(abs(result1.reduce(0, +) - 1.0) < accuracy)
5457
}
5558
}
5659
#endif // canImport(CoreML)
Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
11
import Foundation
2-
import XCTest
32

4-
func XCTAssertEqual<T: FloatingPoint>(
5-
_ expression1: @autoclosure () throws -> [T],
6-
_ expression2: @autoclosure () throws -> [T],
7-
accuracy: T,
8-
_ message: @autoclosure () -> String = "",
9-
file: StaticString = #filePath,
10-
line: UInt = #line
11-
) {
12-
do {
13-
let lhsEvaluated = try expression1()
14-
let rhsEvaluated = try expression2()
15-
XCTAssertEqual(lhsEvaluated.count, rhsEvaluated.count, file: file, line: line)
16-
for (lhs, rhs) in zip(lhsEvaluated, rhsEvaluated) {
17-
XCTAssertEqual(lhs, rhs, accuracy: accuracy, file: file, line: line)
18-
}
19-
} catch {
20-
XCTFail("Unexpected error: \(error)", file: file, line: line)
21-
}
3+
/// Check if two floating-point arrays are equal within a given accuracy
4+
func isClose<T: FloatingPoint>(_ lhs: [T], _ rhs: [T], accuracy: T) -> Bool {
5+
guard lhs.count == rhs.count else { return false }
6+
return zip(lhs, rhs).allSatisfy { abs($0.0 - $0.1) <= accuracy }
227
}

0 commit comments

Comments
 (0)