0
# Property Creation
1
2
Create property-based tests from functions with automatic test case generation, shrinking of counterexamples, and statistical data collection. The property creation system supports functions with 1-8 parameters and provides extensive customization options for generators, shrinkers, and data collectors.
3
4
## Capabilities
5
6
### Basic Property Creation
7
8
Create properties from functions using automatic type class derivation for generators, shrinkers, and pretty printers.
9
10
```scala { .api }
11
def prop[T, R](result: T => R)(implicit
12
arbitrary: Arbitrary[T],
13
shrink: Shrink[T],
14
pretty: T => Pretty,
15
prettyFreqMap: FreqMap[Set[Any]] => Pretty,
16
asResult: AsResult[R],
17
parameters: Parameters
18
): ScalaCheckFunction1[T, R]
19
```
20
21
**Usage:**
22
```scala
23
import org.specs2._
24
import org.specs2.ScalaCheck
25
26
class StringSpec extends Specification with ScalaCheck { def is = s2"""
27
String length property ${prop((s: String) => s.length >= 0)}
28
List reverse property ${prop((xs: List[Int]) => xs.reverse.reverse == xs)}
29
"""
30
}
31
```
32
33
### Multi-Parameter Properties
34
35
Create properties from functions with multiple parameters, supporting up to 8 arguments with individual type class instances for each parameter.
36
37
```scala { .api }
38
def prop[T1, T2, R](result: (T1, T2) => R)(implicit
39
arbitrary1: Arbitrary[T1], shrink1: Shrink[T1], pretty1: T1 => Pretty,
40
arbitrary2: Arbitrary[T2], shrink2: Shrink[T2], pretty2: T2 => Pretty,
41
prettyFreqMap: FreqMap[Set[Any]] => Pretty,
42
asResult: AsResult[R],
43
parameters: Parameters
44
): ScalaCheckFunction2[T1, T2, R]
45
46
def prop[T1, T2, T3, R](result: (T1, T2, T3) => R)(implicit ...): ScalaCheckFunction3[T1, T2, T3, R]
47
def prop[T1, T2, T3, T4, R](result: (T1, T2, T3, T4) => R)(implicit ...): ScalaCheckFunction4[T1, T2, T3, T4, R]
48
def prop[T1, T2, T3, T4, T5, R](result: (T1, T2, T3, T4, T5) => R)(implicit ...): ScalaCheckFunction5[T1, T2, T3, T4, T5, R]
49
def prop[T1, T2, T3, T4, T5, T6, R](result: (T1, T2, T3, T4, T5, T6) => R)(implicit ...): ScalaCheckFunction6[T1, T2, T3, T4, T5, T6, R]
50
def prop[T1, T2, T3, T4, T5, T6, T7, R](result: (T1, T2, T3, T4, T5, T6, T7) => R)(implicit ...): ScalaCheckFunction7[T1, T2, T3, T4, T5, T6, T7, R]
51
def prop[T1, T2, T3, T4, T5, T6, T7, T8, R](result: (T1, T2, T3, T4, T5, T6, T7, T8) => R)(implicit ...): ScalaCheckFunction8[T1, T2, T3, T4, T5, T6, T7, T8, R]
52
```
53
54
**Usage:**
55
```scala
56
class ArithmeticSpec extends Specification with ScalaCheck { def is = s2"""
57
Addition commutativity ${prop((a: Int, b: Int) => a + b == b + a)}
58
String concatenation ${prop((s1: String, s2: String, s3: String) =>
59
(s1 + s2) + s3 == s1 + (s2 + s3))}
60
"""
61
}
62
```
63
64
### Property Function Customization
65
66
Customize property functions with custom generators, shrinkers, pretty printers, data collectors, and execution contexts.
67
68
```scala { .api }
69
// Single parameter property functions
70
trait ScalaCheckFunction1[T, R] extends ScalaCheckFunction {
71
def noShrink: ScalaCheckFunction1[T, R]
72
def setArbitrary(arbitrary: Arbitrary[T]): ScalaCheckFunction1[T, R]
73
def setGen(gen: Gen[T]): ScalaCheckFunction1[T, R]
74
def setShrink(shrink: Shrink[T]): ScalaCheckFunction1[T, R]
75
def setPretty(pretty: T => Pretty): ScalaCheckFunction1[T, R]
76
def pretty(pretty: T => String): ScalaCheckFunction1[T, R]
77
def collect: ScalaCheckFunction1[T, R]
78
def collectArg(f: T => Any): ScalaCheckFunction1[T, R]
79
def prepare(action: T => T): ScalaCheckFunction1[T, R]
80
def setContext(context: Context): ScalaCheckFunction1[T, R]
81
}
82
83
// Multi-parameter property functions (similar pattern for 2-8 parameters)
84
trait ScalaCheckFunction2[T1, T2, R] extends ScalaCheckFunction {
85
def noShrink: ScalaCheckFunction2[T1, T2, R]
86
def setArbitrary1(a1: Arbitrary[T1]): ScalaCheckFunction2[T1, T2, R]
87
def setArbitrary2(a2: Arbitrary[T2]): ScalaCheckFunction2[T1, T2, R]
88
def setArbitraries(a1: Arbitrary[T1], a2: Arbitrary[T2]): ScalaCheckFunction2[T1, T2, R]
89
def setGen1(g1: Gen[T1]): ScalaCheckFunction2[T1, T2, R]
90
def setGen2(g2: Gen[T2]): ScalaCheckFunction2[T1, T2, R]
91
def setGens(g1: Gen[T1], g2: Gen[T2]): ScalaCheckFunction2[T1, T2, R]
92
def setShrink1(s1: Shrink[T1]): ScalaCheckFunction2[T1, T2, R]
93
def setShrink2(s2: Shrink[T2]): ScalaCheckFunction2[T1, T2, R]
94
def setShrinks(s1: Shrink[T1], s2: Shrink[T2]): ScalaCheckFunction2[T1, T2, R]
95
def setPretty1(p1: T1 => Pretty): ScalaCheckFunction2[T1, T2, R]
96
def setPretty2(p2: T2 => Pretty): ScalaCheckFunction2[T1, T2, R]
97
def pretty1(p1: T1 => String): ScalaCheckFunction2[T1, T2, R]
98
def pretty2(p2: T2 => String): ScalaCheckFunction2[T1, T2, R]
99
def setPretties(p1: T1 => Pretty, p2: T2 => Pretty): ScalaCheckFunction2[T1, T2, R]
100
def pretties(p1: T1 => String, p2: T2 => String): ScalaCheckFunction2[T1, T2, R]
101
def collectArg1(f: T1 => Any): ScalaCheckFunction2[T1, T2, R]
102
def collectArg2(f: T2 => Any): ScalaCheckFunction2[T1, T2, R]
103
def collect1: ScalaCheckFunction2[T1, T2, R]
104
def collect2: ScalaCheckFunction2[T1, T2, R]
105
def collectAllArgs(f1: T1 => Any, f2: T2 => Any): ScalaCheckFunction2[T1, T2, R]
106
def collectAll: ScalaCheckFunction2[T1, T2, R]
107
def prepare(action: (T1, T2) => (T1, T2)): ScalaCheckFunction2[T1, T2, R]
108
}
109
```
110
111
**Usage:**
112
```scala
113
class CustomGeneratorSpec extends Specification with ScalaCheck { def is = s2"""
114
Custom generator property ${
115
prop((n: Int) => n >= 0)
116
.setGen(Gen.choose(0, 1000))
117
.noShrink
118
.collect
119
}
120
121
Custom shrinking property ${
122
prop((s: String) => s.nonEmpty)
123
.setGen(Gen.alphaStr.suchThat(_.nonEmpty))
124
.pretty(s => s"String: '$s'")
125
.collectArg(_.length)
126
}
127
"""
128
}
129
```
130
131
### Context Management
132
133
Add setup/teardown operations around property execution using execution contexts.
134
135
```scala { .api }
136
trait ScalaCheckFunction extends ScalaCheckProperty {
137
def context: Option[Context]
138
def setContext(context: Context): SelfType
139
def before(action: =>Any): SelfType
140
def after(action: =>Any): SelfType
141
def beforeAfter(beforeAction: =>Any, afterAction: =>Any): SelfType
142
def around(action: Result => Result): SelfType
143
}
144
```
145
146
**Usage:**
147
```scala
148
class ContextSpec extends Specification with ScalaCheck { def is = s2"""
149
Property with setup ${
150
prop((data: List[Int]) => processData(data).nonEmpty)
151
.before(initializeSystem())
152
.after(cleanupSystem())
153
}
154
155
Property with around context ${
156
prop((input: String) => validateInput(input))
157
.around((result: Result) => withDatabase(result))
158
}
159
"""
160
}
161
```
162
163
## Types
164
165
```scala { .api }
166
// Property creation trait
167
trait ScalaCheckPropertyCreation {
168
def prop[T, R](result: T => R)(implicit ...): ScalaCheckFunction1[T, R]
169
def prop[T1, T2, R](result: (T1, T2) => R)(implicit ...): ScalaCheckFunction2[T1, T2, R]
170
// ... up to 8 parameters
171
}
172
173
// Base property function trait
174
trait ScalaCheckFunction extends ScalaCheckProperty {
175
def noShrink: SelfType
176
def context: Option[Context]
177
def setContext(context: Context): SelfType
178
def before(action: =>Any): SelfType
179
def after(action: =>Any): SelfType
180
def beforeAfter(beforeAction: =>Any, afterAction: =>Any): SelfType
181
def around(action: Result => Result): SelfType
182
}
183
184
// Type class instances container
185
case class ScalaCheckArgInstances[T](
186
arbitrary: Arbitrary[T],
187
shrink: Option[Shrink[T]],
188
collectors: List[T => Any],
189
pretty: T => Pretty
190
) {
191
def collect(t: T, p: Prop): Prop
192
}
193
```