Skip to content

Commit c3a42e8

Browse files
Add XCTUnwrap(_:case:) test helper. (#95)
* Add XCTUnwrap(_:case:) test helper. * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update Package.swift * Update XCTUnwrap.swift * Update XCTUnwrapTests.swift * skip * Update .github/workflows/ci.yml * wip * Update XCTUnwrap.swift * Update Sources/CasePaths/XCTUnwrap.swift Co-authored-by: Stephen Celis <[email protected]>
1 parent bb43642 commit c3a42e8

File tree

6 files changed

+103
-30
lines changed

6 files changed

+103
-30
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,13 @@ concurrency:
1313
cancel-in-progress: true
1414

1515
jobs:
16-
macos-11:
17-
name: MacOS 11
18-
runs-on: macos-11
16+
macos-12:
17+
name: MacOS 12
18+
runs-on: macos-12
1919
strategy:
2020
matrix:
2121
xcode:
22-
- 12.5.1
23-
- '13.0'
24-
steps:
25-
- uses: actions/checkout@v2
26-
- name: Select Xcode ${{ matrix.xcode }}
27-
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
28-
- name: Print Swift version
29-
run: swift --version
30-
- name: Run tests
31-
run: make test-swift
32-
33-
macos-10-15:
34-
name: MacOS 10.15
35-
runs-on: macos-10.15
36-
strategy:
37-
matrix:
38-
xcode:
39-
- 11.3
40-
- 11.7
41-
- 12.4
22+
- '14.2'
4223
steps:
4324
- uses: actions/checkout@v2
4425
- name: Select Xcode ${{ matrix.xcode }}

Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@ test-linux:
55
--rm \
66
-v "$(PWD):$(PWD)" \
77
-w "$(PWD)" \
8-
swift:5.3 \
8+
swift:5.5 \
99
bash -c 'make test-swift'
1010

1111
test-swift:
1212
swift test \
13-
--enable-test-discovery \
1413
--parallel
1514
swift test \
1615
-c release \
17-
--enable-test-discovery \
1816
--parallel
1917

2018
format:

Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,37 @@
1-
// swift-tools-version:5.2
1+
// swift-tools-version:5.5
22

33
import PackageDescription
44

55
let package = Package(
66
name: "swift-case-paths",
7+
platforms: [
8+
.iOS(.v13),
9+
.macOS(.v10_15),
10+
.tvOS(.v13),
11+
.watchOS(.v6),
12+
],
713
products: [
814
.library(
915
name: "CasePaths",
1016
targets: ["CasePaths"]
1117
)
1218
],
1319
dependencies: [
14-
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0")
20+
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
21+
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.8.0"),
1522
],
1623
targets: [
1724
.target(
18-
name: "CasePaths"
25+
name: "CasePaths",
26+
dependencies: [
27+
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
28+
]
1929
),
2030
.testTarget(
2131
name: "CasePathsTests",
2232
dependencies: ["CasePaths"]
2333
),
24-
.target(
34+
.executableTarget(
2535
name: "swift-case-paths-benchmark",
2636
dependencies: [
2737
"CasePaths",

Sources/CasePaths/XCTUnwrap.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Foundation
2+
@_spi(CurrentTestCase) import XCTestDynamicOverlay
3+
4+
/// Asserts that an enum value matches a particular case and returns the associated value.
5+
///
6+
/// - Parameters:
7+
/// - expression: An enum value.
8+
/// - extract: A closure that attempts to extract a particular case from the enum. You can supply
9+
/// a case path literal here, like '/Enum.case'.
10+
/// - message: An optional description of a failure.
11+
/// - Returns: The unwrapped associated value from the matched case of the enum.
12+
public func XCTUnwrap<Root, Case>(
13+
_ expression: @autoclosure () throws -> Root,
14+
case extract: (Root) -> Case?,
15+
_ message: @autoclosure () -> String = "",
16+
file: StaticString = #file,
17+
line: UInt = #line
18+
) throws -> Case {
19+
guard let value = try extract(expression())
20+
else {
21+
#if canImport(ObjectiveC)
22+
_ = XCTCurrentTestCase?.perform(Selector(("setContinueAfterFailure:")), with: false)
23+
#endif
24+
let message = message()
25+
XCTFail(
26+
"""
27+
XCTUnwrap failed: expected non-nil value of type "\(Case.self)"\
28+
\(message.isEmpty ? "" : " - " + message)
29+
""",
30+
file: file,
31+
line: line
32+
)
33+
throw UnwrappingCase()
34+
}
35+
return value
36+
}
37+
38+
private struct UnwrappingCase: Error {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#if DEBUG && (os(iOS) || os(macOS) || os(tvOS) || os(watchOS))
2+
import CasePaths
3+
import XCTest
4+
5+
final class XCTUnwrapTests: XCTestCase {
6+
func testXCTUnwrapFailure() throws {
7+
try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)
8+
9+
XCTExpectFailure {
10+
$0.compactDescription == """
11+
XCTUnwrap failed: expected non-nil value of type "Error"
12+
"""
13+
}
14+
_ = try XCTUnwrap(Result<Int, Error>.success(2), case: /Result.failure)
15+
}
16+
17+
func testXCTUnwrapFailure_WithMessage() throws {
18+
try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)
19+
20+
XCTExpectFailure {
21+
$0.compactDescription == """
22+
XCTUnwrap failed: expected non-nil value of type "Error" - Should be success
23+
"""
24+
}
25+
_ = try XCTUnwrap(Result<Int, Error>.success(2), case: /Result.failure, "Should be success")
26+
}
27+
28+
func testXCTUnwrapPass() throws {
29+
try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)
30+
31+
XCTAssertEqual(
32+
try XCTUnwrap(Result<Int, Error>.success(2), case: /Result.success),
33+
2
34+
)
35+
}
36+
}
37+
#endif

0 commit comments

Comments
 (0)