CheckerAsserting
typeclasses, which are used to implement and determine the result
39 | * type of [[org.scalatest.prop.GeneratorDrivenPropertyChecks GeneratorDrivenPropertyChecks]]'s apply
and forAll
method.
40 | *
41 | *
42 | * Currently, an [[org.scalatest.prop.GeneratorDrivenPropertyChecks GeneratorDrivenPropertyChecks]] expression will have result type Assertion
, if the function passed has result type Assertion
,
43 | * else it will have result type Unit
.
44 | *
check
method.
49 | */
50 | type Result
51 |
52 | def succeed(result: T): (Boolean, Option[Throwable])
53 |
54 | /**
55 | * Perform the property check using the given Prop
and Test.Parameters
.
56 | *
57 | * @param p the Prop
to be used to check
58 | * @param prms the Test.Parameters
to be used to check
59 | * @param prettifier the Prettifier
to be used to prettify error message
60 | * @param pos the Position
of the caller site
61 | * @param argNames the list of argument names
62 | * @return the Result
of the property check.
63 | */
64 | def check(p: Prop, prms: Test.Parameters, prettifier: Prettifier, pos: source.Position, argNames: Option[List[String]] = None): Result
65 | }
66 |
67 | /**
68 | * Class holding lowest priority CheckerAsserting
implicit, which enables [[org.scalatest.prop.GeneratorDrivenPropertyChecks GeneratorDrivenPropertyChecks]] expressions that have result type Unit
.
69 | */
70 | abstract class UnitCheckerAsserting {
71 |
72 | /**
73 | * Abstract subclass of CheckerAsserting
that provides the bulk of the implementations of CheckerAsserting
74 | * check
method.
75 | */
76 | /* protected[scalatest]*/ abstract class CheckerAssertingImpl[T] extends CheckerAsserting[T] {
77 |
78 | import CheckerAsserting._
79 |
80 | /**
81 | * Check the given Prop
and Test.Parameters
by calling [[http://www.scalacheck.org ScalaCheck]]'s Test.check
.
82 | * If the check succeeds, call indicateSuccess
, else call indicateFailure
.
83 | *
84 | *
85 | * @param p the Prop
to be used to check
86 | * @param prms the Test.Parameters
to be used to check
87 | * @param prettifier the Prettifier
to be used to prettify error message
88 | * @param pos the Position
of the caller site
89 | * @param argNames the list of argument names
90 | * @return the Result
of the property check.
91 | */
92 | def check(p: Prop, prms: Test.Parameters, prettifier: Prettifier, pos: source.Position, argNames: Option[List[String]] = None): Result = {
93 |
94 | val result = Test.check(prms, p)
95 | if (!result.passed) {
96 |
97 | val (args, labels) = argsAndLabels(result)
98 |
99 | (result.status: @unchecked) match {
100 |
101 | case Test.Exhausted =>
102 |
103 | val failureMsg =
104 | if (result.succeeded == 1)
105 | FailureMessages.propCheckExhaustedAfterOne(prettifier, result.discarded) + prms.initialSeed.map(s => "\n" + FailureMessages.initSeed(prettifier, longSeed(s.toBase64))).getOrElse("")
106 | else
107 | FailureMessages.propCheckExhausted(prettifier, result.succeeded, result.discarded) + prms.initialSeed.map(s => "\n" + FailureMessages.initSeed(prettifier, longSeed(s.toBase64))).getOrElse("")
108 |
109 | indicateFailure(
110 | sde => failureMsg,
111 | failureMsg,
112 | args,
113 | labels,
114 | None,
115 | pos
116 | )
117 |
118 | case Test.Failed(scalaCheckArgs, scalaCheckLabels) =>
119 |
120 | val stackDepth = 1
121 |
122 | indicateFailure(
123 | sde => FailureMessages.propertyException(prettifier, UnquotedString(sde.getClass.getSimpleName)) + "\n" +
124 | ( sde.failedCodeFileNameAndLineNumberString match { case Some(s) => " (" + s + ")"; case None => "" }) + "\n" +
125 | " " + FailureMessages.propertyFailed(prettifier, result.succeeded) + "\n" +
126 | (
127 | sde match {
128 | case sd: StackDepth if sd.failedCodeFileNameAndLineNumberString.isDefined =>
129 | " " + FailureMessages.thrownExceptionsLocation(prettifier, UnquotedString(sd.failedCodeFileNameAndLineNumberString.get)) + "\n"
130 | case _ => ""
131 | }
132 | ) +
133 | " " + FailureMessages.occurredOnValues() + "\n" +
134 | prettyArgs(getArgsWithSpecifiedNames(argNames, scalaCheckArgs), prettifier) + "\n" +
135 | " )" +
136 | getLabelDisplay(scalaCheckLabels) + prms.initialSeed.map(s => "\n" + FailureMessages.initSeed(prettifier, longSeed(s.toBase64))).getOrElse(""),
137 | FailureMessages.propertyFailed(prettifier, result.succeeded) + prms.initialSeed.map(s => "\n" + FailureMessages.initSeed(prettifier, longSeed(s.toBase64))).getOrElse(""),
138 | scalaCheckArgs,
139 | scalaCheckLabels.toList,
140 | None,
141 | pos
142 | )
143 |
144 | case Test.PropException(scalaCheckArgs, e, scalaCheckLabels) =>
145 |
146 | indicateFailure(
147 | sde => FailureMessages.propertyException(prettifier, UnquotedString(e.getClass.getSimpleName)) + "\n" +
148 | " " + FailureMessages.thrownExceptionsMessage(prettifier, if (e.getMessage == null) "None" else UnquotedString(e.getMessage)) + "\n" +
149 | (
150 | e match {
151 | case sd: StackDepth if sd.failedCodeFileNameAndLineNumberString.isDefined =>
152 | " " + FailureMessages.thrownExceptionsLocation(prettifier, UnquotedString(sd.failedCodeFileNameAndLineNumberString.get)) + "\n"
153 | case _ => ""
154 | }
155 | ) +
156 | " " + FailureMessages.occurredOnValues() + "\n" +
157 | prettyArgs(getArgsWithSpecifiedNames(argNames, scalaCheckArgs), prettifier) + "\n" +
158 | " )" +
159 | getLabelDisplay(scalaCheckLabels) + prms.initialSeed.map(s => "\n" + FailureMessages.initSeed(prettifier, longSeed(s.toBase64))).getOrElse(""),
160 | FailureMessages.propertyException(prettifier, UnquotedString(e.getClass.getName)) + prms.initialSeed.map(s => "\n" + FailureMessages.initSeed(prettifier, longSeed(s.toBase64))).getOrElse(""),
161 | scalaCheckArgs,
162 | scalaCheckLabels.toList,
163 | Some(e),
164 | pos
165 | )
166 | }
167 | } else indicateSuccess(FailureMessages.propertyCheckSucceeded())
168 | }
169 |
170 | private[scalacheck] def indicateSuccess(message: => String): Result
171 |
172 | private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Result
173 | }
174 |
175 | /**
176 | * Provides support of [[org.scalatest.enablers.CheckerAsserting CheckerAsserting]] for Unit. Do nothing when the check succeeds,
177 | * but throw [[org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException GeneratorDrivenPropertyCheckFailedException]]
178 | * when check fails.
179 | */
180 | implicit def assertingNatureOfT[T]: CheckerAsserting[T] { type Result = Unit } =
181 | new CheckerAssertingImpl[T] {
182 | type Result = Unit
183 | def succeed(result: T) = (true, None)
184 | private[scalacheck] def indicateSuccess(message: => String): Unit = ()
185 | private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Unit = {
186 | throw new GeneratorDrivenPropertyCheckFailedException(
187 | messageFun,
188 | optionalCause,
189 | pos,
190 | None,
191 | undecoratedMessage,
192 | scalaCheckArgs,
193 | None,
194 | scalaCheckLabels.toList
195 | )
196 | }
197 | }
198 | }
199 |
200 | /**
201 | * Abstract class that in the future will hold an intermediate priority CheckerAsserting
implicit, which will enable inspector expressions
202 | * that have result type Expectation
, a more composable form of assertion that returns a result instead of throwing an exception when it fails.
203 | */
204 | abstract class ExpectationCheckerAsserting extends UnitCheckerAsserting {
205 |
206 | /*implicit def assertingNatureOfExpectation(implicit prettifier: Prettifier): CheckerAsserting[Expectation] { type Result = Expectation } = {
207 | new CheckerAssertingImpl[Expectation] {
208 | type Result = Expectation
209 | def succeed(result: Expectation) = (result.isYes, result.cause)
210 | private[scalacheck] def indicateSuccess(message: => String): Expectation = Fact.Yes(message)(prettifier)
211 | private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Expectation = {
212 | val gdpcfe =
213 | new GeneratorDrivenPropertyCheckFailedException(
214 | messageFun,
215 | optionalCause,
216 | pos,
217 | None,
218 | undecoratedMessage,
219 | scalaCheckArgs,
220 | None,
221 | scalaCheckLabels.toList
222 | )
223 | val message: String = gdpcfe.getMessage
224 | Fact.No(message)(prettifier)
225 | }
226 | }
227 | }*/
228 | }
229 |
230 | /**
231 | * Companion object to CheckerAsserting
that provides two implicit providers, a higher priority one for passed functions that have result
232 | * type Assertion
, which also yields result type Assertion
, and one for any other type, which yields result type Unit
.
233 | */
234 | object CheckerAsserting extends ExpectationCheckerAsserting {
235 |
236 | /**
237 | * Provides support of [[org.scalatest.enablers.CheckerAsserting CheckerAsserting]] for Assertion. Returns [[org.scalatest.Succeeded Succeeded]] when the check succeeds,
238 | * but throw [[org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException GeneratorDrivenPropertyCheckFailedException]]
239 | * when check fails.
240 | */
241 | implicit def assertingNatureOfAssertion: CheckerAsserting[Assertion] { type Result = Assertion } = {
242 | new CheckerAssertingImpl[Assertion] {
243 | type Result = Assertion
244 | def succeed(result: Assertion) = (true, None)
245 | private[scalacheck] def indicateSuccess(message: => String): Assertion = Succeeded
246 | private[scalacheck] def indicateFailure(messageFun: StackDepthException => String, undecoratedMessage: => String, scalaCheckArgs: List[Any], scalaCheckLabels: List[String], optionalCause: Option[Throwable], pos: source.Position): Assertion = {
247 | throw new GeneratorDrivenPropertyCheckFailedException(
248 | messageFun,
249 | optionalCause,
250 | pos,
251 | None,
252 | undecoratedMessage,
253 | scalaCheckArgs,
254 | None,
255 | scalaCheckLabels.toList
256 | )
257 | }
258 | }
259 | }
260 |
261 | private[scalacheck] def getArgsWithSpecifiedNames(argNames: Option[List[String]], scalaCheckArgs: List[Arg[Any]]) = {
262 | if (argNames.isDefined) {
263 | // length of scalaCheckArgs should equal length of argNames
264 | val zipped = argNames.get zip scalaCheckArgs
265 | zipped map { case (argName, arg) => arg.copy(label = argName) }
266 | }
267 | else
268 | scalaCheckArgs
269 | }
270 |
271 | private[scalacheck] def getLabelDisplay(labels: Set[String]): String =
272 | if (labels.size > 0)
273 | "\n " + (if (labels.size == 1) Resources.propCheckLabel() else Resources.propCheckLabels()) + "\n" + labels.map(" " + _).mkString("\n")
274 | else
275 | ""
276 |
277 | private[scalacheck] def argsAndLabels(result: Test.Result): (List[Any], List[String]) = {
278 |
279 | val (scalaCheckArgs, scalaCheckLabels) =
280 | result.status match {
281 | case Test.Proved(args) => (args.toList, List())
282 | case Test.Failed(args, labels) => (args.toList, labels.toList)
283 | case Test.PropException(args, _, labels) => (args.toList, labels.toList)
284 | case _ => (List(), List())
285 | }
286 |
287 | val args: List[Any] = for (scalaCheckArg <- scalaCheckArgs.toList) yield scalaCheckArg.arg
288 |
289 | // scalaCheckLabels is a Set[String], I think
290 | val labels: List[String] = for (scalaCheckLabel <- scalaCheckLabels.iterator.toList) yield scalaCheckLabel
291 |
292 | (args, labels)
293 | }
294 |
295 | // TODO: Internationalize these, and make them consistent with FailureMessages stuff (only strings get quotes around them, etc.)
296 | private[scalacheck] def prettyTestStats(result: Test.Result, prettifier: Prettifier) = result.status match {
297 |
298 | case Test.Proved(args) =>
299 | "OK, proved property: \n" + prettyArgs(args, prettifier)
300 |
301 | case Test.Passed =>
302 | "OK, passed " + result.succeeded + " tests."
303 |
304 | case Test.Failed(args, labels) =>
305 | "Falsified after " + result.succeeded + " passed tests:\n" + prettyLabels(labels) + prettyArgs(args, prettifier)
306 |
307 | case Test.Exhausted =>
308 | "Gave up after only " + result.succeeded + " passed tests. " +
309 | result.discarded + " tests were discarded."
310 |
311 | case Test.PropException(args, e, labels) =>
312 | FailureMessages.propertyException(prettifier, UnquotedString(e.getClass.getSimpleName)) + "\n" + prettyLabels(labels) + prettyArgs(args, prettifier)
313 | }
314 |
315 | private[scalacheck] def prettyLabels(labels: Set[String]) = {
316 | if (labels.isEmpty) ""
317 | else if (labels.size == 1) "Label of failing property: " + labels.iterator.next + "\n"
318 | else "Labels of failing property: " + labels.mkString("\n") + "\n"
319 | }
320 |
321 | //
322 | // If scalacheck arg contains a type that
323 | // decorateToStringValue processes, then let
324 | // decorateToStringValue handle it. Otherwise use its
325 | // prettyArg method to generate the display string.
326 | //
327 | // Passes 0 as verbosity value to prettyArg function.
328 | //
329 | private[scalacheck] def decorateArgToStringValue[T](arg: T, prettyArg: Pretty, prettifier: Prettifier): String =
330 | arg match {
331 | case null => decorateToStringValue(prettifier, arg)
332 | case _: Unit => decorateToStringValue(prettifier, arg)
333 | case _: String => decorateToStringValue(prettifier, arg)
334 | case _: Char => decorateToStringValue(prettifier, arg)
335 | case _: Array[_] => decorateToStringValue(prettifier, arg)
336 | case _: mutable.WrappedArray[_] => decorateToStringValue(prettifier, arg)
337 | case a if ArrayHelper.isArrayOps(arg) => decorateToStringValue(prettifier, arg)
338 | case _: Many[_] => decorateToStringValue(prettifier, arg)
339 | case _: scala.collection.GenMap[_, _] => decorateToStringValue(prettifier, arg)
340 | case _: Iterable[_] => decorateToStringValue(prettifier, arg)
341 | case _: java.util.Collection[_] => decorateToStringValue(prettifier, arg)
342 | case _: java.util.Map[_, _] => decorateToStringValue(prettifier, arg)
343 | case p: Product if p.productArity > 0 => decorateToStringValue(prettifier, arg)
344 | case _ => prettyArg(new Pretty.Params(0))
345 | }
346 |
347 | private[scalacheck] def prettyArgs(args: List[Arg[_]], prettifier: Prettifier) = {
348 | val strs = for((a, i) <- args.zipWithIndex) yield (
349 | " " +
350 | (if (a.label == "") "arg" + i else a.label) +
351 | " = " + decorateArgToStringValue(a.arg, a.prettyArg, prettifier) + (if (i < args.length - 1) "," else "") +
352 | (if (a.shrinks > 0) " // " + a.shrinks + (if (a.shrinks == 1) " shrink" else " shrinks") + " (orig: " + decorateArgToStringValue(a.origArg, a.prettyOrigArg, prettifier) + ")" else "")
353 | )
354 | strs.mkString("\n")
355 | }
356 |
357 | def longSeed(s: String): Long = {
358 | def fail(s: String): Nothing = throw new IllegalArgumentException(s)
359 |
360 | def dec(c: Char): Long =
361 | if ('A' <= c && c <= 'Z') (c - 'A').toLong
362 | else if ('a' <= c && c <= 'z') ((c - 'a') + 26).toLong
363 | else if ('0' <= c && c <= '9') ((c - '0') + 52).toLong
364 | else if (c == '-') 62L
365 | else if (c == '_') 63L
366 | else fail(s"illegal Base64 character: $c")
367 |
368 | val longs = new Array[Long](4)
369 | @tailrec def decode(x: Long, shift: Int, i: Int, j: Int): Long =
370 | if (i >= 43) {
371 | longs(1)
372 | } else {
373 | val b = dec(s.charAt(i))
374 | if (shift < 58) {
375 | decode(x | (b << shift), shift + 6, i + 1, j)
376 | } else {
377 | longs(j) = x | (b << shift)
378 | val sh = 64 - shift
379 | decode(b >>> sh, 6 - sh, i + 1, j + 1)
380 | }
381 | }
382 |
383 | if (s.length != 44) fail(s"wrong Base64 length: $s")
384 | if (s.charAt(43) != '=') fail(s"wrong Base64 format: $s")
385 | if (s.charAt(42) == '=') fail(s"wrong Base64 format: $s")
386 | decode(0L, 0, 0, 0)
387 |
388 | }
389 | }
390 |
391 |
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/main/scala/org/scalatestplus/scalacheck/Checkers.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus.scalacheck
17 |
18 | import org.scalatest.prop.Configuration
19 | import org.scalatest.Assertion
20 | import org.scalacheck.Arbitrary
21 | import org.scalacheck.Shrink
22 | import org.scalacheck.util.Pretty
23 | import org.scalacheck.Prop
24 | import org.scalacheck.Test
25 | import org.scalactic._
26 |
27 | /**
28 | * Trait that contains several “check” methods that perform ScalaCheck property checks.
29 | * If ScalaCheck finds a test case for which a property doesn't hold, the problem will be reported as a ScalaTest test failure.
30 | *
31 | *
32 | * To use ScalaCheck, you specify properties and, in some cases, generators that generate test data. You need not always
33 | * create generators, because ScalaCheck provides many default generators for you that can be used in many situations.
34 | * ScalaCheck will use the generators to generate test data and with that data run tests that check that the property holds.
35 | * Property-based tests can, therefore, give you a lot more testing for a lot less code than assertion-based tests.
36 | * Here's an example of using ScalaCheck from a JUnitSuite
:
37 | *
39 | * import org.scalatest.junit.JUnitSuite 40 | * import org.scalatest.prop.Checkers 41 | * import org.scalacheck.Arbitrary._ 42 | * import org.scalacheck.Prop._ 43 | * 44 | * class MySuite extends JUnitSuite with Checkers { 45 | * @Test 46 | * def testConcat() { 47 | * check((a: List[Int], b: List[Int]) => a.size + b.size == (a ::: b).size) 48 | * } 49 | * } 50 | *51 | *
52 | * The check
method, defined in Checkers
, makes it easy to write property-based tests inside
53 | * ScalaTest, JUnit, and TestNG test suites. This example specifies a property that List
's :::
method
54 | * should obey. ScalaCheck properties are expressed as function values that take the required
55 | * test data as parameters. ScalaCheck will generate test data using generators and
56 | repeatedly pass generated data to the function. In this case, the test data is composed of integer lists named a
and b
.
57 | * Inside the body of the function, you see:
58 | *
60 | * a.size + b.size == (a ::: b).size 61 | *62 | *
63 | * The property in this case is a Boolean
expression that will yield true if the size of the concatenated list is equal
64 | * to the size of each individual list added together. With this small amount
65 | * of code, ScalaCheck will generate possibly hundreds of value pairs for a
and b
and test each pair, looking for
66 | * a pair of integers for which the property doesn't hold. If the property holds true for every value ScalaCheck tries,
67 | * check
returns normally. Otherwise, check
will complete abruptly with a TestFailedException
that
68 | * contains information about the failure, including the values that cause the property to be false.
69 | *
72 | * For more information on using ScalaCheck properties, see the documentation for ScalaCheck, which is available 73 | * from http://code.google.com/p/scalacheck/. 74 | *
75 | * 76 | *
77 | * To execute a suite that mixes in Checkers
with ScalaTest's Runner
, you must include ScalaCheck's jar file on the class path or runpath.
78 | *
83 | * The property checks performed by the check
methods of this trait can be flexibly configured via the services
84 | * provided by supertrait Configuration
. The five configuration parameters for property checks along with their
85 | * default values and meanings are described in the following table:
86 | *
91 | * Configuration Parameter 92 | * | 93 | *94 | * Default Value 95 | * | 96 | *97 | * Meaning 98 | * | 99 | *
---|---|---|
102 | * minSuccessful 103 | * | 104 | *105 | * 100 106 | * | 107 | *108 | * the minimum number of successful property evaluations required for the property to pass 109 | * | 110 | *
113 | * maxDiscarded 114 | * | 115 | *116 | * 500 117 | * | 118 | *119 | * the maximum number of discarded property evaluations allowed during a property check 120 | * | 121 | *
124 | * minSize 125 | * | 126 | *127 | * 0 128 | * | 129 | *130 | * the minimum size parameter to provide to ScalaCheck, which it will use when generating objects for which size matters (such as strings or lists) 131 | * | 132 | *
135 | * maxSize 136 | * | 137 | *138 | * 100 139 | * | 140 | *141 | * the maximum size parameter to provide to ScalaCheck, which it will use when generating objects for which size matters (such as strings or lists) 142 | * | 143 | *
146 | * workers 147 | * | 148 | *149 | * 1 150 | * | 151 | *152 | * specifies the number of worker threads to use during property evaluation 153 | * | 154 | *
158 | * The check
methods of trait Checkers
each take a PropertyCheckConfiguration
159 | * object as an implicit parameter. This object provides values for each of the five configuration parameters. Trait Configuration
160 | * provides an implicit val
named generatorDrivenConfig
with each configuration parameter set to its default value.
161 | * If you want to set one or more configuration parameters to a different value for all property checks in a suite you can override this
162 | * val (or hide it, for example, if you are importing the members of the Checkers
companion object rather
163 | * than mixing in the trait.) For example, if
164 | * you want all parameters at their defaults except for minSize
and maxSize
, you can override
165 | * generatorDrivenConfig
, like this:
166 | *
167 | *
168 | * implicit override val generatorDrivenConfig = 169 | * PropertyCheckConfiguration(minSize = 10, sizeRange = 10) 170 | *171 | * 172 | *
173 | * Or, if hide it by declaring a variable of the same name in whatever scope you want the changed values to be in effect: 174 | *
175 | * 176 | *177 | * implicit val generatorDrivenConfig = 178 | * PropertyCheckConfiguration(minSize = 10, sizeRange = 10) 179 | *180 | * 181 | *
182 | * In addition to taking a PropertyCheckConfiguration
object as an implicit parameter, the check
methods of trait
183 | * Checkers
also take a variable length argument list of PropertyCheckConfigParam
184 | * objects that you can use to override the values provided by the implicit PropertyCheckConfiguration
for a single check
185 | * invocation. You place these configuration settings after the property or property function, For example, if you want to
186 | * set minSuccessful
to 500 for just one particular check
invocation,
187 | * you can do so like this:
188 | *
191 | * check((n: Int) => n + 0 == n, minSuccessful(500)) 192 | *193 | * 194 | *
195 | * This invocation of check
will use 500 for minSuccessful
and whatever values are specified by the
196 | * implicitly passed PropertyCheckConfiguration
object for the other configuration parameters.
197 | * If you want to set multiple configuration parameters in this way, just list them separated by commas:
198 | *
201 | * check((n: Int) => n + 0 == n, minSuccessful(500), maxDiscardedFactor(0.6)) 202 | *203 | * 204 | *
205 | * The previous configuration approach works the same in Checkers
as it does in GeneratorDrivenPropertyChecks
.
206 | * Trait Checkers
also provides one check
method that takes an org.scalacheck.Test.Parameters
object,
207 | * in case you want to configure ScalaCheck that way.
208 | *
211 | * import org.scalacheck.Prop 212 | * import org.scalacheck.Test.Parameters 213 | * import org.scalatest.prop.Checkers._ 214 | * 215 | * check(Prop.forAll((n: Int) => n + 0 == n), Parameters.Default { override val minSuccessfulTests = 5 }) 216 | *217 | * 218 | *
219 | * For more information, see the documentation
220 | * for supertrait Configuration
.
221 | *
Checkers
members as
377 | * an alternative to mixing it in. One use case is to import Checkers
members so you can use
378 | * them in the Scala interpreter.
379 | *
380 | * @author Bill Venners
381 | */
382 | object Checkers extends Checkers
383 |
384 | /*
385 | * Returns a ScalaCheck Prop
that succeeds if the passed by-name
386 | * parameter, fun
, returns normally; fails if it throws
387 | * an exception.
388 | *
389 | * 390 | * This method enables ScalaTest assertions and matcher expressions to be used 391 | * in property checks. Here's an example: 392 | *
393 | * 394 | *395 | * check((s: String, t: String) => successOf(s + t should endWith (s))) 396 | *397 | * 398 | *
399 | * The detail message of the TestFailedException
that will likely
400 | * be thrown by the matcher expression will be added as a label to the ScalaCheck
401 | * Prop
returned by successOf
. This, this property
402 | * check might fail with an exception like:
403 | *
406 | * org.scalatest.prop.GeneratorDrivenPropertyCheckFailedException: TestFailedException (included as this exception's cause) was thrown during property evaluation. 407 | * Label of failing property: "ab" did not end with substring "a" (script.scala:24) 408 | * > arg0 = "?" (1 shrinks) 409 | * > arg1 = "?" (1 shrinks) 410 | * at org.scalatest.prop.Checkers$class.check(Checkers.scala:252) 411 | * at org.scalatest.prop.Checkers$.check(Checkers.scala:354) 412 | * ... 413 | *414 | * 415 | *
416 | * One use case for using matcher expressions in your properties is to 417 | * get helpful error messages without using ScalaCheck labels. For example, 418 | * instead of: 419 | *
420 | * 421 | *422 | * val complexProp = forAll { (m: Int, n: Int) => 423 | * val res = n * m 424 | * (res >= m) :| "result > #1" && 425 | * (res >= n) :| "result > #2" && 426 | * (res < m + n) :| "result not sum" 427 | * } 428 | *429 | * 430 | *
431 | * You could write: 432 | *
433 | * 434 | *435 | * val complexProp = forAll { (m: Int, n: Int) => 436 | * successOf { 437 | * val res = n * m 438 | * res should be >= m 439 | * res should be >= n 440 | * res should be < (m + n) 441 | * } 442 | *443 | * 444 | * @param fun the expression to evaluate to determine what
Prop
445 | * to return
446 | * @return a ScalaCheck property that passes if the passed by-name parameter,
447 | * fun
, returns normally, fails if it throws an exception
448 | private def successOf(fun: => Unit): Prop =
449 | try {
450 | fun
451 | Prop.passed
452 | }
453 | catch {
454 | case e: StackDepth =>
455 | val msgPart = if (e.message.isDefined) e.message.get + " " else ""
456 | val fileLinePart =
457 | if (e.failedCodeFileNameAndLineNumberString.isDefined)
458 | "(" + e.failedCodeFileNameAndLineNumberString.get + ")"
459 | else
460 | ""
461 | val lbl = msgPart + fileLinePart
462 | Prop.exception(e).label(lbl)
463 | case e => Prop.exception(e) // Not sure what to do here
464 | }
465 | */
466 |
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/main/scala/org/scalatestplus/scalacheck/ScalaCheckConfiguration.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2018 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus.scalacheck
17 |
18 | import org.scalacheck.Test.Parameters
19 | import org.scalacheck.Test.TestCallback
20 | import org.scalatest.prop.Configuration
21 |
22 | private[scalacheck] trait ScalaCheckConfiguration extends Configuration {
23 |
24 | private[scalacheck] def getScalaCheckParams(
25 | configParams: Seq[PropertyCheckConfigParam],
26 | config: PropertyCheckConfiguration
27 | ): Parameters = {
28 |
29 | var minSuccessful: Option[Int] = None
30 | var maxDiscardedFactor: Option[Double] = None
31 | var pminSize: Option[Int] = None
32 | var psizeRange: Option[Int] = None
33 | var pworkers: Option[Int] = None
34 |
35 | var minSuccessfulTotalFound = 0
36 | var maxDiscardedFactorTotalFound = 0
37 | var minSizeTotalFound = 0
38 | var sizeRangeTotalFound = 0
39 | var workersTotalFound = 0
40 |
41 | for (configParam <- configParams) {
42 | configParam match {
43 | case MinSuccessful(value) =>
44 | minSuccessful = Some(value)
45 | minSuccessfulTotalFound += 1
46 | case MaxDiscardedFactor(value) =>
47 | maxDiscardedFactor = Some(value)
48 | maxDiscardedFactorTotalFound += 1
49 | case MinSize(value) =>
50 | pminSize = Some(value)
51 | minSizeTotalFound += 1
52 | case SizeRange(value) =>
53 | psizeRange = Some(value)
54 | sizeRangeTotalFound += 1
55 | case Workers(value) =>
56 | pworkers = Some(value)
57 | workersTotalFound += 1
58 | }
59 | }
60 |
61 | if (minSuccessfulTotalFound > 1)
62 | throw new IllegalArgumentException("can pass at most one MinSuccessful config parameters, but " + minSuccessfulTotalFound + " were passed")
63 | if (maxDiscardedFactorTotalFound > 1)
64 | throw new IllegalArgumentException("can pass at most one MaxDiscardedFactor config parameters, but " + maxDiscardedFactorTotalFound + " were passed")
65 | if (minSizeTotalFound > 1)
66 | throw new IllegalArgumentException("can pass at most one MinSize config parameters, but " + minSizeTotalFound + " were passed")
67 | if (sizeRangeTotalFound > 1)
68 | throw new IllegalArgumentException("can pass at most one SizeRange config parameters, but " + sizeRangeTotalFound + " were passed")
69 | if (workersTotalFound > 1)
70 | throw new IllegalArgumentException("can pass at most one Workers config parameters, but " + workersTotalFound + " were passed")
71 |
72 | val minSuccessfulTests: Int = minSuccessful.getOrElse(config.minSuccessful)
73 |
74 | val minSize: Int = pminSize.getOrElse(config.minSize)
75 |
76 | val maxSize = psizeRange.getOrElse(config.sizeRange.value) + minSize
77 |
78 | val maxDiscardRatio: Float = maxDiscardedFactor.getOrElse(config.maxDiscardedFactor.value).toFloat
79 |
80 | val seed = {
81 | val s = org.scalatest.prop.Seed.configured.fold(scala.util.Random.nextLong)(_.value)
82 | org.scalacheck.rng.Seed.fromLongs(0xf1ea5eed, s, s, s)
83 | }
84 |
85 | Parameters.default
86 | .withMinSuccessfulTests(minSuccessfulTests)
87 | .withMinSize(minSize)
88 | .withMaxSize(maxSize)
89 | .withWorkers(pworkers.getOrElse(config.workers))
90 | .withTestCallback(new TestCallback {})
91 | .withMaxDiscardRatio(maxDiscardRatio)
92 | .withCustomClassLoader(None)
93 | .withInitialSeed(seed)
94 | }
95 |
96 | }
97 |
98 | private[scalacheck] object ScalaCheckConfiguration extends ScalaCheckConfiguration
99 |
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/main/scala/org/scalatestplus/scalacheck/ScalaCheckGenerators.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2016 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /*package org.scalatestplus.scalacheck
17 |
18 | import org.scalatest.prop.{Generator, Randomizer, SizeParam}
19 |
20 | trait ScalaCheckGenerators {
21 |
22 | import org.scalacheck.{Arbitrary, Gen, Shrink}
23 | import org.scalacheck.rng.Seed
24 |
25 | implicit def scalaCheckArbitaryGenerator[T](implicit arb: Arbitrary[T], shrk: Shrink[T]): Generator[T] =
26 | new Generator[T] {
27 | def next(szp: SizeParam, edges: List[T], rnd: Randomizer): (T, List[T], Randomizer) = {
28 | edges match {
29 | case head :: tail =>
30 | (head, tail, rnd)
31 | case _ =>
32 | arb.arbitrary.apply(Gen.Parameters.default.withSize(szp.size), Seed(rnd.seed)) match {
33 | case Some(nextT) => (nextT, Nil, rnd.nextRandomizer)
34 | case None => throw new IllegalStateException("Unable to generate value using ScalaCheck Arbitary.")
35 | }
36 | }
37 | }
38 | override def shrink(value: T, rnd: Randomizer): (Iterator[T], Randomizer) = {
39 | (shrk.shrink(value).take(10000).reverse.toIterator, rnd)
40 | }
41 | }
42 | }
43 |
44 | object ScalaCheckGenerators extends ScalaCheckGenerators
45 | */
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/main/scala/org/scalatestplus/scalacheck/ScalaCheckPropertyChecks.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus
17 | package scalacheck
18 |
19 | import org.scalatest.prop.TableDrivenPropertyChecks
20 |
21 | /**
22 | * Trait that facilitates property checks on data supplied by tables and ScalaCheck generators.
23 | *
24 | *
25 | * This trait extends both TableDrivenPropertyChecks
and
26 | * ScalaCheckDrivenPropertyChecks
. Thus by mixing in
27 | * this trait you can perform property checks on data supplied either by tables or generators. For the details of
28 | * table- and generator-driven property checks, see the documentation for each by following the links above.
29 | *
32 | * For a quick example of using both table and generator-driven property checks in the same suite of tests, however,
33 | * imagine you want to test this Fraction
class:
34 | *
37 | * class Fraction(n: Int, d: Int) { 38 | * 39 | * require(d != 0) 40 | * require(d != Integer.MIN_VALUE) 41 | * require(n != Integer.MIN_VALUE) 42 | * 43 | * val numer = if (d < 0) -1 * n else n 44 | * val denom = d.abs 45 | * 46 | * override def toString = numer + " / " + denom 47 | * } 48 | *49 | * 50 | *
51 | * If you mix in PropertyChecks
, you could use a generator-driven property check to test that the passed values for numerator and
52 | * denominator are properly normalized, like this:
53 | *
56 | * forAll { (n: Int, d: Int) => 57 | * 58 | * whenever (d != 0 && d != Integer.MIN_VALUE 59 | * && n != Integer.MIN_VALUE) { 60 | * 61 | * val f = new Fraction(n, d) 62 | * 63 | * if (n < 0 && d < 0 || n > 0 && d > 0) 64 | * f.numer should be > 0 65 | * else if (n != 0) 66 | * f.numer should be < 0 67 | * else 68 | * f.numer shouldEqual 0 69 | * 70 | * f.denom should be > 0 71 | * } 72 | * } 73 | *74 | * 75 | *
76 | * And you could use a table-driven property check to test that all combinations of invalid values passed to the Fraction
constructor
77 | * produce the expected IllegalArgumentException
, like this:
78 | *
81 | * val invalidCombos = 82 | * Table( 83 | * ("n", "d"), 84 | * (Integer.MIN_VALUE, Integer.MIN_VALUE), 85 | * (1, Integer.MIN_VALUE), 86 | * (Integer.MIN_VALUE, 1), 87 | * (Integer.MIN_VALUE, 0), 88 | * (1, 0) 89 | * ) 90 | * 91 | * forAll (invalidCombos) { (n: Int, d: Int) => 92 | * an [IllegalArgumentException] should be thrownBy { 93 | * new Fraction(n, d) 94 | * } 95 | * } 96 | *97 | * 98 | * @author Bill Venners 99 | */ 100 | trait ScalaCheckPropertyChecks extends TableDrivenPropertyChecks with ScalaCheckDrivenPropertyChecks 101 | 102 | /** 103 | * Companion object that facilitates the importing of
PropertyChecks
members as
104 | * an alternative to mixing it in. One use case is to import PropertyChecks
members so you can use
105 | * them in the Scala interpreter.
106 | *
107 | * @author Bill Venners
108 | */
109 | object ScalaCheckPropertyChecks extends ScalaCheckPropertyChecks
110 |
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/main/scala/org/scalatestplus/scalacheck/UnquotedString.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2019 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus.scalacheck
17 |
18 | // This is used to pass a string to the FailureMessages apply method
19 | // but prevent it from being quoted. This is useful when using a string
20 | // to talk about method names, for example.
21 | private[scalacheck] class UnquotedString(s: String) {
22 | override def toString = s
23 | override def equals(other: Any): Boolean =
24 | other match {
25 | case that: UnquotedString => s == that.toString
26 | case _ => false
27 | }
28 | override def hashCode: Int = s.hashCode
29 | }
30 |
31 | private[scalacheck] object UnquotedString {
32 | def apply(s: String) = new UnquotedString(s)
33 | }
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/test/scala/org/scalatest/check/CheckersSpec.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus.scalacheck
17 |
18 | import org.scalacheck._
19 | import org.scalatest._
20 | import Arbitrary._
21 | import Prop.{BooleanOperators => _, _}
22 | import org.scalatest.matchers.should.Matchers._
23 | import org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException
24 | import org.scalacheck.util.Pretty
25 | import org.scalatest.exceptions.TestFailedException
26 | import org.scalactic.source.Position
27 |
28 | class CheckersSpec extends funspec.AnyFunSpec with Checkers {
29 |
30 | def expectFileNameLineNumber(ex: GeneratorDrivenPropertyCheckFailedException, expectedFileName: String, expectedLineNumber: Int): Unit = {
31 | assertResult(expectedFileName)(ex.failedCodeFileName.getOrElse(null))
32 | assertResult(expectedLineNumber)(ex.failedCodeLineNumber.getOrElse(-1))
33 | }
34 |
35 | describe("test check prop") {
36 | it("should ensure a success does not fail in an exception") {
37 | val propConcatLists = forAll((a: List[Int], b: List[Int]) => a.size + b.size == (a ::: b).size)
38 | check(propConcatLists)
39 | }
40 |
41 | it("should ensure a failed property does throw an assertion error") {
42 | val propConcatListsBadly = forAll((a: List[Int], b: List[Int]) => a.size + b.size == (a ::: b).size + 1)
43 | intercept[TestFailedException] {
44 | check(propConcatListsBadly)
45 | }
46 | }
47 |
48 | it("should ensure a property that throws an exception causes an assertion error") {
49 | val propConcatListsExceptionally = forAll((a: List[Int], b: List[Int]) => throw new StringIndexOutOfBoundsException)
50 | intercept[TestFailedException] {
51 | check(propConcatListsExceptionally)
52 | }
53 | }
54 |
55 | it("should ensure a property that doesn't generate enough test cases throws an assertion error") {
56 | val negativeOne = -1
57 | val propTrivial = forAll( (n: Int) => (negativeOne == 0) ==> (n == 0) )
58 | intercept[TestFailedException] {
59 | check(propTrivial)
60 | }
61 | }
62 |
63 | it("should make sure a Generator that doesn't throw an exception works OK") {
64 | val smallInteger = Gen.choose(0, 100)
65 | val propSmallInteger = Prop.forAll(smallInteger)(n => n >= 0 && n <= 100)
66 | check(propSmallInteger)
67 |
68 | val smallEvenInteger = Gen.choose(0, 200) suchThat (_ % 2 == 0)
69 | val propEvenInteger = Prop.forAll(smallEvenInteger)(n => n >= 0 && n <= 200 && n % 2 == 0)
70 | check(propEvenInteger)
71 | }
72 |
73 | it("should Make sure a Generator t throws an exception results in an TestFailedException") {
74 | // val smallEvenIntegerWithBug = Gen.choose(0, 200) suchThat (throw new ArrayIndexOutOfBoundsException)
75 | val myArrayException = new ArrayIndexOutOfBoundsException
76 | val smallEvenIntegerWithBug = Gen.choose(0, 200) suchThat (n => throw myArrayException )
77 | val propEvenIntegerWithBuggyGen = Prop.forAll(smallEvenIntegerWithBug)(n => n >= 0 && n <= 200 && n % 2 == 0)
78 | val caught1 = intercept[TestFailedException] {
79 | check(propEvenIntegerWithBuggyGen)
80 | }
81 | assert(caught1.getCause === myArrayException)
82 | }
83 |
84 | it("should make sure that I get a thrown exception back as the TFE's cause") {
85 | val myIAE = new IllegalArgumentException
86 | val caught2 = intercept[TestFailedException] {
87 | check((s: String, t: String, u: String) => { throw myIAE })
88 | }
89 | assert(caught2.getCause === myIAE)
90 |
91 | val complexProp = forAll { (m: Int, n: Int) =>
92 | val res = n * m
93 | (res >= m) :| "result > #1" &&
94 | (res >= n) :| "result > #2" &&
95 | (res < m + n) :| "result not sum"
96 | }
97 |
98 | intercept[GeneratorDrivenPropertyCheckFailedException] {
99 | check(complexProp)
100 | }
101 | }
102 |
103 | it("should work correctly for code shows up in the front page for ScalaTest") {
104 | import scala.collection.mutable.Stack
105 | check {
106 | (list: List[Int]) => {
107 | val stack = new Stack[Int]
108 | for (element <- list) stack.push(element)
109 | stack.iterator.toList == list.reverse
110 | }
111 | }
112 | }
113 |
114 | it("should give correct stack depth") {
115 | val ex1 = intercept[GeneratorDrivenPropertyCheckFailedException] { check((a: List[Int]) => a.size == a.size + 1) }
116 | expectFileNameLineNumber(ex1, "CheckersSpec.scala", Position.here.lineNumber - 1)
117 | val ex2 = intercept[GeneratorDrivenPropertyCheckFailedException] { check((a: List[Int], b: List[Int]) => a.size + b.size == (a ::: b).size + 1) }
118 | expectFileNameLineNumber(ex2, "CheckersSpec.scala", Position.here.lineNumber - 1)
119 | val ex3 = intercept[GeneratorDrivenPropertyCheckFailedException] { check((a: List[Int], b: List[Int], c: List[Int]) => a.size + b.size + c.size == (a ::: b ::: c).size + 1) }
120 | expectFileNameLineNumber(ex3, "CheckersSpec.scala", Position.here.lineNumber - 1)
121 | val ex4 = intercept[GeneratorDrivenPropertyCheckFailedException] { check((a: List[Int], b: List[Int], c: List[Int], d: List[Int]) => a.size + b.size + c.size == (a ::: b ::: c ::: d).size + 1) }
122 | expectFileNameLineNumber(ex4, "CheckersSpec.scala", Position.here.lineNumber - 1)
123 | val ex5 = intercept[GeneratorDrivenPropertyCheckFailedException] { check((a: List[Int], b: List[Int], c: List[Int], d: List[Int], e: List[Int]) => a.size + b.size + c.size == (a ::: b ::: c ::: d ::: e).size + 1) }
124 | expectFileNameLineNumber(ex5, "CheckersSpec.scala", Position.here.lineNumber - 1)
125 | val ex6 = intercept[GeneratorDrivenPropertyCheckFailedException] { check((a: List[Int], b: List[Int], c: List[Int], d: List[Int], e: List[Int], f: List[Int]) => a.size + b.size + c.size == (a ::: b ::: c ::: d ::: e ::: f).size + 1) }
126 | expectFileNameLineNumber(ex6, "CheckersSpec.scala", Position.here.lineNumber - 1)
127 | val ex7 = intercept[GeneratorDrivenPropertyCheckFailedException] { check(Prop.forAll((n: Int) => n + 0 == n + 1)) }
128 | expectFileNameLineNumber(ex7, "CheckersSpec.scala", Position.here.lineNumber - 1)
129 | val ex8 = intercept[GeneratorDrivenPropertyCheckFailedException] { check(Prop.forAll((n: Int) => n + 0 == n + 1), Test.Parameters.default.withMinSuccessfulTests(5)) }
130 | expectFileNameLineNumber(ex8, "CheckersSpec.scala", Position.here.lineNumber - 1)
131 |
132 | try {
133 | check((a: List[Int], b: List[Int]) => a.size + b.size == (a ::: b).size + 1)
134 | }
135 | catch {
136 | case ex: GeneratorDrivenPropertyCheckFailedException =>
137 | expectFileNameLineNumber(ex, "CheckersSpec.scala", Position.here.lineNumber - 4)
138 | }
139 | }
140 |
141 | it("should print pretty arg in error message when failure occurs") {
142 | class Thingie(val whatzit: Int)
143 |
144 | val g = new Thingie(23)
145 |
146 | val p: Thingie => Pretty = { t =>
147 | Pretty { _ => "Thingie "+ t.whatzit }
148 | }
149 |
150 | val tfe = intercept[TestFailedException] {
151 | check(
152 | Prop.forAll(g) { _ => false }(implicitly[Boolean => Prop],
153 | implicitly[Shrink[Thingie]],
154 | p)
155 | )
156 | }
157 | assert(tfe.toString.contains("arg0 = Thingie 23"))
158 | }
159 | }
160 |
161 | describe("test check prop with success of") {
162 |
163 | it("should ensure a success does not fail in an exception") {
164 | val propConcatLists = forAll { (a: List[Int], b: List[Int]) =>
165 | a.size + b.size should equal ((a ::: b).size)
166 | true
167 | }
168 | check(propConcatLists)
169 | }
170 |
171 | it("should ensure a failed property does throw an assertion error") {
172 | val propConcatListsBadly = forAll { (a: List[Int], b: List[Int]) =>
173 | a.size + b.size should equal ((a ::: b).size + 1)
174 | true
175 | }
176 | intercept[TestFailedException] {
177 | check(propConcatListsBadly)
178 | }
179 | }
180 |
181 | it("should ensure a property that throws an exception causes an assertion error") {
182 | val propConcatListsExceptionally = forAll { (a: List[Int], b: List[Int]) =>
183 | throw new StringIndexOutOfBoundsException
184 | true
185 | }
186 | intercept[TestFailedException] {
187 | check(propConcatListsExceptionally)
188 | }
189 | }
190 |
191 | it("should ensure a property that doesn't generate enough test cases throws an assertion error") {
192 | val propTrivial = forAll { (n: Int) =>
193 | (n == 8) ==> {
194 | n should equal (8)
195 | true
196 | }
197 | }
198 | intercept[TestFailedException] {
199 | check(propTrivial)
200 | }
201 | }
202 |
203 | it("should make sure a Generator that doesn't throw an exception works OK") {
204 | val smallIntegers = Gen.choose(0, 100)
205 | val propSmallInteger = Prop.forAll(smallIntegers) { n =>
206 | n should (be >= 0 and be <= 100)
207 | true
208 | }
209 | check(propSmallInteger)
210 |
211 | val smallEvenIntegers = Gen.choose(0, 200) suchThat (_ % 2 == 0)
212 | val propEvenInteger = Prop.forAll(smallEvenIntegers) { n =>
213 | n should (be >= 0 and be <= 200)
214 | n % 2 should equal (0)
215 | true
216 | }
217 | check(propEvenInteger)
218 | }
219 |
220 | it("should make sure a Generator t throws an exception results in an TestFailedException") {
221 | // val smallEvenIntegerWithBug = Gen.choose(0, 200) suchThat (throw new ArrayIndexOutOfBoundsException)
222 | val myArrayException = new ArrayIndexOutOfBoundsException
223 | val smallEvenIntegerWithBug = Gen.choose(0, 200) suchThat (n => throw myArrayException )
224 | val propEvenIntegerWithBuggyGen = Prop.forAll(smallEvenIntegerWithBug) { n =>
225 | n should (be >= 0 and be <= 200)
226 | n % 2 should equal (0)
227 | true
228 | }
229 | val caught1 = intercept[TestFailedException] {
230 | check(propEvenIntegerWithBuggyGen)
231 | }
232 | assert(caught1.getCause === myArrayException)
233 | }
234 |
235 | it("should make sure that I get a thrown exception back as the TFE's cause") {
236 | val myIAE = new IllegalArgumentException
237 | val caught2 = intercept[TestFailedException] {
238 | check((s: String, t: String, u: String) => throw myIAE)
239 | }
240 | assert(caught2.getCause === myIAE)
241 |
242 | val complexProp = forAll { (m: Int, n: Int) =>
243 | val res = n * m
244 | res should be >= m
245 | res should be >= n
246 | res should be < (m + n)
247 | true
248 | }
249 |
250 | intercept[GeneratorDrivenPropertyCheckFailedException] {
251 | check(complexProp)
252 | }
253 | }
254 |
255 | it("should work correctly for code shows up in the front page for ScalaTest") {
256 | import scala.collection.mutable.Stack
257 | check {
258 | (list: List[Int]) => {
259 | val stack = new Stack[Int]
260 | for (element <- list) stack.push(element)
261 | stack.iterator.toList == list.reverse
262 | }
263 | }
264 | }
265 | }
266 |
267 | }
268 |
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/test/scala/org/scalatest/check/PropertyCheckConfigurationHelperSuite.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus
17 | package scalacheck
18 |
19 | import org.scalactic.anyvals._
20 |
21 | class PropertyCheckConfigurationHelperSuite extends org.scalatest.funsuite.AnyFunSuite with org.scalatest.matchers.should.Matchers {
22 |
23 | import org.scalatestplus.scalacheck.ScalaCheckConfiguration._
24 |
25 | val DefaultMinSuccessful: PosInt = 9
26 | val PassedMinSuccessful: PosInt = 3
27 |
28 | val DefaultMinSize: PosZInt = 99
29 | val PassedMinSize: PosZInt = 33
30 |
31 | val DefaultWorkers: PosInt = 99
32 | val PassedWorkers: PosInt = 33
33 |
34 | val DefaultSizeRange: PosZInt = 0
35 | val PassedSizeRange: PosZInt = 10
36 |
37 | val DefaultMaxDiscardedFactor: PosZDouble = 1.0
38 | val PassedMaxDiscardedFactor: PosZDouble = 0.5
39 |
40 | val defaultConfig =
41 | PropertyCheckConfiguration(
42 | minSuccessful = DefaultMinSuccessful,
43 | maxDiscardedFactor = DefaultMaxDiscardedFactor,
44 | minSize = DefaultMinSize,
45 | sizeRange = DefaultSizeRange,
46 | workers = DefaultWorkers
47 | )
48 |
49 | // minSuccessful
50 | test("getScalaCheckParams returns passed minSuccessful config param") {
51 | val params = getScalaCheckParams(Seq(MinSuccessful(PassedMinSuccessful)), defaultConfig)
52 | params.minSuccessfulTests should equal (PassedMinSuccessful.value)
53 | }
54 |
55 | test("getScalaCheckParams throws IAE if passed multiple minSuccessful config params") {
56 | intercept[IllegalArgumentException] {
57 | getScalaCheckParams(Seq(MinSuccessful(33), MinSuccessful(34)), defaultConfig)
58 | }
59 | }
60 |
61 | test("getScalaCheckParams returns default minSuccessful config param if none passed") {
62 | val params = getScalaCheckParams(Seq(Workers(DefaultWorkers)), defaultConfig)
63 | params.minSuccessfulTests should equal (DefaultMinSuccessful.value)
64 | }
65 |
66 | def maxDiscardRatio(maxDiscardedTests: Int, minSuccessfulTests: Int): Float =
67 | (maxDiscardedTests: Float)/(minSuccessfulTests: Float)
68 |
69 | // maxDiscarded
70 | test("getScalaCheckParams returns passed maxDiscarded config param") {
71 | val params = getScalaCheckParams(Seq(MaxDiscardedFactor(PassedMaxDiscardedFactor)), defaultConfig)
72 | params.maxDiscardRatio should equal (PassedMaxDiscardedFactor.value)
73 | }
74 |
75 | test("getScalaCheckParams throws IAE if passed multiple maxDiscarded config params") {
76 | intercept[IllegalArgumentException] {
77 | getScalaCheckParams(Seq(MaxDiscardedFactor(33.0), MaxDiscardedFactor(34.0)), defaultConfig)
78 | }
79 | }
80 |
81 | test("getScalaCheckParams returns default maxDiscarded config param if none passed") {
82 | val params = getScalaCheckParams(Seq(MinSuccessful(PassedMinSuccessful)), defaultConfig)
83 | params.maxDiscardRatio should equal (DefaultMaxDiscardedFactor.value)
84 | }
85 |
86 | // minSize
87 | test("getScalaCheckParams returns passed minSize config param") {
88 | val params = getScalaCheckParams(Seq(MinSize(PassedMinSize)), defaultConfig)
89 | params.minSize should equal (PassedMinSize.value)
90 | }
91 |
92 | test("getScalaCheckParams throws IAE if passed multiple minSize config params") {
93 | intercept[IllegalArgumentException] {
94 | getScalaCheckParams(Seq(MinSize(33), MinSize(34)), defaultConfig)
95 | }
96 | }
97 |
98 | test("getScalaCheckParams returns default minSize config param if none passed") {
99 | val params = getScalaCheckParams(Seq(MinSuccessful(PassedMinSuccessful)), defaultConfig)
100 | params.minSize should equal (DefaultMinSize.value)
101 | }
102 |
103 | // sizeRange
104 | test("getScalaCheckParams returns passed sizeRange config param") {
105 | val params = getScalaCheckParams(Seq(SizeRange(PassedSizeRange)), defaultConfig)
106 | params.maxSize should equal (DefaultMinSize + PassedSizeRange)
107 | }
108 |
109 | test("getScalaCheckParams returns passed minSize and sizeRange config param") {
110 | val params = getScalaCheckParams(Seq(MinSize(PassedMinSize), SizeRange(PassedSizeRange)), defaultConfig)
111 | params.maxSize should equal (PassedMinSize + PassedSizeRange)
112 | }
113 |
114 | test("getScalaCheckParams throws IAE if passed multiple sizeRange config params") {
115 | intercept[IllegalArgumentException] {
116 | getScalaCheckParams(Seq(SizeRange(33), SizeRange(34)), defaultConfig)
117 | }
118 | }
119 |
120 | test("getScalaCheckParams returns default sizeRange config if none passed") {
121 | val params = getScalaCheckParams(Seq(MinSuccessful(PassedMinSuccessful)), defaultConfig)
122 | params.maxSize should equal (DefaultMinSize + DefaultSizeRange)
123 | }
124 |
125 | // workers
126 | test("getScalaCheckParams returns passed workers config param") {
127 | val params = getScalaCheckParams(Seq(Workers(PassedWorkers)), defaultConfig)
128 | params.workers should equal (PassedWorkers.value)
129 | }
130 |
131 | test("getScalaCheckParams throws IAE if passed multiple workers config params") {
132 | intercept[IllegalArgumentException] {
133 | getScalaCheckParams(Seq(Workers(33), Workers(34)), defaultConfig)
134 | }
135 | }
136 |
137 | test("getScalaCheckParams returns default workers config param if none passed") {
138 | val params = getScalaCheckParams(Seq(MinSuccessful(PassedMinSuccessful)), defaultConfig)
139 | params.workers should equal (DefaultWorkers.value)
140 | }
141 |
142 | test("getScalaCheckParams returns all default if no config params passed") {
143 | val params = getScalaCheckParams(Seq(), defaultConfig)
144 | params.minSuccessfulTests should equal (DefaultMinSuccessful.value)
145 | params.maxDiscardRatio should equal (DefaultMaxDiscardedFactor.value)
146 | params.minSize should equal (DefaultMinSize.value)
147 | params.maxSize should equal (DefaultMinSize.value + DefaultSizeRange.value)
148 | params.workers should equal (DefaultWorkers.value)
149 | }
150 |
151 | test("getScalaCheckParams returns all passed if all config params passed") {
152 | val params = getScalaCheckParams(Seq(MinSuccessful(PassedMinSuccessful), MaxDiscardedFactor(PassedMaxDiscardedFactor), MinSize(PassedMinSize),
153 | SizeRange(PassedSizeRange), Workers(PassedWorkers)), defaultConfig)
154 | params.minSuccessfulTests should equal (PassedMinSuccessful.value)
155 | params.maxDiscardRatio should equal (PassedMaxDiscardedFactor.value)
156 | params.minSize should equal (PassedMinSize.value)
157 | params.maxSize should equal (PassedMinSize.value + PassedSizeRange.value)
158 | params.workers should equal (PassedWorkers.value)
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/test/scala/org/scalatest/check/ScalaCheckDrivenPropertyChecksSpec.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2022 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.scalatestplus.scalacheck
17 |
18 | import org.scalacheck.Gen
19 | import org.scalactic.{Prettifier, SizeLimit}
20 | import org.scalatest._
21 | import org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException
22 |
23 | class ScalaCheckDrivenPropertyChecksSpec extends funspec.AnyFunSpec with ScalaCheckDrivenPropertyChecks {
24 |
25 | describe("ScalaCheckDrivnePropertyChecks") {
26 | it("should truncate argument using passed in Prettifier") {
27 | val listGen: Gen[List[Int]] = {
28 | val gens = List(Gen.chooseNum(1, 2), Gen.chooseNum(3, 4), Gen.chooseNum(5, 6))
29 | Gen.sequence[List[Int], Int](gens)
30 | }
31 |
32 | var failingList: List[Int] = null
33 | implicit val prettifer = Prettifier.truncateAt(SizeLimit(2))
34 |
35 | val e =
36 | intercept[GeneratorDrivenPropertyCheckFailedException] {
37 | forAll(listGen) { list =>
38 | failingList = list
39 | assert(list.length != 3)
40 | }
41 | }
42 |
43 | assert(e.getMessage().contains("List(" + failingList.take(2).mkString(", ") + ", ...)"))
44 | }
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/scalatestPlusScalaCheck/src/test/scala/org/scalatest/check/ScalaCheckGeneratorsSpec.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2016 Artima, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /*package org.scalatestplus.scalacheck
17 |
18 | import org.scalacheck._
19 | import org.scalatest._
20 | import Arbitrary._
21 | import Prop.{BooleanOperators => _, _}
22 | import org.scalatest.Matchers._
23 | import org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException
24 | import org.scalacheck.util.Pretty
25 | import org.scalatest.exceptions.TestFailedException
26 | import org.scalatest.prop.{PropertyChecks, Randomizer}
27 |
28 | class ScalaCheckGeneratorsSpec extends funspec.AnyFunSpec with PropertyChecks {
29 |
30 | describe("The ScalaCheckGenerators trait") {
31 | it("should provide an implicit Generator for a type given an implicit Arbitrary and Shrink for that type") {
32 | import ScalaCheckGenerators._
33 | case class Person(name: String, age: Int)
34 | val personGen: Gen[Person] =
35 | for {
36 | name <- implicitly[Arbitrary[String]].arbitrary
37 | age <- implicitly[Arbitrary[Int]].arbitrary
38 | } yield Person(name, age)
39 |
40 | implicit val personArb: Arbitrary[Person] = Arbitrary(personGen)
41 | forAll { (p: Person) =>
42 | p shouldEqual p
43 | }
44 | }
45 | }
46 |
47 |
48 | it("should be able to use a ScalaCheck Arbitary and Shrink") {
49 | import org.scalacheck.{Arbitrary, Gen, Shrink}
50 | import org.scalacheck.rng.Seed
51 | val intShrink = implicitly[Shrink[Int]]
52 | val intArbitrary = implicitly[Arbitrary[Int]]
53 | val intGen = intArbitrary.arbitrary
54 | val intGenerator = ScalaCheckGenerators.scalaCheckArbitaryGenerator(intArbitrary, intShrink)
55 | val (edges, er) = intGenerator.initEdges(100, Randomizer.default)
56 | edges should equal (Nil) // A ScalaCheck-backed generator would have no edges
57 | val scalaCheckShrinkList = intShrink.shrink(100)
58 | val (scalaTestShrinkIt, _) = intGenerator.shrink(100, Randomizer.default)
59 | val scalaTestShrinkList = scalaTestShrinkIt.toList
60 | scalaTestShrinkList shouldEqual scalaCheckShrinkList.reverse
61 | }
62 | }*/
63 |
64 |
--------------------------------------------------------------------------------