summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/pages/2 - Configuring Mill.md71
-rw-r--r--scalalib/src/JavaModule.scala34
2 files changed, 74 insertions, 31 deletions
diff --git a/docs/pages/2 - Configuring Mill.md b/docs/pages/2 - Configuring Mill.md
index f6ca86a0..0df98a5c 100644
--- a/docs/pages/2 - Configuring Mill.md
+++ b/docs/pages/2 - Configuring Mill.md
@@ -7,11 +7,11 @@ import mill._, scalalib._
object foo extends ScalaModule {
def scalaVersion = "2.12.4"
-
+
def scalacOptions = Seq("-Ydelambdafy:inline")
-
+
def forkArgs = Seq("-Xmx4g")
-
+
def forkEnv = Map("HELLO_MY_ENV_VAR" -> "WORLD")
}
```
@@ -74,8 +74,8 @@ def repositories = super.repositories ++ Seq(
)
```
-To add custom resolvers to the initial bootstrap of the build, you can create a
-custom `ZincWorkerModule`, and override the `zincWorker` method in your
+To add custom resolvers to the initial bootstrap of the build, you can create a
+custom `ZincWorkerModule`, and override the `zincWorker` method in your
`ScalaModule` by pointing it to that custom object:
```scala
@@ -84,7 +84,7 @@ import coursier.maven.MavenRepository
object CustomZincWorkerModule extends ZincWorkerModule {
def repositories() = super.repositories ++ Seq(
MavenRepository("https://oss.sonatype.org/content/repositories/releases")
- )
+ )
}
object YourBuild extends ScalaModule {
@@ -101,7 +101,7 @@ import mill._, scalalib._
object foo extends ScalaModule {
def scalaVersion = "2.12.4"
- object test extends Tests {
+ object test extends Tests {
def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.6.0")
def testFrameworks = Seq("utest.runner.Framework")
}
@@ -163,11 +163,11 @@ import mill._, scalalib._
object foo extends ScalaModule {
def scalaVersion = "2.12.4"
- object test extends Tests {
+ object test extends Tests {
def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.6.0")
def testFrameworks = Seq("utest.runner.Framework")
}
- object integration extends Tests {
+ object integration extends Tests {
def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.6.0")
def testFrameworks = Seq("utest.runner.Framework")
}
@@ -182,21 +182,46 @@ configuration options apply.
## Custom Test Frameworks
+Integrating with test frameworks like Scalatest or specs2 is simply a matter of adding it
+to `ivyDeps` and specifying the `testFrameworks` you want to use.
+
+Scalatest example:
+
+
```scala
// build.sc
import mill._, scalalib._
object foo extends ScalaModule {
def scalaVersion = "2.12.4"
- def ivyDeps = Agg(ivy"org.scalatest::scalatest:3.0.4")
- def testFrameworks = Seq("org.scalatest.tools.Framework")
+
+ object test extends Tests {
+ def ivyDeps = Agg(ivy"org.scalatest::scalatest:3.0.4")
+ def testFrameworks = Seq("org.scalatest.tools.Framework")
+ }
}
```
-Integrating with test frameworks like Scalatest is simply a matter of adding it
-to `ivyDeps` and specifying the `testFrameworks` you want to use. After that you
-can [add a test suite](#adding-a-test-suite) and `mill foo.test` as usual,
-passing args to the test suite via `mill foo.test arg1 arg2 arg3`
+Specs2 example:
+
+```scala
+// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = "2.12.4"
+
+ object test extends Tests {
+ def ivyDeps = Agg(ivy"org.specs2::specs2-core:4.6.0")
+ def testFrameworks = Seq("org.specs2.runner.Specs2Framework")
+ def scalacOptions = foo.scalacOptions() ++ Seq(
+ "-Yrangepos" // Required by specs2
+ )
+ }
+}
+```
+
+After that, you can follow the instructions in [add a test suite](#adding-a-test-suite), and use `mill foo.test` as usual, or pass args to the test suite via `mill foo.test arg1 arg2 arg3`.
## Scala Compiler Plugins
@@ -206,7 +231,7 @@ import mill._, scalalib._
object foo extends ScalaModule {
def scalaVersion = "2.12.4"
-
+
def compileIvyDeps = Agg(ivy"com.lihaoyi::acyclic:0.1.7")
def scalacOptions = Seq("-P:acyclic:force")
def scalacPluginIvyDeps = Agg(ivy"com.lihaoyi::acyclic:0.1.7")
@@ -252,7 +277,7 @@ import mill._, scalalib._
trait CommonModule extends ScalaModule {
def scalaVersion = "2.12.4"
}
-
+
object foo extends CommonModule
object bar extends CommonModule {
def moduleDeps = Seq(foo)
@@ -267,11 +292,11 @@ the same testing framework, etc. and all that can be extracted out into the
## Global configuration
-Mill builds on ammonite which allows you to
-[define global configuration](http://ammonite.io/#ScriptPredef). Depending on
-how you start mill 2 different files will be loaded. For interactive mode it's
-`~/.mill/ammonite/predef.sc` and from the command line it's
-`~/.mill/ammonite/predefScript.sc`. You might want to create a symlink from one
+Mill builds on ammonite which allows you to
+[define global configuration](http://ammonite.io/#ScriptPredef). Depending on
+how you start mill 2 different files will be loaded. For interactive mode it's
+`~/.mill/ammonite/predef.sc` and from the command line it's
+`~/.mill/ammonite/predefScript.sc`. You might want to create a symlink from one
to the other to avoid duplication.
Example `~/.mill/ammonite/predef.sc`
@@ -300,7 +325,7 @@ object foo extends ScalaModule {
}
def lineCount = T {
-
+
foo.sources().flatMap(ref => os.walk(ref.path)).filter(_.isFile).flatMap(read.lines).size
}
diff --git a/scalalib/src/JavaModule.scala b/scalalib/src/JavaModule.scala
index 051f6804..54fd5943 100644
--- a/scalalib/src/JavaModule.scala
+++ b/scalalib/src/JavaModule.scala
@@ -5,8 +5,7 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import coursier.Repository
-import mill.define.Task
-import mill.define.TaskModule
+import mill.define.{Command, Task, TaskModule}
import mill.eval.{PathRef, Result}
import mill.modules.{Assembly, Jvm}
import mill.modules.Jvm.{createAssembly, createJar}
@@ -567,9 +566,29 @@ trait TestModule extends JavaModule with TaskModule {
def testFrameworks: T[Seq[String]]
/**
* Discovers and runs the module's tests in a subprocess, reporting the
- * results to the console
+ * results to the console.
+ * @see [[testCached]]
*/
- def test(args: String*) = T.command{
+ def test(args: String*): Command[(String, Seq[TestRunner.Result])] = T.command {
+ testTask(T.task{args})()
+ }
+
+ /**
+ * Args to be used by [[testCached]].
+ */
+ def testCachedArgs: T[Seq[String]] = T{ Seq[String]() }
+
+ /**
+ * Discovers and runs the module's tests in a subprocess, reporting the
+ * results to the console.
+ * If no input has changed since the last run, no test were executed.
+ * @see [[test()]]
+ */
+ def testCached: T[(String, Seq[TestRunner.Result])] = T {
+ testTask(testCachedArgs)()
+ }
+
+ protected def testTask(args: Task[Seq[String]]): Task[(String, Seq[TestRunner.Result])] = T.task {
val outputPath = T.ctx().dest/"out.json"
Jvm.runSubprocess(
@@ -582,8 +601,8 @@ trait TestModule extends JavaModule with TaskModule {
testFrameworks() ++
Seq(runClasspath().length.toString) ++
runClasspath().map(_.path.toString) ++
- Seq(args.length.toString) ++
- args ++
+ Seq(args().length.toString) ++
+ args() ++
Seq(outputPath.toString, T.ctx().log.colored.toString, compile().classes.path.toString, T.ctx().home.toString),
workingDir = forkWorkingDir()
)
@@ -595,14 +614,13 @@ trait TestModule extends JavaModule with TaskModule {
}catch{case e: Throwable =>
Result.Failure("Test reporting failed: " + e)
}
-
}
/**
* Discovers and runs the module's tests in-process in an isolated classloader,
* reporting the results to the console
*/
- def testLocal(args: String*) = T.command{
+ def testLocal(args: String*) = T.command {
val outputPath = T.ctx().dest/"out.json"
val (doneMsg, results) = TestRunner.runTests(