Last active
November 27, 2024 08:43
-
-
Save jubishop/695f6938a5d673b2f973e8d6ae0d28ef to your computer and use it in GitHub Desktop.
expect() testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright Justin Bishop, 2024 | |
import Foundation | |
import Testing | |
public actor Fulfillment { | |
private var _fulfilled: Bool = false | |
public func callAsFunction() { | |
_fulfilled = true | |
} | |
} | |
private extension Fulfillment { | |
var fulfilled: Bool { | |
_fulfilled | |
} | |
func reset() { | |
_fulfilled = false | |
} | |
} | |
// This can be used two ways: | |
// ``` | |
// let fulfilled = Fulfillment() | |
// await somethingDelayed() { | |
// await fulfilled() | |
// } | |
// await expect("Something delayed", is: fulfilled, in: .milliseconds(100)) | |
// ``` | |
// The passed in `fulfilled` object will be automatically reset for reuse. | |
// | |
// Or: | |
// ``` | |
// await expect("Something delayed", in: .milliseconds(100)) { fulfilled in | |
// await somethingDelayed() { | |
// await fulfilled() | |
// } | |
// } | |
// ``` | |
// | |
// Note: | |
// `in:` parameter is optional, defaults to .milliseconds(100) | |
public func expect( | |
_ comment: Comment, | |
is fulfillment: Fulfillment? = nil, | |
in timeout: Duration = .milliseconds(100), | |
_ block: ((Fulfillment) async throws -> Void)? = nil | |
) async { | |
guard fulfillment != nil || block != nil else { | |
Issue.record( | |
""" | |
Fulfillment of \"\(comment)\" cannot be tested: \ | |
either a trailing closure or Fulfillment variable must be provided. | |
""" | |
) | |
return | |
} | |
let actualFulfillment = fulfillment ?? Fulfillment() | |
if let block = block { | |
do { | |
try await block(actualFulfillment) | |
} catch { | |
Issue.record("Fulfillment of \"\(comment)\" threw error: \(error)") | |
return | |
} | |
} | |
let startTime = ContinuousClock.now | |
var timeElapsed = Duration.zero | |
while timeElapsed <= timeout { | |
if await actualFulfillment.fulfilled { | |
await actualFulfillment.reset() | |
return | |
} | |
timeElapsed = ContinuousClock.now - startTime | |
try! await Task.sleep(for: .milliseconds(10)) | |
} | |
Issue.record("Expected fulfillment of: \"\(comment)\" never occurred") | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Testing | |
@testable import PodHaven | |
@Suite("of DownloadManager tests") | |
class DownloadManagerTests { | |
@Test("that a single download works successfully") | |
func singleSuccessfulDownload() async { | |
let url = URL(string: "https://example.com/data")! | |
let expectedData = "Test data".data(using: .utf8)! | |
MockURLProtocol.requestHandler = { request in | |
#expect(request.url == url, "URL Requested should be what was added") | |
let response = try #require( | |
HTTPURLResponse( | |
url: url, | |
statusCode: 200, | |
httpVersion: nil, | |
headerFields: nil | |
) | |
) | |
return (response, expectedData) | |
} | |
let configuration = URLSessionConfiguration.ephemeral | |
configuration.protocolClasses = [MockURLProtocol.self] | |
let session = URLSession(configuration: configuration) | |
let downloadManager = DownloadManager( | |
session: session, | |
maxConcurrentDownloads: 2 | |
) | |
await expect("Single download handler") { fulfilled in | |
await downloadManager.addURL(url) { result in | |
switch result { | |
case .success(let data): | |
#expect(data == expectedData, "Returned data should match") | |
await fulfilled() | |
case .failure(let error): | |
Issue.record("Expected success, got error: \(error)") | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment