diff --git a/Source/ViewControllerPresentationSpy/AlertVerifier.swift b/Source/ViewControllerPresentationSpy/AlertVerifier.swift index 6a8511e..400cfb0 100644 --- a/Source/ViewControllerPresentationSpy/AlertVerifier.swift +++ b/Source/ViewControllerPresentationSpy/AlertVerifier.swift @@ -4,6 +4,7 @@ import UIKit import XCTest +import Testing /** Captures presented UIAlertControllers. @@ -49,7 +50,7 @@ public class AlertVerifier: NSObject { @objc override public init() { super.init() guard !AlertVerifier.isSwizzled else { - XCTFail(""" + fail(""" More than one instance of AlertVerifier exists. This may be caused by \ creating one setUp() but failing to set the property to nil in tearDown(). """) @@ -136,36 +137,37 @@ extension AlertVerifier { preferredStyle: UIAlertController.Style = .alert, presentingViewController: UIViewController? = nil, file: StaticString = #filePath, - line: UInt = #line + line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation ) { - let abort = verifyCalledOnce(actual: presentedCount, action: "present", file: file, line: line) + let abort = verifyCalledOnce(actual: presentedCount, action: "present", file: file, line: line, sourceLocation: sourceLocation) if abort { return } - XCTAssertEqual(self.title, title, "alert title", file: file, line: line) - XCTAssertEqual(self.message, message, "alert message", file: file, line: line) - verifyAnimated(actual: self.animated, expected: animated, action: "present", file: file, line: line) - verifyActions(expected: actions, file: file, line: line) - verifyPreferredStyle(expected: preferredStyle, file: file, line: line) + assertEqual(self.title, title, "alert title", file: file, line: line, sourceLocation: sourceLocation) + assertEqual(self.message, message, "alert message", file: file, line: line, sourceLocation: sourceLocation) + verifyAnimated(actual: self.animated, expected: animated, action: "present", file: file, line: line, sourceLocation: sourceLocation) + verifyActions(expected: actions, file: file, line: line, sourceLocation: sourceLocation) + verifyPreferredStyle(expected: preferredStyle, file: file, line: line, sourceLocation: sourceLocation) verifyViewController(actual: self.presentingViewController, expected: presentingViewController, - adjective: "presenting", file: file, line: line) + adjective: "presenting", file: file, line: line, sourceLocation: sourceLocation) } - private func verifyActions(expected: [Action], file: StaticString, line: UInt) { + private func verifyActions(expected: [Action], file: StaticString, line: UInt, sourceLocation: SourceLocation) { let actual = actionsAsSwiftType() let minCount = min(actual.count, expected.count) for i in 0 ..< minCount { if actual[i] != expected[i] { - XCTFail("Action \(i): Expected \(expected[i]), but was \(actual[i])", - file: file, line: line) + fail("Action \(i): Expected \(expected[i]), but was \(actual[i])", + file: file, line: line, sourceLocation: sourceLocation) } } if actual.count < expected.count { let missing = expected[actual.count ..< expected.count].map { $0.description } - XCTFail("Did not meet count of \(expected.count) actions, missing \(missing.joined(separator: ", "))", - file: file, line: line) + fail("Did not meet count of \(expected.count) actions, missing \(missing.joined(separator: ", "))", + file: file, line: line, sourceLocation: sourceLocation) } else if actual.count > expected.count { let extra = actual[expected.count ..< actual.count].map { $0.description } - XCTFail("Exceeded count of \(expected.count) actions, with unexpected \(extra.joined(separator: ", "))", - file: file, line: line) + fail("Exceeded count of \(expected.count) actions, with unexpected \(extra.joined(separator: ", "))", + file: file, line: line, sourceLocation: sourceLocation) } } @@ -186,15 +188,16 @@ extension AlertVerifier { private func verifyPreferredStyle(expected: UIAlertController.Style, file: StaticString, - line: UInt) + line: UInt, + sourceLocation: SourceLocation) { let actual = preferredStyle if actual != expected { switch expected { case .actionSheet: - XCTFail("Expected preferred style .actionSheet, but was .alert", file: file, line: line) + fail("Expected preferred style .actionSheet, but was .alert", file: file, line: line, sourceLocation: sourceLocation) case .alert: - XCTFail("Expected preferred style .alert, but was .actionSheet", file: file, line: line) + fail("Expected preferred style .alert, but was .actionSheet", file: file, line: line, sourceLocation: sourceLocation) @unknown default: fatalError("Unknown UIAlertController.Style for preferred style") } diff --git a/Source/ViewControllerPresentationSpy/DismissalVerifier.swift b/Source/ViewControllerPresentationSpy/DismissalVerifier.swift index 82e23c1..3fa8f8d 100644 --- a/Source/ViewControllerPresentationSpy/DismissalVerifier.swift +++ b/Source/ViewControllerPresentationSpy/DismissalVerifier.swift @@ -4,6 +4,7 @@ import UIKit import XCTest +import Testing /** Captures dismissed view controllers. @@ -38,7 +39,7 @@ public class DismissalVerifier: NSObject { @objc override public init() { super.init() guard !DismissalVerifier.isSwizzled else { - XCTFail(""" + fail(""" More than one instance of DismissalVerifier exists. This may be caused by \ creating one setUp() but failing to set the property to nil in tearDown(). """) @@ -87,12 +88,13 @@ public extension DismissalVerifier { animated: Bool, dismissedViewController: UIViewController? = nil, file: StaticString = #file, - line: UInt = #line + line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation ) { - let abort = verifyCalledOnce(actual: dismissedCount, action: "dismiss", file: file, line: line) + let abort = verifyCalledOnce(actual: dismissedCount, action: "dismiss", file: file, line: line, sourceLocation: sourceLocation) if abort { return } - verifyAnimated(actual: self.animated, expected: animated, action: "dismiss", file: file, line: line) + verifyAnimated(actual: self.animated, expected: animated, action: "dismiss", file: file, line: line, sourceLocation: sourceLocation) verifyViewController(actual: self.dismissedViewController, expected: dismissedViewController, - adjective: "dismissed", file: file, line: line) + adjective: "dismissed", file: file, line: line, sourceLocation: sourceLocation) } } diff --git a/Source/ViewControllerPresentationSpy/PresentationVerifier.swift b/Source/ViewControllerPresentationSpy/PresentationVerifier.swift index 15e24c4..d4f8736 100644 --- a/Source/ViewControllerPresentationSpy/PresentationVerifier.swift +++ b/Source/ViewControllerPresentationSpy/PresentationVerifier.swift @@ -4,6 +4,7 @@ import UIKit import XCTest +import Testing /** Captures presented view controllers. @@ -41,14 +42,14 @@ public class PresentationVerifier: NSObject { @objc override public init() { super.init() guard !PresentationVerifier.isSwizzled else { - XCTFail(""" + fail(""" More than one instance of PresentationVerifier exists. This may be caused by \ creating one setUp() but failing to set the property to nil in tearDown(). """) return } guard !AlertVerifier.isSwizzled else { - XCTFail(""" + fail(""" A PresentationVerifier may not be created while an AlertVerifier exists. Try \ making the AlertVerifier optional, and setting it to nil before creating the \ PresentationVerifier. @@ -99,17 +100,18 @@ public extension PresentationVerifier { animated: Bool, presentingViewController: UIViewController? = nil, file: StaticString = #filePath, - line: UInt = #line + line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation ) -> VC? { - let abort = verifyCalledOnce(actual: presentedCount, action: "present", file: file, line: line) + let abort = verifyCalledOnce(actual: presentedCount, action: "present", file: file, line: line, sourceLocation: sourceLocation) if abort { return nil } - verifyAnimated(actual: self.animated, expected: animated, action: "present", file: file, line: line) + verifyAnimated(actual: self.animated, expected: animated, action: "present", file: file, line: line, sourceLocation: sourceLocation) verifyViewController(actual: self.presentingViewController, expected: presentingViewController, - adjective: "presenting", file: file, line: line) + adjective: "presenting", file: file, line: line, sourceLocation: sourceLocation) let nextVC = presentedViewController as? VC if nextVC == nil { - XCTFail("Expected presented view controller to be \(VC.self)), " + - "but was \(String(describing: presentedViewController))", file: file, line: line) + fail("Expected presented view controller to be \(VC.self)), but was \(String(describing: presentedViewController))", + file: file, line: line, sourceLocation: sourceLocation) } return nextVC } diff --git a/Source/ViewControllerPresentationSpy/VerifyHelpers.swift b/Source/ViewControllerPresentationSpy/VerifyHelpers.swift index a57a5fb..819539f 100644 --- a/Source/ViewControllerPresentationSpy/VerifyHelpers.swift +++ b/Source/ViewControllerPresentationSpy/VerifyHelpers.swift @@ -4,24 +4,25 @@ import UIKit import XCTest +import Testing -func verifyCalledOnce(actual: Int, action: String, file: StaticString, line: UInt) -> Bool { +func verifyCalledOnce(actual: Int, action: String, file: StaticString, line: UInt, sourceLocation: SourceLocation) -> Bool { if actual == 0 { - XCTFail("\(action) not called", file: file, line: line) + fail("\(action) not called", file: file, line: line, sourceLocation: sourceLocation) return true // Abort test } if actual > 1 { - XCTFail("\(action) called \(actual) times", file: file, line: line) + fail("\(action) called \(actual) times", file: file, line: line, sourceLocation: sourceLocation) } return false // Continue test } -func verifyAnimated(actual: Bool, expected: Bool, action: String, file: StaticString, line: UInt) { +func verifyAnimated(actual: Bool, expected: Bool, action: String, file: StaticString, line: UInt, sourceLocation: SourceLocation) { if actual != expected { if expected { - XCTFail("Expected animated \(action), but was not animated", file: file, line: line) + fail("Expected animated \(action), but was not animated", file: file, line: line, sourceLocation: sourceLocation) } else { - XCTFail("Expected non-animated \(action), but was animated", file: file, line: line) + fail("Expected non-animated \(action), but was animated", file: file, line: line, sourceLocation: sourceLocation) } } } @@ -30,12 +31,42 @@ func verifyViewController(actual: UIViewController?, expected: UIViewController?, adjective: String, file: StaticString, - line: UInt) { + line: UInt, + sourceLocation: SourceLocation) { if let expected = expected, let actual = actual { - XCTAssertTrue( + assertTrue( expected === actual, "Expected \(adjective) view controller to be \(expected)), but was \(actual)", file: file, - line: line) + line: line, + sourceLocation: sourceLocation) } } + +func fail(_ comment: Comment, + file: StaticString = #file, + line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation) { + XCTFail(comment.rawValue, file: file, line: line) + Issue.record(comment, sourceLocation: sourceLocation) +} + +func assertEqual(_ expression1: @autoclosure () -> T, + _ expression2: @autoclosure () -> T, + _ comment: Comment? = nil, + file: StaticString = #filePath, + line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation) where T : Equatable { + XCTAssertEqual(expression1(), expression2(), comment?.rawValue ?? "", file: file, line: line) + #expect(expression1() == expression2(), comment, sourceLocation: sourceLocation) +} + + +func assertTrue(_ expression: @autoclosure () -> Bool, + _ comment: Comment? = nil, + file: StaticString = #filePath, + line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation) { + XCTAssertTrue(expression(), comment?.rawValue ?? "", file: file, line: line) + #expect(expression(), comment, sourceLocation: sourceLocation) +}