Skip to content

Commit 1281c48

Browse files
authored
Add "EnableShrinking" package trait for changing default behavior
1 parent 002dde7 commit 1281c48

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

Package.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
import PackageDescription
44

5+
#if swift(>=6.2)
6+
let shrinkByDefault = true
7+
#else
8+
let shrinkByDefault = false
9+
#endif
10+
511
let package = Package(
612
name: "PropertyBased",
713
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13), .visionOS(.v1)],
@@ -11,6 +17,14 @@ let package = Package(
1117
targets: ["PropertyBased"]
1218
)
1319
],
20+
traits: [
21+
.default(enabledTraits: shrinkByDefault ? ["EnableShrinking"] : []),
22+
.trait(
23+
name: "EnableShrinking",
24+
description:
25+
"This trait enables the shrinker by default. Regardless of this trait being set, you can use the shrinking() TestTrait to enable/disable the shrinker on a case-by-case basis."
26+
),
27+
],
1428
dependencies: [],
1529
targets: [
1630
.target(

README.md

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,40 @@
55

66
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#.
77

8-
Property-Based Testing can be used as an alternative for (or in addition to) testing with hardcoded values. Run tests with composable random inputs, then easily switch to specific failing cases just by adding a single line.
8+
Property-Based Testing can be used as an alternative for (or in addition to) testing with hardcoded values.
99

10-
This project aims to support all platforms which can run Swift Testing, including platforms without [Foundation](https://developer.apple.com/documentation/foundation) support.
10+
## Features
11+
12+
* Works through Swift Testing, including on platforms without [Foundation](https://developer.apple.com/documentation/foundation) support
13+
* Contains a set of generators for all commonly-used types in the Swift standard library, as well as Dates, `OptionSet` and `CaseIterable` enums
14+
* Compose generators to create more complex inputs
15+
* Automatically [shrink](#shrinking) large inputs to easily digestable inputs, including for custom types without extra effort
16+
* Switch to specific failing cases with just [a single line](#using-fixed-seeds)
1117

1218
## Requirements
1319

14-
* Swift 6.1 (or Xcode 16.3)
20+
* Swift 6.2 (or Xcode 26)
21+
* Limited support for Swift 6.1 and Xcode 16.3
1522
* Any platform supported by Swift Testing
1623
* macOS 10.15+
1724
* iOS/tvOS 13.0+, watchOS 6.0+, visionOS 1.0+
1825
* Linux, Windows, etc.
1926

27+
## Installation
28+
29+
### When writing a Swift package:
30+
31+
Add the following line to the dependencies array in your `Package.swift` file:
32+
```swift
33+
.package(url: "https://github.com/x-sheep/swift-property-based.git", from: "1.0.0")
34+
```
35+
36+
### When writing an Xcode project:
37+
38+
1. Open your Project
39+
2. Go to File > Add Package Dependencies...
40+
3. Paste the repository URL in the search field: `https://github.com/x-sheep/swift-property-based.git`
41+
2042
## Examples
2143

2244
Simple example:
@@ -77,9 +99,6 @@ func failsSometimes() async {
7799

78100
# Shrinking
79101

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-
83102
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.
84103

85104
For example, the following test fails when the given numbers sum to a value above a certain threshold:
@@ -95,16 +114,17 @@ For example, the following test fails when the given numbers sum to a value abov
95114

96115
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`.
97116

98-
Enable the shrinker by adding the `shrinking` trait:
117+
After shrinking, the new failing case is `[46, 97, 68, 23, 16]`, which sums to exactly `250`. The first few elements have been removed, while the middle element has been reduced to be closer to the edge. PropertyBased will output both the shrunk input and the original input:
99118

100-
```swift
101-
@Test(.shrinking) func checkSumInRange() async
102119
```
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, while the middle element has been reduced to be closer to the edge.
120+
Failure occured with input [46, 97, 68, 23, 16].
121+
(shrunk down from [63, 61, 33, 53, 97, 68, 23, 16] after 7 iterations)
122+
```
105123

106124
When using the built-in generators and the `zip` function, shrinkers will also be composed.
107125

126+
The `.shrinking` TestTrait or SuiteTrait can be used to override shrinking behavior.
127+
108128
# License
109129

110130
Copyright (c) 2025 Lennard Sprong.

Sources/PropertyBased/EnableShrinkTrait.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Testing
1111
///
1212
/// Use ``shrinking(_:)`` to construct an instance of this trait.
1313
///
14-
/// > Note: This feature is experimental, and disabled by default. The shrinking output will be very verbose, due to a limitation in Swift Testing.
14+
/// The Swift Package Trait `"EnableShrinking"` controls if shrinking defaults to being enabled. On Swift 6.2, this is set by default.
1515
public struct EnableShrinkTrait: TestTrait, SuiteTrait, TestScoping {
1616
@_documentation(visibility: internal)
1717
public var isRecursive: Bool { false }
@@ -24,16 +24,25 @@ public struct EnableShrinkTrait: TestTrait, SuiteTrait, TestScoping {
2424
}
2525
}
2626

27+
#if EnableShrinking
28+
@TaskLocal static var isEnabled = true
29+
#else
2730
@TaskLocal static var isEnabled = false
31+
#endif
2832

2933
var shouldEnable: Bool
3034
}
3135

3236
extension Trait where Self == EnableShrinkTrait {
3337
/// Enable shrinking within this test or test suite.
38+
///
39+
/// The Swift Package Trait `"EnableShrinking"` controls if shrinking defaults to being enabled. On Swift 6.2, this is set by default.
3440
public static var shrinking: Self { shrinking(true) }
3541

3642
/// Enable or disable shrinking within this test or test suite.
43+
///
44+
/// The Swift Package Trait `"EnableShrinking"` controls if shrinking defaults to being enabled. On Swift 6.2, this is set by default.
45+
///
3746
/// - Parameter enabled: Whether to enable shrinking.
3847
/// - Returns: An instance of ``EnableShrinkTrait``.
3948
public static func shrinking(_ enabled: Bool = true) -> Self {

0 commit comments

Comments
 (0)