Skip to content

Commit 0337cc6

Browse files
committed
swift6: migrate test suite from XCTest to Swift Testing
Converts all 10 test files to the @Suite/@test style that ships with Swift 6.x, matching the pattern used by swift-vips. VIPS-dependent suites (Photo/Keyword/Album/Gallery) use @suite(.serialized) since libvips is not concurrent-safe for our use. Class-based suites retain setUp/tearDown state via init() throws / deinit; value-type suites use struct. Drops 7 trivial test() placeholders that carried no coverage (61 -> 54 tests, all passing).
1 parent 4512a88 commit 0337cc6

11 files changed

Lines changed: 466 additions & 597 deletions

FUTURES.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,9 @@ drop the small ANSI helper.
153153
since changed twice. Commit 23's relaxed assertions trade exact-count
154154
coverage for robustness; refine to exact counts once the example tree
155155
stabilises, or parameterise on the actual source tree.
156-
- `TestSetup` could bootstrap a shared temp directory once per test class
157-
rather than per test, amortising the VIPS init cost.
158-
- Swift Testing (the new non-XCTest framework) ships with Swift 6.3 but
159-
MuninKitTests is still on XCTest. A lift to Swift Testing would shorten
160-
test code and integrate with Xcode 16's test UI; see how `swift-vips`
161-
has done it.
156+
- The GalleryTests suite creates a fresh temp directory per test via
157+
`randomString` to guarantee isolation under `@Suite(.serialized)`.
158+
Consider amortising setup cost further if test run time grows.
162159

163160
---
164161

Lines changed: 71 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,44 @@
1-
import XCTest
1+
import Foundation
2+
import Testing
23

34
@testable import MuninKit
45

5-
final class AlbumTests: XCTestCase {
6+
@Suite(.serialized)
7+
final class AlbumTests {
68
let albumPath = "example/album/"
79
let outPath = "example/content/"
810
let configPath = "example/munin.json"
9-
var config: GalleryConfiguration!
10-
var ctx: Context!
11+
let config: GalleryConfiguration
12+
let ctx: Context
1113

12-
override func setUp() {
13-
super.setUp()
14+
init() {
1415
VIPSSetup.ensure()
1516
let manager = ConfigurationManager()
1617
manager
17-
.load(file: configPath, relativeFrom: .customPath("")).load(["progress": false])
18-
config = GalleryConfiguration(manager)
19-
ctx = Context(config: config)
18+
.load(file: configPath, relativeFrom: .customPath(""))
19+
.load(["progress": false])
20+
self.config = GalleryConfiguration(manager)
21+
self.ctx = Context(config: config)
2022
}
2123

22-
override func tearDown() {
23-
config = nil
24-
ctx = nil
25-
super.tearDown()
26-
}
27-
28-
func test() {
29-
XCTAssertEqual("test", "test")
30-
}
31-
32-
func testReadStateFromInputDirectory() async throws {
33-
24+
@Test func readStateFromInputDirectoryReturnsExpectedCounts() async throws {
3425
let album = try await readStateFromInputDirectory(
3526
ctx: ctx, atPath: albumPath, outPath: outPath, name: "test", parents: [])
3627

37-
let photoCount = album.numberOfPhotos(travers: true)
38-
XCTAssertEqual(photoCount, 104)
39-
let albumCount = album.numberOfAlbums(travers: true)
40-
XCTAssertEqual(albumCount, 12)
28+
#expect(album.numberOfPhotos(travers: true) == 104)
29+
#expect(album.numberOfAlbums(travers: true) == 12)
4130
}
4231

43-
func testExpectedFiles() async throws {
32+
@Test func expectedFilesMatchAcrossAlbumTree() async throws {
4433
let album = try await readStateFromInputDirectory(
4534
ctx: ctx, atPath: albumPath + "/Misc", outPath: outPath, name: "test",
4635
parents: [Parent(name: "", url: "")])
4736

48-
let photoCount = album.numberOfPhotos(travers: true)
49-
XCTAssertEqual(photoCount, 3)
50-
let albumCount = album.numberOfAlbums(travers: true)
51-
XCTAssertEqual(albumCount, 0)
37+
#expect(album.numberOfPhotos(travers: true) == 3)
38+
#expect(album.numberOfAlbums(travers: true) == 0)
5239

5340
let cwd = FileManager.default.currentDirectoryPath
5441
let contentDir = "\(cwd)/example/content"
55-
5642
let expectedFiles = [
5743
"\(contentDir)/test/20180510-171752-IMG_7165.json",
5844
"\(contentDir)/test/20180510-171752-IMG_7165_180.jpg",
@@ -77,50 +63,38 @@ final class AlbumTests: XCTestCase {
7763
"\(contentDir)/test/portrait_mm_original.jpeg",
7864
].sorted()
7965
let actualFiles = album.expectedFiles.map { $0.path }.sorted()
80-
XCTAssertEqual(actualFiles, expectedFiles)
66+
#expect(actualFiles == expectedFiles)
8167
}
8268

83-
func testUnreferencedFilesNoOutputDirectory() async throws {
69+
@Test func unreferencedFilesEmptyWithoutOutputDirectory() async throws {
8470
let album = try await readStateFromInputDirectory(
8571
ctx: ctx, atPath: albumPath + "/Misc", outPath: outPath, name: "test",
8672
parents: [Parent(name: "", url: "")])
8773

88-
let photoCount = album.numberOfPhotos(travers: true)
89-
XCTAssertEqual(photoCount, 3)
90-
let albumCount = album.numberOfAlbums(travers: true)
91-
XCTAssertEqual(albumCount, 0)
92-
93-
let unreferenced = album.unreferencedFiles
94-
95-
XCTAssertEqual(unreferenced, [])
74+
#expect(album.numberOfPhotos(travers: true) == 3)
75+
#expect(album.numberOfAlbums(travers: true) == 0)
76+
#expect(album.unreferencedFiles == [])
9677
}
9778

98-
func testUnreferencedFilesWithOutputDirectory() async throws {
79+
@Test func unreferencedFilesWithOutputDirectory() async throws {
9980
let album = try await readStateFromInputDirectory(
10081
ctx: ctx, atPath: albumPath, outPath: outPath, name: "root", parents: [])
10182

102-
let photoCount = album.numberOfPhotos(travers: true)
103-
XCTAssertEqual(photoCount, 104)
104-
let albumCount = album.numberOfAlbums(travers: true)
105-
XCTAssertEqual(albumCount, 12)
106-
let unreferenced = album.unreferencedFiles
107-
108-
XCTAssertEqual(unreferenced, [])
83+
#expect(album.numberOfPhotos(travers: true) == 104)
84+
#expect(album.numberOfAlbums(travers: true) == 12)
85+
#expect(album.unreferencedFiles == [])
10986
}
11087

111-
func testMissingFilesNoOutputDirectory() async throws {
88+
@Test func missingFilesReportedWhenOutputIsEmpty() async throws {
11289
let album = try await readStateFromInputDirectory(
11390
ctx: ctx, atPath: albumPath + "/Misc", outPath: outPath, name: "test",
11491
parents: [Parent(name: "", url: "")])
11592

116-
let photoCount = album.numberOfPhotos(travers: true)
117-
XCTAssertEqual(photoCount, 3)
118-
let albumCount = album.numberOfAlbums(travers: true)
119-
XCTAssertEqual(albumCount, 0)
93+
#expect(album.numberOfPhotos(travers: true) == 3)
94+
#expect(album.numberOfAlbums(travers: true) == 0)
12095

12196
let cwd = FileManager.default.currentDirectoryPath
12297
let contentDir = "\(cwd)/example/content"
123-
12498
let expectedFiles = [
12599
"\(contentDir)/test/20180510-171752-IMG_7165.json",
126100
"\(contentDir)/test/20180510-171752-IMG_7165_180.jpg",
@@ -145,26 +119,19 @@ final class AlbumTests: XCTestCase {
145119
"\(contentDir)/test/portrait_mm_original.jpeg",
146120
].sorted()
147121
let missing = album.missingFiles.map { $0.path }.sorted()
148-
149-
XCTAssertEqual(missing, expectedFiles)
122+
#expect(missing == expectedFiles)
150123
}
151124

152-
func testMissingFilesWithOutputDirectory() async throws {
125+
@Test func missingFilesEmptyWhenOutputExists() async throws {
153126
let album = try await readStateFromInputDirectory(
154127
ctx: ctx, atPath: albumPath, outPath: outPath, name: "root", parents: [])
155128

156-
let photoCount = album.numberOfPhotos(travers: true)
157-
XCTAssertEqual(photoCount, 104)
158-
let albumCount = album.numberOfAlbums(travers: true)
159-
XCTAssertEqual(albumCount, 12)
160-
161-
let expectedFiles: [String] = []
162-
let missing = album.missingFiles.map { $0.path }.sorted()
163-
164-
XCTAssertEqual(missing, expectedFiles)
129+
#expect(album.numberOfPhotos(travers: true) == 104)
130+
#expect(album.numberOfAlbums(travers: true) == 12)
131+
#expect(album.missingFiles.map { $0.path }.sorted() == [])
165132
}
166133

167-
func testChangedPhotos() {
134+
@Test func changedPhotosDetectedViaSetDifference() {
168135
var input = Album(name: "root", path: "", parents: [])
169136
var current = Album(name: "root", path: "", parents: [])
170137
let ph1 = Photo(
@@ -173,102 +140,81 @@ final class AlbumTests: XCTestCase {
173140
let ph2 = Photo(name: "photo2")
174141
let ph3 = Photo(name: "photo3")
175142
let ph4 = Photo(name: "photo4")
176-
let ph1_2 = Photo(
143+
let ph1Modified = Photo(
177144
name: "photo1", url: "", originalImageURL: "", originalImagePath: "", scaledPhotos: [],
178145
modifiedDate: Date(timeIntervalSince1970: 1_610_471_000), parents: [])
179146

180147
input.photos = [ph1, ph2]
181148
current.photos = [ph3, ph4]
182-
XCTAssertEqual(current.changedPhotos(input), [ph1, ph2])
149+
#expect(current.changedPhotos(input) == [ph1, ph2])
183150

184151
input.photos = [ph1, ph2, ph3]
185152
current.photos = [ph3, ph4]
186-
XCTAssertEqual(current.changedPhotos(input), [ph1, ph2])
153+
#expect(current.changedPhotos(input) == [ph1, ph2])
187154

188-
input.photos = [ph1_2, ph3]
155+
input.photos = [ph1Modified, ph3]
189156
current.photos = [ph1, ph3, ph2, ph4]
190-
XCTAssertEqual(
191-
current.changedPhotos(input).map { $0.name }.sorted(), ["photo1"])
157+
#expect(current.changedPhotos(input).map { $0.name }.sorted() == ["photo1"])
192158

193-
input.photos = [ph1_2, ph3, ph2, ph4]
159+
input.photos = [ph1Modified, ph3, ph2, ph4]
194160
current.photos = [ph1, ph3]
195-
XCTAssertEqual(
196-
current.changedPhotos(input).map { $0.name }.sorted(), ["photo1", "photo2", "photo4"])
161+
#expect(
162+
current.changedPhotos(input).map { $0.name }.sorted()
163+
== ["photo1", "photo2", "photo4"])
197164
}
198165

199-
func testChangedAlbums() {
166+
@Test func changedAlbumsDetectedViaSetDifference() {
200167
var input = Album(name: "root", path: "", parents: [])
201168
var current = Album(name: "root", path: "", parents: [])
202169

203170
let child1 = Album(name: "child1", path: "", parents: [])
204171
let child2 = Album(name: "child2", path: "", parents: [])
205172
let child3 = Album(name: "child3", path: "", parents: [])
206-
var child1_2 = Album(name: "child1", path: "", parents: [])
207-
child1_2.photos = [Photo(name: "photo4")]
208-
var child1_3 = Album(name: "child1", path: "", parents: [])
209-
child1_3.photos = [Photo(name: "photo2")]
173+
var child1Variant = Album(name: "child1", path: "", parents: [])
174+
child1Variant.photos = [Photo(name: "photo4")]
175+
var child1Deep = Album(name: "child1", path: "", parents: [])
176+
child1Deep.photos = [Photo(name: "photo2")]
210177

211178
input.albums = [child1, child2]
212179
current.albums = [child3]
213-
XCTAssertEqual(current.changedAlbums(input), [child1, child2])
180+
#expect(current.changedAlbums(input) == [child1, child2])
214181

215182
input.albums = [child1, child2]
216183
current.albums = [child2, child3]
217-
XCTAssertEqual(current.changedAlbums(input), [child1])
184+
#expect(current.changedAlbums(input) == [child1])
218185

219-
input.albums = [child1_2, child3]
186+
input.albums = [child1Variant, child3]
220187
current.albums = [child1, child2]
221-
XCTAssertEqual(
222-
current.changedAlbums(input).map { $0.name }.sorted(), ["child1", "child3"])
188+
#expect(
189+
current.changedAlbums(input).map { $0.name }.sorted() == ["child1", "child3"])
223190

224191
var parentOfChild1 = Album(name: "parentOfChild1", path: "", parents: [])
225-
var parentOfChild1_3 = Album(name: "parentOfChild1", path: "", parents: [])
192+
var parentOfChild1Deep = Album(name: "parentOfChild1", path: "", parents: [])
226193

227194
parentOfChild1.albums = [child1]
228-
parentOfChild1_3.albums = [child1_3]
195+
parentOfChild1Deep.albums = [child1Deep]
229196

230197
var parentOfParentOfChild1 = Album(name: "parentOfParentOfChild1", path: "", parents: [])
231-
var parentOfParentOfChild1_3 = Album(name: "parentOfParentOfChild1", path: "", parents: [])
198+
var parentOfParentOfChild1Deep = Album(
199+
name: "parentOfParentOfChild1", path: "", parents: [])
232200

233201
parentOfParentOfChild1.albums = [parentOfChild1]
234-
parentOfParentOfChild1_3.albums = [parentOfChild1_3]
202+
parentOfParentOfChild1Deep.albums = [parentOfChild1Deep]
235203

236-
input.albums = [parentOfParentOfChild1_3]
204+
input.albums = [parentOfParentOfChild1Deep]
237205
current.albums = [parentOfParentOfChild1]
238-
XCTAssertEqual(
239-
current.changedAlbums(input).map { $0.name }.sorted(), ["parentOfParentOfChild1"])
240-
241-
}
242-
243-
func testChangedAlbumsInputHasChildAlbum() {
244-
// input has a new child
245-
var input2 = Album(name: "root", path: "", parents: [])
246-
let current2 = Album(name: "root", path: "", parents: [])
247-
248-
let child_2 = Album(name: "child1", path: "", parents: [])
249-
input2.albums = [child_2]
250-
let changed2 = current2.changedAlbums(input2)
251-
XCTAssertNotNil(changed2)
252-
XCTAssertEqual(changed2.count, 1)
253-
XCTAssertEqual(Array(changed2)[0], child_2)
206+
#expect(
207+
current.changedAlbums(input).map { $0.name }.sorted() == ["parentOfParentOfChild1"])
254208
}
255209

256-
func testClean() {}
257-
258-
// This is a silly test to ensure that concurrency does not
259-
// cause inconsistent reads of the albums
260-
// func testReadStateFromInputDirectoryMultipleTime() {
261-
// let config = Config.readConfig(configFormat: GalleryConfiguration.self, atPath: configPath)
262-
263-
// for _ in 1...100 {
264-
// let ctx = Context(config: config)
265-
// let album = readStateFromInputDirectory(
266-
// ctx: ctx, atPath: albumPath, outPath: outPath, name: "test", parents: [])
210+
@Test func changedAlbumsDetectsInputHasExtraChild() {
211+
var input = Album(name: "root", path: "", parents: [])
212+
let current = Album(name: "root", path: "", parents: [])
267213

268-
// let photoCount = album.numberOfPhotos(travers: true)
269-
// XCTAssertEqual(photoCount, 102)
270-
// let albumCount = album.numberOfAlbums(travers: true)
271-
// XCTAssertEqual(albumCount, 10)
272-
// }
273-
// }
214+
let child = Album(name: "child1", path: "", parents: [])
215+
input.albums = [child]
216+
let changed = current.changedAlbums(input)
217+
#expect(changed.count == 1)
218+
#expect(Array(changed)[0] == child)
219+
}
274220
}

0 commit comments

Comments
 (0)