You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: LICENSE
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
MIT License
2
2
3
-
Copyright (c) 2025 Lennard Sprong
3
+
Copyright (c) 2025 Lennard Sprong. Portions copyright Point-Free, Inc.
4
4
5
5
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Copy file name to clipboardExpand all lines: README.md
+38-12Lines changed: 38 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ PropertyBased is a Swift 6 library that enables Property-Based Testing in `swift
7
7
8
8
Property-Based Testing can be used as an alternative for (or in addition to) testing with hardcoded values. Run tests with random values, and easily switch to specific values when debugging a test failure.
9
9
10
-
This library uses [swift-gen by Point-Free](https://github.com/pointfreeco/swift-gen) for reproducible random generation.
10
+
This project aims to support all platforms which can run Swift Testing, including platforms without [Foundation](https://developer.apple.com/documentation/foundation) support.
11
11
12
12
## Requirements
13
13
@@ -25,21 +25,20 @@ import Testing
25
25
importPropertyBased
26
26
27
27
@TestfunctestDuplication() async {
28
-
awaitpropertyCheck(input: .int(in: 0...100)) { n in
28
+
awaitpropertyCheck(input: Gen.int(in: 0...100)) { n in
29
29
#expect(n + n == n *2)
30
30
}
31
31
}
32
32
```
33
33
Example with multiple inputs, and a custom repeat count:
34
34
```swift
35
35
importTesting
36
-
importGen
37
36
importPropertyBased
38
37
39
-
let stringCreator = Gen.letterOrNumber.string(of: .int(in: 1...10))
38
+
let stringCreator = Gen.letterOrNumber.string(of: Gen.int(in: 1...10))
40
39
41
40
@TestfunctestStringRepeat() async {
42
-
awaitpropertyCheck(count: 500, input: stringCreator, .int(in: 0...5)) { str, n in
41
+
awaitpropertyCheck(count: 500, input: stringCreator, Gen.int(in: 0...5)) { str, n in
43
42
let actual =String(repeating: str, count: n)
44
43
#expect(actual.length== str.length* n)
45
44
}
@@ -52,7 +51,7 @@ It's possible that a test only fails on very specific inputs that don't trigger
52
51
53
52
```swift
54
53
@TestfuncfailsSometimes() async {
55
-
awaitpropertyCheck(input: .int(in: 0...1000)) { n in
54
+
awaitpropertyCheck(input: Gen.int(in: 0...1000)) { n in
56
55
#expect(n <990)
57
56
}
58
57
}
@@ -70,19 +69,46 @@ You can supply the fixed seed to reproduce the issue every time.
awaitpropertyCheck(input: .int(in: 0...1000)) { n in
72
+
awaitpropertyCheck(input: Gen.int(in: 0...1000)) { n in
74
73
#expect(n <990)
75
74
}
76
75
}
77
76
```
78
77
79
-
# Limitations
78
+
# Shrinking
80
79
81
-
This library currently does not include shrinking functionality, which would allow for failing inputs to be reduced to simpler values (e.g. numbers closer to zero, or collections with fewer elements).
80
+
> [!NOTE]
81
+
> This feature is experimental, and disabled by default. The shrinking output will be very verbose, due to a limitation in Swift Testing.
82
82
83
-
1. The version of the Testing library that's bundled with Swift currently doesn't allow third-party plugins to change the behavior of issue reporting. Without changes, every intermediate step in the shrinking process will be reported as a new issue.
84
-
2. Adding shrinker functions to `swift-gen` is possibly out of scope for that package. Since valid shrinker values depend on the specifications of the generator, a new fork of that project would be required in the future.
83
+
When a failing case has been found, it's possible that the input is large and contrived, such as arrays with many elements. When _shrinking_ is enabled, PropertyBased will repeat a failing test until it finds the smallest possible input that still causes a failure.
84
+
85
+
For example, the following test fails when the given numbers sum to a value above a certain threshold:
86
+
87
+
```swift
88
+
@TestfunccheckSumInRange() async {
89
+
awaitpropertyCheck(input: Gen.int(in: 0...100).array(of: 1...10)) { numbers in
90
+
let sum = numbers.reduce(0, +)
91
+
#expect(sum <250)
92
+
}
93
+
}
94
+
```
95
+
96
+
The generator could come up with an array like `[63, 61, 33, 53, 97, 68, 23, 16]`, which sums to `414`. Ideally, we want to have an input that sums to exactly `250`.
97
+
98
+
Enable the shrinker by adding the `shrinking` trait:
99
+
100
+
```swift
101
+
@Test(.shrinking) funccheckSumInRange() async
102
+
```
103
+
104
+
After shrinking, the new failing case is `[46, 97, 68, 23, 16]`, which sums to exactly `250`. The first few elements have been removed, which the middle element has been reduced to be closer to the edge.
105
+
106
+
When using the built-in generators and the `zip` function, shrinkers will also be composed.
PropertyBased is a Swift 6 library that enables Property-Based Testing in `swift-testing`, similar to QuickCheck for Haskell or FsCheck for F# and C#.
4
+
5
+
Property-Based Testing can be used as an alternative for (or in addition to) testing with hardcoded values. Run tests with random values, and easily switch to specific values when debugging a test failure.
0 commit comments