├── .github └── workflows │ └── maven.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── notes.txt ├── pom.xml ├── src ├── changes │ └── changes.xml ├── it │ ├── it-parent │ │ └── pom.xml │ ├── lift │ │ ├── pom.xml │ │ ├── src │ │ │ ├── main │ │ │ │ ├── scala │ │ │ │ │ ├── bootstrap │ │ │ │ │ │ └── liftweb │ │ │ │ │ │ │ └── Boot.scala │ │ │ │ │ └── demo │ │ │ │ │ │ └── helloworld │ │ │ │ │ │ ├── comet │ │ │ │ │ │ └── .keep │ │ │ │ │ │ ├── model │ │ │ │ │ │ └── .keep │ │ │ │ │ │ ├── snippet │ │ │ │ │ │ ├── .keep │ │ │ │ │ │ └── HelloWorld.scala │ │ │ │ │ │ └── view │ │ │ │ │ │ └── .keep │ │ │ │ └── webapp │ │ │ │ │ ├── WEB-INF │ │ │ │ │ └── web.xml │ │ │ │ │ ├── index.html │ │ │ │ │ └── templates-hidden │ │ │ │ │ └── default.html │ │ │ └── test │ │ │ │ └── scala │ │ │ │ ├── LiftConsole.scala │ │ │ │ ├── RunWebApp.scala │ │ │ │ └── demo │ │ │ │ └── helloworld │ │ │ │ └── AppTest.scala │ │ └── verify.groovy │ ├── manual │ │ └── gui │ │ │ └── pom.xml │ ├── no-scalatest-ignore │ │ ├── pom.xml │ │ └── verify.groovy │ ├── redirect-output │ │ ├── README.md │ │ ├── invoker.properties │ │ ├── pom.xml │ │ ├── src │ │ │ ├── main │ │ │ │ └── scala │ │ │ │ │ └── org │ │ │ │ │ └── example │ │ │ │ │ └── App.scala │ │ │ └── test │ │ │ │ └── scala │ │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── AppTest.scala │ │ └── verify.groovy │ ├── settings.xml │ └── spaces in path │ │ ├── README.md │ │ ├── invoker.properties │ │ ├── pom.xml │ │ ├── src │ │ ├── main │ │ │ └── scala │ │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── App.scala │ │ └── test │ │ │ └── scala │ │ │ └── org │ │ │ └── example │ │ │ └── AppTest.scala │ │ └── verify.groovy ├── main │ ├── java │ │ └── org │ │ │ └── scalatest │ │ │ └── tools │ │ │ └── maven │ │ │ ├── AbstractScalaTestMojo.java │ │ │ ├── MojoUtils.java │ │ │ ├── ReporterMojo.java │ │ │ └── TestMojo.java │ └── resources │ │ └── mojoResources.properties ├── site │ ├── apt │ │ └── usage.apt │ └── site.xml └── test │ └── scala │ └── org │ └── scalatest │ └── tools │ └── maven │ ├── MojoUtilsTest.scala │ ├── PluginMatchers.scala │ └── PluginTest.scala └── stale_outputs_checked /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: scalatest-maven-plugin 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | verify: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - name: git 12 | uses: actions/checkout@v2 13 | 14 | - name: java 15 | uses: actions/setup-java@v3 16 | with: 17 | java-version: '8' 18 | distribution: 'temurin' 19 | 20 | - name: maven 21 | run: mvn -B clean verify --file pom.xml 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | # Editor files 4 | .dir-locals.el 5 | 6 | # IDE files 7 | .idea/ 8 | *.iml 9 | 10 | pom.xml.asc 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | sudo: false 4 | 5 | jdk: 6 | - oraclejdk8 7 | 8 | cache: 9 | directories: 10 | - $HOME/.m2 11 | 12 | # skip mvn install 13 | install: true 14 | 15 | script: mvn clean package invoker:install invoker:run 16 | -------------------------------------------------------------------------------- /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, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ScalaTest Maven Plugin 2 | ====================== 3 | 4 | Building ScalaTest Maven Plugin 5 | ------------------------------- 6 | 7 | Maven 3 is used to manage the build process. To build this plugin, please make sure you have the following installed:- 8 | 9 | * The Git command line tools 10 | * A recent JDK (the [current Oracle JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html) is recommended) 11 | * Maven 3 (http://maven.apache.org/download.html) 12 | 13 | You then clone and checkout master trunk:- 14 | 15 | $ git clone git://github.com/scalatest/scalatest-maven-plugin.git 16 | 17 | $ cd scalatest-maven-plugin 18 | 19 | Finally use the following commands to build for ScalaTest Maven Plugin: 20 | 21 | $ mvn clean package 22 | 23 | The built output will be available in target/. 24 | 25 | Using ScalaTest Maven Plugin 26 | ---------------------------- 27 | 28 | To use the ScalaTest Maven plugin, you need to disable SureFire and enable ScalaTest. Here's an example of how to do this in your pom.xml: 29 | 30 | 227 | [3.0.4,) 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | release 240 | 241 | 242 | 243 | org.apache.maven.plugins 244 | maven-javadoc-plugin 245 | 2.7 246 | 247 | -Xdoclint:none 248 | 249 | 250 | 251 | org.apache.maven.plugins 252 | maven-gpg-plugin 253 | ${maven.gpg.plugin.version} 254 | 255 | 256 | sign-artifacts 257 | verify 258 | 259 | sign 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | org.apache.maven.plugins 270 | maven-plugin-plugin 271 | 2.6 272 | 273 | 274 | org.codehaus.mojo 275 | cobertura-maven-plugin 276 | 2.5.1 277 | 278 | 279 | org.apache.maven.plugins 280 | maven-changes-plugin 281 | 2.6 282 | 283 | true 284 | 285 | 286 | 287 | org.apache.maven.plugins 288 | maven-dependency-plugin 289 | 2.3 290 | 291 | 292 | org.apache.maven.plugins 293 | maven-javadoc-plugin 294 | 2.7 295 | 296 | UTF-8 297 | UTF-8 298 | true 299 | package 300 | ${java.version} 301 | true 302 | 303 | 304 | 305 | org.apache.maven.plugins 306 | maven-jxr-plugin 307 | 2.2 308 | 309 | UTF-8 310 | UTF-8 311 | 312 | 313 | 314 | org.apache.maven.plugins 315 | maven-surefire-report-plugin 316 | 2.5 317 | 318 | 319 | 320 | 321 | 322 | 323 | -------------------------------------------------------------------------------- /src/changes/changes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Maven ScalaTest Plugin 4 | 5 | 6 | 7 | Created initial version. Jon gets credit for most of the work in this release. 8 | Updated to work with Scala 2.8 and cleaned up for release. 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/it/it-parent/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | maven.scalatest.plugin.its 5 | it-parent 6 | 1.0-SNAPSHOT 7 | pom 8 | it-parent 9 | 10 | 11 | 12 | maven-3 13 | 14 | 15 | 16 | ${basedir} 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-site-plugin 25 | 3.5.1 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.scalatest 38 | scalatest-maven-plugin 39 | @project.version@ 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-project-info-reports-plugin 44 | @maven.project.info.reports.plugin.version@ 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/it/lift/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | maven.scalatest.plugin.its 5 | lift-it 6 | 1.0-SNAPSHOT 7 | war 8 | lift-it 9 | Runs the plugin against a basic Lift application. 10 | 11 | 12 | 3.2.0 13 | 14 | 15 | 16 | maven.scalatest.plugin.its 17 | it-parent 18 | 1.0-SNAPSHOT 19 | ../it-parent 20 | 21 | 22 | 23 | 24 | org.scala-lang 25 | scala-library 26 | @scala.version@ 27 | 28 | 29 | net.liftweb 30 | lift-util_@scala.major.version@ 31 | ${lift.version} 32 | 33 | 34 | net.liftweb 35 | lift-webkit_@scala.major.version@ 36 | ${lift.version} 37 | 38 | 39 | net.liftweb 40 | lift-mapper_@scala.major.version@ 41 | ${lift.version} 42 | 43 | 44 | javax.servlet 45 | servlet-api 46 | 2.5 47 | provided 48 | 49 | 50 | org.scalatest 51 | scalatest_@scala.major.version@ 52 | @scalatest.version@ 53 | test 54 | 55 | 56 | org.mortbay.jetty 57 | jetty 58 | [6.1.6,) 59 | test 60 | 61 | 62 | 63 | org.scala-lang 64 | scala-compiler 65 | @scala.version@ 66 | test 67 | 68 | 69 | 70 | 71 | src/main/scala 72 | src/test/scala 73 | 74 | 75 | net.alchim31.maven 76 | scala-maven-plugin 77 | @scala.maven.plugin.version@ 78 | 79 | incremental 80 | ${scala.version} 81 | 82 | 83 | 84 | scala-compile 85 | process-resources 86 | 87 | add-source 88 | compile 89 | 90 | 91 | 92 | scala-test-compile 93 | process-test-resources 94 | 95 | testCompile 96 | 97 | 98 | 99 | 100 | 101 | org.mortbay.jetty 102 | maven-jetty-plugin 103 | 6.1.26 104 | 105 | / 106 | 5 107 | 108 | 109 | 110 | net.sf.alchim 111 | yuicompressor-maven-plugin 112 | 0.7.1 113 | 114 | 115 | 116 | compress 117 | 118 | 119 | 120 | 121 | true 122 | 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-surefire-plugin 128 | 2.7 129 | 130 | true 131 | 132 | 133 | 134 | 135 | org.scalatest 136 | scalatest-maven-plugin 137 | 138 | 139 | 140 | test 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | org.scalatest 151 | scalatest-maven-plugin 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /src/it/lift/src/main/scala/bootstrap/liftweb/Boot.scala: -------------------------------------------------------------------------------- 1 | package bootstrap.liftweb 2 | 3 | import _root_.net.liftweb.util._ 4 | import _root_.net.liftweb.http._ 5 | import _root_.net.liftweb.sitemap._ 6 | import _root_.net.liftweb.sitemap.Loc._ 7 | import Helpers._ 8 | 9 | /** 10 | * A class that's instantiated early and run. It allows the application 11 | * to modify lift's environment 12 | */ 13 | class Boot { 14 | def boot { 15 | // where to search snippet 16 | LiftRules.addToPackages("demo.helloworld") 17 | 18 | // Build SiteMap 19 | val entries = Menu(Loc("Home", List("index"), "Home")) :: Nil 20 | LiftRules.setSiteMap(SiteMap(entries:_*)) 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/it/lift/src/main/scala/demo/helloworld/comet/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scalatest/scalatest-maven-plugin/383f396162b7654930758b76a0696d3aa2ce5686/src/it/lift/src/main/scala/demo/helloworld/comet/.keep -------------------------------------------------------------------------------- /src/it/lift/src/main/scala/demo/helloworld/model/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scalatest/scalatest-maven-plugin/383f396162b7654930758b76a0696d3aa2ce5686/src/it/lift/src/main/scala/demo/helloworld/model/.keep -------------------------------------------------------------------------------- /src/it/lift/src/main/scala/demo/helloworld/snippet/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scalatest/scalatest-maven-plugin/383f396162b7654930758b76a0696d3aa2ce5686/src/it/lift/src/main/scala/demo/helloworld/snippet/.keep -------------------------------------------------------------------------------- /src/it/lift/src/main/scala/demo/helloworld/snippet/HelloWorld.scala: -------------------------------------------------------------------------------- 1 | package demo.helloworld.snippet 2 | 3 | class HelloWorld { 4 | def howdy = Welcome to helloworld at {new _root_.java.util.Date} 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/it/lift/src/main/scala/demo/helloworld/view/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scalatest/scalatest-maven-plugin/383f396162b7654930758b76a0696d3aa2ce5686/src/it/lift/src/main/scala/demo/helloworld/view/.keep -------------------------------------------------------------------------------- /src/it/lift/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | LiftFilter 10 | Lift Filter 11 | The Filter that intercepts lift calls 12 | net.liftweb.http.LiftFilter 13 | 14 | 15 | 16 | 17 | LiftFilter 18 | /* 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/it/lift/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to your project!

3 |

4 |
5 | 6 | -------------------------------------------------------------------------------- /src/it/lift/src/main/webapp/templates-hidden/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | demo.helloworld:helloworld:1.0-SNAPSHOT 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/it/lift/src/test/scala/LiftConsole.scala: -------------------------------------------------------------------------------- 1 | import _root_.bootstrap.liftweb.Boot 2 | import _root_.scala.tools.nsc.MainGenericRunner 3 | 4 | object LiftConsole { 5 | def main(args : Array[String]) { 6 | // Instantiate your project's Boot file 7 | val b = new Boot() 8 | // Boot your project 9 | b.boot 10 | // Now run the MainGenericRunner to get your repl 11 | MainGenericRunner.main(args) 12 | // After the repl exits, then exit the scala script 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/it/lift/src/test/scala/RunWebApp.scala: -------------------------------------------------------------------------------- 1 | import _root_.org.mortbay.jetty.Connector 2 | import _root_.org.mortbay.jetty.Server 3 | import _root_.org.mortbay.jetty.webapp.WebAppContext 4 | 5 | object RunWebApp extends App { 6 | val server = new Server(8080) 7 | val context = new WebAppContext() 8 | context.setServer(server) 9 | context.setContextPath("/") 10 | context.setWar("src/main/webapp") 11 | 12 | server.addHandler(context) 13 | 14 | try { 15 | println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP") 16 | server.start() 17 | while (System.in.available() == 0) { 18 | Thread.sleep(5000) 19 | } 20 | server.stop() 21 | server.join() 22 | } catch { 23 | case exc : Exception => { 24 | exc.printStackTrace() 25 | System.exit(100) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/it/lift/src/test/scala/demo/helloworld/AppTest.scala: -------------------------------------------------------------------------------- 1 | package demo.helloworld 2 | 3 | import _root_.java.io.File 4 | import _root_.org.scalatest.funsuite.AnyFunSuite 5 | import _root_.scala.xml.XML 6 | import _root_.net.liftweb.common.Full 7 | import _root_.net.liftweb.util.PCDataXmlParser 8 | 9 | /** 10 | * Unit test for simple App. 11 | */ 12 | class AppTest extends AnyFunSuite { 13 | 14 | /** 15 | * Rigourous Tests :-) 16 | */ 17 | test("OK"){ 18 | assert(true === true) 19 | } 20 | 21 | ignore("KO"){ 22 | assert(true === false) 23 | } 24 | 25 | /** 26 | * Tests to make sure the project's XML files are well-formed. 27 | * 28 | * Finds every *.html and *.xml file in src/main/webapp (and its 29 | * subdirectories) and tests to make sure they are well-formed. 30 | */ 31 | test("xml"){ 32 | var failed: List[File] = Nil 33 | 34 | def handledXml(file: String) = 35 | file.endsWith(".xml") 36 | 37 | def handledXHtml(file: String) = 38 | file.endsWith(".html") || file.endsWith(".htm") || file.endsWith(".xhtml") 39 | 40 | def wellFormed(file: File) { 41 | if (file.isDirectory) 42 | for (f <- file.listFiles) wellFormed(f) 43 | 44 | if (file.isFile && handledXml(file.getName)) { 45 | try { 46 | val f = javax.xml.parsers.SAXParserFactory.newInstance() 47 | f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false) 48 | val p = f.newSAXParser() 49 | XML.withSAXParser(p).loadFile(file) 50 | } catch { 51 | case e: _root_.org.xml.sax.SAXParseException => 52 | e.printStackTrace() 53 | failed = file :: failed 54 | } 55 | } 56 | if (file.isFile && handledXHtml(file.getName)) { 57 | PCDataXmlParser(new java.io.FileInputStream(file.getAbsolutePath)) match { 58 | case Full(_) => // file is ok 59 | case _ => failed = file :: failed 60 | } 61 | } 62 | } 63 | 64 | wellFormed(new File("src/main/webapp")) 65 | 66 | val numFails = failed.size 67 | if (numFails > 0) { 68 | val fileStr = if (numFails == 1) "file" else "files" 69 | val msg = "Malformed XML in " + numFails + " " + fileStr + ": " + failed.mkString(", ") 70 | println(msg) 71 | fail(msg) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/it/lift/verify.groovy: -------------------------------------------------------------------------------- 1 | 2 | def logsFile = new File(basedir, "build.log") 3 | 4 | if (!logsFile.exists()) { 5 | throw new Exception("Could not find build.log. Searched: " + logsFile) 6 | } 7 | 8 | def testSummaryLines = [] 9 | 10 | logsFile.filterLine { 11 | it ==~ /.*Tests: succeeded [0-9]*, failed [0-9]*, canceled [0-9]*, ignored [0-9]*, pending [0-9]*.*/ 12 | }.each { line -> testSummaryLines << "" + line } 13 | 14 | if (testSummaryLines.size == 0) { 15 | throw new Exception("Could not find scalatest's summary line in build.log") 16 | } else if (testSummaryLines.size > 1) { 17 | throw new Exception("Found more than one scalatest summary line in build.log") 18 | } 19 | 20 | def theLine = testSummaryLines[0] 21 | 22 | if (theLine.isEmpty()) { 23 | throw new Exception("Could not find scalatest's non empty summary line in build.log") 24 | } 25 | 26 | if (theLine.contains("Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0")) { 27 | throw new Exception("No tests were run by scalatest!") 28 | } 29 | 30 | return true 31 | -------------------------------------------------------------------------------- /src/it/manual/gui/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.jteigen 6 | maven-scalatest-plugin-it-gui 7 | jar 8 | 1.0-SNAPSHOT 9 | Manual gui test 10 | 11 | 12 | maven.scalatest.plugin.its 13 | it-parent 14 | 1.0-SNAPSHOT 15 | ../it-parent 16 | 17 | 18 | 19 | 20 | org.scalatest 21 | scalatest 22 | 1.2 23 | test 24 | 25 | 26 | org.scala-lang 27 | scala-library 28 | 2.8.1 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.scalatest 36 | maven-scalatest-plugin 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/it/no-scalatest-ignore/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | org.scalatest 6 | no-scalatest-ignore 7 | jar 8 | 1.0-SNAPSHOT 9 | No ScalaTest Ignore configuration test 10 | 11 | 12 | 13 | org.scala-lang 14 | scala-library 15 | @scala.version@ 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.scalatest 23 | scalatest-maven-plugin 24 | @project.version@ 25 | 26 | true 27 | 28 | 29 | 30 | test 31 | 32 | test 33 | 34 | 35 | 36 | 37 | 38 | org.apache.maven.plugins 39 | maven-project-info-reports-plugin 40 | @maven.project.info.reports.plugin.version@ 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 2.7 46 | 47 | true 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/it/no-scalatest-ignore/verify.groovy: -------------------------------------------------------------------------------- 1 | 2 | def logsFile = new File(basedir, "build.log") 3 | 4 | if (!logsFile.exists()) { 5 | throw new Exception("Could not find build.log. Searched: " + logsFile) 6 | } 7 | 8 | def result = logsFile.readLines().findAll() { 9 | it.contains("Skipped because ScalaTest not available on classpath.") 10 | } 11 | if (result.size == 0) { 12 | throw new Exception("Could not find skipped because ScalaTest not available on classpath message in build.log") 13 | } 14 | 15 | return true 16 | -------------------------------------------------------------------------------- /src/it/redirect-output/README.md: -------------------------------------------------------------------------------- 1 | # redirect output 2 | 3 | This project is part of scalatest-maven-plugin's suite of integration tests. It is meant to check that scalatest-maven-plugin can run for projects that use test output redirect. -------------------------------------------------------------------------------- /src/it/redirect-output/invoker.properties: -------------------------------------------------------------------------------- 1 | # A comma or space separated list of goals/phases to execute, may 2 | # specify an empty list to execute the default goal of the IT project 3 | invoker.goals = clean test 4 | -------------------------------------------------------------------------------- /src/it/redirect-output/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | redirect-output-it 5 | 1.0-SNAPSHOT 6 | jar 7 | redirect-output 8 | Runs the plugin for a project that uses test output redirect. 9 | 10 | 11 | maven.scalatest.plugin.its 12 | it-parent 13 | 1.0-SNAPSHOT 14 | ../it-parent 15 | 16 | 17 | 18 | 19 | org.scala-lang 20 | scala-library 21 | @scala.version@ 22 | 23 | 24 | org.scalatest 25 | scalatest_@scala.major.version@ 26 | @scalatest.version@ 27 | test 28 | 29 | 30 | 31 | 32 | src/main/scala 33 | src/test/scala 34 | 35 | 36 | net.alchim31.maven 37 | scala-maven-plugin 38 | @scala.maven.plugin.version@ 39 | 40 | incremental 41 | ${scala.version} 42 | 43 | 44 | 45 | scala-compile 46 | process-resources 47 | 48 | add-source 49 | compile 50 | 51 | 52 | 53 | scala-test-compile 54 | process-test-resources 55 | 56 | testCompile 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-surefire-plugin 65 | 2.7 66 | 67 | true 68 | 69 | 70 | 71 | 72 | org.scalatest 73 | scalatest-maven-plugin 74 | 75 | true 76 | true 77 | 78 | 79 | 80 | 81 | test 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | org.scalatest 92 | scalatest-maven-plugin 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/it/redirect-output/src/main/scala/org/example/App.scala: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | class App { 4 | def runApp(): String = { 5 | "It ran!" 6 | } 7 | } -------------------------------------------------------------------------------- /src/it/redirect-output/src/test/scala/org/example/AppTest.scala: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import org.scalatest.flatspec.AnyFlatSpec 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class AppTest extends AnyFlatSpec with Matchers { 7 | "Our example App" should "run" in { 8 | val app = new App 9 | app.runApp() shouldBe "It ran!" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/it/redirect-output/verify.groovy: -------------------------------------------------------------------------------- 1 | 2 | def reportsDir = new File(basedir, "target" + File.separator + "scalatest-reports") 3 | def logsFile = new File(reportsDir, "scalatest-output.txt") 4 | 5 | if (!logsFile.exists()) { 6 | throw new Exception("Could not find output.txt. Searched: " + logsFile) 7 | } 8 | 9 | def testSummaryLines = [] 10 | 11 | logsFile.filterLine { 12 | it ==~ /.*Tests: succeeded [0-9]*, failed [0-9]*, canceled [0-9]*, ignored [0-9]*, pending [0-9]*.*/ 13 | }.each { line -> testSummaryLines << "" + line } 14 | 15 | if (testSummaryLines.size == 0) { 16 | throw new Exception("Could not find scalatest's summary line in output.txt") 17 | } else if (testSummaryLines.size > 1) { 18 | throw new Exception("Found more than one scalatest summary line in output.txt") 19 | } 20 | 21 | def theLine = testSummaryLines[0] 22 | 23 | if (theLine.isEmpty()) { 24 | throw new Exception("Could not find scalatest's non-empty summary line in output.txt") 25 | } 26 | 27 | if (theLine.contains("Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0")) { 28 | throw new Exception("No tests were run by scalatest!") 29 | } 30 | 31 | return true 32 | -------------------------------------------------------------------------------- /src/it/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | it-repo 6 | 7 | true 8 | 9 | 10 | 11 | local.central 12 | @localRepositoryUrl@ 13 | 14 | true 15 | 16 | 17 | true 18 | 19 | 20 | 21 | 22 | 23 | local.central 24 | @localRepositoryUrl@ 25 | 26 | true 27 | 28 | 29 | true 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/it/spaces in path/README.md: -------------------------------------------------------------------------------- 1 | # spaces in path 2 | 3 | This project is part of scalatest-maven-plugin's suite of integration tests. It is meant to check that scalatest-maven-plugin can run for projects that contain spaces in their file path. -------------------------------------------------------------------------------- /src/it/spaces in path/invoker.properties: -------------------------------------------------------------------------------- 1 | # A comma or space separated list of goals/phases to execute, may 2 | # specify an empty list to execute the default goal of the IT project 3 | invoker.goals = clean test 4 | -------------------------------------------------------------------------------- /src/it/spaces in path/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | spaces-in-path-it 5 | 1.0-SNAPSHOT 6 | jar 7 | spaces-in-path-it 8 | Runs the plugin for a project that contains spaces in the path. 9 | 10 | 11 | maven.scalatest.plugin.its 12 | it-parent 13 | 1.0-SNAPSHOT 14 | ../it-parent 15 | 16 | 17 | 18 | 19 | org.scala-lang 20 | scala-library 21 | @scala.version@ 22 | 23 | 24 | org.scalatest 25 | scalatest_@scala.major.version@ 26 | @scalatest.version@ 27 | test 28 | 29 | 30 | 31 | 32 | src/main/scala 33 | src/test/scala 34 | 35 | 36 | net.alchim31.maven 37 | scala-maven-plugin 38 | @scala.maven.plugin.version@ 39 | 40 | incremental 41 | ${scala.version} 42 | 43 | 44 | 45 | scala-compile 46 | process-resources 47 | 48 | add-source 49 | compile 50 | 51 | 52 | 53 | scala-test-compile 54 | process-test-resources 55 | 56 | testCompile 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-surefire-plugin 65 | 2.7 66 | 67 | true 68 | 69 | 70 | 71 | 72 | org.scalatest 73 | scalatest-maven-plugin 74 | 75 | true 76 | 77 | 78 | 79 | 80 | test 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | org.scalatest 91 | scalatest-maven-plugin 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/it/spaces in path/src/main/scala/org/example/App.scala: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | class App { 4 | def runApp(): String = { 5 | "It ran!" 6 | } 7 | } -------------------------------------------------------------------------------- /src/it/spaces in path/src/test/scala/org/example/AppTest.scala: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import org.scalatest.flatspec.AnyFlatSpec 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class AppTest extends AnyFlatSpec with Matchers { 7 | "Our example App" should "run" in { 8 | val app = new App 9 | app.runApp() shouldBe "It ran!" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/it/spaces in path/verify.groovy: -------------------------------------------------------------------------------- 1 | 2 | def logsFile = new File(basedir, "build.log") 3 | 4 | if (!logsFile.exists()) { 5 | throw new Exception("Could not find build.log. Searched: " + logsFile) 6 | } 7 | 8 | def testSummaryLines = [] 9 | 10 | logsFile.filterLine { 11 | it ==~ /.*Tests: succeeded [0-9]*, failed [0-9]*, canceled [0-9]*, ignored [0-9]*, pending [0-9]*.*/ 12 | }.each { line -> testSummaryLines << "" + line } 13 | 14 | if (testSummaryLines.size == 0) { 15 | throw new Exception("Could not find scalatest's summary line in build.log") 16 | } else if (testSummaryLines.size > 1) { 17 | throw new Exception("Found more than one scalatest summary line in build.log") 18 | } 19 | 20 | def theLine = testSummaryLines[0] 21 | 22 | if (theLine.isEmpty()) { 23 | throw new Exception("Could not find scalatest's non empty summary line in build.log") 24 | } 25 | 26 | if (theLine.contains("Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0")) { 27 | throw new Exception("No tests were run by scalatest!") 28 | } 29 | 30 | return true 31 | -------------------------------------------------------------------------------- /src/main/java/org/scalatest/tools/maven/AbstractScalaTestMojo.java: -------------------------------------------------------------------------------- 1 | package org.scalatest.tools.maven; 2 | 3 | import org.apache.maven.artifact.DependencyResolutionRequiredException; 4 | import org.apache.maven.plugin.AbstractMojo; 5 | import org.apache.maven.plugin.MojoFailureException; 6 | import org.apache.maven.project.MavenProject; 7 | import org.codehaus.plexus.util.cli.*; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.io.PrintWriter; 12 | import java.io.Writer; 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.lang.reflect.Method; 15 | import java.net.MalformedURLException; 16 | import java.net.URL; 17 | import java.net.URLClassLoader; 18 | import java.util.*; 19 | 20 | import static java.util.Collections.singletonList; 21 | import static java.util.Collections.unmodifiableList; 22 | import static org.scalatest.tools.maven.MojoUtils.*; 23 | 24 | /** 25 | * Provides the base for all mojos. 26 | * 27 | * @author Jon-Anders Teigen 28 | * @author Sean Griffin 29 | * @author Mike Pilquist 30 | * @author Bill Venners 31 | * 32 | * @requiresDependencyResolution test 33 | */ 34 | abstract class AbstractScalaTestMojo extends AbstractMojo { 35 | /** 36 | * Injected by Maven so that forked process can be 37 | * launched from the working directory of current maven project in a multi-module build. Should not be user facing. 38 | * @parameter default-value="${project}" 39 | * @required 40 | * @readonly 41 | */ 42 | MavenProject project; 43 | 44 | /** 45 | * Injected by Maven so that it can be included in the run path. Should not be user facing. 46 | * @parameter property="project.build.testOutputDirectory" 47 | * @required 48 | * @readOnly 49 | */ 50 | File testOutputDirectory; 51 | 52 | /** 53 | * Injected by Maven so that it can be included in the run path. Should not be user facing. 54 | * @parameter property="project.build.outputDirectory" 55 | * @required 56 | * @readOnly 57 | */ 58 | File outputDirectory; 59 | 60 | /** 61 | * Comma separated list of additional elements to be added 62 | * to the ScalaTest runpath. ${project.build.outputDirectory} and 63 | * ${project.build.testOutputDirectory} are included by default 64 | * @parameter property="runpath" 65 | */ 66 | String runpath; 67 | 68 | /** 69 | * Comma separated list of suites to be executed. 70 | * @parameter property="suites" 71 | */ 72 | String suites; 73 | 74 | /** 75 | * Comma separated list of tests to be executed 76 | * @parameter property="tests" 77 | */ 78 | String tests; 79 | 80 | /** 81 | * Regex of suffixes to filter discovered suites 82 | * @parameter property="suffixes" 83 | */ 84 | String suffixes; 85 | 86 | /** 87 | * Comma separated list of tags to include 88 | * @parameter property="tagsToInclude" 89 | */ 90 | String tagsToInclude; 91 | 92 | /** 93 | * Comma separated list of tags to exclude 94 | * @parameter property="tagsToExclude" 95 | */ 96 | String tagsToExclude; 97 | 98 | /** 99 | * Comma separated list of configuration parameters to pass to ScalaTest. 100 | * The parameters must be of the format <key>=<value>. E.g foo=bar,monkey=donkey 101 | * @parameter property="config" 102 | */ 103 | String config; 104 | 105 | /** 106 | * Set to true to run suites concurrently 107 | * @parameter property="parallel" 108 | */ 109 | boolean parallel; 110 | 111 | /** 112 | * Set to true to enable suite sorting, this only takes effect if parallel is set to true. 113 | * @parameter property="suiteSorting" 114 | */ 115 | boolean suiteSorting; 116 | 117 | /** 118 | * Set the thread count for parallel tests execution, this only takes effect if parallel is set to true. 119 | * @parameter property="threadCount" 120 | */ 121 | int threadCount; 122 | 123 | /** 124 | * Comma separated list of packages containing suites to execute 125 | * @parameter property="membersOnlySuites" 126 | */ 127 | String membersOnlySuites; 128 | 129 | // TODO: Change this to wildcard and membersOnly 130 | /** 131 | * Comma separated list of wildcard suite names to execute 132 | * @parameter property="wildcardSuites" 133 | */ 134 | String wildcardSuites; 135 | 136 | /** 137 | * Comma separated list of testNG xml files to execute 138 | * @parameter property="testNGXMLFiles" 139 | */ 140 | String testNGConfigFiles; 141 | 142 | /** 143 | * Comma separated list of files to store names of failed and 144 | * canceled tests into. 145 | * @parameter property="memoryFiles" 146 | */ 147 | String memoryFiles; 148 | 149 | /** 150 | * Comma separated list of files to store names of failed and 151 | * canceled tests into. 152 | * @parameter property="testsFiles" 153 | */ 154 | String testsFiles; 155 | 156 | /** 157 | * Comma separated list of JUnit suites/tests to execute 158 | * @parameter property="junitClasses" 159 | */ 160 | String jUnitClasses; 161 | 162 | /** 163 | * Option to specify the forking mode. Can be "never" or "once". "always", which would 164 | * fork for each test-class, may be supported later. 165 | * 166 | * @parameter property="forkMode" default-value="once" 167 | */ 168 | String forkMode; 169 | 170 | /** 171 | * Option to specify additional JVM options to pass to the forked process. 172 | * 173 | * @parameter property="argLine" 174 | */ 175 | String argLine; 176 | 177 | /** 178 | * Additional environment variables to pass to the forked process. 179 | * 180 | * @parameter 181 | */ 182 | Map environmentVariables; 183 | 184 | /** 185 | * Additional system properties to pass to the forked process. 186 | * 187 | * @parameter 188 | */ 189 | Map systemProperties; 190 | 191 | /** 192 | * Option to specify whether the forked process should wait at startup for a remote debugger to attach. 193 | * 194 | *

If set to true, the forked process will suspend at startup and wait for a remote 195 | * debugger to attach to the configured port.

196 | * 197 | * @parameter property="debugForkedProcess" default-value="false" 198 | */ 199 | boolean debugForkedProcess; 200 | 201 | /** 202 | * JVM options to pass to the forked process when debugForkedProcess is true. 203 | * 204 | *

If set to a non-empty value, the standard debug arguments are replaced by the specified arguments. 205 | * This allows customization of how remote debugging is done, without having to reconfigure the JVM 206 | * options in argLine. 207 | * 208 | * @parameter property="debugArgLine" 209 | */ 210 | String debugArgLine; 211 | 212 | /** 213 | * Port to listen on when debugging the forked process. 214 | * 215 | * @parameter property="debuggerPort" default-value="5005" 216 | */ 217 | int debuggerPort = 5005; 218 | 219 | /** 220 | * Timeout in seconds to allow the forked process to run before killing it and failing the test run. 221 | * 222 | *

If set to 0, process never times out.

223 | * 224 | * @parameter property="timeout" default-value="0" 225 | */ 226 | int forkedProcessTimeoutInSeconds = 0; 227 | 228 | /** 229 | * Whether or not to log the command used to launch the forked process. 230 | * 231 | * @parameter property="logForkedProcessCommand" default-value="false" 232 | */ 233 | boolean logForkedProcessCommand; 234 | 235 | /** 236 | * Span scale factor. 237 | * 238 | * @parameter property="spanScaleFactor" default-value="1.0" 239 | */ 240 | double spanScaleFactor = 1.0; 241 | 242 | /** 243 | * The current working directory for forked process. Optional. If not specified, basedir will be used. 244 | * 245 | * @parameter property="workingDirectory" 246 | */ 247 | String workingDirectory; 248 | 249 | /** 250 | * Option to specify an alternative path to JVM (or path to the java executable) to use with 251 | * the forked process. 252 | * 253 | * @parameter property="jvm" 254 | */ 255 | String jvm; 256 | 257 | // runScalaTest is called by the concrete mojo subclasses TODO: make it protected and others too 258 | // Returns true if all tests pass 259 | boolean runScalaTest(String[] args) throws MojoFailureException { 260 | getLog().debug(Arrays.toString(args)); 261 | if (forkMode.equals("never")) { 262 | return runWithoutForking(args); 263 | } 264 | else { 265 | if (!forkMode.equals("once")) { 266 | getLog().error("Invalid forkMode: \"" + forkMode + "\"; Using once instead."); 267 | } 268 | return runForkingOnce(args); 269 | } 270 | } 271 | 272 | // Returns true if all tests pass 273 | private boolean runWithoutForking(String[] args) { 274 | try { 275 | return (Boolean) run().invoke(null, new Object[]{args}); 276 | } catch (IllegalAccessException e) { 277 | throw new IllegalStateException(e); 278 | } catch (InvocationTargetException e) { 279 | Throwable target = e.getTargetException(); 280 | if(target instanceof RuntimeException){ 281 | throw (RuntimeException)target; 282 | } else { 283 | throw new IllegalArgumentException(target); 284 | } 285 | } 286 | } 287 | 288 | // Returns true if all tests pass 289 | private boolean runForkingOnce(String[] args) throws MojoFailureException { 290 | 291 | final Commandline cli = new Commandline(); 292 | if ((this.workingDirectory == null || this.workingDirectory.isEmpty())) { 293 | cli.setWorkingDirectory(project.getBasedir()); 294 | } else { 295 | cli.setWorkingDirectory(workingDirectory); 296 | } 297 | 298 | if (this.jvm == null || this.jvm.isEmpty()) { 299 | cli.setExecutable(getJvm()); 300 | } else { 301 | cli.setExecutable(this.jvm); 302 | } 303 | 304 | // Set up environment 305 | if (environmentVariables != null) { 306 | for (final Map.Entry entry : environmentVariables.entrySet()) { 307 | cli.addEnvironment(entry.getKey(), entry.getValue()); 308 | } 309 | } 310 | cli.addEnvironment("CLASSPATH", buildClassPathEnvironment()); 311 | 312 | // Set up system properties 313 | if (systemProperties != null) { 314 | for (final Map.Entry entry : systemProperties.entrySet()) { 315 | cli.createArg().setValue(String.format("-D%s=%s", entry.getKey(), entry.getValue())); 316 | } 317 | } 318 | cli.createArg().setValue(String.format("-Dbasedir=%s", project.getBasedir().getAbsolutePath())); 319 | 320 | // Set user specified JVM arguments 321 | if (argLine != null) { 322 | cli.createArg().setLine(stripNewLines(argLine)); 323 | } 324 | 325 | // Set debugging JVM arguments if debugging is enabled 326 | if (debugForkedProcess) { 327 | cli.createArg().setLine(stripNewLines(forkedProcessDebuggingArguments())); 328 | } 329 | 330 | // Set ScalaTest arguments 331 | cli.createArg().setValue("org.scalatest.tools.Runner"); 332 | for (final String arg : args) { 333 | cli.createArg().setValue(arg); 334 | } 335 | 336 | // Log command string 337 | final String commandLogStatement = "Forking ScalaTest via: " + cli; 338 | if (logForkedProcessCommand) { 339 | getLog().info(commandLogStatement); 340 | } else { 341 | getLog().debug(commandLogStatement); 342 | } 343 | 344 | try ( 345 | final Writer outputWriter = getOutputWriter() 346 | ) { 347 | final StreamConsumer outputConsumer = new WriterStreamConsumer(outputWriter); 348 | 349 | final int result = CommandLineUtils.executeCommandLine(cli, outputConsumer, outputConsumer, 350 | forkedProcessTimeoutInSeconds); 351 | 352 | return result == 0; 353 | } 354 | catch (final CommandLineTimeOutException e) { 355 | throw new MojoFailureException(String.format("Timed out after %d seconds waiting for forked process to complete.", forkedProcessTimeoutInSeconds), e); 356 | } 357 | catch (final CommandLineException e) { 358 | throw new MojoFailureException("Exception while executing forked process.", e); 359 | } 360 | catch (IOException e) { 361 | throw new MojoFailureException("Unable to close the output writer ", e); 362 | } 363 | } 364 | 365 | protected Writer getOutputWriter() throws MojoFailureException { 366 | return new PrintWriter(System.out) { 367 | @Override 368 | public void close() { 369 | out = null; // System.out should stay open 370 | } 371 | }; 372 | } 373 | 374 | private String buildClassPathEnvironment() { 375 | StringBuffer buf = new StringBuffer(); 376 | boolean first = true; 377 | for (String e : testClasspathElements()) { 378 | if (first) { 379 | first = false; 380 | } 381 | else { 382 | buf.append(File.pathSeparator); 383 | } 384 | buf.append(e); 385 | } 386 | return buf.toString(); 387 | } 388 | 389 | private String forkedProcessDebuggingArguments() { 390 | if (debugArgLine == null) { 391 | return String.format("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%s", debuggerPort); 392 | } else { 393 | return debugArgLine; 394 | } 395 | } 396 | 397 | protected boolean isScalaTestAvailable() { 398 | try { 399 | classLoader().loadClass("org.scalatest.tools.Runner"); 400 | return true; 401 | } 402 | catch (ClassNotFoundException e) { 403 | return false; 404 | } 405 | } 406 | 407 | // This is just used by runScalaTest to get the method to invoke 408 | private Method run() { 409 | try { 410 | Class runner = classLoader().loadClass("org.scalatest.tools.Runner"); 411 | return runner.getMethod("run", String[].class); 412 | } catch (NoSuchMethodException e) { 413 | throw new IllegalStateException(e); 414 | } catch (ClassNotFoundException e) { 415 | throw new IllegalStateException("scalatest is missing from classpath"); 416 | } 417 | } 418 | 419 | // This is just used by run to get a class loader from which to load ScalaTest 420 | private ClassLoader classLoader() { 421 | try { 422 | List urls = new ArrayList(); 423 | for (String element : testClasspathElements()) { 424 | File file = new File(element); 425 | if (file.isFile()) { 426 | urls.add(file.toURI().toURL()); 427 | } 428 | } 429 | URL[] u = urls.toArray(new URL[urls.size()]); 430 | return new URLClassLoader(u); 431 | } catch (MalformedURLException e) { 432 | throw new IllegalStateException(e); 433 | } 434 | } 435 | 436 | // Have to use the programmatic way of getting the classpath elements 437 | // instead of the field-level injection since that apparently doesn't work 438 | // for ReporterMojos in maven-2.2 (it does work in maven-3) 439 | private List testClasspathElements() { 440 | try { 441 | return (List) project.getTestClasspathElements(); 442 | } 443 | catch (DependencyResolutionRequiredException e) { 444 | // There's really no known way this exception can happen since 445 | // the @requiresDependencyResolution at the top of the class 446 | // defines test-scoped resolution. 447 | throw new IllegalStateException("Dependency resolution should be test-scoped.", e); 448 | } 449 | } 450 | 451 | // This is the configuration parameters shared by all concrete Mojo subclasses 452 | List sharedConfiguration() { 453 | return unmodifiableList( 454 | new ArrayList() {{ 455 | addAll(runpath()); 456 | addAll(config()); 457 | addAll(tagsToInclude()); 458 | addAll(tagsToExclude()); 459 | addAll(parallel()); 460 | addAll(tests()); 461 | addAll(suites()); 462 | addAll(suffixes()); 463 | addAll(membersOnlySuites()); 464 | addAll(wildcardSuites()); 465 | addAll(testNGConfigFiles()); 466 | addAll(memoryFiles()); 467 | addAll(testsFiles()); 468 | addAll(junitClasses()); 469 | addAll(spanScaleFactor()); 470 | }}); 471 | } 472 | 473 | private List config() { 474 | List c = new ArrayList(); 475 | for(String pair : splitOnComma(config)){ 476 | c.add("-D"+pair); 477 | } 478 | return unmodifiableList(c); 479 | } 480 | 481 | private List runpath() { 482 | checkRunpathArgument("Output", outputDirectory); 483 | checkRunpathArgument("Test output", testOutputDirectory); 484 | 485 | String outputPath = outputDirectory.getAbsolutePath(); 486 | if(outputPath.contains(" ")) { 487 | outputPath = outputPath.replaceAll(" ","\\\\ "); 488 | getLog().debug(String.format("Escaped output directory path: %s", outputPath)); 489 | } 490 | 491 | String testOutputPath = testOutputDirectory.getAbsolutePath(); 492 | if(testOutputPath.contains(" ")) { 493 | testOutputPath = testOutputPath.replaceAll(" ","\\\\ "); 494 | getLog().debug(String.format("Escaped test output directory path: %s", testOutputPath)); 495 | } 496 | 497 | return compoundArg("-R", 498 | outputPath, 499 | testOutputPath, 500 | runpath); 501 | } 502 | 503 | private void checkRunpathArgument(String directoryName, File directory) { 504 | if(!directory.exists()) { 505 | getLog().warn(String.format("%s directory does not exist: %s", directoryName, directory.getAbsolutePath())); 506 | } else if(!directory.isDirectory()) { 507 | getLog().warn(String.format("%s is not a directory: %s", directoryName, directory.getAbsolutePath())); 508 | } else if(!directory.canRead()) { 509 | getLog().warn(String.format("%s directory is not readable: %s", directoryName, directory.getAbsolutePath())); 510 | } 511 | } 512 | 513 | private List tagsToInclude() { 514 | return compoundArg("-n", tagsToInclude); 515 | } 516 | 517 | private List tagsToExclude() { 518 | return compoundArg("-l", tagsToExclude); 519 | } 520 | 521 | private List parallel() { 522 | if (parallel) { 523 | String useSuiteSorting = suiteSorting ? "S" : ""; 524 | String useThreadCount = threadCount == 0 ? "" : ("" + threadCount); 525 | return unmodifiableList(singletonList("-P" + useSuiteSorting + useThreadCount)); 526 | } 527 | else 528 | return Collections.emptyList(); 529 | } 530 | 531 | // 532 | // Generates a -s argument for each suite in comma-delimited list 533 | // 'suites', with optionally a -z or -t argument for a test name 534 | // if one follows the suite name. 535 | // 536 | // Test names follow suite names after whitespace, and may be prefixed 537 | // by an '@' sign to indicate they are an exact test name instead of 538 | // a substring. A -t argument is used for tests preceded by an '@' 539 | // sign, and -z is used for others. 540 | // 541 | private List suites() { 542 | List list = new ArrayList(); 543 | 544 | for (String suite: splitOnComma(suites)) { 545 | SuiteTestPair pair = new SuiteTestPair(suite); 546 | 547 | if (pair.suite != null) { 548 | list.add("-s"); 549 | list.add(pair.suite); 550 | 551 | if (pair.test != null) { 552 | addTest(list, pair.test); 553 | } 554 | } 555 | } 556 | return unmodifiableList(list); 557 | } 558 | 559 | // 560 | // Parses a string containing a Suite name followed 561 | // optionally by a test name. 562 | // 563 | // E.g. "HelloSuite hello there" would produce suite "HelloSuite" 564 | // and test "hello there". 565 | // 566 | static private class SuiteTestPair { 567 | String suite; 568 | String test; 569 | 570 | SuiteTestPair(String str) { 571 | if (str != null) { 572 | String trimStr = str.trim(); 573 | 574 | if (trimStr.length() > 0) { 575 | String[] splits = trimStr.split("(?s)\\s", 2); 576 | if (splits.length > 1) { 577 | suite = splits[0]; 578 | test = splits[1].trim(); 579 | } 580 | else { 581 | suite = trimStr; 582 | } 583 | } 584 | } 585 | } 586 | } 587 | 588 | // 589 | // Adds a -t or -z arg for specified test name. Uses -t if name is 590 | // prefixed by an '@' sign, or -z otherwise. 591 | // 592 | private void addTest(List list, String testParm) { 593 | if (testParm != null) { 594 | String test = testParm.trim(); 595 | 596 | if (test.length() > 0) { 597 | if (test.charAt(0) == '@') { 598 | String atTest = test.substring(1).trim(); 599 | 600 | if (atTest.length() > 0) { 601 | list.add("-t"); 602 | list.add(atTest); 603 | } 604 | } 605 | else { 606 | list.add("-z"); 607 | list.add(test); 608 | } 609 | } 610 | } 611 | } 612 | 613 | // 614 | // Generates a -z or -t argument for each name in comma-delimited 615 | // 'tests' list, with -t used for those names prefixed by '@'. 616 | // 617 | private List tests() { 618 | List list = new ArrayList(); 619 | 620 | for (String test: splitOnComma(tests)) { 621 | addTest(list, test); 622 | } 623 | return unmodifiableList(list); 624 | } 625 | 626 | private List spanScaleFactor() { 627 | List list = new ArrayList(); 628 | if (spanScaleFactor != 1.0) { 629 | list.add("-F"); 630 | list.add(spanScaleFactor + ""); 631 | } 632 | return unmodifiableList(list); 633 | } 634 | 635 | private List suffixes() { 636 | return compoundArg("-q", suffixes); 637 | } 638 | 639 | private List membersOnlySuites() { 640 | return suiteArg("-m", membersOnlySuites); 641 | } 642 | 643 | private List wildcardSuites() { 644 | return suiteArg("-w", wildcardSuites); 645 | } 646 | 647 | private List testNGConfigFiles() { 648 | return suiteArg("-b", testNGConfigFiles); 649 | } 650 | 651 | private List memoryFiles() { 652 | return suiteArg("-M", memoryFiles); 653 | } 654 | 655 | private List testsFiles() { 656 | List list = new ArrayList(); 657 | for (String param : splitOnComma(testsFiles)) { 658 | File file = new File(param); 659 | if (file.exists()) { 660 | list.add("-A"); 661 | list.add(param); 662 | } 663 | } 664 | return unmodifiableList(list); 665 | } 666 | 667 | private List junitClasses() { 668 | return suiteArg("-j", jUnitClasses); 669 | } 670 | } 671 | -------------------------------------------------------------------------------- /src/main/java/org/scalatest/tools/maven/MojoUtils.java: -------------------------------------------------------------------------------- 1 | package org.scalatest.tools.maven; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import static org.apache.commons.lang3.StringUtils.isEmpty; 8 | 9 | import static java.util.Collections.unmodifiableList; 10 | 11 | /** 12 | * Provides internal utilities for the Mojo's operations. 13 | * 14 | * @author Jon-Anders Teigen 15 | */ 16 | final class MojoUtils { 17 | private MojoUtils() { 18 | } 19 | 20 | static interface F { 21 | public String f(String in); 22 | } 23 | 24 | static F passThrough = new F() { 25 | public String f(String in) { 26 | return in; 27 | } 28 | }; 29 | 30 | static F fileRelativeTo(final File relative) { 31 | return new F() { 32 | public String f(String in) { 33 | File file = new File(relative, in); 34 | File parentDir = file.getParentFile(); 35 | createIfNotExists(parentDir); // sideeffect! 36 | return file.getAbsolutePath(); 37 | } 38 | }; 39 | } 40 | 41 | static F dirRelativeTo(final File relative){ 42 | return new F(){ 43 | public String f(String in){ 44 | File dir = new File(relative, in); 45 | createIfNotExists(dir); // sideeffect! 46 | return dir.getAbsolutePath(); 47 | } 48 | }; 49 | } 50 | 51 | // sideeffect! 52 | private static synchronized void createIfNotExists(File dir) { 53 | if(!dir.exists() && !dir.mkdirs()){ 54 | throw new IllegalStateException("Cannot create directory " + dir); 55 | } 56 | } 57 | 58 | static List compoundArg(String name, String...strings){ 59 | List list = new ArrayList(); 60 | List params = new ArrayList(); 61 | for(String commaSeparated : strings){ 62 | params.addAll(splitOnComma(commaSeparated)); 63 | } 64 | if (params.size() > 0) { 65 | list.add(name); 66 | String prefix = ""; 67 | String a = ""; 68 | for (String param : params) { 69 | a += prefix; 70 | a += param; 71 | prefix = " "; 72 | } 73 | list.add(a); 74 | } 75 | return unmodifiableList(list); 76 | } 77 | 78 | static List suiteArg(String name, String commaSeparated) { 79 | List list = new ArrayList(); 80 | for (String param : splitOnComma(commaSeparated)) { 81 | list.add(name); 82 | list.add(param); 83 | } 84 | return unmodifiableList(list); 85 | } 86 | 87 | static List reporterArg(String name, String commaSeparated, F map) { 88 | List r = new ArrayList(); 89 | for (String arg : splitOnComma(commaSeparated)) { 90 | String[] split = arg.split("\\s"); 91 | if (split.length == 1) { 92 | r.add(name); 93 | r.add(map.f(split[0])); 94 | } else { 95 | r.add(name + split[0]); 96 | r.add(map.f(split[1])); 97 | } 98 | } 99 | return unmodifiableList(r); 100 | } 101 | 102 | // 103 | // Splits a comma-delimited string. Supports backslash escapes for 104 | // commas where string should not be split. E.g. "a, b, c" returns 105 | // list ("a", "b", "c"), but "a\, b, c" returns ("a, b", "c"). 106 | // 107 | static List splitOnComma(String cs) { 108 | List args = new ArrayList(); 109 | if (cs == null) { 110 | return unmodifiableList(args); 111 | } else { 112 | String[] split = cs.split("(?...lists){ 121 | List c = new ArrayList(); 122 | for(List l : lists){ 123 | c.addAll(l); 124 | } 125 | return c.toArray(new String[c.size()]); 126 | } 127 | 128 | private static String getJavaHome() { 129 | final String result; 130 | if (!isEmpty(System.getProperty("java.home"))) { 131 | result = System.getProperty("java.home"); 132 | } 133 | else if (!isEmpty(System.getenv("JAVA_HOME"))) { 134 | result = System.getenv("JAVA_HOME"); 135 | } else { 136 | result = null; 137 | } 138 | return result; 139 | } 140 | 141 | static String getJvm() { 142 | final String jh = getJavaHome(); 143 | final String result; 144 | if (jh == null) { 145 | result = "java"; 146 | } else { 147 | result = jh + File.separator + "bin" + File.separator + "java"; 148 | } 149 | return result; 150 | } 151 | 152 | static String stripNewLines(String argLine) { 153 | return argLine.replaceAll("[\r\n]{1,2}", " "); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/org/scalatest/tools/maven/ReporterMojo.java: -------------------------------------------------------------------------------- 1 | package org.scalatest.tools.maven; 2 | 3 | import org.codehaus.doxia.sink.Sink; 4 | import org.apache.maven.plugin.MojoExecutionException; 5 | import org.apache.maven.plugin.MojoFailureException; 6 | import org.apache.maven.reporting.MavenReport; 7 | import org.apache.maven.reporting.MavenReportException; 8 | 9 | import java.io.*; 10 | import java.util.List; 11 | import java.util.Locale; 12 | import java.util.ResourceBundle; 13 | 14 | import static org.scalatest.tools.maven.MojoUtils.*; 15 | 16 | /** 17 | * A reporting mojo to capture the ScalaTest output as a file that integrates into the Maven site of a project. 18 | * 19 | * @author Jon-Anders Teigen 20 | * @author Sean Griffin 21 | * @author Mike Pilquist 22 | * @author Bill Venners 23 | * @phase site 24 | * @goal reporter 25 | */ 26 | public class ReporterMojo extends AbstractScalaTestMojo implements MavenReport { 27 | 28 | /** 29 | * Directory where reports will go. 30 | * 31 | * @parameter property="project.reporting.outputDirectory" 32 | * @required 33 | * @readonly 34 | */ 35 | private File reportingOutputDirectory; 36 | 37 | /** 38 | * Consists of an optional configuration parameters for the file reporter. 39 | * For more info on configuring reporters, see the ScalaTest documentation. 40 | * @parameter property="fileReporterOptions" 41 | */ 42 | private String fileReporterOptions; 43 | 44 | public void execute() throws MojoExecutionException, MojoFailureException { 45 | // no op, Maven doesn't even call this method but I have to implement it because it's on the interface. 46 | } 47 | 48 | public void generate(Sink sink, Locale locale) throws MavenReportException { 49 | try { 50 | runScalaTest(configuration()); 51 | } 52 | catch (MojoFailureException e) { 53 | throw new MavenReportException("Failure executing ScalaTest", e); 54 | } 55 | catch (RuntimeException e) { 56 | throw new MavenReportException("Failure executing ScalaTest", e); 57 | } 58 | 59 | // ScalaTest outputs plain text but the Mojo requires HTML output so we'll create a bare-bones HTML doc and 60 | // embed the ScalaTest output inside a
 in that doc.
 61 | 
 62 |         try {
 63 |             sink.head();
 64 |             sink.title();
 65 |             sink.text(getLocalizedString(locale, "reporter.mojo.outputTitle"));
 66 |             sink.title_();
 67 |             sink.head_();
 68 | 
 69 |             sink.body();
 70 |             sink.sectionTitle1();
 71 |             sink.text(getLocalizedString(locale, "reporter.mojo.outputTitle"));
 72 |             sink.sectionTitle1_();
 73 |             sink.verbatim(false);
 74 |             sink.text(getScalaTestOutputFromFile());
 75 |             sink.verbatim_();
 76 |             sink.body_();
 77 | 
 78 |             sink.flush();
 79 |             sink.close();
 80 |         }
 81 |         catch (IOException ioe) {
 82 |             throw new MavenReportException("Failure generating ScalaTest report", ioe);
 83 |         }
 84 |     }
 85 | 
 86 |     private String[] configuration() {
 87 |         return concat(
 88 |                 sharedConfiguration(),
 89 |                 fileReporterConfig()
 90 |         );
 91 |     }
 92 | 
 93 |     private List fileReporterConfig() {
 94 |         File tmpDir = new File(System.getProperty("java.io.tmpdir"));
 95 |         if (fileReporterOptions != null) {
 96 |             return reporterArg("-f", fileReporterOptions + " tempScalaTestOutput.txt", fileRelativeTo(tmpDir));
 97 |         }
 98 |         return reporterArg("-f", "tempScalaTestOutput.txt", fileRelativeTo(tmpDir));
 99 |     }
100 | 
101 |     private String getScalaTestOutputFromFile() throws IOException {
102 |         StringWriter fileContents = new StringWriter(1024);
103 |         PrintWriter writer = new PrintWriter(fileContents, true);
104 | 
105 |         // ScalaTest's FileReporter uses default character encoding so that's what we'll use here, too.
106 |         File outputFile = new File(System.getProperty("java.io.tmpdir"), "tempScalaTestOutput.txt");
107 |         BufferedReader reader = new BufferedReader(new FileReader(outputFile));
108 | 
109 |         try {
110 |             String line = null;
111 |             while ((line = reader.readLine()) != null) {
112 |                 writer.println(line);
113 |             }
114 |             return fileContents.toString();
115 |         }
116 |         finally {
117 |             try {
118 |                 reader.close();
119 |                 outputFile.delete();
120 |             }
121 |             catch (IOException ignored) {}
122 |         }
123 |     }
124 | 
125 |     public String getOutputName() {
126 |         return "scalatest-output";
127 |     }
128 | 
129 |     public String getCategoryName() {
130 |         return CATEGORY_PROJECT_REPORTS;
131 |     }
132 | 
133 |     public String getName(Locale locale) {
134 |         return getLocalizedString(locale, "reporter.mojo.name");
135 |     }
136 | 
137 |     public String getDescription(Locale locale) {
138 |         return getLocalizedString(locale, "reporter.mojo.description");
139 |     }
140 | 
141 |     public void setReportOutputDirectory(File outputDirectory) {
142 |         reportingOutputDirectory = outputDirectory;
143 |     }
144 | 
145 |     public File getReportOutputDirectory() {
146 |         return reportingOutputDirectory;
147 |     }
148 | 
149 |     public boolean isExternalReport() {
150 |         return false;
151 |     }
152 | 
153 |     public boolean canGenerateReport() {
154 |         return true;
155 |     }
156 | 
157 |     private String getLocalizedString(Locale locale, String resourceKey) {
158 |         return ResourceBundle.getBundle("mojoResources", locale, getClass().getClassLoader()).getString(resourceKey);
159 |     }
160 | }
161 | 


--------------------------------------------------------------------------------
/src/main/java/org/scalatest/tools/maven/TestMojo.java:
--------------------------------------------------------------------------------
  1 | package org.scalatest.tools.maven;
  2 | 
  3 | import org.apache.maven.plugin.MojoFailureException;
  4 | 
  5 | import java.io.File;
  6 | import java.io.FileWriter;
  7 | import java.io.IOException;
  8 | import java.io.Writer;
  9 | import java.util.ArrayList;
 10 | import java.util.Collections;
 11 | import java.util.List;
 12 | 
 13 | import static java.util.Collections.singletonList;
 14 | import static java.util.Collections.unmodifiableList;
 15 | import static org.scalatest.tools.maven.MojoUtils.*;
 16 | 
 17 | /**
 18 |  * Provides a bridge between Maven and the command-line form of ScalaTest's Runner.
 19 |  * Many of the configuration options available on this goal
 20 |  * are directly reflected in the Runner ScalaDoc on http://www.scalatest.org.
 21 |  *
 22 |  * @author Sean Griffin
 23 |  * @author Mike Pilquist
 24 |  * @author Jon-Anders Teigen
 25 |  * @author Bill Venners
 26 |  * @phase test
 27 |  * @goal test
 28 |  * @threadSafe
 29 |  */
 30 | public class TestMojo extends AbstractScalaTestMojo {
 31 | 
 32 |     /**
 33 |      * Output directory in which ScalaTest file reports should be written to.  Passed to ScalaTest via the -f argument.
 34 |      * @parameter default-value="${project.build.directory}/scalatest-reports" property="scalatest.reportsDirectory"
 35 |      * @required
 36 |      */
 37 |     File reportsDirectory;
 38 | 
 39 |     /**
 40 |      * Set to true to skip execution of tests.
 41 |      * @parameter property="skipTests"
 42 |      */
 43 |     boolean skipTests;
 44 | 
 45 |     /**
 46 |      * Set to true to avoid failing the build when tests fail
 47 |      * @parameter property="maven.test.failure.ignore"
 48 |      */
 49 |     boolean testFailureIgnore;
 50 | 
 51 |     /**
 52 |      * Set to true to avoid failing the build when ScalaTest is not available on classpath
 53 |      * @parameter property="noScalaTestIgnore"
 54 |      */
 55 |     boolean noScalaTestIgnore;
 56 | 
 57 |     /**
 58 |      * Comma separated list of filereporters. A filereporter consists of an optional
 59 |      * configuration and a mandatory filename, separated by a whitespace. E.g all.txt,XE ignored_and_pending.txt
 60 |      * For more info on configuring reporters, see the scalatest documentation.
 61 |      * @parameter property="filereports"
 62 |      */
 63 |     String filereports;
 64 | 
 65 |     /**
 66 |      * Comma separated list of htmlreporters.  An htmlreporter
 67 |      * consists of a mandatory directory and an optional css file
 68 |      * name, separated by whitespace. E.g:
 69 |      * 
 70 |      *   <htmlreporters>
 71 |      *     target/htmldir,
 72 |      *     target/myhtmldir src/my.css
 73 |      *   </htmlreporters>
 74 |      * 
 75 |      * For more info on configuring reporters, see the scalatest documentation.
 76 |      * @parameter property="htmlreporters"
 77 |      */
 78 |     String htmlreporters;
 79 | 
 80 |     /**
 81 |      * Comma separated list of reporters. A reporter consist of an optional configuration
 82 |      * and a mandatory reporter classname, separated by whitespace. The reporter classname
 83 |      * must be the fully qualified name of a class extending org.scalatest.Reporter
 84 |      * E.g C my.SuccessReporter,my.EverythingReporter
 85 |      * For more info on configuring reporters, see the ScalaTest documentation.
 86 |      * @parameter property="reporters"
 87 |      */
 88 |     String reporters;
 89 | 
 90 |     /**
 91 |      * Comma separated list of junitxml. A junitxml consists of an optional configuration
 92 |      * and a mandatory directory for the xml files, separated by whitespace.
 93 |      * For more info on configuring reporters, see the scalatest documentation.
 94 |      * @parameter property="junitxml"
 95 |      */
 96 |     String junitxml;
 97 | 
 98 |     /**
 99 |      * Configuration for logging to stdout. (This logger is always enabled)
100 |      * For more info on configuring reporters, see the scalatest documentation.
101 |      * @parameter property="stdout"
102 |      */
103 |     String stdout;
104 | 
105 |     /**
106 |      * Configuration for logging to stderr. It is disabled by default, but will be enabled
107 |      * when configured. Empty configuration just means enable.
108 |      * For more info on configuring reporters, see the scalatest documentation.
109 |      * @parameter property="stderr"
110 |      */
111 |     String stderr;
112 | 
113 |     /**
114 |      * Set this to "true" to redirect the unit test standard output to a file
115 |      * (found in reportsDirectory/scalatest-output.txt by default).
116 |      * 

117 | * NOTE: Works only if forkMode="once" 118 | * 119 | * @parameter property="maven.test.redirectTestOutputToFile" default-value="false" 120 | */ 121 | boolean redirectTestOutputToFile; 122 | 123 | /** 124 | * Name of the file where the test output is redirected if enabled 125 | * 126 | * @parameter default-value="scalatest-output.txt" 127 | */ 128 | String testOutputFileName; 129 | 130 | public void execute() throws MojoFailureException { 131 | getLog().info("ScalaTest report directory: " + reportsDirectory); 132 | 133 | if (skipTests) { 134 | getLog().info("Tests are skipped."); 135 | } 136 | else if (noScalaTestIgnore) { 137 | if (isScalaTestAvailable()) { 138 | if (!runScalaTest(configuration()) && !testFailureIgnore) { 139 | throw new MojoFailureException("There are test failures"); 140 | } 141 | } 142 | else 143 | getLog().info("Skipped because ScalaTest not available on classpath."); 144 | } 145 | else { 146 | if (!runScalaTest(configuration()) && !testFailureIgnore) { 147 | if (isScalaTestAvailable()) 148 | throw new MojoFailureException("There are test failures"); 149 | else 150 | throw new MojoFailureException("Failure because ScalaTest not available on classpath."); 151 | } 152 | } 153 | } 154 | 155 | String[] configuration() { 156 | return concat( 157 | sharedConfiguration(), 158 | stdout(), 159 | stderr(), 160 | filereports(), 161 | htmlreporters(), 162 | reporters(), 163 | junitxml() 164 | ); 165 | } 166 | 167 | // These private methods create the relevant portion of the command line 168 | // to pass to Runner based on the corresponding Maven configuration parameter. 169 | private List stdout() { 170 | final String stdoutProcessed = maybeRemoveAnsiCodes(stdout); 171 | return unmodifiableList(singletonList(stdoutProcessed == null ? "-o" : "-o" + stdoutProcessed)); 172 | } 173 | 174 | private List stderr() { 175 | return stderr == null ? Collections.emptyList() : unmodifiableList(singletonList("-e" + stderr)); 176 | } 177 | 178 | private String maybeRemoveAnsiCodes(String streamParams) { 179 | return redirectTestOutputToFile 180 | ? maybeAppendLetter(streamParams, "W") 181 | : streamParams; 182 | } 183 | 184 | private String maybeAppendLetter(String string, String letter) { 185 | if (string == null) { 186 | return letter; 187 | } 188 | 189 | if (string.contains(letter)) { 190 | return string; 191 | } 192 | 193 | return string + letter; 194 | } 195 | 196 | private List filereports() { 197 | return unmodifiableList(reporterArg("-f", filereports, fileRelativeTo(reportsDirectory))); 198 | } 199 | 200 | private List htmlreporters() { 201 | List r = new ArrayList(); 202 | 203 | for (String arg : splitOnComma(htmlreporters)) { 204 | String[] split = arg.split("\\s+"); 205 | 206 | if (split.length > 0) { 207 | r.add("-h"); 208 | r.add(split[0]); 209 | 210 | if (split.length > 1) { 211 | r.add("-Y"); 212 | r.add(split[1]); 213 | } 214 | } 215 | } 216 | return unmodifiableList(r); 217 | } 218 | 219 | private List reporters() { 220 | return reporterArg("-C", reporters, passThrough); 221 | } 222 | 223 | private List junitxml(){ 224 | return reporterArg("-u", junitxml, dirRelativeTo(reportsDirectory)); 225 | } 226 | 227 | protected Writer getOutputWriter() throws MojoFailureException { 228 | return redirectTestOutputToFile ? newFileWriter() : super.getOutputWriter(); 229 | } 230 | 231 | private Writer newFileWriter() throws MojoFailureException { 232 | final File outputFile = new File(reportsDirectory, testOutputFileName); 233 | 234 | if (!reportsDirectory.exists() && !reportsDirectory.mkdirs()) { 235 | throw new MojoFailureException("Unable to create directory path: " + reportsDirectory); 236 | } 237 | 238 | try { 239 | return new FileWriter(outputFile); 240 | } catch (IOException e) { 241 | throw new MojoFailureException("Unable to access the output file: '" + outputFile + "'", e); 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /src/main/resources/mojoResources.properties: -------------------------------------------------------------------------------- 1 | reporter.mojo.name = ScalaTest Results 2 | reporter.mojo.description = The test results from the ScalaTest run 3 | reporter.mojo.outputTitle = ScalaTest Results -------------------------------------------------------------------------------- /src/site/apt/usage.apt: -------------------------------------------------------------------------------- 1 | Usage Documentation 2 | 3 | Replacing the use of Maven's Surefire plugin with this plugin involves two simple steps: 4 | 5 | [[1]] Disable the maven-surefire-plugin 6 | 7 | [[2]] Configure this scalatest-maven-plugin to run in the test phase 8 | 9 | [] 10 | 11 | To replace the maven-surefire-report-plugin with this plugin, simply add the scalatest-maven-plugin instead of 12 | the maven-surefire-report-plugin to the reporting section of the POM. 13 | 14 | For example, in the build section of the POM, add something like the following: 15 | 16 | +-- 17 | 18 | ... 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-surefire-plugin 24 | 25 | true 26 | 27 | 28 | 29 | 30 | 31 | org.scalatest 32 | scalatest-maven-plugin 33 | 34 | 35 | 36 | test 37 | 38 | 39 | ... 40 | 41 | 42 | 43 | 44 | 45 | ... 46 | 47 | +-- 48 | 49 | The important item in the above POM definition is the \ configuration specified 50 | on the maven-surefire-plugin. There is nothing inherently wrong in having Surefire run your 51 | tests, but if you want all your tests to run through ScalaTest instead, then disabling Surefire 52 | in this manner will keep your tests from running twice. Since the "test" goal of the 53 | scalatest-maven-plugin is tied to the test phase by default you do not need to do this explicitly 54 | in your POM. 55 | 56 | Optionally, in the reporting section of the POM you can add something like the following: 57 | 58 | +-- 59 | 60 | ... 61 | 62 | 63 | org.scalatest 64 | scalatest-maven-plugin 65 | 66 | ... 67 | 68 | 69 | 70 | ... 71 | 72 | +-- 73 | 74 | Adding this configuration will tell the plugin's "reporter" goal to execute during 75 | site generation. This goal will run the tests and output the results to an HTML file that 76 | will link into the project's site. ScalaTest does not yet have an HTML Reporter implementation, 77 | so this goal will instead embed the plain text output of ScalaTest's FileReporter into a \ 78 | element in a wrapper HTML page with seamless incorporation into Maven's site infrastructure. 79 | 80 | <> Adding the reporter goal will, like the default behavior of maven-surefire-report-plugin, cause 81 | your tests to run twice: once in the test phase and again in the site phase. Unlike the maven-surefire-report-plugin, 82 | the reporter goal of this plugin have a "report-only" configuration option to incorporate the test 83 | results of the prior run. 84 | 85 | * Customizing ScalaTest 86 | 87 | While using this plugin does allow Maven to execute your tests without the need to 88 | use the "@RunWith(classOf[JUnitRunner])" boilerplate at the top of every test class, which is certainly 89 | an advantage, the main benefit of this plugin is that it allows you to leverage the customization 90 | options of ScalaTest's Runner class as part of the standard Maven build. It is true that through either 91 | the exec-maven-plugin or the "run" goal of the maven-scala-plugin you could launch the Runner class 92 | with command-line arguments tailored to your preferences, but that approach is not integrated with the 93 | Maven lifecycle; it's a manual step, test failures will not fail your build, and the test results 94 | will not be included in your project site. This plugin addresses those problems. 95 | 96 | The configuration options available to each of the goals are included in the goal documentation, but generally 97 | speaking, all or at least most of the command line arguments available on the Runner class are exposed 98 | as options on the "test" and "gui" goals. Creative use of these configuration options can allow you to 99 | run your "fast" tests in one Maven profile and your "slow" tests in a different Maven profile or to filter 100 | certain suites from the execution. 101 | 102 | For example, let's say that you have some tests tagged with a "Slow" Tag and others tagged with a "Fast" Tag. 103 | All the goals in this plugin support the "includes" and "excludes" configuration options, which map to the -n 104 | and -l Runner command-line arguments, respectively. Now let's also say that you want to run your "Fast" tests 105 | on every SCM commit while only running the "Slow" tests manually or from a nightly build. Using Maven profiles, 106 | you can configure your POM similar to the following to accomplish this objective: 107 | 108 | +-- 109 | 110 | ... 111 | 112 | org.scalatest 113 | scalatest-maven-plugin 114 | 115 | 116 | 117 | test 118 | 119 | 120 | test-results 121 | Slow 122 | 123 | 124 | 125 | 126 | ... 127 | 128 | ... 129 | 130 | 131 | nightly-build 132 | 133 | 134 | 135 | org.scalatest 136 | scalatest-maven-plugin 137 | 138 | 139 | 140 | test 141 | 142 | 143 | test-results 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | +-- 154 | 155 | The "test" and "gui" goals support multiple Reporters of different types and formatting options for each 156 | of those Reporters. For example, given this elaborate Reporter configuration 157 | 158 | +-- 159 | NCXEHLOWFD test-results/text/constrained.txt,test-results/text/full.txt 160 | test-results/xml 161 | +-- 162 | 163 | the test results will be written to three locations: 164 | 165 | [[1]] the constrained.txt file in the test-results/text directory with the NCXEHLOWFD Reporting options applied 166 | 167 | [[2]] the full.txt file in the test-results/text directory with no Reporting options applied 168 | 169 | [[3]] the test-results/xml directory as a set of files that adhere to the JUnit XML format 170 | 171 | [] 172 | 173 | The "reporter" goal does not support this level of customization, however, because it doesn't really apply. 174 | Instead, this goal has a "fileReporterOptions" option that allows you to specify the formatting options to 175 | pass to the FileReporter. The plugin itself controls the name of that file, and the location of the file 176 | is configured through the standard "reportOutputDirectory" as is convention in report goals of other plugins. 177 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/test/scala/org/scalatest/tools/maven/MojoUtilsTest.scala: -------------------------------------------------------------------------------- 1 | package org.scalatest.tools.maven 2 | 3 | import org.junit.contrib.java.lang.system.{ClearSystemProperties, EnvironmentVariables} 4 | import org.junit.{Rule, Test} 5 | 6 | class MojoUtilsTest { 7 | val _env: EnvironmentVariables = new EnvironmentVariables() 8 | val _sys: ClearSystemProperties = new ClearSystemProperties("java.home") 9 | 10 | @Rule 11 | def env: EnvironmentVariables = _env 12 | 13 | @Rule 14 | def sys: ClearSystemProperties = _sys 15 | 16 | @Test 17 | def getJvmHappyPath(): Unit = { 18 | env.clear("JAVA_HOME") 19 | System.setProperty("java.home", "/test/jvm") 20 | assert(MojoUtils.getJvm == "/test/jvm/bin/java") 21 | } 22 | 23 | @Test 24 | def getJvmWithoutJavaHome(): Unit = { 25 | env.clear("JAVA_HOME") 26 | assert(MojoUtils.getJvm == "java") 27 | } 28 | 29 | @Test 30 | def getJvmFromEnvironment(): Unit = { 31 | env.clear("JAVA_HOME") 32 | env.set("JAVA_HOME", "/opt/jdk-11") 33 | Console.print(MojoUtils.getJvm) 34 | assert(MojoUtils.getJvm == "/opt/jdk-11/bin/java") 35 | } 36 | 37 | @Test 38 | def getJvmJavaHomeIsPriority(): Unit = { 39 | System.setProperty("java.home", "/test/jvm") 40 | env.set("JAVA_HOME", "/opt/jdk-11") 41 | assert(MojoUtils.getJvm == "/test/jvm/bin/java") 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/scala/org/scalatest/tools/maven/PluginMatchers.scala: -------------------------------------------------------------------------------- 1 | package org.scalatest.tools.maven 2 | 3 | import org.scalatest.matchers.{MatchResult, Matcher} 4 | 5 | /** 6 | * @author Jon-Anders Teigen 7 | */ 8 | trait PluginMatchers { 9 | def containSlice(slice: String*) = new Matcher[Array[String]] { 10 | def apply(seq: Array[String]) = { 11 | MatchResult( 12 | seq containsSlice slice, 13 | "The " + seq + " did not contain the slice " + slice, 14 | "The " + seq + " did contain the slice " + slice 15 | ) 16 | } 17 | } 18 | 19 | def containCompoundArgs(name:String, values:String*) = new Matcher[Array[String]] { 20 | def apply(seq: Array[String]) = { 21 | MatchResult( 22 | seq containsSlice List(name,values.mkString(" ")), 23 | "The compoundArgs for " + name + " and " + values.mkString(" ") + " where not found in " + seq, 24 | "The compoundArgs for " + name + " and " + values.mkString(" ") + " where found in " + seq 25 | ) 26 | } 27 | } 28 | 29 | def containSuiteArgs(name:String, values:String*) = new Matcher[Array[String]] { 30 | def apply(seq: Array[String]) = { 31 | MatchResult( 32 | values.forall(v => seq.containsSlice(List(name, v))), 33 | "The suiteArgs " + name +" "+ values.mkString(" ") + " were not all found in " + seq, 34 | "The suiteArgs for " + name +" "+ values.mkString(" ") + " were all found in " + seq 35 | ) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/scala/org/scalatest/tools/maven/PluginTest.scala: -------------------------------------------------------------------------------- 1 | package org.scalatest.tools.maven 2 | 3 | import java.io.File 4 | import org.scalatest.matchers.should.Matchers 5 | import org.scalatestplus.junit.JUnit3Suite 6 | import java.util.ArrayList 7 | import org.scalatest.BeforeAndAfterAll 8 | 9 | /** 10 | * @author Jon -Anders Teigen 11 | */ 12 | final class PluginTest 13 | extends JUnit3Suite 14 | with BeforeAndAfterAll 15 | with Matchers 16 | with PluginMatchers { 17 | val tmpDir = new File(System.getProperty("java.io.tmpdir")) 18 | val reportsDirectory = new File(tmpDir, "reportsDirectory") 19 | val baseDir = new File(tmpDir, "basedir"); 20 | val testOutputDirectory = { 21 | val dir = new File(reportsDirectory, "testOutputDirectory") 22 | dir.mkdirs() 23 | dir.getAbsolutePath 24 | } 25 | val outputDirectory = { 26 | val dir = new File(reportsDirectory, "outputDirectory") 27 | dir.mkdirs() 28 | dir.getAbsolutePath 29 | } 30 | 31 | override def afterAll() { 32 | def delete(it: File) { 33 | if (it.isFile) { 34 | it.delete() 35 | } else { 36 | for (d <- it.listFiles) 37 | delete(d) 38 | } 39 | } 40 | delete(reportsDirectory) 41 | delete(baseDir); 42 | } 43 | 44 | def jlist(a: String*) = new ArrayList[String]() {for (e <- a) this.add(e)} 45 | 46 | def comma(a: String*) = a mkString "," 47 | 48 | def configure(m: TestMojo => Unit) = { 49 | val mojo = new TestMojo 50 | mojo.reportsDirectory = reportsDirectory 51 | mojo.testOutputDirectory = new File(testOutputDirectory) 52 | mojo.outputDirectory = new File(outputDirectory) 53 | m(mojo) 54 | mojo.configuration 55 | } 56 | 57 | def testDefault { 58 | val config = configure(_ => ()) 59 | config should contain("-o") 60 | config should containCompoundArgs("-R", outputDirectory, testOutputDirectory) 61 | config should have length (3) 62 | } 63 | 64 | def testConfigs { 65 | val config = configure(_.config = comma("foo=bar", "monkey=donkey")) 66 | config should contain("-Dfoo=bar") 67 | config should contain("-Dmonkey=donkey") 68 | } 69 | 70 | def testRunpath { 71 | configure(_.runpath = comma("http://foo.com/my.jar", "/some/where")) should containCompoundArgs("-R", outputDirectory, testOutputDirectory, "http://foo.com/my.jar", "/some/where") 72 | } 73 | 74 | def testFilereporters { 75 | val config = configure(_.filereports = comma("foo.txt", "YZT some.txt")) 76 | config should containSlice("-f", new File(reportsDirectory, "foo.txt").getAbsolutePath) 77 | config should containSlice("-fYZT", new File(reportsDirectory, "some.txt").getAbsolutePath) 78 | } 79 | 80 | def testHtmlreporters { 81 | val config = configure(_.htmlreporters = 82 | comma("target/htmldir", "target/myhtmldir src/resources/my.css")) 83 | 84 | config should containSlice("-h", "target/htmldir") 85 | config should containSlice("-h", "target/myhtmldir", 86 | "-Y", "src/resources/my.css") 87 | } 88 | 89 | def testReporters { 90 | val config = configure(_.reporters = comma("YZT org.my.reporter", "org.your.reporter")) 91 | config should containSlice("-CYZT", "org.my.reporter") 92 | config should containSlice("-C", "org.your.reporter") 93 | } 94 | 95 | def testJUnitXmlReporters { 96 | val config = configure(_.junitxml = comma("some/foo.xml", "XYZ other.xml")) 97 | config should containSlice("-u", new File(reportsDirectory, "some/foo.xml").getAbsolutePath) 98 | config should containSlice("-uXYZ", new File(reportsDirectory, "other.xml").getAbsolutePath) 99 | } 100 | 101 | def testStdOutReporter { 102 | configure(_.stdout = "GUP") should contain("-oGUP") 103 | } 104 | 105 | def testStdOutReporterWithRedirect { 106 | configure(_.redirectTestOutputToFile = true) should contain("-oW") 107 | } 108 | 109 | def testStdErrReporter { 110 | configure(_.stderr = "BIS") should contain("-eBIS") 111 | } 112 | 113 | def testIncludes { 114 | configure(_.tagsToInclude = comma("a", "b", "c")) should containCompoundArgs("-n", "a", "b", "c") 115 | } 116 | 117 | def testExcludes { 118 | configure(_.tagsToExclude = comma("a", "b", "c")) should containCompoundArgs("-l", "a", "b", "c") 119 | } 120 | 121 | def testConcurrent { 122 | configure(_.parallel = true) should contain("-P") 123 | configure(_.parallel = false) should not contain ("-P") 124 | } 125 | 126 | def testConcurrentSuiteSorting { 127 | configure { m => 128 | m.parallel = true 129 | m.suiteSorting = true 130 | } should containSlice("-PS") 131 | } 132 | 133 | def testConcurrentThreadCount { 134 | configure { m => 135 | m.parallel = true 136 | m.threadCount = 4 137 | } should containSlice("-P4") 138 | } 139 | 140 | def testConcurrentSuiteSortingThreadCount { 141 | configure { m => 142 | m.parallel = true 143 | m.suiteSorting = true 144 | m.threadCount = 4 145 | } should containSlice("-PS4") 146 | } 147 | 148 | def testSuiteSorting { 149 | // Suite sorting count should have no effect if parallel is not set to true. 150 | configure { m => 151 | m.suiteSorting = true 152 | } shouldNot containSlice ("-PS") 153 | } 154 | 155 | def testSuiteSortingThreadCount { 156 | // Suite sorting and thread count should have no effect if parallel is not set to true. 157 | configure { m => 158 | m.suiteSorting = true 159 | m.threadCount = 4 160 | } shouldNot containSlice ("-PS4") 161 | } 162 | 163 | def testThreadCount { 164 | // Thread count should have no effect if parallel is not set to true. 165 | configure { m => 166 | m.threadCount = 4 167 | } shouldNot containSlice ("-P4") 168 | } 169 | 170 | def testSuites { 171 | val suites: String = comma(" a ", 172 | "b", 173 | "foo @bar baz", 174 | " zowie\n zip zap ") 175 | 176 | val config = configure(_.suites = suites) 177 | 178 | config should containSlice ("-s", "a") 179 | config should containSlice ("-s", "b") 180 | config should containSlice ("-s", "foo", "-t", "bar baz") 181 | config should containSlice ("-s", "zowie", "-z", "zip zap") 182 | } 183 | 184 | def testSuitesAndTests { 185 | val suites: String = comma(" a ", "b c") 186 | val tests: String = comma(" d ", "@e") 187 | 188 | val config = configure(x => {x.suites = suites; x.tests = tests}) 189 | 190 | config should containSlice ("-z", "d", 191 | "-t", "e", 192 | "-s", "a", 193 | "-s", "b", "-z", "c") 194 | } 195 | 196 | def testTests { 197 | val tests: String= comma(" @a ", " b ", "@c") 198 | 199 | val config = configure(_.tests = tests) 200 | 201 | config should containSlice("-t", "a") 202 | config should containSlice("-z", "b") 203 | config should containSlice("-t", "c") 204 | } 205 | 206 | // 207 | // Verify that a comma can be escaped with a backslash in order to 208 | // support a test name that contains a comma. 209 | // 210 | def testTestsWithCommas { 211 | configure(_.tests = comma("a\\, bc", "b", "c")) should containSuiteArgs("-z", "a, bc", "b", "c") 212 | } 213 | 214 | def testSuffixes { 215 | configure(_.suffixes = "(?