Skip to content

Commit

Permalink
Add XCTUnwrap(_:case:) test helper. (#95)
Browse files Browse the repository at this point in the history
* 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 <stephen@stephencelis.com>
  • Loading branch information
mbrandonw and stephencelis authored Dec 30, 2022
1 parent bb43642 commit c3a42e8
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 30 deletions.
27 changes: 4 additions & 23 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,13 @@ concurrency:
cancel-in-progress: true

jobs:
macos-11:
name: MacOS 11
runs-on: macos-11
macos-12:
name: MacOS 12
runs-on: macos-12
strategy:
matrix:
xcode:
- 12.5.1
- '13.0'
steps:
- uses: actions/checkout@v2
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Print Swift version
run: swift --version
- name: Run tests
run: make test-swift

macos-10-15:
name: MacOS 10.15
runs-on: macos-10.15
strategy:
matrix:
xcode:
- 11.3
- 11.7
- 12.4
- '14.2'
steps:
- uses: actions/checkout@v2
- name: Select Xcode ${{ matrix.xcode }}
Expand Down
4 changes: 1 addition & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ test-linux:
--rm \
-v "$(PWD):$(PWD)" \
-w "$(PWD)" \
swift:5.3 \
swift:5.5 \
bash -c 'make test-swift'

test-swift:
swift test \
--enable-test-discovery \
--parallel
swift test \
-c release \
--enable-test-discovery \
--parallel

format:
Expand Down
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@
"revision": "3303b164430d9a7055ba484c8ead67a52f7b74f6",
"version": "1.0.0"
}
},
{
"package": "xctest-dynamic-overlay",
"repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay.git",
"state": {
"branch": null,
"revision": "a9daebf0bf65981fd159c885d504481a65a75f02",
"version": "0.8.0"
}
}
]
},
Expand Down
18 changes: 14 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
// swift-tools-version:5.2
// swift-tools-version:5.5

import PackageDescription

let package = Package(
name: "swift-case-paths",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.tvOS(.v13),
.watchOS(.v6),
],
products: [
.library(
name: "CasePaths",
targets: ["CasePaths"]
)
],
dependencies: [
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0")
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.8.0"),
],
targets: [
.target(
name: "CasePaths"
name: "CasePaths",
dependencies: [
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
]
),
.testTarget(
name: "CasePathsTests",
dependencies: ["CasePaths"]
),
.target(
.executableTarget(
name: "swift-case-paths-benchmark",
dependencies: [
"CasePaths",
Expand Down
38 changes: 38 additions & 0 deletions Sources/CasePaths/XCTUnwrap.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Foundation
@_spi(CurrentTestCase) import XCTestDynamicOverlay

/// Asserts that an enum value matches a particular case and returns the associated value.
///
/// - Parameters:
/// - expression: An enum value.
/// - extract: A closure that attempts to extract a particular case from the enum. You can supply
/// a case path literal here, like '/Enum.case'.
/// - message: An optional description of a failure.
/// - Returns: The unwrapped associated value from the matched case of the enum.
public func XCTUnwrap<Root, Case>(
_ expression: @autoclosure () throws -> Root,
case extract: (Root) -> Case?,
_ message: @autoclosure () -> String = "",
file: StaticString = #file,
line: UInt = #line
) throws -> Case {
guard let value = try extract(expression())
else {
#if canImport(ObjectiveC)
_ = XCTCurrentTestCase?.perform(Selector(("setContinueAfterFailure:")), with: false)
#endif
let message = message()
XCTFail(
"""
XCTUnwrap failed: expected non-nil value of type "\(Case.self)"\
\(message.isEmpty ? "" : " - " + message)
""",
file: file,
line: line
)
throw UnwrappingCase()
}
return value
}

private struct UnwrappingCase: Error {}
37 changes: 37 additions & 0 deletions Tests/CasePathsTests/XCTUnwrapTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#if DEBUG && (os(iOS) || os(macOS) || os(tvOS) || os(watchOS))
import CasePaths
import XCTest

final class XCTUnwrapTests: XCTestCase {
func testXCTUnwrapFailure() throws {
try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)

XCTExpectFailure {
$0.compactDescription == """
XCTUnwrap failed: expected non-nil value of type "Error"
"""
}
_ = try XCTUnwrap(Result<Int, Error>.success(2), case: /Result.failure)
}

func testXCTUnwrapFailure_WithMessage() throws {
try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)

XCTExpectFailure {
$0.compactDescription == """
XCTUnwrap failed: expected non-nil value of type "Error" - Should be success
"""
}
_ = try XCTUnwrap(Result<Int, Error>.success(2), case: /Result.failure, "Should be success")
}

func testXCTUnwrapPass() throws {
try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)

XCTAssertEqual(
try XCTUnwrap(Result<Int, Error>.success(2), case: /Result.success),
2
)
}
}
#endif

0 comments on commit c3a42e8

Please sign in to comment.