├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .jvmopts ├── LICENSE ├── README.md ├── build.sbt ├── project ├── GenResources.scala ├── GenScalaCheckGen.scala ├── build.properties ├── build.sbt └── plugins.sbt └── scalatestPlusScalaCheck ├── .js └── src │ └── main │ └── html │ └── addl.css ├── .jvm └── src │ └── main │ ├── html │ └── addl.css │ └── resources │ └── org │ └── scalatestplus │ └── scalacheck │ └── MessageBundle.properties ├── .native └── src │ └── main │ └── html │ └── addl.css └── src ├── main └── scala │ └── org │ └── scalatestplus │ └── scalacheck │ ├── CheckerAsserting.scala │ ├── Checkers.scala │ ├── ScalaCheckConfiguration.scala │ ├── ScalaCheckGenerators.scala │ ├── ScalaCheckPropertyChecks.scala │ └── UnquotedString.scala └── test └── scala └── org └── scalatest └── check ├── CheckersSpec.scala ├── PropertyCheckConfigurationHelperSuite.scala ├── ScalaCheckDrivenPropertyChecksSpec.scala └── ScalaCheckGeneratorsSpec.scala /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | - name: Setup JDK 12 | uses: actions/setup-java@v3 13 | with: 14 | distribution: temurin 15 | java-version: 8 16 | - name: Build and Test 17 | run: sbt -v +test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | target 4 | .idea/ 5 | _site/ 6 | .bsp/ -------------------------------------------------------------------------------- /.jvmopts: -------------------------------------------------------------------------------- 1 | -Xms512M 2 | -Xmx4G 3 | -Xss10M -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ScalaTest Plus ScalaCheck 2 | ScalaTest + ScalaCheck provides integration support between ScalaTest and ScalaCheck. 3 | 4 | **Usage** 5 | 6 | To use it for ScalaTest 3.2.19 and ScalaCheck 1.18.x: 7 | 8 | SBT: 9 | 10 | ``` 11 | libraryDependencies += "org.scalatestplus" %% "scalacheck-1-18" % "3.2.19.0" % "test" 12 | ``` 13 | 14 | Maven: 15 | 16 | ``` 17 | 18 | org.scalatestplus 19 | scalacheck-1-18_3 20 | 3.2.19.0 21 | test 22 | 23 | ``` 24 | 25 | For more information, please checkout our property-based testing user guide at https://www.scalatest.org/user_guide/property_based_testing . 26 | 27 | **Publishing** 28 | 29 | Please use the following commands to publish to Sonatype: 30 | 31 | ``` 32 | $ sbt clean +publishSigned 33 | ``` 34 | 35 | **Creating Scaladoc** 36 | 37 | 1. Run sbt doc: 38 | 39 | ``` 40 | > sbt doc 41 | ``` 42 | 43 | 2. Copy generated files in .jvm to main source: 44 | 45 | ``` 46 | > cp -r scalatestPlusScalaCheck/.jvm/target/scala-2.13/src_managed/main/org scalatestPlusScalaCheck/src/main/scala/ 47 | ``` 48 | 49 | 3. Comment out source generators in build.sbt under sharedSettings and scalatestPlusScalaCheck's .jvmSettings . 50 | 51 | 4. Syntax highlight the source: 52 | 53 | ``` 54 | > cd ../highlight-scaladoc 55 | > ant highlight-in-place -Dsrcdir=../scalatestplus-scalacheck/scalatestPlusScalaCheck/src/main 56 | ``` 57 | 5. Rebuild the scaladoc:: 58 | 59 | ``` 60 | > cd ../scalatestplus-scalacheck 61 | > sbt scalatestPlusScalaCheckJVM/clean scalatestPlusScalaCheckJVM/doc 62 | ``` 63 | 64 | 6. Copy out the scaladoc and add ads section: 65 | 66 | ``` 67 | > cp -r scalatestPlusScalaCheck/.jvm/target/scala-2.13/api ../scalatest-doc 68 | > cd ../scalatest-doc 69 | > ../highlight-scaladoc/scripts/add_adbutler_scalatest.sh 70 | > ../highlight-scaladoc/scripts/add_ga4_scalatest.sh 71 | ``` -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType} 2 | import scala.xml.{Node => XmlNode, NodeSeq => XmlNodeSeq, _} 3 | import scala.xml.transform.{RewriteRule, RuleTransformer} 4 | import java.io.PrintWriter 5 | import scala.io.Source 6 | 7 | val defaultScalaVersion = "2.13.13" 8 | 9 | scalaVersion := defaultScalaVersion 10 | 11 | publishTo := { 12 | val nexus = "https://oss.sonatype.org/" 13 | Some("publish-releases" at nexus + "service/local/staging/deploy/maven2") 14 | } 15 | 16 | publishArtifact := false 17 | 18 | publish := {} 19 | 20 | publishLocal := {} 21 | 22 | def docTask(docDir: File, resDir: File, projectName: String): File = { 23 | val docLibDir = docDir / "lib" 24 | val htmlSrcDir = resDir / "html" 25 | val cssFile = docLibDir / "template.css" 26 | val addlCssFile = htmlSrcDir / "addl.css" 27 | 28 | val css = Source.fromFile(cssFile).mkString 29 | val addlCss = Source.fromFile(addlCssFile).mkString 30 | 31 | if (!css.contains("pre.stHighlighted")) { 32 | val writer = new PrintWriter(cssFile) 33 | 34 | try { 35 | writer.println(css) 36 | writer.println(addlCss) 37 | } 38 | finally { writer.close } 39 | } 40 | 41 | if (projectName.contains("scalatest")) { 42 | (htmlSrcDir * "*.gif").get.foreach { gif => 43 | IO.copyFile(gif, docLibDir / gif.name) 44 | } 45 | } 46 | docDir 47 | } 48 | 49 | val sharedSettings = Seq( 50 | name := "scalacheck-1.18", 51 | organization := "org.scalatestplus", 52 | version := "3.2.19.0", 53 | homepage := Some(url("https://github.com/scalatest/scalatestplus-scalacheck")), 54 | licenses := List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")), 55 | developers := List( 56 | Developer( 57 | "bvenners", 58 | "Bill Venners", 59 | "bill@artima.com", 60 | url("https://github.com/bvenners") 61 | ), 62 | Developer( 63 | "cheeseng", 64 | "Chua Chee Seng", 65 | "cheeseng@amaseng.com", 66 | url("https://github.com/cheeseng") 67 | ) 68 | ), 69 | resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", 70 | libraryDependencies ++= Seq( 71 | "org.scalatest" %%% "scalatest-core" % "3.2.19", 72 | "org.scalacheck" %%% "scalacheck" % "1.18.0", 73 | "org.scalatest" %%% "scalatest-shouldmatchers" % "3.2.18" % "test", 74 | "org.scalatest" %%% "scalatest-funspec" % "3.2.18" % "test", 75 | "org.scalatest" %%% "scalatest-funsuite" % "3.2.18" % "test" 76 | ), 77 | // skip dependency elements with a scope 78 | pomPostProcess := { (node: XmlNode) => 79 | new RuleTransformer(new RewriteRule { 80 | override def transform(node: XmlNode): XmlNodeSeq = node match { 81 | case e: Elem if e.label == "dependency" 82 | && e.child.exists(child => child.label == "scope") => 83 | def txt(label: String): String = "\"" + e.child.filter(_.label == label).flatMap(_.text).mkString + "\"" 84 | Comment(s""" scoped dependency ${txt("groupId")} % ${txt("artifactId")} % ${txt("version")} % ${txt("scope")} has been omitted """) 85 | case _ => node 86 | } 87 | }).transform(node).head 88 | }, 89 | Compile / sourceGenerators += { 90 | Def.task { 91 | GenScalaCheckGen.genMain((Compile / sourceManaged).value / "org" / "scalatest" / "check", version.value, scalaVersion.value) 92 | } 93 | }, 94 | Test / sourceGenerators += { 95 | Def.task { 96 | GenScalaCheckGen.genTest((Test / sourceManaged).value / "org" / "scalatest" / "check", version.value, scalaVersion.value) 97 | } 98 | }, 99 | publishTo := { 100 | val nexus = "https://oss.sonatype.org/" 101 | Some("publish-releases" at nexus + "service/local/staging/deploy/maven2") 102 | }, 103 | publishMavenStyle := true, 104 | Test / publishArtifact := false, 105 | pomIncludeRepository := { _ => false }, 106 | pomExtra := ( 107 | 108 | https://github.com/scalatest/scalatestplus-scalacheck 109 | scm:git:git@github.com:scalatest/scalatestplus-scalacheck.git 110 | 111 | scm:git:git@github.com:scalatest/scalatestplus-scalacheck.git 112 | 113 | 114 | ), 115 | credentials += Credentials(Path.userHome / ".ivy2" / ".credentials"), 116 | Compile / doc := docTask((Compile / doc).value, 117 | (Compile / sourceDirectory).value, 118 | name.value), 119 | Compile / doc / scalacOptions := { 120 | if (scalaBinaryVersion.value startsWith "3") 121 | Seq.empty 122 | else 123 | Seq("-doc-title", s"ScalaTest + ScalaCheck ${version.value}", 124 | "-sourcepath", baseDirectory.value.getParentFile().getAbsolutePath(), 125 | "-doc-source-url", s"https://github.com/scalatest/releases-source/blob/main/scalatestplus-scalacheck/${version.value}€{FILE_PATH}.scala") 126 | }, 127 | Compile / packageDoc / publishArtifact := { 128 | if (scalaBinaryVersion.value startsWith "3") 129 | false // Temporary disable publishing of doc in dotty, can't get it to build. 130 | else 131 | true 132 | } 133 | ) 134 | 135 | lazy val scalatestPlusScalaCheck = 136 | // select supported platforms 137 | crossProject(JSPlatform, JVMPlatform, NativePlatform) 138 | .crossType(CrossType.Pure) // [Pure, Full, Dummy], default: CrossType.Full 139 | .settings(sharedSettings) 140 | .enablePlugins(SbtOsgi) 141 | .settings(osgiSettings: _*).settings( 142 | scalaVersion := defaultScalaVersion, 143 | crossScalaVersions := List("2.12.19", defaultScalaVersion, "3.3.3"), 144 | OsgiKeys.exportPackage := Seq( 145 | "org.scalatestplus.scalacheck.*" 146 | ), 147 | OsgiKeys.importPackage := Seq( 148 | "org.scalatest.*", 149 | "org.scalactic.*", 150 | "scala.*;version=\"$>\"", 151 | "*;resolution:=optional" 152 | ), 153 | OsgiKeys.additionalHeaders:= Map( 154 | "Bundle-Name" -> "ScalaTestPlusScalaCheck", 155 | "Bundle-Description" -> "ScalaTest+ScalaCheck is an open-source integration library between ScalaTest and ScalaCheck for Scala projects.", 156 | "Bundle-DocURL" -> "http://www.scalacheck.org/", 157 | "Bundle-Vendor" -> "Artima, Inc." 158 | ) 159 | ) 160 | .jsSettings( 161 | Compile / sourceGenerators += { 162 | Def.task { 163 | GenResourcesJSVM.genResources((Compile / sourceManaged).value / "org" / "scalatestplus" / "scalacheck", version.value, scalaVersion.value) ++ 164 | GenResourcesJSVM.genFailureMessages((Compile / sourceManaged).value / "org" / "scalatestplus" / "scalacheck", version.value, scalaVersion.value) 165 | } 166 | } 167 | ) 168 | .jvmSettings( 169 | Compile / sourceGenerators += { 170 | Def.task { 171 | GenResourcesJVM.genResources((Compile / sourceManaged).value / "org" / "scalatestplus" / "scalacheck", version.value, scalaVersion.value) ++ 172 | GenResourcesJVM.genFailureMessages((Compile / sourceManaged).value / "org" / "scalatestplus" / "scalacheck", version.value, scalaVersion.value) 173 | } 174 | } 175 | ) 176 | .nativeSettings( 177 | Compile / sourceGenerators += { 178 | Def.task { 179 | GenResourcesJSVM.genResources((Compile / sourceManaged).value / "org" / "scalatestplus" / "scalacheck", version.value, scalaVersion.value) ++ 180 | GenResourcesJSVM.genFailureMessages((Compile / sourceManaged).value / "org" / "scalatestplus" / "scalacheck", version.value, scalaVersion.value) 181 | } 182 | } 183 | ) 184 | 185 | lazy val scalatestPlusScalaCheckJS = scalatestPlusScalaCheck.js 186 | lazy val scalatestPlusScalaCheckJVM = scalatestPlusScalaCheck.jvm 187 | lazy val scalatestPlusScalaCheckNative = scalatestPlusScalaCheck.native 188 | -------------------------------------------------------------------------------- /project/GenResources.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2001-2015 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 | 17 | import java.io._ 18 | import scala.io.Source 19 | import scala.util.parsing.combinator.JavaTokenParsers 20 | 21 | trait GenResources { 22 | 23 | val generatorSource = new File("GenResources.scala") 24 | 25 | def packageName: String = "scalacheck" 26 | 27 | def resourcesTemplate(methods: String): String 28 | 29 | def failureMessagesTemplate(methods: String): String 30 | 31 | def resourcesKeyValueTemplate(kv: KeyValue, paramCount: Int): String 32 | 33 | def failureMessagesKeyValueTemplate(kv: KeyValue, paramCount: Int): String 34 | 35 | def propertiesFile: File = new File("scalatestPlusScalaCheck/.jvm/src/main/resources/org/scalatestplus/scalacheck/MessageBundle.properties") 36 | 37 | val paramRegex = "\\{\\d+\\}".r 38 | 39 | case class KeyValue(key: String, value: String) 40 | 41 | object KeyValueParser extends JavaTokenParsers { 42 | def equalParser: Parser[String] = "=" 43 | def keyParser: Parser[String] = """([\p{L}_$][\p{L}\p{N}_$]*\.)*[\p{L}_$][\p{L}\p{N}_$]*""".r // use Java class name parser for now for key 44 | def valueParser: Parser[String] = ".*".r 45 | def keyValueParser: Parser[KeyValue] = keyParser ~ equalParser ~ valueParser ^^ { 46 | case ~(~(key, _), value) => KeyValue(key, value) 47 | } 48 | def parse(s: String): KeyValue = 49 | parseAll(keyValueParser, s) match { 50 | case Success(kv, _) => kv 51 | case other => throw new RuntimeException("invalid key value syntax: " + s) 52 | } 53 | } 54 | 55 | def genResources(targetDir: File, version: String, scalaVersion: String): Seq[File] = { 56 | targetDir.mkdirs() 57 | 58 | val sourcePropertiesFile = propertiesFile 59 | val lines = Source.fromFile(sourcePropertiesFile).getLines 60 | 61 | val resourcesMethods = 62 | lines.filter(!_.trim.isEmpty).map { line => 63 | val kv = KeyValueParser.parse(line) 64 | val paramTokens = paramRegex.findAllIn(kv.value) 65 | val paramCount = if (paramTokens.isEmpty) 0 else paramTokens.map(t => t.substring(1, t.length - 1).toInt).max + 1 66 | resourcesKeyValueTemplate(kv, paramCount) 67 | }.mkString("\n\n") 68 | 69 | val resourcesFile = new File(targetDir, "Resources.scala") 70 | if (!resourcesFile.exists || generatorSource.lastModified > resourcesFile.lastModified) { 71 | val resourcesWriter = new BufferedWriter(new FileWriter(resourcesFile)) 72 | try { 73 | resourcesWriter.write(resourcesTemplate(resourcesMethods)) 74 | } 75 | finally { 76 | resourcesWriter.flush() 77 | resourcesWriter.close() 78 | println("Generated " + resourcesFile.getAbsolutePath) 79 | } 80 | } 81 | 82 | Vector(resourcesFile) 83 | } 84 | 85 | def genFailureMessages(targetDir: File, version: String, scalaVersion: String): Seq[File] = { 86 | targetDir.mkdirs() 87 | 88 | val sourcePropertiesFile = propertiesFile 89 | val lines = Source.fromFile(sourcePropertiesFile).getLines 90 | 91 | val failureMessagesMethods = 92 | lines.filter(!_.trim.isEmpty).map { line => 93 | val kv = KeyValueParser.parse(line) 94 | val paramTokens = paramRegex.findAllIn(kv.value) 95 | val paramCount = if (paramTokens.isEmpty) 0 else paramTokens.map(t => t.substring(1, t.length - 1).toInt).max + 1 96 | failureMessagesKeyValueTemplate(kv, paramCount) 97 | }.mkString("\n\n") 98 | 99 | val failureMessagesFile = new File(targetDir, "FailureMessages.scala") 100 | if (!failureMessagesFile.exists || generatorSource.lastModified > failureMessagesFile.lastModified) { 101 | val failureMessagesWriter = new BufferedWriter(new FileWriter(failureMessagesFile)) 102 | try { 103 | failureMessagesWriter.write(failureMessagesTemplate(failureMessagesMethods)) 104 | } 105 | finally { 106 | failureMessagesWriter.flush() 107 | failureMessagesWriter.close() 108 | println("Generated " + failureMessagesFile.getAbsolutePath) 109 | } 110 | } 111 | 112 | Vector(failureMessagesFile) 113 | } 114 | 115 | } 116 | 117 | object GenResourcesJVM extends GenResources { 118 | 119 | def resourcesTemplate(methods: String): String = 120 | s"""package org.scalatestplus.$packageName 121 | | 122 | |import java.util.ResourceBundle 123 | |import java.text.MessageFormat 124 | | 125 | |private[$packageName] object Resources { 126 | | 127 | |lazy val resourceBundle = ResourceBundle.getBundle("org.scalatestplus.scalacheck.MessageBundle") 128 | | 129 | |def makeString(resourceName: String, args: Array[Any]): String = { 130 | | val raw = resourceBundle.getString(resourceName) 131 | | formatString(raw, args) 132 | |} 133 | | 134 | |def formatString(rawString: String, args: Array[Any]): String = { 135 | | val msgFmt = new MessageFormat(rawString) 136 | | msgFmt.format(args.toArray) 137 | |} 138 | | 139 | |$methods 140 | | 141 | |def bigProblems(ex: Throwable): String = { 142 | | val message = if (ex.getMessage == null) "" else ex.getMessage.trim 143 | | if (message.length > 0) Resources.bigProblemsWithMessage(message) else Resources.bigProblems() 144 | |} 145 | |} 146 | """.stripMargin 147 | 148 | def failureMessagesTemplate(methods: String): String = 149 | s"""package org.scalatestplus.$packageName 150 | | 151 | |private[$packageName] object FailureMessages { 152 | | 153 | |def decorateToStringValue(prettifier: org.scalactic.Prettifier, o: Any): String = prettifier.apply(o) 154 | | 155 | |$methods 156 | | 157 | |} 158 | """.stripMargin 159 | 160 | def resourcesKeyValueTemplate(kv: KeyValue, paramCount: Int): String = 161 | ( 162 | if (paramCount > 0) 163 | "def " + kv.key + "(" + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = makeString(\"" + kv.key + "\", Array(" + (for (i <- 0 until paramCount) yield s"param$i").mkString(", ") + "))" 164 | else 165 | "def " + kv.key + "(): String = resourceBundle.getString(\"" + kv.key + "\")" 166 | ) + "\n\n" + 167 | "def raw" + kv.key.capitalize + ": String = resourceBundle.getString(\"" + kv.key + "\")" 168 | 169 | def failureMessagesKeyValueTemplate(kv: KeyValue, paramCount: Int): String = 170 | "def " + kv.key + (if (paramCount == 0) "(" else "(prettifier: org.scalactic.Prettifier, ") + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = Resources." + kv.key + "(" + (for (i <- 0 until paramCount) yield s"prettifier.apply(param$i)").mkString(", ") + ")" 171 | 172 | } 173 | 174 | object GenResourcesJSVM extends GenResources { 175 | 176 | def resourcesTemplate(methods: String): String = 177 | s"""package org.scalatestplus.$packageName 178 | | 179 | |private[$packageName] object Resources { 180 | | 181 | |def formatString(rawString: String, args: Array[Any]): String = { 182 | | args.zipWithIndex.foldLeft(rawString) { case (result, (arg, idx)) => 183 | | result.replaceAllLiterally("{" + idx + "}", arg.toString()) 184 | | } 185 | |} 186 | | 187 | |$methods 188 | | 189 | |def bigProblems(ex: Throwable): String = { 190 | | val message = if (ex.getMessage == null) "" else ex.getMessage.trim 191 | | if (message.length > 0) Resources.bigProblemsWithMessage(message) else Resources.bigProblems() 192 | |} 193 | |} 194 | """.stripMargin 195 | 196 | def failureMessagesTemplate(methods: String): String = 197 | s"""package org.scalatestplus.$packageName 198 | | 199 | |private[$packageName] object FailureMessages { 200 | | 201 | |def decorateToStringValue(prettifier: org.scalactic.Prettifier, o: Any): String = prettifier.apply(o) 202 | | 203 | |$methods 204 | | 205 | |} 206 | """.stripMargin 207 | 208 | def resourcesKeyValueTemplate(kv: KeyValue, paramCount: Int): String = 209 | "final val raw" + kv.key.capitalize + " = \"" + kv.value.replaceAllLiterally("\"", "\\\"").replaceAllLiterally("''", "'") + "\"\n\n" + 210 | ( 211 | if (paramCount == 0 ) 212 | "final def " + kv.key + "() = raw" + kv.key.capitalize 213 | else 214 | "def " + kv.key + "(" + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = \n" + 215 | " raw" + kv.key.capitalize + (for (i <- 0 until paramCount) yield ".replaceAllLiterally(\"{" + i + "}\", param" + i + ".toString())").mkString + "\n" 216 | /*"object " + kv.key + " { \ndef apply(" + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = \n" + 217 | " raw" + kv.key.capitalize + (for (i <- 0 until paramCount) yield ".replaceAllLiterally(\"{" + i + "}\", param" + i + " + \"\")").mkString + "\n" + 218 | "}"*/ 219 | ) 220 | /*"def " + kv.key + "(" + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = \n" + 221 | " raw" + kv.key.capitalize + (for (i <- 0 until paramCount) yield ".replaceAllLiterally(\"{" + i + "}\", param" + i + " + \"\")").mkString + "\n\n" + 222 | "val raw" + kv.key.capitalize + ": String = \"" + kv.value.replaceAllLiterally("\"", "\\\"") + "\""*/ 223 | 224 | def failureMessagesKeyValueTemplate(kv: KeyValue, paramCount: Int): String = 225 | if (paramCount == 0) 226 | "final def " + kv.key + "() = Resources." + kv.key + "()" 227 | else 228 | "object " + kv.key + " { \ndef apply(" + (if (paramCount == 0) "" else "prettifier: org.scalactic.Prettifier, ") + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = \n" + 229 | " Resources." + kv.key + "(" + (for (i <- 0 until paramCount) yield s"decorateToStringValue(prettifier, param$i)").mkString(", ") + ")" + "\n" + 230 | "}" 231 | //"def " + kv.key + "(" + (for (i <- 0 until paramCount) yield s"param$i: Any").mkString(", ") + "): String = Resources." + kv.key + "(" + (for (i <- 0 until paramCount) yield s"decorateToStringValue(param$i)").mkString(", ") + ")" 232 | 233 | } 234 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.5.8 2 | -------------------------------------------------------------------------------- /project/build.sbt: -------------------------------------------------------------------------------- 1 | libraryDependencies += "org.antlr" % "stringtemplate" % "3.2" -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") 2 | 3 | addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.0.0") 4 | 5 | val scalaJSVersion = Option(System.getenv("SCALAJS_VERSION")).getOrElse("1.16.0") 6 | 7 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJSVersion) 8 | 9 | addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.1") 10 | 11 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1") 12 | 13 | addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") 14 | -------------------------------------------------------------------------------- /scalatestPlusScalaCheck/.js/src/main/html/addl.css: -------------------------------------------------------------------------------- 1 | 2 | pre.stExamples { 3 | background-color: #1b3449; 4 | padding: 10px; 5 | color: white; 6 | } 7 | 8 | pre.stREPL { 9 | background-color: #1b3449; 10 | padding: 10px; 11 | color: white; 12 | } 13 | 14 | .stYellow { 15 | color: #cfc923; 16 | } 17 | 18 | .stCyan { 19 | color: #00dddd; 20 | } 21 | 22 | .stGreen { 23 | color: #00cc00; 24 | } 25 | 26 | .stRed { 27 | color: #dd2233; 28 | } 29 | 30 | pre.stHighlighted { 31 | font-family: "Lucida Console", Monaco, monospace; 32 | font-size: 95%; 33 | line-height: 110%; 34 | padding: 10px; 35 | background-color: #ecedec; 36 | color: black; 37 | text-align: left; 38 | } 39 | 40 | pre.stGray { 41 | font-family: "Lucida Console", Monaco, monospace; 42 | font-size: 95%; 43 | line-height: 110%; 44 | padding: 10px; 45 | background-color: #ecedec; 46 | color: black; 47 | text-align: left; 48 | } 49 | 50 | .stType { 51 | color: #418da7; 52 | } 53 | 54 | .stLiteral { 55 | color: #2b875e; 56 | } 57 | 58 | .stQuotedString { 59 | color: #2b875e; 60 | } 61 | 62 | .stReserved { 63 | color: #00008b; 64 | } 65 | 66 | .stBlockComment, .stLineComment { 67 | color: gray; 68 | font-style: italic; 69 | } 70 | 71 | table.stTable { 72 | border-collapse: collapse; 73 | border: 1px solid black; 74 | } 75 | 76 | th.stHeadingCell { 77 | background-color: #CCCCCC; 78 | border-width: 1px; 79 | padding: 3px; 80 | text-align: center; 81 | border: 1px solid black; 82 | } 83 | 84 | td.stTableCell { 85 | border-width: 1px; 86 | padding: 3px; 87 | text-align: center; 88 | border: 1px solid black; 89 | } 90 | 91 | td.usage { 92 | background-color: #EEEEEE; 93 | border-width: 1px; 94 | padding: 0.5em; 95 | border: 1px solid black; 96 | } 97 | 98 | img.stScreenShot { 99 | border:1px solid #333; 100 | } 101 | -------------------------------------------------------------------------------- /scalatestPlusScalaCheck/.jvm/src/main/html/addl.css: -------------------------------------------------------------------------------- 1 | 2 | pre.stExamples { 3 | background-color: #1b3449; 4 | padding: 10px; 5 | color: white; 6 | } 7 | 8 | pre.stREPL { 9 | background-color: #1b3449; 10 | padding: 10px; 11 | color: white; 12 | } 13 | 14 | .stYellow { 15 | color: #cfc923; 16 | } 17 | 18 | .stCyan { 19 | color: #00dddd; 20 | } 21 | 22 | .stGreen { 23 | color: #00cc00; 24 | } 25 | 26 | .stRed { 27 | color: #dd2233; 28 | } 29 | 30 | pre.stHighlighted { 31 | font-family: "Lucida Console", Monaco, monospace; 32 | font-size: 95%; 33 | line-height: 110%; 34 | padding: 10px; 35 | background-color: #ecedec; 36 | color: black; 37 | text-align: left; 38 | } 39 | 40 | pre.stGray { 41 | font-family: "Lucida Console", Monaco, monospace; 42 | font-size: 95%; 43 | line-height: 110%; 44 | padding: 10px; 45 | background-color: #ecedec; 46 | color: black; 47 | text-align: left; 48 | } 49 | 50 | .stType { 51 | color: #418da7; 52 | } 53 | 54 | .stLiteral { 55 | color: #2b875e; 56 | } 57 | 58 | .stQuotedString { 59 | color: #2b875e; 60 | } 61 | 62 | .stReserved { 63 | color: #00008b; 64 | } 65 | 66 | .stBlockComment, .stLineComment { 67 | color: gray; 68 | font-style: italic; 69 | } 70 | 71 | table.stTable { 72 | border-collapse: collapse; 73 | border: 1px solid black; 74 | } 75 | 76 | th.stHeadingCell { 77 | background-color: #CCCCCC; 78 | border-width: 1px; 79 | padding: 3px; 80 | text-align: center; 81 | border: 1px solid black; 82 | } 83 | 84 | td.stTableCell { 85 | border-width: 1px; 86 | padding: 3px; 87 | text-align: center; 88 | border: 1px solid black; 89 | } 90 | 91 | td.usage { 92 | background-color: #EEEEEE; 93 | border-width: 1px; 94 | padding: 0.5em; 95 | border: 1px solid black; 96 | } 97 | 98 | img.stScreenShot { 99 | border:1px solid #333; 100 | } 101 | -------------------------------------------------------------------------------- /scalatestPlusScalaCheck/.jvm/src/main/resources/org/scalatestplus/scalacheck/MessageBundle.properties: -------------------------------------------------------------------------------- 1 | propCheckLabel=Label of failing property: 2 | propCheckLabels=Labels of failing property: 3 | propertyException={0} was thrown during property evaluation. 4 | propCheckExhausted=Gave up after {0} successful property evaluations. {1} evaluations were discarded. 5 | propCheckExhaustedAfterOne=Gave up after 1 successful property evaluation. {0} evaluations were discarded. 6 | propertyFailed=Falsified after {0} successful property evaluations. 7 | propertyCheckSucceeded=Property check succeeded 8 | thrownExceptionsLocation=Location: ({0}) 9 | occurredOnValues=Occurred when passed generated values ( 10 | thrownExceptionsMessage=Message: {0} 11 | bigProblems=An exception or error caused a run to abort. 12 | bigProblemsWithMessage=An exception or error caused a run to abort: {0} 13 | initSeed=Init Seed: {0} -------------------------------------------------------------------------------- /scalatestPlusScalaCheck/.native/src/main/html/addl.css: -------------------------------------------------------------------------------- 1 | 2 | pre.stExamples { 3 | background-color: #1b3449; 4 | padding: 10px; 5 | color: white; 6 | } 7 | 8 | pre.stREPL { 9 | background-color: #1b3449; 10 | padding: 10px; 11 | color: white; 12 | } 13 | 14 | .stYellow { 15 | color: #cfc923; 16 | } 17 | 18 | .stCyan { 19 | color: #00dddd; 20 | } 21 | 22 | .stGreen { 23 | color: #00cc00; 24 | } 25 | 26 | .stRed { 27 | color: #dd2233; 28 | } 29 | 30 | pre.stHighlighted { 31 | font-family: "Lucida Console", Monaco, monospace; 32 | font-size: 95%; 33 | line-height: 110%; 34 | padding: 10px; 35 | background-color: #ecedec; 36 | color: black; 37 | text-align: left; 38 | } 39 | 40 | pre.stGray { 41 | font-family: "Lucida Console", Monaco, monospace; 42 | font-size: 95%; 43 | line-height: 110%; 44 | padding: 10px; 45 | background-color: #ecedec; 46 | color: black; 47 | text-align: left; 48 | } 49 | 50 | .stType { 51 | color: #418da7; 52 | } 53 | 54 | .stLiteral { 55 | color: #2b875e; 56 | } 57 | 58 | .stQuotedString { 59 | color: #2b875e; 60 | } 61 | 62 | .stReserved { 63 | color: #00008b; 64 | } 65 | 66 | .stBlockComment, .stLineComment { 67 | color: gray; 68 | font-style: italic; 69 | } 70 | 71 | table.stTable { 72 | border-collapse: collapse; 73 | border: 1px solid black; 74 | } 75 | 76 | th.stHeadingCell { 77 | background-color: #CCCCCC; 78 | border-width: 1px; 79 | padding: 3px; 80 | text-align: center; 81 | border: 1px solid black; 82 | } 83 | 84 | td.stTableCell { 85 | border-width: 1px; 86 | padding: 3px; 87 | text-align: center; 88 | border: 1px solid black; 89 | } 90 | 91 | td.usage { 92 | background-color: #EEEEEE; 93 | border-width: 1px; 94 | padding: 0.5em; 95 | border: 1px solid black; 96 | } 97 | 98 | img.stScreenShot { 99 | border:1px solid #333; 100 | } 101 | -------------------------------------------------------------------------------- /scalatestPlusScalaCheck/src/main/scala/org/scalatestplus/scalacheck/CheckerAsserting.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.scalactic.{FailureMessages => _, Resources => _, UnquotedString => _, _} 19 | import NameUtil.getSimpleNameOfAnObjectsClass 20 | import org.scalacheck.Prop 21 | import org.scalacheck.Prop.Arg 22 | import org.scalacheck.Test 23 | import org.scalacheck.util.Pretty 24 | import org.scalatest.Assertion 25 | 26 | import scala.collection.mutable 27 | //import org.scalatest.Expectation 28 | import org.scalatest.Fact 29 | import org.scalatest.Succeeded 30 | import org.scalatest.exceptions.StackDepthException 31 | import org.scalatestplus.scalacheck.FailureMessages.decorateToStringValue 32 | import org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException 33 | import org.scalatest.exceptions.StackDepth 34 | import scala.util.Try 35 | import scala.annotation.tailrec 36 | 37 | /** 38 | * Supertrait for 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 | *

45 | */ 46 | trait CheckerAsserting[T] { 47 | /** 48 | * The result type of the 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 | *

38 | *
 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 | *

59 | *
 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 | *

70 | * 71 | *

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 | *

79 | * 80 | *

Property check configuration

81 | * 82 | *

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 | *

87 | * 88 | * 89 | * 90 | * 93 | * 96 | * 99 | * 100 | * 101 | * 104 | * 107 | * 110 | * 111 | * 112 | * 115 | * 118 | * 121 | * 122 | * 123 | * 126 | * 129 | * 132 | * 133 | * 134 | * 137 | * 140 | * 143 | * 144 | * 145 | * 148 | * 151 | * 154 | * 155 | *
91 | * Configuration Parameter 92 | * 94 | * Default Value 95 | * 97 | * Meaning 98 | *
102 | * minSuccessful 103 | * 105 | * 100 106 | * 108 | * the minimum number of successful property evaluations required for the property to pass 109 | *
113 | * maxDiscarded 114 | * 116 | * 500 117 | * 119 | * the maximum number of discarded property evaluations allowed during a property check 120 | *
124 | * minSize 125 | * 127 | * 0 128 | * 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 | *
135 | * maxSize 136 | * 138 | * 100 139 | * 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 | *
146 | * workers 147 | * 149 | * 1 150 | * 152 | * specifies the number of worker threads to use during property evaluation 153 | *
156 | * 157 | *

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 | *

189 | * 190 | *
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 | *

199 | * 200 | *
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 | *

209 | * 210 | *
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 | *

222 | * 223 | * @author Bill Venners 224 | */ 225 | trait Checkers extends ScalaCheckConfiguration { 226 | 227 | private val asserting: CheckerAsserting[Assertion] { type Result = Assertion } = CheckerAsserting.assertingNatureOfAssertion 228 | 229 | /** 230 | * Convert the passed 1-arg function into a property, and check it. 231 | * 232 | * @param f the function to be converted into a property and checked 233 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 234 | */ 235 | def check[A1, P](f: A1 => P, configParams: PropertyCheckConfigParam*) 236 | (implicit 237 | config: PropertyCheckConfiguration, 238 | p: P => Prop, 239 | a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, 240 | prettifier: Prettifier, 241 | pos: source.Position 242 | ): Assertion = { 243 | val params = getScalaCheckParams(configParams, config) 244 | asserting.check(Prop.forAll(f)(p, a1, s1, pp1), params, prettifier, pos) 245 | } 246 | 247 | /** 248 | * Convert the passed 2-arg function into a property, and check it. 249 | * 250 | * @param f the function to be converted into a property and checked 251 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 252 | */ 253 | def check[A1, A2, P](f: (A1,A2) => P, configParams: PropertyCheckConfigParam*) 254 | (implicit 255 | config: PropertyCheckConfiguration, 256 | p: P => Prop, 257 | a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, 258 | a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, 259 | prettifier: Prettifier, 260 | pos: source.Position 261 | ): Assertion = { 262 | val params = getScalaCheckParams(configParams, config) 263 | asserting.check(Prop.forAll(f)(p, a1, s1, pp1, a2, s2, pp2), params, prettifier, pos) 264 | } 265 | 266 | /** 267 | * Convert the passed 3-arg function into a property, and check it. 268 | * 269 | * @param f the function to be converted into a property and checked 270 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 271 | */ 272 | def check[A1, A2, A3, P](f: (A1,A2,A3) => P, configParams: PropertyCheckConfigParam*) 273 | (implicit 274 | config: PropertyCheckConfiguration, 275 | p: P => Prop, 276 | a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, 277 | a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, 278 | a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, 279 | prettifier: Prettifier, 280 | pos: source.Position 281 | ): Assertion = { 282 | val params = getScalaCheckParams(configParams, config) 283 | asserting.check(Prop.forAll(f)(p, a1, s1, pp1, a2, s2, pp2, a3, s3, pp3), params, prettifier, pos) 284 | } 285 | 286 | /** 287 | * Convert the passed 4-arg function into a property, and check it. 288 | * 289 | * @param f the function to be converted into a property and checked 290 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 291 | */ 292 | def check[A1, A2, A3, A4, P](f: (A1,A2,A3,A4) => P, configParams: PropertyCheckConfigParam*) 293 | (implicit 294 | config: PropertyCheckConfiguration, 295 | p: P => Prop, 296 | a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, 297 | a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, 298 | a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, 299 | a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, 300 | prettifier: Prettifier, 301 | pos: source.Position 302 | ): Assertion = { 303 | val params = getScalaCheckParams(configParams, config) 304 | asserting.check(Prop.forAll(f)(p, a1, s1, pp1, a2, s2, pp2, a3, s3, pp3, a4, s4, pp4), params, prettifier, pos) 305 | } 306 | 307 | /** 308 | * Convert the passed 5-arg function into a property, and check it. 309 | * 310 | * @param f the function to be converted into a property and checked 311 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 312 | */ 313 | def check[A1, A2, A3, A4, A5, P](f: (A1,A2,A3,A4,A5) => P, configParams: PropertyCheckConfigParam*) 314 | (implicit 315 | config: PropertyCheckConfiguration, 316 | p: P => Prop, 317 | a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, 318 | a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, 319 | a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, 320 | a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, 321 | a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty, 322 | prettifier: Prettifier, 323 | pos: source.Position 324 | ): Assertion = { 325 | val params = getScalaCheckParams(configParams, config) 326 | asserting.check(Prop.forAll(f)(p, a1, s1, pp1, a2, s2, pp2, a3, s3, pp3, a4, s4, pp4, a5, s5, pp5), params, prettifier, pos) 327 | } 328 | 329 | /** 330 | * Convert the passed 6-arg function into a property, and check it. 331 | * 332 | * @param f the function to be converted into a property and checked 333 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 334 | */ 335 | def check[A1, A2, A3, A4, A5, A6, P](f: (A1,A2,A3,A4,A5,A6) => P, configParams: PropertyCheckConfigParam*) 336 | (implicit 337 | config: PropertyCheckConfiguration, 338 | p: P => Prop, 339 | a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, 340 | a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, 341 | a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, 342 | a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, 343 | a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty, 344 | a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty, 345 | prettifier: Prettifier, 346 | pos: source.Position 347 | ): Assertion = { 348 | val params = getScalaCheckParams(configParams, config) 349 | asserting.check(Prop.forAll(f)(p, a1, s1, pp1, a2, s2, pp2, a3, s3, pp3, a4, s4, pp4, a5, s5, pp5, a6, s6, pp6), params, prettifier, pos) 350 | } 351 | 352 | /** 353 | * Check a property with the given testing parameters. 354 | * 355 | * @param p the property to check 356 | * @param prms the test parameters 357 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 358 | */ 359 | def check(p: Prop, prms: Test.Parameters)(implicit prettifier: Prettifier, pos: source.Position): Assertion = { 360 | asserting.check(p, prms, prettifier, pos) 361 | } 362 | 363 | /** 364 | * Check a property. 365 | * 366 | * @param p the property to check 367 | * @throws TestFailedException if a test case is discovered for which the property doesn't hold. 368 | */ 369 | def check(p: Prop, configParams: PropertyCheckConfigParam*)(implicit config: PropertyCheckConfiguration, prettifier: Prettifier, pos: source.Position): Assertion = { 370 | val params = getScalaCheckParams(configParams, config) 371 | asserting.check(p, params, prettifier, pos) 372 | } 373 | } 374 | 375 | /** 376 | * Companion object that facilitates the importing of 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 | *

404 | * 405 | *
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 | *

30 | * 31 | *

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 | *

35 | * 36 | *
 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 | *

54 | * 55 | *
 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 | *

79 | * 80 | *
 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 | --------------------------------------------------------------------------------