Skip to content

Commit dc8bc46

Browse files
committed
Refactor
1 parent bc510fd commit dc8bc46

5 files changed

Lines changed: 88 additions & 48 deletions

File tree

Sources/PropertyBased/Generator.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,3 @@ extension Generator {
315315
)
316316
}
317317
}
318-
319-
/// Errors that may be thrown by a generator.
320-
public enum GeneratorError: Error {
321-
/// A generator failed to generate a valid value within the specified amount of attempts.
322-
case runLimitExceeded(Int)
323-
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// GeneratorError.swift
3+
// PropertyBased
4+
//
5+
// Created by Lennard Sprong on 13/08/2026.
6+
//
7+
8+
#if canImport(Foundation)
9+
import Foundation
10+
#endif
11+
12+
/// Errors that may be thrown by a generator.
13+
public enum GeneratorError: Equatable, Error, CustomStringConvertible {
14+
/// A generator failed to generate a valid value within the specified amount of attempts.
15+
case runLimitExceeded(Int)
16+
17+
public var description: String {
18+
switch self {
19+
case .runLimitExceeded(let count):
20+
"Failed to generate a valid input after \(count) attempts. Check if the Generator is filtering too many values."
21+
}
22+
}
23+
}
24+
25+
#if canImport(Foundation)
26+
extension GeneratorError: LocalizedError {
27+
public var localizedDescription: String { description }
28+
}
29+
#endif

Sources/PropertyBased/PropertyCheck.swift

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,9 @@ public func propertyCheck<InputValue, ResultValue>(
131131
do {
132132
(inputValue, resultValue) = try input.runFull(&rng, runLimit ?? 10000)
133133
} catch {
134-
var failureMessage: String
135-
if let genError = error as? GeneratorError, case .runLimitExceeded(let count) = genError {
136-
failureMessage =
137-
"Failed to generate a valid input after \(count) attempts. Check if the Generator is filtering too many values."
138-
139-
if runLimit == nil {
140-
failureMessage += "\n\nYou can add `.maxAttempts()` to the Test or Suite to increase the limit."
141-
}
142-
} else {
143-
failureMessage = "Unknown error during generation: \(error)"
134+
var failureMessage = String(describing: error)
135+
if runLimit == nil, let genError = error as? GeneratorError, case .runLimitExceeded = genError {
136+
failureMessage += "\n\nYou can add `.maximumAttempts()` to the Test or Suite to increase the limit."
144137
}
145138

146139
if fixedRng == nil {

Tests/PropertyBasedTests/MaxAttemptsTraitTest.swift

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//
2+
// MaximumAttemptsTraitTest.swift
3+
// PropertyBased
4+
//
5+
// Created by Lennard Sprong on 10/08/2026.
6+
//
7+
8+
import Testing
9+
10+
@testable import PropertyBased
11+
12+
@Suite struct MaximumAttemptsTraitTest {
13+
@Test func testRunUsesLimit() {
14+
let useless = Gen.always(false).filter { $0 }
15+
16+
#expect(throws: GeneratorError.runLimitExceeded(25)) {
17+
var rng = Xoshiro()
18+
_ = try useless.run(using: &rng, limit: 25)
19+
}
20+
}
21+
22+
@Test func testTraitCanModifyCount() async throws {
23+
let useless = Gen.always(false).filter { $0 }
24+
25+
let trait = MaximumAttemptsTrait.maximumAttempts(20)
26+
let scope = try #require(trait.scopeProvider(for: Test.current!, testCase: Test.Case.current))
27+
28+
let issues = await gatherIssues {
29+
try await scope.provideScope(for: Test.current!, testCase: Test.Case.current) {
30+
await propertyCheck(input: useless) { _ in
31+
try #require(Bool(false), "block must not be called")
32+
}
33+
}
34+
}
35+
#expect(issues.count == 1)
36+
#expect(
37+
issues.contains(where: {
38+
$0.contains("20 attempts") && !$0.contains("maximumAttempts()")
39+
}))
40+
}
41+
42+
@Test func testTraitSuggestion() async throws {
43+
let useless = Gen.always(false).filter { $0 }
44+
let issues = await gatherIssues {
45+
await propertyCheck(input: useless) { _ in
46+
try #require(Bool(false), "block must not be called")
47+
}
48+
}
49+
50+
#expect(issues.count == 1)
51+
#expect(
52+
issues.contains(where: {
53+
$0.contains("maximumAttempts()")
54+
}))
55+
}
56+
}

0 commit comments

Comments
 (0)