Skip to content

Commit 2709184

Browse files
Merge pull request #3695 from SwiftPackageIndex/issue-3655-swift-testing-part-16
Issue 3655 swift testing part 16
2 parents d9efc0a + c5ccf11 commit 2709184

File tree

3 files changed

+173
-156
lines changed

3 files changed

+173
-156
lines changed

Tests/AppTests/Joined3Tests.swift

Lines changed: 68 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,89 +14,97 @@
1414

1515
@testable import App
1616

17+
import Testing
1718
import Vapor
18-
import XCTest
1919

20-
class Joined3Tests: AppTestCase {
2120

22-
func test_query_no_version() async throws {
23-
// setup
24-
let p = try await savePackage(on: app.db, "1")
25-
try await Repository(package: p).save(on: app.db)
21+
@Suite struct Joined3Tests {
2622

27-
// MUT
28-
let res = try await Joined3<Package, Repository, Version>.query(on: app.db).all()
29-
30-
// validate
31-
XCTAssertEqual(res.map(\.model.id), [])
32-
}
33-
34-
func test_query_multiple_versions() async throws {
35-
// Ensure multiple versions don't multiply the package selection
36-
// setup
37-
let p = try await savePackage(on: app.db, "1")
38-
try await Repository(package: p).save(on: app.db)
39-
try await Version(package: p, latest: .defaultBranch).save(on: app.db)
40-
try await Version(package: p, latest: .release).save(on: app.db)
41-
42-
// MUT
43-
let res = try await Joined3<Package, Repository, Version>
44-
.query(on: app.db, version: .defaultBranch)
45-
.all()
46-
47-
// validate
48-
XCTAssertEqual(res.map(\.model.id), [p.id])
49-
}
23+
@Test func query_no_version() async throws {
24+
try await withApp { app in
25+
// setup
26+
let p = try await savePackage(on: app.db, "1")
27+
try await Repository(package: p).save(on: app.db)
5028

29+
// MUT
30+
let res = try await Joined3<Package, Repository, Version>.query(on: app.db).all()
5131

52-
func test_query_relationship_properties() async throws {
53-
// Ensure relationship properties are populated by query
54-
// setup
55-
let p = try await savePackage(on: app.db, "1")
56-
try await Repository(package: p, owner: "owner").save(on: app.db)
57-
try await Version(package: p,
58-
latest: .defaultBranch,
59-
packageName: "package name").save(on: app.db)
60-
61-
// MUT
62-
let res = try await Joined3<Package, Repository, Version>
63-
.query(on: app.db, version: .defaultBranch)
64-
.all()
65-
66-
// validate
67-
XCTAssertEqual(res.map { $0.repository.owner }, ["owner"])
68-
XCTAssertEqual(res.map { $0.version.packageName }, ["package name"])
32+
// validate
33+
#expect(res.map(\.model.id) == [])
34+
}
6935
}
7036

71-
func test_query_missing_relations() async throws {
72-
// Neither should be possible in practice, this is just ensuring we cannot
73-
// force unwrap the `repository` or `version` properties in the pathological
74-
// event, because there are no results to access the properties on.
75-
do { // no repository
37+
@Test func query_multiple_versions() async throws {
38+
// Ensure multiple versions don't multiply the package selection
39+
try await withApp { app in
40+
// setup
7641
let p = try await savePackage(on: app.db, "1")
77-
try await Version(package: p,
78-
latest: .defaultBranch,
79-
packageName: "package name").save(on: app.db)
42+
try await Repository(package: p).save(on: app.db)
43+
try await Version(package: p, latest: .defaultBranch).save(on: app.db)
44+
try await Version(package: p, latest: .release).save(on: app.db)
8045

8146
// MUT
8247
let res = try await Joined3<Package, Repository, Version>
8348
.query(on: app.db, version: .defaultBranch)
8449
.all()
8550

86-
// validate - result is empty, `res[0].repository` cannot be called
87-
XCTAssertTrue(res.isEmpty)
51+
// validate
52+
#expect(res.map(\.model.id) == [p.id])
8853
}
89-
do { // no version
90-
let p = try await savePackage(on: app.db, "2")
54+
}
55+
56+
@Test func query_relationship_properties() async throws {
57+
// Ensure relationship properties are populated by query
58+
try await withApp { app in
59+
// setup
60+
let p = try await savePackage(on: app.db, "1")
9161
try await Repository(package: p, owner: "owner").save(on: app.db)
62+
try await Version(package: p,
63+
latest: .defaultBranch,
64+
packageName: "package name").save(on: app.db)
9265

9366
// MUT
9467
let res = try await Joined3<Package, Repository, Version>
9568
.query(on: app.db, version: .defaultBranch)
9669
.all()
9770

98-
// validate - result is empty, `res[0].repository` cannot be called
99-
XCTAssertTrue(res.isEmpty)
71+
// validate
72+
#expect(res.map { $0.repository.owner } == ["owner"])
73+
#expect(res.map { $0.version.packageName } == ["package name"])
74+
}
75+
}
76+
77+
@Test func query_missing_relations() async throws {
78+
// Neither should be possible in practice, this is just ensuring we cannot
79+
// force unwrap the `repository` or `version` properties in the pathological
80+
// event, because there are no results to access the properties on.
81+
try await withApp { app in
82+
do { // no repository
83+
let p = try await savePackage(on: app.db, "1")
84+
try await Version(package: p,
85+
latest: .defaultBranch,
86+
packageName: "package name").save(on: app.db)
87+
88+
// MUT
89+
let res = try await Joined3<Package, Repository, Version>
90+
.query(on: app.db, version: .defaultBranch)
91+
.all()
92+
93+
// validate - result is empty, `res[0].repository` cannot be called
94+
#expect(res.isEmpty)
95+
}
96+
do { // no version
97+
let p = try await savePackage(on: app.db, "2")
98+
try await Repository(package: p, owner: "owner").save(on: app.db)
99+
100+
// MUT
101+
let res = try await Joined3<Package, Repository, Version>
102+
.query(on: app.db, version: .defaultBranch)
103+
.all()
104+
105+
// validate - result is empty, `res[0].repository` cannot be called
106+
#expect(res.isEmpty)
107+
}
100108
}
101109
}
102110

Tests/AppTests/JoinedQueryBuilderTests.swift

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,55 +15,57 @@
1515
@testable import App
1616

1717
import FluentKit
18-
import XCTest
18+
import Testing
1919

2020

2121
/// `JoinedQueryBuilder` is essentially a "pass-through" class that wraps a `QueryBuilder`
2222
/// and forwards method calls to it. This test class tests this behaviour in principle for `sort`
2323
/// but not for any other methods at this time, because the instrumentation is quite mechanical
2424
/// and essentially compiler checked.
25-
class JoinedQueryBuilderTests: AppTestCase {
25+
@Suite struct JoinedQueryBuilderTests {
2626

27-
func test_sort() async throws {
28-
// setup
29-
for idx in (0..<3).shuffled() {
30-
try await Package(url: "\(idx)".url).save(on: app.db)
31-
}
32-
// query helper
33-
func query() -> JoinedQueryBuilder<Package> {
34-
JoinedQueryBuilder<Package>(
35-
queryBuilder: Package.query(on: app.db)
36-
)
37-
}
38-
39-
do { // test sort(_ sort: DatabaseQuery.Sort)
40-
// MUT
41-
let res = try await query()
42-
.sort(DatabaseQuery.Sort.sort(.sql(unsafeRaw: "url"), .descending))
43-
.all()
44-
45-
// validate
46-
XCTAssertEqual(res.map(\.url), ["2", "1", "0"])
47-
}
48-
49-
do { // test sort<Field>(_ field: KeyPath<...>, _ direction:)
50-
// MUT
51-
let res = try await query()
52-
.sort(\.$url, .descending)
53-
.all()
54-
55-
// validate
56-
XCTAssertEqual(res.map(\.url), ["2", "1", "0"])
57-
}
58-
59-
do { // test sort(_ field: DatabaseQuery.Field, _ direction:)
60-
// MUT
61-
let res = try await query()
62-
.sort(DatabaseQuery.Field.sql(unsafeRaw: "url"), .descending)
63-
.all()
64-
65-
// validate
66-
XCTAssertEqual(res.map(\.url), ["2", "1", "0"])
27+
@Test func sort() async throws {
28+
try await withApp { app in
29+
// setup
30+
for idx in (0..<3).shuffled() {
31+
try await Package(url: "\(idx)".url).save(on: app.db)
32+
}
33+
// query helper
34+
func query() -> JoinedQueryBuilder<Package> {
35+
JoinedQueryBuilder<Package>(
36+
queryBuilder: Package.query(on: app.db)
37+
)
38+
}
39+
40+
do { // test sort(_ sort: DatabaseQuery.Sort)
41+
// MUT
42+
let res = try await query()
43+
.sort(DatabaseQuery.Sort.sort(.sql(unsafeRaw: "url"), .descending))
44+
.all()
45+
46+
// validate
47+
#expect(res.map(\.url) == ["2", "1", "0"])
48+
}
49+
50+
do { // test sort<Field>(_ field: KeyPath<...>, _ direction:)
51+
// MUT
52+
let res = try await query()
53+
.sort(\.$url, .descending)
54+
.all()
55+
56+
// validate
57+
#expect(res.map(\.url) == ["2", "1", "0"])
58+
}
59+
60+
do { // test sort(_ field: DatabaseQuery.Field, _ direction:)
61+
// MUT
62+
let res = try await query()
63+
.sort(DatabaseQuery.Field.sql(unsafeRaw: "url"), .descending)
64+
.all()
65+
66+
// validate
67+
#expect(res.map(\.url) == ["2", "1", "0"])
68+
}
6769
}
6870
}
6971

Tests/AppTests/JoinedTests.swift

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,78 +14,85 @@
1414

1515
@testable import App
1616

17-
import XCTest
17+
import Testing
1818

19-
class JoinedTests: AppTestCase {
19+
20+
@Suite struct JoinedTests {
2021
typealias JPR = Joined<Package, Repository>
2122

22-
func test_query_owner_repository() async throws {
23-
// setup
24-
let pkg = Package(url: "1")
25-
try await pkg.save(on: app.db)
26-
try await Repository(package: pkg, name: "bar", owner: "foo")
27-
.save(on: app.db)
28-
do { // inselected package
29-
let pkg = Package(url: "2")
23+
@Test func query_owner_repository() async throws {
24+
try await withApp { app in
25+
// setup
26+
let pkg = Package(url: "1")
3027
try await pkg.save(on: app.db)
31-
try await Repository(package: pkg, name: "bar2", owner: "foo")
28+
try await Repository(package: pkg, name: "bar", owner: "foo")
3229
.save(on: app.db)
33-
}
30+
do { // inselected package
31+
let pkg = Package(url: "2")
32+
try await pkg.save(on: app.db)
33+
try await Repository(package: pkg, name: "bar2", owner: "foo")
34+
.save(on: app.db)
35+
}
3436

35-
// MUT
36-
let jpr = try await JPR.query(on: app.db, owner: "foo", repository: "bar")
37+
// MUT
38+
let jpr = try await JPR.query(on: app.db, owner: "foo", repository: "bar")
3739

38-
// validate
39-
XCTAssertEqual(jpr.package.id, pkg.id)
40-
XCTAssertEqual(jpr.repository?.owner, "foo")
41-
XCTAssertEqual(jpr.repository?.name, "bar")
40+
// validate
41+
#expect(jpr.package.id == pkg.id)
42+
#expect(jpr.repository?.owner == "foo")
43+
#expect(jpr.repository?.name == "bar")
44+
}
4245
}
4346

44-
func test_repository_access() async throws {
47+
@Test func repository_access() async throws {
4548
// Test accessing repository through the join vs through the package relation
46-
// setup
47-
let p = try await savePackage(on: app.db, "1")
48-
try await Repository(package: p).save(on: app.db)
49+
try await withApp { app in
50+
// setup
51+
let p = try await savePackage(on: app.db, "1")
52+
try await Repository(package: p).save(on: app.db)
4953

50-
// MUT
51-
let jpr = try await XCTUnwrapAsync(try await JPR.query(on: app.db).first())
54+
// MUT
55+
let jpr = try await XCTUnwrapAsync(try await JPR.query(on: app.db).first())
5256

53-
// validate
54-
XCTAssertNotNil(jpr.repository)
55-
// Assert the relationship is not loaded - that's the point of the join
56-
// In particular, this means that
57-
// let repos = jpr.model.repositories
58-
// will fatalError. (This risk has always been there, it's just handled a
59-
// bit better now via `Joined<...>`.)
60-
// There is unfortunately no simple way to make this safe other that replacing/
61-
// wrapping all of the types involved.
62-
XCTAssertNil(jpr.model.$repositories.value)
57+
// validate
58+
#expect(jpr.repository != nil)
59+
// Assert the relationship is not loaded - that's the point of the join
60+
// In particular, this means that
61+
// let repos = jpr.model.repositories
62+
// will fatalError. (This risk has always been there, it's just handled a
63+
// bit better now via `Joined<...>`.)
64+
// There is unfortunately no simple way to make this safe other that replacing/
65+
// wrapping all of the types involved.
66+
#expect(jpr.model.$repositories.value == nil)
67+
}
6368
}
6469

65-
func test_repository_update() async throws {
70+
@Test func repository_update() async throws {
6671
// Test updating the repository through the join
67-
// setup
68-
let p = try await savePackage(on: app.db, "1")
69-
try await Repository(package: p).save(on: app.db)
72+
try await withApp { app in
73+
// setup
74+
let p = try await savePackage(on: app.db, "1")
75+
try await Repository(package: p).save(on: app.db)
7076

71-
let jpr = try await XCTUnwrapAsync(try await JPR.query(on: app.db).first())
72-
let repo = try XCTUnwrap(jpr.repository)
73-
XCTAssertEqual(repo.name, nil)
74-
repo.name = "foo"
77+
let jpr = try await XCTUnwrapAsync(try await JPR.query(on: app.db).first())
78+
let repo = try #require(jpr.repository)
79+
#expect(repo.name == nil)
80+
repo.name = "foo"
7581

76-
// MUT
77-
try await repo.update(on: app.db)
82+
// MUT
83+
try await repo.update(on: app.db)
7884

79-
// validate
80-
do { // test in-place updates
81-
XCTAssertEqual(repo.name, "foo")
82-
XCTAssertEqual(jpr.repository?.name, "foo")
83-
}
84-
do { // ensure value is persisted
85-
let r = try await XCTUnwrapAsync(try await Repository.query(on: app.db).first())
86-
XCTAssertEqual(r.name, "foo")
87-
let reloadedJPR = try await XCTUnwrapAsync(try await JPR.query(on: app.db).first())
88-
XCTAssertEqual(reloadedJPR.repository?.name, "foo")
85+
// validate
86+
do { // test in-place updates
87+
#expect(repo.name == "foo")
88+
#expect(jpr.repository?.name == "foo")
89+
}
90+
do { // ensure value is persisted
91+
let r = try await XCTUnwrapAsync(try await Repository.query(on: app.db).first())
92+
#expect(r.name == "foo")
93+
let reloadedJPR = try await XCTUnwrapAsync(try await JPR.query(on: app.db).first())
94+
#expect(reloadedJPR.repository?.name == "foo")
95+
}
8996
}
9097
}
9198

0 commit comments

Comments
 (0)