summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Tatarinov <5min4eq.unity@gmail.com>2018-02-01 22:07:39 +0300
committerGitHub <noreply@github.com>2018-02-01 22:07:39 +0300
commit5be2c5aea4527cf637948e6bf2e4c56e3273fbd9 (patch)
tree38d9c675c68ac7505708f182170589119453db21
parentbc777b3c4e83149f45df7edda245868e22495eb3 (diff)
downloadmill-5be2c5aea4527cf637948e6bf2e4c56e3273fbd9.tar.gz
mill-5be2c5aea4527cf637948e6bf2e4c56e3273fbd9.tar.bz2
mill-5be2c5aea4527cf637948e6bf2e4c56e3273fbd9.zip
WIP: Scala js testing (#119)
fixes #102. Use scala js testing framework to launch tests
-rw-r--r--build.sbt28
-rwxr-xr-xbuild.sc28
-rw-r--r--core/test/src/mill/util/TestEvaluator.scala2
-rw-r--r--scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala (renamed from scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSLinkerBridge.scala)27
-rw-r--r--scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala (renamed from scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSLinkerBridge.scala)21
-rw-r--r--scalajslib/src/mill/scalajslib/ScalaJSBridge.scala (renamed from scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala)62
-rw-r--r--scalajslib/src/mill/scalajslib/ScalaJSModule.scala127
-rw-r--r--scalajslib/test/resources/hello-js-world/src/ArgsParser.scala3
-rw-r--r--scalajslib/test/resources/hello-js-world/src/Main.scala5
-rw-r--r--scalajslib/test/resources/hello-js-world/test/src/scalatest/ArgsParserSpec.scala18
-rw-r--r--scalajslib/test/resources/hello-js-world/test/src/scalatest/MainSpec.scala15
-rw-r--r--scalajslib/test/resources/hello-js-world/test/src/utest/ArgsParserTests.scala21
-rw-r--r--scalajslib/test/resources/hello-js-world/test/src/utest/MainTests.scala20
-rw-r--r--scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala109
-rw-r--r--scalalib/src/mill/scalalib/ScalaModule.scala4
-rw-r--r--scalalib/src/mill/scalalib/ScalaWorkerApi.scala2
-rw-r--r--scalalib/src/mill/scalalib/TestRunner.scala5
-rw-r--r--scalaworker/src/mill/scalaworker/ScalaWorker.scala10
18 files changed, 409 insertions, 98 deletions
diff --git a/build.sbt b/build.sbt
index 837397a4..c3be03d9 100644
--- a/build.sbt
+++ b/build.sbt
@@ -152,7 +152,10 @@ lazy val scalalib = project
pluginSettings,
name := "mill-scalalib",
fork := true,
- baseDirectory in Test := (baseDirectory in Test).value / ".."
+ baseDirectory in Test := (baseDirectory in Test).value / "..",
+ libraryDependencies ++= Seq(
+ "org.scala-sbt" % "test-interface" % "1.0"
+ )
)
lazy val scalaworker: Project = project
@@ -163,8 +166,7 @@ lazy val scalaworker: Project = project
name := "mill-scalaworker",
fork := true,
libraryDependencies ++= Seq(
- "org.scala-sbt" %% "zinc" % "1.0.5",
- "org.scala-sbt" % "test-interface" % "1.0"
+ "org.scala-sbt" %% "zinc" % "1.0.5"
)
)
@@ -204,10 +206,25 @@ def jsbridge(binary: String, version: String) =
organization := "com.lihaoyi",
scalaVersion := "2.12.4",
name := "mill-js-bridge",
- libraryDependencies ++= Seq("org.scala-js" %% "scalajs-tools" % version)
+ libraryDependencies ++= Seq(
+ "org.scala-js" %% "scalajs-tools" % version,
+ "org.scala-js" %% "scalajs-sbt-test-adapter" % version
+ )
+ )
+
+lazy val scalajsbridge_0_6 = jsbridge("0.6", "0.6.22")
+ .settings(
+ libraryDependencies ++= Seq(
+ "org.scala-js" %% "scalajs-js-envs" % "0.6.22"
+ )
)
-lazy val scalajsbridge_0_6 = jsbridge("0.6", "0.6.21")
+
lazy val scalajsbridge_1_0 = jsbridge("1.0", "1.0.0-M2")
+ .settings(
+ libraryDependencies ++= Seq(
+ "org.scala-js" %% "scalajs-env-nodejs" % "1.0.0-M2"
+ )
+ )
javaOptions in (scalajslib, Test) := jsbridgeProps.value.toSeq ++ scalaWorkerProps.value
@@ -275,6 +292,7 @@ lazy val bin = project
baseDirectory in (Test, run) := (baseDirectory in (Compile, run)).value / ".." / "..",
javaOptions in (Test, run) := {
(javaOptions in (scalalib, Compile)).value ++
+ jsbridgeProps.value.toSeq ++
scalaWorkerProps.value
},
assemblyOption in assembly := {
diff --git a/build.sc b/build.sc
index bd3cff07..2ec94ccb 100755
--- a/build.sc
+++ b/build.sc
@@ -119,8 +119,7 @@ object scalaworker extends MillModule{
def moduleDeps = Seq(core, scalalib)
def ivyDeps = Agg(
- ivy"org.scala-sbt::zinc:1.0.5",
- ivy"org.scala-sbt:test-interface:1.0"
+ ivy"org.scala-sbt::zinc:1.0.5"
)
def testArgs = Seq(
"-DMILL_SCALA_WORKER=" + runClasspath().map(_.path).mkString(",")
@@ -131,6 +130,10 @@ object scalaworker extends MillModule{
object scalalib extends MillModule {
def moduleDeps = Seq(core)
+ def ivyDeps = Agg(
+ ivy"org.scala-sbt:test-interface:1.0"
+ )
+
def bridgeCompiles = mill.define.Task.traverse(bridges.items)(_._2.compile)
def genTask(m: ScalaModule) = T.task{
@@ -175,13 +178,20 @@ object scalajslib extends MillModule {
object jsbridges extends Cross[JsBridgeModule]("0.6", "1.0")
class JsBridgeModule(scalajsBinary: String) extends MillModule{
def moduleDeps = Seq(scalajslib)
- val scalajsVersion = scalajsBinary match {
- case "0.6" => "0.6.21"
- case "1.0" => "1.0.0-M2"
+ def ivyDeps = scalajsBinary match {
+ case "0.6" =>
+ Agg(
+ ivy"org.scala-js::scalajs-tools:0.6.22",
+ ivy"org.scala-js::scalajs-sbt-test-adapter:0.6.22",
+ ivy"org.scala-js::scalajs-js-envs:0.6.22"
+ )
+ case "1.0" =>
+ Agg(
+ ivy"org.scala-js::scalajs-tools:1.0.0-M2",
+ ivy"org.scala-js::scalajs-sbt-test-adapter:1.0.0-M2",
+ ivy"org.scala-js::scalajs-env-nodejs:1.0.0-M2"
+ )
}
- def ivyDeps = Agg(
- ivy"org.scala-js::scalajs-tools:$scalajsVersion"
- )
}
}
def testRepos = T{
@@ -234,4 +244,4 @@ def releaseAssembly = T{
assemblyBase(Agg.from(assemblyClasspath().flatten.map(_.path)), "")
}
-def idea() = T.command{ mill.scalalib.GenIdea() } \ No newline at end of file
+def idea() = T.command{ mill.scalalib.GenIdea() }
diff --git a/core/test/src/mill/util/TestEvaluator.scala b/core/test/src/mill/util/TestEvaluator.scala
index 465a891d..2301efe6 100644
--- a/core/test/src/mill/util/TestEvaluator.scala
+++ b/core/test/src/mill/util/TestEvaluator.scala
@@ -14,7 +14,7 @@ class TestEvaluator[T <: TestUtil.BaseModule](module: T,
basePath: Path)
(implicit discover: Discover[T]){
val evaluator = new Evaluator(workspacePath, basePath, module, discover, DummyLogger)
- //val evaluator = new Evaluator(workspacePath, basePath, module, new PrintLogger(true, ammonite.util.Colors.Default, System.out, System.out, System.err))
+// val evaluator = new Evaluator(workspacePath, basePath, module, discover, new PrintLogger(true, ammonite.util.Colors.Default, System.out, System.out, System.err))
def apply[T](t: Task[T]): Either[Result.Failing, (T, Int)] = {
val evaluated = evaluator.evaluate(Agg(t))
diff --git a/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSLinkerBridge.scala b/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala
index 3ed17f16..3525e69e 100644
--- a/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSLinkerBridge.scala
+++ b/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala
@@ -5,11 +5,15 @@ package bridge
import java.io.File
import org.scalajs.core.tools.io.IRFileCache.IRContainer
-import org.scalajs.core.tools.io.{AtomicWritableFileVirtualJSFile, FileVirtualBinaryFile, FileVirtualScalaJSIRFile, VirtualJarFile}
+import org.scalajs.core.tools.io._
+import org.scalajs.core.tools.jsdep.ResolvedJSDependency
import org.scalajs.core.tools.linker.{ModuleInitializer, StandardLinker}
import org.scalajs.core.tools.logging.ScalaConsoleLogger
+import org.scalajs.jsenv._
+import org.scalajs.jsenv.nodejs._
+import org.scalajs.testadapter.TestAdapter
-class ScalaJSLinkerBridge extends mill.scalajslib.ScalaJSLinkerBridge{
+class ScalaJSBridge extends mill.scalajslib.ScalaJSBridge {
def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean): Unit = {
val config = StandardLinker.Config().withOptimizer(fullOpt)
val linker = StandardLinker(config)
@@ -21,4 +25,21 @@ class ScalaJSLinkerBridge extends mill.scalajslib.ScalaJSLinkerBridge{
val initializer = Option(main).map { cls => ModuleInitializer.mainMethodWithArgs(cls, "main") }
linker.link(sourceSJSIRs ++ jarSJSIRs, initializer.toSeq, destFile, logger)
}
-} \ No newline at end of file
+
+ def getFramework(frameworkName: String,
+ linkedFile: File): sbt.testing.Framework = {
+ val env = new NodeJSEnv().loadLibs(
+ Seq(ResolvedJSDependency.minimal(new FileVirtualJSFile(linkedFile)))
+ )
+ val jsConsole = ConsoleJSConsole
+ val config = TestAdapter.Config().withLogger(new ScalaConsoleLogger)
+ val adapter =
+ new TestAdapter(env, config)
+
+ adapter
+ .loadFrameworks(List(List(frameworkName)))
+ .flatten
+ .headOption
+ .getOrElse(throw new RuntimeException("Failed to get framework"))
+ }
+}
diff --git a/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSLinkerBridge.scala b/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala
index 8bd28e49..15a3d65b 100644
--- a/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSLinkerBridge.scala
+++ b/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala
@@ -7,8 +7,10 @@ import java.io.File
import org.scalajs.core.tools.io._
import org.scalajs.core.tools.linker.{ModuleInitializer, StandardLinker}
import org.scalajs.core.tools.logging.ScalaConsoleLogger
+import org.scalajs.testadapter.TestAdapter
+import org.scalajs.jsenv.nodejs._
-class ScalaJSLinkerBridge extends mill.scalajslib.ScalaJSLinkerBridge{
+class ScalaJSBridge extends mill.scalajslib.ScalaJSBridge {
def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean): Unit = {
val config = StandardLinker.Config().withOptimizer(fullOpt)
val linker = StandardLinker(config)
@@ -21,4 +23,19 @@ class ScalaJSLinkerBridge extends mill.scalajslib.ScalaJSLinkerBridge{
val initializer = Option(main).map { cls => ModuleInitializer.mainMethodWithArgs(cls, "main") }
linker.link(sourceIRs ++ libraryIRs, initializer.toSeq, destFile, logger)
}
-} \ No newline at end of file
+
+ def getFramework(frameworkName: String,
+ linkedFile: File): sbt.testing.Framework = {
+ val env = new NodeJSEnv()
+ val config = TestAdapter.Config().withLogger(new ScalaConsoleLogger)
+
+ val adapter =
+ new TestAdapter(env, Seq(FileVirtualJSFile(linkedFile)), config)
+
+ adapter
+ .loadFrameworks(List(List(frameworkName)))
+ .flatten
+ .headOption
+ .getOrElse(throw new RuntimeException("Failed to get framework"))
+ }
+}
diff --git a/scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala b/scalajslib/src/mill/scalajslib/ScalaJSBridge.scala
index ae282152..10dd42d6 100644
--- a/scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala
+++ b/scalajslib/src/mill/scalajslib/ScalaJSBridge.scala
@@ -11,41 +11,33 @@ sealed trait OptimizeMode
object FastOpt extends OptimizeMode
object FullOpt extends OptimizeMode
-class ScalaJSLinkerWorker {
- var scalaInstanceCache = Option.empty[(Long, ScalaJSLinkerBridge)]
- def link(toolsClasspath: Agg[Path],
- sources: Agg[Path],
- libraries: Agg[Path],
- dest: File,
- main: Option[String],
- fullOpt: Boolean): Unit = {
+class ScalaJSWorker {
+ private var scalaInstanceCache = Option.empty[(Long, ScalaJSBridge)]
- val classloaderSig = {
+ private def bridge(toolsClasspath: Agg[Path]) = {
+ val classloaderSig =
toolsClasspath.map(p => p.toString().hashCode + p.mtime.toMillis).sum
- }
-
- val bridge = scalaInstanceCache match{
+ scalaInstanceCache match {
case Some((sig, bridge)) if sig == classloaderSig => bridge
case _ =>
- val outerClassLoader = getClass.getClassLoader
- val cl = new URLClassLoader(toolsClasspath.map(_.toIO.toURI.toURL).toArray){
- override def findClass(name: String) = {
- if (name.startsWith("mill.scalajslib.ScalaJSLinkerBridge")){
- outerClassLoader.loadClass(name)
- }else{
- super.findClass(name)
- }
- }
- }
+ val cl = new URLClassLoader(toolsClasspath.map(_.toIO.toURI.toURL).toArray)
val bridge = cl
- .loadClass("mill.scalajslib.bridge.ScalaJSLinkerBridge")
+ .loadClass("mill.scalajslib.bridge.ScalaJSBridge")
.getDeclaredConstructor()
.newInstance()
- .asInstanceOf[ScalaJSLinkerBridge]
+ .asInstanceOf[ScalaJSBridge]
scalaInstanceCache = Some((classloaderSig, bridge))
bridge
}
- bridge.link(
+ }
+
+ def link(toolsClasspath: Agg[Path],
+ sources: Agg[Path],
+ libraries: Agg[Path],
+ dest: File,
+ main: Option[String],
+ fullOpt: Boolean): Unit = {
+ bridge(toolsClasspath).link(
sources.items.map(_.toIO).toArray,
libraries.items.map(_.toIO).toArray,
dest,
@@ -54,19 +46,27 @@ class ScalaJSLinkerWorker {
)
}
+ def getFramework(toolsClasspath: Agg[Path],
+ frameworkName: String,
+ linkedFile: File): sbt.testing.Framework = {
+ bridge(toolsClasspath).getFramework(frameworkName, linkedFile)
+ }
+
}
-trait ScalaJSLinkerBridge {
+trait ScalaJSBridge {
def link(sources: Array[File],
libraries: Array[File],
dest: File,
main: String,
fullOpt: Boolean): Unit
+
+ def getFramework(frameworkName: String,
+ linkedFile: File): sbt.testing.Framework
+
}
-object ScalaJSLinkerBridge extends mill.define.BaseModule(ammonite.ops.pwd){
+object ScalaJSBridge extends mill.define.BaseModule(ammonite.ops.pwd) {
- def scalaJSLinkerBridge = T.worker{
- new ScalaJSLinkerWorker()
- }
-} \ No newline at end of file
+ def scalaJSBridge = T.worker { new ScalaJSWorker() }
+}
diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala
index d76a50db..82000c6e 100644
--- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala
+++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala
@@ -1,24 +1,25 @@
package mill
package scalajslib
-import java.io.File
-
-import mill.scalalib.DepSyntax
import ammonite.ops.{Path, ls, mkdir, rm}
import coursier.Cache
import coursier.maven.MavenRepository
import mill.eval.PathRef
import mill.eval.Result.Success
import mill.scalalib.Lib.resolveDependencies
-import mill.scalalib.{Dep, PublishModule, ScalaModule, TestModule}
-import mill.util.Loose
-
-import scala.collection.breakOut
+import mill.scalalib.{CompilationResult, Dep, DepSyntax, TestModule}
+import mill.util.{Ctx, Loose}
trait ScalaJSModule extends scalalib.ScalaModule { outer =>
def scalaJSVersion: T[String]
+ trait Tests extends TestScalaJSModule {
+ override def scalaVersion = outer.scalaVersion()
+ override def scalaJSVersion = outer.scalaJSVersion()
+ override def moduleDeps = Seq(outer)
+ }
+
private val ReleaseVersion = raw"""(\d+)\.(\d+)\.(\d+)""".r
private val MinorSnapshotVersion = raw"""(\d+)\.(\d+)\.([1-9]\d*)-SNAPSHOT""".r
@@ -32,7 +33,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
def scalaJSBridgeVersion = T{ scalaJSVersion().split('.').dropRight(1).mkString(".") }
- def sjsLinkerBridgeClasspath = T {
+ def sjsBridgeClasspath = T {
val jsBridgeKey = "MILL_SCALAJS_BRIDGE_" + scalaJSBridgeVersion().replace('.', '_')
val jsBridgePath = sys.props(jsBridgeKey)
if (jsBridgePath != null) Success(
@@ -49,41 +50,78 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
).map(_.find(_.path.toString.contains("mill-jsbridge")).get)
}
-
def scalaJSLinkerClasspath: T[Loose.Agg[PathRef]] = T{
+ val commonDeps = Seq(
+ ivy"org.scala-js::scalajs-tools:${scalaJSVersion()}",
+ ivy"org.scala-js::scalajs-sbt-test-adapter:${scalaJSVersion()}"
+ )
+ val envDep = scalaJSBinaryVersion() match {
+ case v if v.startsWith("0.6") => ivy"org.scala-js::scalajs-js-envs:${scalaJSVersion()}"
+ case v if v.startsWith("1.0") => ivy"org.scala-js::scalajs-env-nodejs:${scalaJSVersion()}"
+ }
resolveDependencies(
repositories,
"2.12.4",
"2.12",
- Seq(ivy"org.scala-js::scalajs-tools:${scalaJSVersion()}")
+ commonDeps :+ envDep
+ )
+ }
+
+ def toolsClasspath = T { Agg(sjsBridgeClasspath()) ++ scalaJSLinkerClasspath() }
+
+ def fastOpt = T {
+ link(
+ ScalaJSBridge.scalaJSBridge(),
+ toolsClasspath(),
+ Seq(compile()),
+ compileDepClasspath(),
+ mainClass(),
+ FastOpt
+ )
+ }
+
+ def fullOpt = T {
+ link(
+ ScalaJSBridge.scalaJSBridge(),
+ toolsClasspath(),
+ Seq(compile()),
+ compileDepClasspath(),
+ mainClass(),
+ FullOpt
)
}
- def genericOpt(mode: OptimizeMode) = T.task{
- val outputPath = T.ctx().dest / "out.js"
+ def link(worker: ScalaJSWorker,
+ toolsClasspath: Agg[PathRef],
+ input: Seq[CompilationResult],
+ libraries: Agg[PathRef],
+ mainClass: Option[String],
+ mode: OptimizeMode)(implicit ctx: Ctx.DestCtx): PathRef = {
+ val outputPath = ctx.dest / "out.js"
- mkdir(T.ctx().dest)
+ mkdir(ctx.dest)
rm(outputPath)
- val inputFiles = Agg.from(ls(compile().classes.path).filter(_.ext == "sjsir"))
- val inputLibraries = compileDepClasspath().map(_.path).filter(_.ext == "jar")
- mill.scalajslib.ScalaJSLinkerBridge.scalaJSLinkerBridge().link(
- (Agg(sjsLinkerBridgeClasspath()) ++ scalaJSLinkerClasspath()).map(_.path),
+
+ val inputFiles = Agg.from(for {
+ compiled <- input
+ file <- ls(compiled.classes.path)
+ if file.ext == "sjsir"
+ } yield file)
+ val inputLibraries = libraries.map(_.path).filter(_.ext == "jar")
+ worker.link(
+ toolsClasspath.map(_.path),
inputFiles,
inputLibraries,
outputPath.toIO,
- mainClass(),
+ mainClass,
mode == FullOpt
)
PathRef(outputPath)
}
- def fastOpt = T{ genericOpt(FastOpt)() }
-
- def fullOpt = T{ genericOpt(FullOpt)() }
-
override def scalacPluginIvyDeps = T{ Loose.Agg(Dep.Point("org.scala-js", "scalajs-compiler", scalaJSVersion())) }
- override def ivyDeps = T{ Loose.Agg(Dep("org.scala-js", "scalajs-library", scalaJSVersion())) }
+ override def ivyDeps = T{ Loose.Agg(ivy"org.scala-js::scalajs-library:${scalaJSVersion()}") }
// publish artifact with name "mill_sjs0.6.4_2.12" instead of "mill_sjs0.6_2.12"
def crossFullScalaJSVersion: T[Boolean] = false
@@ -96,4 +134,45 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
}
-trait TestScalaJSModule extends ScalaJSModule with TestModule \ No newline at end of file
+trait TestScalaJSModule extends ScalaJSModule with TestModule {
+ def scalaJSTestDeps = T {
+ resolveDeps(T.task {
+ Loose.Agg(
+ ivy"org.scala-js::scalajs-library:${scalaJSVersion()}",
+ ivy"org.scala-js::scalajs-test-interface:${scalaJSVersion()}"
+ )
+ })
+ }
+
+ def fastOptTest = T {
+ link(
+ ScalaJSBridge.scalaJSBridge(),
+ toolsClasspath(),
+ compile() +: upstreamCompileOutput(),
+ scalaJSTestDeps() ++ compileDepClasspath(),
+ None,
+ FastOpt
+ )
+ }
+
+ override def testLocal(args: String*) = T.command { test(args:_*) }
+
+ override def test(args: String*) = T.command {
+ val framework = mill.scalajslib.ScalaJSBridge.scalaJSBridge().getFramework(
+ toolsClasspath().map(_.path),
+ testFramework(),
+ fastOptTest().path.toIO
+ )
+
+ val (doneMsg, results) = mill.scalalib.ScalaWorkerApi
+ .scalaWorker()
+ .apply(
+ _ => framework,
+ runClasspath().map(_.path),
+ Agg(compile().classes.path),
+ args
+ )
+ TestModule.handleResults(doneMsg, results)
+ }
+
+}
diff --git a/scalajslib/test/resources/hello-js-world/src/ArgsParser.scala b/scalajslib/test/resources/hello-js-world/src/ArgsParser.scala
new file mode 100644
index 00000000..cf13d452
--- /dev/null
+++ b/scalajslib/test/resources/hello-js-world/src/ArgsParser.scala
@@ -0,0 +1,3 @@
+object ArgsParser {
+ def parse(s:String): Seq[String] = s.split(":").toSeq
+}
diff --git a/scalajslib/test/resources/hello-js-world/src/Main.scala b/scalajslib/test/resources/hello-js-world/src/Main.scala
index 60cef56d..636d9ea1 100644
--- a/scalajslib/test/resources/hello-js-world/src/Main.scala
+++ b/scalajslib/test/resources/hello-js-world/src/Main.scala
@@ -1,3 +1,6 @@
object Main extends App {
- println("Hello " + sys.props("java.vm.name"))
+
+ println("Hello " + vmName)
+
+ def vmName = sys.props("java.vm.name")
}
diff --git a/scalajslib/test/resources/hello-js-world/test/src/scalatest/ArgsParserSpec.scala b/scalajslib/test/resources/hello-js-world/test/src/scalatest/ArgsParserSpec.scala
new file mode 100644
index 00000000..807decb9
--- /dev/null
+++ b/scalajslib/test/resources/hello-js-world/test/src/scalatest/ArgsParserSpec.scala
@@ -0,0 +1,18 @@
+import org.scalatest._
+
+class ArgsParserSpec extends FlatSpec with Matchers {
+
+ behavior of "ArgsParser"
+
+ "parse" should "one" in {
+ val result = ArgsParser.parse("hello:world")
+ result should have length 2
+ result should contain only ("hello", "world")
+ }
+
+ it should "two" in {
+ val result = ArgsParser.parse("hello:world")
+ result should have length 80
+ }
+
+}
diff --git a/scalajslib/test/resources/hello-js-world/test/src/scalatest/MainSpec.scala b/scalajslib/test/resources/hello-js-world/test/src/scalatest/MainSpec.scala
new file mode 100644
index 00000000..0c1eb76f
--- /dev/null
+++ b/scalajslib/test/resources/hello-js-world/test/src/scalatest/MainSpec.scala
@@ -0,0 +1,15 @@
+import org.scalatest._
+
+class MainSpec extends FlatSpec with Matchers {
+
+ behavior of "Main"
+
+ "vmName" should "contain js" in {
+ Main.vmName should include ("js")
+ }
+
+ it should "contain Scala" in {
+ Main.vmName should include ("Scala")
+ }
+
+}
diff --git a/scalajslib/test/resources/hello-js-world/test/src/utest/ArgsParserTests.scala b/scalajslib/test/resources/hello-js-world/test/src/utest/ArgsParserTests.scala
new file mode 100644
index 00000000..d0baa965
--- /dev/null
+++ b/scalajslib/test/resources/hello-js-world/test/src/utest/ArgsParserTests.scala
@@ -0,0 +1,21 @@
+import utest._
+
+object ArgsParserTests extends TestSuite {
+
+ def tests: Tests = Tests {
+ 'one - {
+ val result = ArgsParser.parse("hello:world")
+ assert(
+ result.length == 2,
+ result == Seq("hello", "world")
+ )
+ }
+ 'two - { // we fail this test to check testing in scala.js
+ val result = ArgsParser.parse("hello:world")
+ assert(
+ result.length == 80
+ )
+ }
+ }
+
+}
diff --git a/scalajslib/test/resources/hello-js-world/test/src/utest/MainTests.scala b/scalajslib/test/resources/hello-js-world/test/src/utest/MainTests.scala
new file mode 100644
index 00000000..937d96f8
--- /dev/null
+++ b/scalajslib/test/resources/hello-js-world/test/src/utest/MainTests.scala
@@ -0,0 +1,20 @@
+import utest._
+
+object MainTests extends TestSuite {
+
+ def tests: Tests = Tests {
+ 'vmName - {
+ 'containJs - {
+ assert(
+ Main.vmName.contains("js")
+ )
+ }
+ 'containScala - {
+ assert(
+ Main.vmName.contains("Scala")
+ )
+ }
+ }
+ }
+
+}
diff --git a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala
index 4cfe464d..88792366 100644
--- a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala
+++ b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala
@@ -26,11 +26,35 @@ object HelloJSWorldTests extends TestSuite {
object HelloJSWorld extends TestUtil.BaseModule {
val matrix = for {
scala <- Seq("2.11.8", "2.12.3", "2.12.4")
- scalaJS <- Seq("0.6.20", "0.6.21", "1.0.0-M2")
+ scalaJS <- Seq("0.6.22", "1.0.0-M2")
} yield (scala, scalaJS)
object build extends Cross[BuildModule](matrix:_*)
+ object buildUTest extends Cross[BuildModuleUtest](matrix:_*)
+ class BuildModuleUtest(scalaVersion0: String, sjsVersion0: String)
+ extends BuildModule(scalaVersion0: String, sjsVersion0: String) {
+ object test extends super.Tests {
+ override def sources = T.input{ Agg(PathRef(basePath / 'src / 'utest)) }
+ def testFramework: T[String] = "utest.runner.Framework"
+ override def ivyDeps = Agg(
+ ivy"com.lihaoyi:utest_sjs${scalaJSBinaryVersion()}_${scalaBinaryVersion()}:0.6.3"
+ )
+ }
+ }
+
+ object buildScalaTest extends Cross[BuildModuleScalaTest](matrix:_*)
+ class BuildModuleScalaTest(scalaVersion0: String, sjsVersion0: String)
+ extends BuildModule(scalaVersion0: String, sjsVersion0: String) {
+ object test extends super.Tests {
+ override def sources = T.input{ Agg(PathRef(basePath / 'src / 'scalatest)) }
+ def testFramework: T[String] = "org.scalatest.tools.Framework"
+ override def ivyDeps = Agg(
+ ivy"org.scalatest:scalatest_sjs${scalaJSBinaryVersion()}_${scalaBinaryVersion()}:3.0.4"
+ )
+ }
+ }
+
class BuildModule(scalaVersion0: String, sjsVersion0: String) extends HelloJSWorldModule {
def scalaVersion = scalaVersion0
def scalaJSVersion = sjsVersion0
@@ -98,9 +122,9 @@ object HelloJSWorldTests extends TestSuite {
assert(unchangedEvalCount == 0)
}
- 'fromScratch_2124_0621 - testCompileFromScratch("2.12.4", "0.6.21")
- 'fromScratch_2123_0621 - testCompileFromScratch("2.12.3", "0.6.21")
- 'fromScratch_2118_0621 - testCompileFromScratch("2.11.8", "0.6.21")
+ 'fromScratch_2124_0621 - testCompileFromScratch("2.12.4", "0.6.22")
+ 'fromScratch_2123_0621 - testCompileFromScratch("2.12.3", "0.6.22")
+ 'fromScratch_2118_0621 - testCompileFromScratch("2.11.8", "0.6.22")
'fromScratch_2124_100M2 - testCompileFromScratch("2.12.4", "1.0.0-M2")
}
@@ -117,20 +141,20 @@ object HelloJSWorldTests extends TestSuite {
}
'fullOpt - {
- 'run_2124_0621 - testRun("2.12.4", "0.6.21", FullOpt)
- 'run_2123_0621 - testRun("2.12.3", "0.6.21", FullOpt)
- 'run_2118_0621 - testRun("2.11.8", "0.6.21", FullOpt)
+ 'run_2124_0621 - testRun("2.12.4", "0.6.22", FullOpt)
+ 'run_2123_0621 - testRun("2.12.3", "0.6.22", FullOpt)
+ 'run_2118_0621 - testRun("2.11.8", "0.6.22", FullOpt)
'run_2124_100M2 - testRun("2.12.4", "1.0.0-M2", FullOpt)
}
'fastOpt - {
- 'run_2124_0621 - testRun("2.12.4", "0.6.21", FastOpt)
- 'run_2123_0621 - testRun("2.12.3", "0.6.21", FastOpt)
- 'run_2118_0621 - testRun("2.11.8", "0.6.21", FastOpt)
+ 'run_2124_0621 - testRun("2.12.4", "0.6.22", FastOpt)
+ 'run_2123_0621 - testRun("2.12.3", "0.6.22", FastOpt)
+ 'run_2118_0621 - testRun("2.11.8", "0.6.22", FastOpt)
'run_2124_100M2 - testRun("2.12.4", "1.0.0-M2", FastOpt)
}
'jar - {
'containsSJSIRs - {
- val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.build("2.12.4", "0.6.21").jar)
+ val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.build("2.12.4", "0.6.22").jar)
val jar = result.path
val entries = new JarFile(jar.toIO).entries().asScala.map(_.getName)
assert(entries.contains("Main$.sjsir"))
@@ -143,12 +167,71 @@ object HelloJSWorldTests extends TestSuite {
val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.build(scalaVersion, scalaJSVersion).artifact)
assert(result.id == artifactId)
}
- 'artifactId_0621 - testArtifactId("2.12.4", "0.6.21", "hello-js-world_sjs0.6_2.12")
- 'artifactId_0621 - testArtifactId("2.12.4", "1.0.0-M2", "hello-js-world_sjs1.0.0-M2_2.12")
+ 'artifactId_0621 - testArtifactId("2.12.4", "0.6.22", "hello-js-world_sjs0.6_2.12")
+ 'artifactId_100M2 - testArtifactId("2.12.4", "1.0.0-M2", "hello-js-world_sjs1.0.0-M2_2.12")
+ }
+ 'test - {
+ def runTests(testTask: define.Command[(String, Seq[TestRunner.Result])]): Map[String, Map[String, TestRunner.Result]] = {
+ val Right(((_, testResults), evalCount)) = helloWorldEvaluator(testTask)
+
+ assert(evalCount > 0)
+
+ testResults
+ .groupBy(_.fullyQualifiedName)
+ .mapValues(_.map(e => e.selector -> e).toMap)
+ }
+
+ def checkUtest(scalaVersion: String, scalaJSVersion: String) = {
+ val resultMap = runTests(HelloJSWorld.buildUTest(scalaVersion, scalaJSVersion).test.test())
+
+ val mainTests = resultMap("MainTests")
+ val argParserTests = resultMap("ArgsParserTests")
+
+ assert(
+ mainTests.size == 2,
+ mainTests("MainTests.vmName.containJs").status == "Success",
+ mainTests("MainTests.vmName.containScala").status == "Success",
+
+ argParserTests.size == 2,
+ argParserTests("ArgsParserTests.one").status == "Success",
+ argParserTests("ArgsParserTests.two").status == "Failure"
+ )
+ }
+
+ def checkScalaTest(scalaVersion: String, scalaJSVersion: String) = {
+ val resultMap = runTests(HelloJSWorld.buildScalaTest(scalaVersion, scalaJSVersion).test.test())
+
+ val mainSpec = resultMap("MainSpec")
+ val argParserSpec = resultMap("ArgsParserSpec")
+
+ assert(
+ mainSpec.size == 2,
+ mainSpec("vmName should contain js").status == "Success",
+ mainSpec("vmName should contain Scala").status == "Success",
+
+ argParserSpec.size == 2,
+ argParserSpec("parse should one").status == "Success",
+ argParserSpec("parse should two").status == "Failure"
+ )
+ }
+
+ 'utest_2118_0621 - checkUtest("2.11.8", "0.6.22")
+ 'utest_2124_0621 - checkUtest("2.12.4", "0.6.22")
+ 'utest_2118_100M2 - checkUtest("2.11.8", "1.0.0-M2")
+ 'utest_2124_100M2 - checkUtest("2.12.4", "1.0.0-M2")
+
+ 'scalaTest_2118_0621 - checkScalaTest("2.11.8", "0.6.22")
+ 'scalaTest_2124_0621 - checkScalaTest("2.12.4", "0.6.22")
+// No scalatest artifact for scala.js 1.0.0-M2 published yet
+// 'scalaTest_2118_100M2 - checkScalaTest("2.11.8", "1.0.0-M2")
+// 'scalaTest_2124_100M2 - checkScalaTest("2.12.4", "1.0.0-M2")
}
}
def compileClassfiles(parentDir: Path) = Set(
+ parentDir / "ArgsParser$.class",
+ parentDir / "ArgsParser$.sjsir",
+ parentDir / "ArgsParser.class",
parentDir / "Main.class",
parentDir / "Main$.class",
parentDir / "Main$delayedInit$body.class",
diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala
index b79b32dc..8f635906 100644
--- a/scalalib/src/mill/scalalib/ScalaModule.scala
+++ b/scalalib/src/mill/scalalib/ScalaModule.scala
@@ -323,7 +323,7 @@ trait TestModule extends ScalaModule with TaskModule {
val outputPath = T.ctx().dest/"out.json"
mill.scalalib.ScalaWorkerApi.scalaWorker().apply(
- testFramework(),
+ TestRunner.framework(testFramework()),
runClasspath().map(_.path),
Agg(compile().classes.path),
args
@@ -334,4 +334,4 @@ trait TestModule extends ScalaModule with TaskModule {
TestModule.handleResults(doneMsg, results)
}
-} \ No newline at end of file
+}
diff --git a/scalalib/src/mill/scalalib/ScalaWorkerApi.scala b/scalalib/src/mill/scalalib/ScalaWorkerApi.scala
index 8ff45a48..21ba45e1 100644
--- a/scalalib/src/mill/scalalib/ScalaWorkerApi.scala
+++ b/scalalib/src/mill/scalalib/ScalaWorkerApi.scala
@@ -52,7 +52,7 @@ trait ScalaWorkerApi {
upstreamCompileOutput: Seq[CompilationResult])
(implicit ctx: mill.util.Ctx): CompilationResult
- def apply(frameworkName: String,
+ def apply(frameworkInstance: ClassLoader => sbt.testing.Framework,
entireClasspath: Agg[Path],
testClassfilePath: Agg[Path],
args: Seq[String])
diff --git a/scalalib/src/mill/scalalib/TestRunner.scala b/scalalib/src/mill/scalalib/TestRunner.scala
index 025364be..e7521989 100644
--- a/scalalib/src/mill/scalalib/TestRunner.scala
+++ b/scalalib/src/mill/scalalib/TestRunner.scala
@@ -2,6 +2,11 @@ package mill.scalalib
import mill.util.JsonFormatters._
object TestRunner {
+ def framework(frameworkName: String)(cl: ClassLoader): sbt.testing.Framework = {
+ cl.loadClass(frameworkName)
+ .newInstance()
+ .asInstanceOf[sbt.testing.Framework]
+ }
case class Result(fullyQualifiedName: String,
selector: String,
diff --git a/scalaworker/src/mill/scalaworker/ScalaWorker.scala b/scalaworker/src/mill/scalaworker/ScalaWorker.scala
index dfb8892a..70cfb604 100644
--- a/scalaworker/src/mill/scalaworker/ScalaWorker.scala
+++ b/scalaworker/src/mill/scalaworker/ScalaWorker.scala
@@ -37,7 +37,7 @@ object ScalaWorker{
def main(args: Array[String]): Unit = {
try{
val result = new ScalaWorker(null).apply(
- frameworkName = args(0),
+ frameworkInstance = TestRunner.framework(args(0)),
entireClasspath = Agg.from(args(1).split(" ").map(Path(_))),
testClassfilePath = Agg.from(args(2).split(" ").map(Path(_))),
args = args(3) match{ case "" => Nil case x => x.split(" ").toList }
@@ -194,16 +194,14 @@ class ScalaWorker(ctx0: mill.util.Ctx) extends mill.scalalib.ScalaWorkerApi{
CompilationResult(zincFile, PathRef(classesDir))
}
- def apply(frameworkName: String,
+ def apply(frameworkInstance: ClassLoader => sbt.testing.Framework,
entireClasspath: Agg[Path],
testClassfilePath: Agg[Path],
args: Seq[String])
(implicit ctx: mill.util.Ctx.LogCtx): (String, Seq[Result]) = {
Jvm.inprocess(entireClasspath, classLoaderOverrideSbtTesting = true, cl => {
- val framework = cl.loadClass(frameworkName)
- .newInstance()
- .asInstanceOf[sbt.testing.Framework]
+ val framework = frameworkInstance(cl)
val testClasses = runTests(cl, framework, testClassfilePath)
@@ -287,4 +285,4 @@ class ScalaWorker(ctx0: mill.util.Ctx) extends mill.scalalib.ScalaWorkerApi{
}
testClasses
}
-} \ No newline at end of file
+}