Skip to content

Commit fda3bb7

Browse files
author
Andreas Günther
committed
SwiftPackage copied from another workspace to its own git repo to release independent
1 parent b15fb08 commit fda3bb7

10 files changed

Lines changed: 506 additions & 0 deletions

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/config/registries.json
8+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9+
.netrc

Package.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// swift-tools-version: 5.4
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "SwiftAsyncAssert",
8+
products: [
9+
.library(
10+
name: "SwiftAsyncAssert",
11+
targets: ["SwiftAsyncAssert"]),
12+
],
13+
targets: [
14+
.target(name: "SwiftAsyncAssert"),
15+
.testTarget(
16+
name: "SwiftAsyncAssertTests",
17+
dependencies: ["SwiftAsyncAssert"]),
18+
]
19+
)

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SwiftAsyncAssert
2+
3+
XCTAssert variants to evaluate async expressions in XCTests.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// AssertExpressionEvaluator.swift
3+
//
4+
//
5+
// Created by Andreas Guenther on 11.08.23.
6+
//
7+
8+
import XCTest
9+
10+
enum AssertExpressionEvaluator {
11+
12+
/// Evaluated in case an evaluated expression throws an error
13+
static var failurePrompt: (String, StaticString, UInt) -> Void = { XCTFail($0, file: $1, line: $2) }
14+
15+
static func evaluate(_ expression: () async throws -> Void,
16+
_ message: @autoclosure () -> String = "",
17+
function: StaticString = #function,
18+
file: StaticString = #filePath,
19+
line: UInt = #line) async {
20+
do {
21+
try await expression()
22+
} catch {
23+
Self.failurePrompt(ThrownErrorFormatter.formattedStringForThrownError(error,
24+
in: "\(function)",
25+
message: message()),
26+
file,
27+
line)
28+
}
29+
}
30+
}
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import XCTest
2+
3+
public func AsyncAssert(_ expression: @autoclosure () async throws -> Bool,
4+
_ message: @autoclosure () -> String = "",
5+
file: StaticString = #filePath,
6+
line: UInt = #line) async {
7+
await AssertExpressionEvaluator.evaluate({
8+
let result = try await expression()
9+
XCTAssert(result, message(), file: file, line: line)
10+
},
11+
message(),
12+
file: file,
13+
line: line)
14+
}
15+
16+
public func AsyncAssertEqual<T>(_ expression1: @autoclosure () async throws -> T,
17+
_ expression2: @autoclosure () async throws -> T,
18+
_ message: @autoclosure () -> String = "",
19+
file: StaticString = #filePath,
20+
line: UInt = #line) async where T : Equatable {
21+
await AssertExpressionEvaluator.evaluate({
22+
let result1 = try await expression1()
23+
let result2 = try await expression2()
24+
XCTAssertEqual(result1, result2, message(), file: file, line: line)
25+
},
26+
message(),
27+
file: file,
28+
line: line)
29+
}
30+
31+
public func AsyncAssertEqual<T>(_ expression1: @autoclosure () async throws -> T,
32+
_ expression2: @autoclosure () async throws -> T,
33+
accuracy: T,
34+
_ message: @autoclosure () -> String = "",
35+
file: StaticString = #filePath,
36+
line: UInt = #line) async where T : FloatingPoint {
37+
await AssertExpressionEvaluator.evaluate({
38+
let result1 = try await expression1()
39+
let result2 = try await expression2()
40+
XCTAssertEqual(result1, result2, accuracy: accuracy, message(), file: file, line: line)
41+
},
42+
message(),
43+
file: file,
44+
line: line)
45+
}
46+
47+
public func AsyncAssertEqual<T>(_ expression1: @autoclosure () async throws -> T,
48+
_ expression2: @autoclosure () async throws -> T,
49+
accuracy: T,
50+
_ message: @autoclosure () -> String = "",
51+
file: StaticString = #filePath,
52+
line: UInt = #line) async where T : Numeric {
53+
await AssertExpressionEvaluator.evaluate({
54+
let result1 = try await expression1()
55+
let result2 = try await expression2()
56+
XCTAssertEqual(result1, result2, accuracy: accuracy, message(), file: file, line: line)
57+
},
58+
message(),
59+
file: file,
60+
line: line)
61+
}
62+
63+
public func AsyncAssertFalse(_ expression: @autoclosure () async throws -> Bool, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async {
64+
await AssertExpressionEvaluator.evaluate({
65+
let result = try await expression()
66+
XCTAssertFalse(result, message(), file: file, line: line)
67+
},
68+
message(),
69+
file: file,
70+
line: line)
71+
}
72+
73+
public func AsyncAssertGreaterThan<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : Comparable {
74+
await AssertExpressionEvaluator.evaluate({
75+
let result1 = try await expression1()
76+
let result2 = try await expression2()
77+
XCTAssertGreaterThan(result1, result2, message(), file: file, line: line)
78+
},
79+
message(),
80+
file: file,
81+
line: line)
82+
}
83+
84+
public func AsyncAssertGreaterThanOrEqual<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : Comparable {
85+
await AssertExpressionEvaluator.evaluate({
86+
let result1 = try await expression1()
87+
let result2 = try await expression2()
88+
XCTAssertGreaterThanOrEqual(result1, result2, message(), file: file, line: line)
89+
},
90+
message(),
91+
file: file,
92+
line: line)
93+
}
94+
95+
public func AsyncAssertIdentical(_ expression1: @autoclosure () async throws -> AnyObject?, _ expression2: @autoclosure () async throws -> AnyObject?, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async {
96+
await AssertExpressionEvaluator.evaluate({
97+
let result1 = try await expression1()
98+
let result2 = try await expression2()
99+
XCTAssertIdentical(result1, result2, message(), file: file, line: line)
100+
},
101+
message(),
102+
file: file,
103+
line: line)
104+
}
105+
106+
public func AsyncAssertLessThan<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : Comparable {
107+
await AssertExpressionEvaluator.evaluate({
108+
let result1 = try await expression1()
109+
let result2 = try await expression2()
110+
XCTAssertLessThan(result1, result2, message(), file: file, line: line)
111+
},
112+
message(),
113+
file: file,
114+
line: line)
115+
}
116+
117+
public func AsyncAssertLessThanOrEqual<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : Comparable {
118+
await AssertExpressionEvaluator.evaluate({
119+
let result1 = try await expression1()
120+
let result2 = try await expression2()
121+
XCTAssertLessThanOrEqual(result1, result2, message(), file: file, line: line)
122+
},
123+
message(),
124+
file: file,
125+
line: line)
126+
}
127+
128+
public func AsyncAssertNil(_ expression: @autoclosure () async throws -> Any?, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async {
129+
await AssertExpressionEvaluator.evaluate({
130+
let result = try await expression()
131+
XCTAssertNil(result, message(), file: file, line: line)
132+
},
133+
message(),
134+
file: file,
135+
line: line)
136+
}
137+
138+
public func AsyncAssertNoThrow<T>(_ expression: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async {
139+
do {
140+
let _ = try await expression()
141+
XCTAssertNoThrow({}(), message(), file: file, line: line)
142+
} catch {
143+
XCTAssertNoThrow(try { throw error }(), message(), file: file, line: line)
144+
}
145+
}
146+
147+
public func AsyncAssertNotEqual<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : Equatable {
148+
await AssertExpressionEvaluator.evaluate({
149+
let result1 = try await expression1()
150+
let result2 = try await expression2()
151+
XCTAssertNotEqual(result1, result2, message(), file: file, line: line)
152+
},
153+
message(),
154+
file: file,
155+
line: line)
156+
}
157+
158+
public func AsyncAssertNotEqual<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, accuracy: T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : FloatingPoint {
159+
await AssertExpressionEvaluator.evaluate({
160+
let result1 = try await expression1()
161+
let result2 = try await expression2()
162+
XCTAssertNotEqual(result1, result2, accuracy: accuracy, message(), file: file, line: line)
163+
},
164+
message(),
165+
file: file,
166+
line: line)
167+
}
168+
169+
public func AsyncAssertNotEqual<T>(_ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, accuracy: T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async where T : Numeric {
170+
await AssertExpressionEvaluator.evaluate({
171+
let result1 = try await expression1()
172+
let result2 = try await expression2()
173+
XCTAssertNotEqual(result1, result2, accuracy: accuracy, message(), file: file, line: line)
174+
},
175+
message(),
176+
file: file,
177+
line: line)
178+
}
179+
180+
public func AsyncAssertNotIdentical(_ expression1: @autoclosure () async throws -> AnyObject?, _ expression2: @autoclosure () async throws -> AnyObject?, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async {
181+
await AssertExpressionEvaluator.evaluate({
182+
let result1 = try await expression1()
183+
let result2 = try await expression2()
184+
XCTAssertNotIdentical(result1, result2, message(), file: file, line: line)
185+
},
186+
message(),
187+
file: file,
188+
line: line)
189+
}
190+
191+
public func AsyncAssertNotNil(_ expression: @autoclosure () async throws -> Any?, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) async {
192+
await AssertExpressionEvaluator.evaluate({
193+
let result = try await expression()
194+
XCTAssertNotNil(result, message(), file: file, line: line)
195+
},
196+
message(),
197+
file: file,
198+
line: line)
199+
}
200+
201+
public func AsyncAssertThrowsError<T>(_ expression: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line, _ errorHandler: (_ error: Error) -> Void = { _ in }) async {
202+
do {
203+
let _ = try await expression()
204+
XCTAssertThrowsError({}(), message(), file: file, line: line)
205+
} catch {
206+
XCTAssertThrowsError(try { throw error }(), message(), file: file, line: line)
207+
}
208+
}
209+
210+
public func AsyncAssertTrue(_ expression: @autoclosure () async throws -> Bool,
211+
_ message: @autoclosure () -> String = "",
212+
file: StaticString = #filePath,
213+
line: UInt = #line) async {
214+
await AssertExpressionEvaluator.evaluate({
215+
let result = try await expression()
216+
XCTAssertTrue(result, message(), file: file, line: line)
217+
},
218+
message(),
219+
file: file,
220+
line: line)
221+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// ThrownErrorFormatter.swift
3+
//
4+
//
5+
// Created by Andreas Guenther on 11.08.23.
6+
//
7+
8+
import Foundation
9+
10+
final class ThrownErrorFormatter {
11+
12+
static func formattedStringForThrownError(_ error: Error, in function: String, message: String) -> String {
13+
// Format '<func name> failed: threw error "<error>" - <message>'
14+
return ["\(formatFunctionName(function)) failed: threw error \"\(error)\"",
15+
message]
16+
.filter({ $0.isEmpty == false })
17+
.joined(separator: " - ")
18+
}
19+
20+
private static func formatFunctionName(_ functionName: String) -> String {
21+
return functionName.components(separatedBy: "(").first ?? functionName
22+
}
23+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// AssertExpressionEvaluatorTest.swift
3+
//
4+
//
5+
// Created by Andreas Guenther on 11.08.23.
6+
//
7+
8+
import XCTest
9+
10+
@testable import SwiftAsyncAssert
11+
12+
final class AssertExpressionEvaluatorTest: XCTestCase {
13+
14+
func test_should_succeed_when_evaluated_expression_executes_successfully() async throws {
15+
var isFailurePromptCalled = false
16+
17+
AssertExpressionEvaluator.failurePrompt = { _, _, _ in
18+
isFailurePromptCalled = true
19+
}
20+
21+
await AssertExpressionEvaluator.evaluate({
22+
// Here gets code executed that does not throw an error
23+
})
24+
25+
XCTAssertFalse(isFailurePromptCalled)
26+
}
27+
28+
func test_should_fail_when_evaluated_expression_throws_error() async throws {
29+
var isFailurePromptCalled = false
30+
31+
AssertExpressionEvaluator.failurePrompt = { _, _, _ in
32+
isFailurePromptCalled = true
33+
}
34+
35+
await AssertExpressionEvaluator.evaluate({
36+
throw TestingError.systemFailedToWork
37+
})
38+
39+
XCTAssertTrue(isFailurePromptCalled)
40+
}
41+
}

0 commit comments

Comments
 (0)