diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index f62ada40..1391d5d7 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,5 @@ # Scala Steward: Reformat with sbt-java-formatter 0.8.0 9e5e7610a81938d804d8edf533844b03ef125b5a + +# adjust scalafmt config +2087aa17546b6526511b5848faa0aa9819432181 diff --git a/.scalafmt.conf b/.scalafmt.conf index 0a1ac1ad..4132e26d 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -2,17 +2,62 @@ version = "3.8.5" assumeStandardLibraryStripMargin = true +align { + preset = none + stripMargin = true +} + // Docstring wrapping breaks doctests -docstrings.wrap = false -docstrings.style = Asterisk +docstrings { + wrap = false + style = Asterisk +} -project.git=true -project.excludeFilters = [ - "LinesSuite.scala" -] +project { + git = true + excludeFilters = [ + "LinesSuite.scala" + ] + layout = StandardConvention +} runner.dialect = scala212 -fileOverride { - "glob:**/src/{main,test}/scala-3/**" { - runner.dialect = scala3 + +newlines { + avoidForSimpleOverflow = all + inInterpolation = avoid + source = fold +} + +rewrite { + rules = [ + AvoidInfix, + Imports, + RedundantBraces, + RedundantParens, + SortModifiers, + ] + imports { + expand = true + sort = ascii + groups = [ + ["munit\\..*"], + ["sbt\\..*"], + ["java.?\\..*"], + ["scala\\..*"], + ["org\\..*"], + ["com\\..*"], + ] + } + redundantBraces { + preset = all + oneStatApply { + parensMaxSpan = 300 + bracesMinSpan = 300 + } + } + redundantParens { + preset = all } + sortModifiers.preset = styleGuide + trailingCommas.style = multiple } diff --git a/build.sbt b/build.sbt index e4b3bcbd..438c55de 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,7 @@ -import sbtcrossproject.CrossPlugin.autoImport.crossProject -import sbtcrossproject.CrossPlugin.autoImport.CrossType import scala.collection.mutable + +import sbtcrossproject.CrossPlugin.autoImport.CrossType +import sbtcrossproject.CrossPlugin.autoImport.crossProject def previousVersion = "1.0.0-RC1" def scala213 = "2.13.16" @@ -10,43 +11,37 @@ def scala212 = "2.12.20" def scala3 = "3.3.4" def junitVersion = "4.13.2" def gcp = "com.google.cloud" % "google-cloud-storage" % "2.47.0" -inThisBuild( +inThisBuild { List( version ~= { old => - if ("true" == System.getProperty("CI") && old.contains("+0-")) { - old.replaceAll("\\+0-.*", "") - } else { - old - } + if ("true" == System.getProperty("CI")) old.replaceAll("\\+0-.*", "") + else old }, organization := "org.scalameta", homepage := Some(url("https://github.com/scalameta/munit")), - licenses := List( - "Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0") - ), - developers := List( - Developer( - "olafurpg", - "Ólafur Páll Geirsson", - "olafurpg@gmail.com", - url("https://geirsson.com") - ) - ), + licenses := + List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")), + developers := List(Developer( + "olafurpg", + "Ólafur Páll Geirsson", + "olafurpg@gmail.com", + url("https://geirsson.com"), + )), scalaVersion := scala213, - useSuperShell := false + useSuperShell := false, ) -) +} publish / skip := true mimaPreviousArtifacts := Set.empty crossScalaVersions := List() addCommandAlias( "scalafixAll", - s"; ++$scala212 ; scalafixEnable ; all scalafix test:scalafix" + s"; ++$scala212 ; scalafixEnable ; all scalafix test:scalafix", ) addCommandAlias( "scalafixCheckAll", - s"; ++$scala212 ; scalafixEnable ; scalafix --check ; test:scalafix --check" + s"; ++$scala212 ; scalafixEnable ; scalafix --check ; test:scalafix --check", ) val isPreScala213 = Set[Option[(Long, Long)]](Some((2, 11)), Some((2, 12))) val scala2Versions = List(scala213, scala212) @@ -55,39 +50,34 @@ val scala3Versions = List(scala3) val allScalaVersions = scala2Versions ++ scala3Versions def isScala2(v: Option[(Long, Long)]): Boolean = v.exists(_._1 == 2) -val isScala3Setting = Def.setting { - isScala3(CrossVersion.partialVersion(scalaVersion.value)) -} +val isScala3Setting = Def + .setting(isScala3(CrossVersion.partialVersion(scalaVersion.value))) def isScala3(v: Option[(Long, Long)]): Boolean = v.exists(_._1 == 3) // NOTE(olafur): disable Scala.js and Native settings for IntelliJ. -lazy val skipIdeaSettings = - SettingKey[Boolean]("ide-skip-project").withRank(KeyRanks.Invisible) := true +lazy val skipIdeaSettings = SettingKey[Boolean]("ide-skip-project") + .withRank(KeyRanks.Invisible) := true lazy val mimaEnable: List[Def.Setting[_]] = List( mimaBinaryIssueFilters ++= List.empty, mimaPreviousArtifacts := { if (crossPaths.value) Set("org.scalameta" %% moduleName.value % previousVersion) else Set("org.scalameta" % moduleName.value % previousVersion) - } + }, ) -val sharedJVMSettings: List[Def.Setting[_]] = List( - crossScalaVersions := allScalaVersions -) ++ mimaEnable +val sharedJVMSettings: List[Def.Setting[_]] = + List(crossScalaVersions := allScalaVersions) ++ mimaEnable val sharedJSSettings: List[Def.Setting[_]] = List( skipIdeaSettings, - crossScalaVersions := allScalaVersions.filterNot(_.startsWith("0.")) + crossScalaVersions := allScalaVersions.filterNot(_.startsWith("0.")), ) -val sharedJSConfigure: Project => Project = - _.disablePlugins(MimaPlugin) +val sharedJSConfigure: Project => Project = _.disablePlugins(MimaPlugin) -val sharedNativeSettings: List[Def.Setting[_]] = List( - skipIdeaSettings, - crossScalaVersions := allScalaVersions -) +val sharedNativeSettings: List[Def.Setting[_]] = + List(skipIdeaSettings, crossScalaVersions := allScalaVersions) val sharedNativeConfigure: Project => Project = _.disablePlugins(ScalafixPlugin, MimaPlugin) @@ -95,92 +85,70 @@ val sharedSettings = List( javacOptions ++= Seq("-source", "1.8", "-target", "1.8"), scalacOptions ++= { CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 11)) => - List( + case Some((2, 11)) => List( "-Yrangepos", "-Xexperimental", "-Ywarn-unused-import", - "-target:jvm-1.8" + "-target:jvm-1.8", ) case Some((major, _)) if major != 2 => - List( - "-language:implicitConversions" - ) - case _ => - List( + List("-language:implicitConversions") + case _ => List( "-target:jvm-1.8", "-Yrangepos", // -Xlint is unusable because of // https://github.com/scala/bug/issues/10448 - "-Ywarn-unused:imports" + "-Ywarn-unused:imports", ) } - } + }, ) -lazy val junit = project - .in(file("junit-interface")) - .settings( - mimaEnable, - moduleName := "junit-interface", - description := "A Java implementation of sbt's test interface for JUnit 4", - autoScalaLibrary := false, - crossPaths := false, - sbtPlugin := false, - crossScalaVersions := List(allScalaVersions.head), - libraryDependencies ++= List( - "junit" % "junit" % junitVersion, - "org.scala-sbt" % "test-interface" % "1.0" - ), - Compile / javacOptions ++= List("-target", "1.8", "-source", "1.8"), - Compile / doc / javacOptions --= List("-target", "1.8") - ) +lazy val junit = project.in(file("junit-interface")).settings( + mimaEnable, + moduleName := "junit-interface", + description := "A Java implementation of sbt's test interface for JUnit 4", + autoScalaLibrary := false, + crossPaths := false, + sbtPlugin := false, + crossScalaVersions := List(allScalaVersions.head), + libraryDependencies ++= List( + "junit" % "junit" % junitVersion, + "org.scala-sbt" % "test-interface" % "1.0", + ), + Compile / javacOptions ++= List("-target", "1.8", "-source", "1.8"), + Compile / doc / javacOptions --= List("-target", "1.8"), +) -lazy val munit = crossProject(JSPlatform, JVMPlatform, NativePlatform) - .settings( - sharedSettings, - Compile / unmanagedSourceDirectories ++= - crossBuildingDirectories("munit", "main").value, - libraryDependencies ++= List( - "org.scala-lang" % "scala-reflect" % { - if (isScala3Setting.value) scala213 - else scalaVersion.value - } % Provided - ) - ) - .nativeConfigure(sharedNativeConfigure) - .nativeSettings( - sharedNativeSettings, - libraryDependencies ++= List( - "org.scala-native" %%% "test-interface" % nativeVersion - ) - ) - .jsConfigure(sharedJSConfigure) - .jsSettings( - sharedJSSettings, - libraryDependencies ++= List( - ("org.scala-js" %% "scalajs-test-interface" % scalaJSVersion) - .cross(CrossVersion.for3Use2_13), - ("org.scala-js" %% "scalajs-junit-test-runtime" % scalaJSVersion) - .cross(CrossVersion.for3Use2_13) - ) - ) - .jvmSettings( - sharedJVMSettings, - libraryDependencies ++= List( - "junit" % "junit" % junitVersion - ) - ) - .jvmConfigure(_.dependsOn(junit)) - .dependsOn(munitDiff) +lazy val munit = crossProject(JSPlatform, JVMPlatform, NativePlatform).settings( + sharedSettings, + Compile / unmanagedSourceDirectories ++= + crossBuildingDirectories("munit", "main").value, + libraryDependencies ++= List("org.scala-lang" % "scala-reflect" % { + if (isScala3Setting.value) scala213 else scalaVersion.value + } % Provided), +).nativeConfigure(sharedNativeConfigure).nativeSettings( + sharedNativeSettings, + libraryDependencies ++= + List("org.scala-native" %%% "test-interface" % nativeVersion), +).jsConfigure(sharedJSConfigure).jsSettings( + sharedJSSettings, + libraryDependencies ++= List( + ("org.scala-js" %% "scalajs-test-interface" % scalaJSVersion) + .cross(CrossVersion.for3Use2_13), + ("org.scala-js" %% "scalajs-junit-test-runtime" % scalaJSVersion) + .cross(CrossVersion.for3Use2_13), + ), +).jvmSettings( + sharedJVMSettings, + libraryDependencies ++= List("junit" % "junit" % junitVersion), +).jvmConfigure(_.dependsOn(junit)).dependsOn(munitDiff) lazy val munitJVM = munit.jvm lazy val munitJS = munit.js lazy val munitNative = munit.native -lazy val plugin = project - .in(file("munit-sbt")) - .enablePlugins(BuildInfoPlugin) +lazy val plugin = project.in(file("munit-sbt")).enablePlugins(BuildInfoPlugin) .settings( sharedSettings, moduleName := "sbt-munit", @@ -188,57 +156,37 @@ lazy val plugin = project scalaVersion := scala212, crossScalaVersions := List(scala212), buildInfoPackage := "munit.sbtmunit", - buildInfoKeys := Seq[BuildInfoKey]( - "munitVersion" -> version.value - ), + buildInfoKeys := Seq[BuildInfoKey]("munitVersion" -> version.value), crossScalaVersions := List(scala212), - libraryDependencies ++= List( - gcp - ) - ) - .disablePlugins(MimaPlugin) + libraryDependencies ++= List(gcp), + ).disablePlugins(MimaPlugin) lazy val munitDiff = crossProject(JSPlatform, JVMPlatform, NativePlatform) - .in(file("munit-diff")) - .settings( + .in(file("munit-diff")).settings( moduleName := "munit-diff", sharedSettings, - libraryDependencies ++= List( - "org.scala-lang" % "scala-reflect" % { - if (isScala3Setting.value) scala213 - else scalaVersion.value - } % Provided - ) - ) - .jvmSettings( - sharedJVMSettings - ) - .nativeConfigure(sharedNativeConfigure) - .nativeSettings( - sharedNativeSettings - ) - .jsConfigure(sharedJSConfigure) + libraryDependencies ++= List("org.scala-lang" % "scala-reflect" % { + if (isScala3Setting.value) scala213 else scalaVersion.value + } % Provided), + ).jvmSettings(sharedJVMSettings).nativeConfigure(sharedNativeConfigure) + .nativeSettings(sharedNativeSettings).jsConfigure(sharedJSConfigure) .jsSettings(sharedJSSettings) lazy val tests = crossProject(JSPlatform, JVMPlatform, NativePlatform) - .dependsOn(munit) - .enablePlugins(BuildInfoPlugin) - .settings( + .dependsOn(munit).enablePlugins(BuildInfoPlugin).settings( sharedSettings, buildInfoPackage := "munit", buildInfoKeys := Seq[BuildInfoKey]( "sourceDirectory" -> - ((ThisBuild / baseDirectory).value / "tests" / "shared" / "src" / "main").getAbsolutePath.toString, - scalaVersion + ((ThisBuild / baseDirectory).value / "tests" / "shared" / "src" / "main") + .getAbsolutePath.toString, + scalaVersion, ), Test / unmanagedSourceDirectories ++= crossBuildingDirectories("tests", "test").value, - publish / skip := true - ) - .nativeConfigure(sharedNativeConfigure) - .nativeSettings(sharedNativeSettings) - .jsConfigure(sharedJSConfigure) - .jsSettings( + publish / skip := true, + ).nativeConfigure(sharedNativeConfigure).nativeSettings(sharedNativeSettings) + .jsConfigure(sharedJSConfigure).jsSettings( sharedJSSettings, jsEnv := { val log = sLog.value @@ -249,24 +197,19 @@ lazy val tests = crossProject(JSPlatform, JVMPlatform, NativePlatform) log.info("Testing in NodeJSEnv") new org.scalajs.jsenv.nodejs.NodeJSEnv } - } - ) - .jvmSettings( + }, + ).jvmSettings( sharedJVMSettings, fork := true, Test / parallelExecution := true, - Test / testOptions += Tests.Argument(TestFrameworks.MUnit, "+b") - ) - .disablePlugins(MimaPlugin) + Test / testOptions += Tests.Argument(TestFrameworks.MUnit, "+b"), + ).disablePlugins(MimaPlugin) lazy val testsJVM = tests.jvm lazy val testsJS = tests.js lazy val testsNative = tests.native -lazy val docs = project - .in(file("munit-docs")) - .dependsOn(munitJVM) - .enablePlugins(MdocPlugin, DocusaurusPlugin) - .disablePlugins(MimaPlugin) +lazy val docs = project.in(file("munit-docs")).dependsOn(munitJVM) + .enablePlugins(MdocPlugin, DocusaurusPlugin).disablePlugins(MimaPlugin) .settings( sharedSettings, publish / skip := true, @@ -274,30 +217,23 @@ lazy val docs = project libraryDependencies += "org.scalameta" %% "munit-scalacheck" % "1.0.0", crossScalaVersions := List(scala213, scala212), test := {}, - mdocOut := - (ThisBuild / baseDirectory).value / "website" / "target" / "docs", + mdocOut := (ThisBuild / baseDirectory).value / "website" / "target" / "docs", mdocExtraArguments := List("--no-link-hygiene"), mdocVariables := Map( "VERSION" -> version.value.replaceFirst("\\+.*", ""), - "STABLE_VERSION" -> "1.0.4" + "STABLE_VERSION" -> "1.0.4", ), - fork := false + fork := false, ) -Global / excludeLintKeys ++= Set( - mimaPreviousArtifacts -) -def crossBuildingDirectories(name: String, config: String) = - Def.setting[Seq[File]] { +Global / excludeLintKeys ++= Set(mimaPreviousArtifacts) +def crossBuildingDirectories(name: String, config: String) = Def + .setting[Seq[File]] { val root = (ThisBuild / baseDirectory).value / name val base = root / "shared" / "src" / config val result = mutable.ListBuffer.empty[File] val partialVersion = CrossVersion.partialVersion(scalaVersion.value) - if (isPreScala213(partialVersion)) { - result += base / "scala-pre-2.13" - } - if (isScala2(partialVersion)) { - result += base / "scala-2" - } + if (isPreScala213(partialVersion)) result += base / "scala-pre-2.13" + if (isScala2(partialVersion)) result += base / "scala-2" result.toList } diff --git a/munit-diff/shared/src/main/scala/munit/diff/Diff.scala b/munit-diff/shared/src/main/scala/munit/diff/Diff.scala index 57996767..7656ef47 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/Diff.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/Diff.scala @@ -1,7 +1,7 @@ package munit.diff -import munit.diff.console.Printers import munit.diff.console.AnsiColors +import munit.diff.console.Printers import scala.collection.JavaConverters._ @@ -15,20 +15,14 @@ class Diff(val obtained: String, val expected: String) extends Serializable { def createReport( title: String, - printObtainedAsStripMargin: Boolean = true + printObtainedAsStripMargin: Boolean = true, ): String = { val sb = new StringBuilder - if (title.nonEmpty) { - sb.append(title) - .append("\n") - } + if (title.nonEmpty) sb.append(title).append("\n") if (obtainedClean.length < 1000) { header("Obtained", sb).append("\n") - if (printObtainedAsStripMargin) { - sb.append(asStripMargin(obtainedClean)) - } else { - sb.append(obtainedClean) - } + if (printObtainedAsStripMargin) sb.append(asStripMargin(obtainedClean)) + else sb.append(obtainedClean) sb.append("\n") } appendDiffOnlyReport(sb) @@ -46,67 +40,48 @@ class Diff(val obtained: String, val expected: String) extends Serializable { val red = AnsiColors.use(AnsiColors.LightRed) val reset = AnsiColors.use(AnsiColors.Reset) val green = AnsiColors.use(AnsiColors.LightGreen) - sb.append(s" (${red}- obtained${reset}, ${green}+ expected${reset})") + sb.append(s" ($red- obtained$reset, $green+ expected$reset)") sb.append("\n") sb.append(unifiedDiff) } - private def asStripMargin(obtained: String): String = { + private def asStripMargin(obtained: String): String = if (!obtained.contains("\n")) Printers.print(obtained) else { val out = new StringBuilder val lines = obtained.trim.linesIterator val head = if (lines.hasNext) lines.next() else "" out.append(" \"\"\"|" + head + "\n") - lines.foreach(line => { - out.append(" |").append(line).append("\n") - }) + lines.foreach(line => out.append(" |").append(line).append("\n")) out.append(" |\"\"\".stripMargin") out.toString() } - } - private def header(t: String, sb: StringBuilder): StringBuilder = { - sb.append(AnsiColors.c(s"=> $t", AnsiColors.Bold)) - } + private def header(t: String, sb: StringBuilder): StringBuilder = sb + .append(AnsiColors.c(s"=> $t", AnsiColors.Bold)) private def createUnifiedDiff( original: Seq[String], - revised: Seq[String] + revised: Seq[String], ): String = { val diff = DiffUtils.diff(original.asJava, revised.asJava) val result = if (diff.getDeltas.isEmpty) "" - else { - DiffUtils - .generateUnifiedDiff( - "obtained", - "expected", - original.asJava, - diff, - 1 - ) - .asScala - .iterator - .drop(2) - .filterNot(_.startsWith("@@")) - .map { line => - if (line.isEmpty()) line - else if (line.last == ' ') line + "∙" - else line - } - .map { line => - if (line.startsWith("-")) AnsiColors.c(line, AnsiColors.LightRed) - else if (line.startsWith("+")) - AnsiColors.c(line, AnsiColors.LightGreen) - else line - } - .mkString("\n") - } + else DiffUtils + .generateUnifiedDiff("obtained", "expected", original.asJava, diff, 1) + .asScala.iterator.drop(2).filterNot(_.startsWith("@@")).map(line => + if (line.isEmpty()) line + else if (line.last == ' ') line + "∙" + else line + ).map(line => + if (line.startsWith("-")) AnsiColors.c(line, AnsiColors.LightRed) + else if (line.startsWith("+")) AnsiColors + .c(line, AnsiColors.LightGreen) + else line + ).mkString("\n") result } - private def splitIntoLines(string: String): Seq[String] = { - string.trim().replace("\r\n", "\n").split("\n").toIndexedSeq - } + private def splitIntoLines(string: String): Seq[String] = string.trim() + .replace("\r\n", "\n").split("\n").toIndexedSeq } diff --git a/munit-diff/shared/src/main/scala/munit/diff/DiffUtils.scala b/munit-diff/shared/src/main/scala/munit/diff/DiffUtils.scala index 79c9e1e3..84a213c0 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/DiffUtils.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/DiffUtils.scala @@ -8,8 +8,8 @@ object DiffUtils { revised: String, originalLines: util.List[String], patch: Patch[String], - contextSize: Int - ): util.List[String] = { + contextSize: Int, + ): util.List[String] = if (!patch.getDeltas.isEmpty) { val ret: util.List[String] = new util.ArrayList() ret.add("--- " + original) @@ -21,51 +21,44 @@ object DiffUtils { var delta = patchDeltas.get(0) deltas.add(delta) - if (patchDeltas.size() > 1) { - for (i <- 1 until patchDeltas.size) { - val position = delta.getOriginal.getPosition // store - // the - // current - // position - // of - // the first Delta - // Check if the next Delta is too close to the current - // position. - // And if it is, add it to the current set - val nextDelta = patchDeltas.get(i) - if ( - (position + delta.getOriginal.size + contextSize) >= - (nextDelta.getOriginal.getPosition - contextSize) - ) { - deltas.add(nextDelta) - } else { // if it isn't, output the current set, - // then create a new set and add the current Delta to - // it. - val curBlock = processDeltas(originalLines, deltas, contextSize) - ret.addAll(curBlock) - deltas.clear() - deltas.add(nextDelta) - } - delta = nextDelta + if (patchDeltas.size() > 1) for (i <- 1 until patchDeltas.size) { + val position = delta.getOriginal.getPosition // store + // the + // current + // position + // of + // the first Delta + // Check if the next Delta is too close to the current + // position. + // And if it is, add it to the current set + val nextDelta = patchDeltas.get(i) + if ( + position + delta.getOriginal.size + contextSize >= + nextDelta.getOriginal.getPosition - contextSize + ) deltas.add(nextDelta) + else { // if it isn't, output the current set, + // then create a new set and add the current Delta to + // it. + val curBlock = processDeltas(originalLines, deltas, contextSize) + ret.addAll(curBlock) + deltas.clear() + deltas.add(nextDelta) } + delta = nextDelta } val curBlock = processDeltas(originalLines, deltas, contextSize) ret.addAll(curBlock) ret - } else { - new util.ArrayList[String]() - } - } + } else new util.ArrayList[String]() def diff( original: util.List[String], - revised: util.List[String] - ): Patch[String] = - new MyersDiff[String]().diff(original, revised) + revised: util.List[String], + ): Patch[String] = new MyersDiff[String]().diff(original, revised) private def processDeltas( origLines: util.List[String], deltas: util.List[Delta[String]], - contextSize: Int + contextSize: Int, ) = { val buffer = new util.ArrayList[String] var origTotal = 0 // counter for total lines output from Original @@ -82,9 +75,7 @@ object DiffUtils { if (contextStart < 0) contextStart = 0 // clamp to the start of the file // output the context before the first Delta line = contextStart - while ({ - line < curDelta.getOriginal.getPosition - }) { // + while (line < curDelta.getOriginal.getPosition) { // buffer.add(" " + origLines.get(line)) origTotal += 1 revTotal += 1 @@ -96,16 +87,12 @@ object DiffUtils { origTotal += curDelta.getOriginal.getLines.size revTotal += curDelta.getRevised.getLines.size var deltaIndex = 1 - while ({ - deltaIndex < deltas.size - }) { // for each of the other Deltas + while (deltaIndex < deltas.size) { // for each of the other Deltas val nextDelta = deltas.get(deltaIndex) - val intermediateStart = - curDelta.getOriginal.getPosition + curDelta.getOriginal.getLines.size + val intermediateStart = curDelta.getOriginal.getPosition + + curDelta.getOriginal.getLines.size line = intermediateStart - while ({ - line < nextDelta.getOriginal.getPosition - }) { // output the code between the last Delta and this one + while (line < nextDelta.getOriginal.getPosition) { // output the code between the last Delta and this one buffer.add(" " + origLines.get(line)) origTotal += 1 revTotal += 1 @@ -120,12 +107,10 @@ object DiffUtils { deltaIndex += 1 } // Now output the post-Delta context code, clamping the end of the file - contextStart = - curDelta.getOriginal.getPosition + curDelta.getOriginal.getLines.size + contextStart = curDelta.getOriginal.getPosition + + curDelta.getOriginal.getLines.size line = contextStart - while ({ - (line < (contextStart + contextSize)) && (line < origLines.size) - }) { + while (line < contextStart + contextSize && line < origLines.size) { buffer.add(" " + origLines.get(line)) origTotal += 1 revTotal += 1 @@ -151,12 +136,8 @@ object DiffUtils { private def getDeltaText(delta: Delta[String]) = { import scala.collection.JavaConverters._ val buffer = new util.ArrayList[String] - for (line <- delta.getOriginal.getLines.asScala) { - buffer.add("-" + line) - } - for (line <- delta.getRevised.getLines.asScala) { - buffer.add("+" + line) - } + for (line <- delta.getOriginal.getLines.asScala) buffer.add("-" + line) + for (line <- delta.getRevised.getLines.asScala) buffer.add("+" + line) buffer } diff --git a/munit-diff/shared/src/main/scala/munit/diff/Diffs.scala b/munit-diff/shared/src/main/scala/munit/diff/Diffs.scala index 828084c7..b1c0b300 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/Diffs.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/Diffs.scala @@ -5,24 +5,18 @@ object Diffs { def create(obtained: String, expected: String): Diff = new Diff(obtained, expected) - def createDiffOnlyReport( - obtained: String, - expected: String - ): String = { + def createDiffOnlyReport(obtained: String, expected: String): String = create(obtained, expected).createDiffOnlyReport() - } def createReport( obtained: String, expected: String, title: String, - printObtainedAsStripMargin: Boolean = true - ): String = { - create(obtained, expected).createReport(title, printObtainedAsStripMargin) - } + printObtainedAsStripMargin: Boolean = true, + ): String = create(obtained, expected) + .createReport(title, printObtainedAsStripMargin) - def unifiedDiff(obtained: String, expected: String): String = { + def unifiedDiff(obtained: String, expected: String): String = create(obtained, expected).unifiedDiff - } } diff --git a/munit-diff/shared/src/main/scala/munit/diff/Equalizer.scala b/munit-diff/shared/src/main/scala/munit/diff/Equalizer.scala index d7136f67..d6686cc4 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/Equalizer.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/Equalizer.scala @@ -5,8 +5,7 @@ trait Equalizer[T] { } object Equalizer { def default[T]: Equalizer[T] = new Equalizer[T] { - override def equals(original: T, revised: T): Boolean = { - original.equals(revised) - } + override def equals(original: T, revised: T): Boolean = original + .equals(revised) } } diff --git a/munit-diff/shared/src/main/scala/munit/diff/MyersDiff.scala b/munit-diff/shared/src/main/scala/munit/diff/MyersDiff.scala index 5304b196..e211eb76 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/MyersDiff.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/MyersDiff.scala @@ -7,60 +7,42 @@ class MyersDiff[T](equalizer: Equalizer[T]) def this() = this(Equalizer.default[T]) override def diff( original: util.List[T], - revised: util.List[T] - ): munit.diff.Patch[T] = { - try { - buildRevision(buildPath(original, revised), original, revised) - } catch { + revised: util.List[T], + ): munit.diff.Patch[T] = + try buildRevision(buildPath(original, revised), original, revised) + catch { case e: DifferentiationFailedException => e.printStackTrace() new munit.diff.Patch[T]() } - } private def buildRevision( _path: PathNode, orig: util.List[T], - rev: util.List[T] + rev: util.List[T], ): munit.diff.Patch[T] = { var path = _path val patch = new munit.diff.Patch[T] if (path.isSnake) path = path.prev - while ( - path != null && - path.prev != null && - path.prev.j >= 0 - ) { - if (path.isSnake) - throw new IllegalStateException( - "bad diffpath: found snake when looking for diff" - ) + while (path != null && path.prev != null && path.prev.j >= 0) { + if (path.isSnake) throw new IllegalStateException( + "bad diffpath: found snake when looking for diff" + ) val i = path.i val j = path.j path = path.prev val ianchor = path.i val janchor = path.j val original = - new munit.diff.Chunk[T]( - ianchor, - copyOfRange(orig, ianchor, i) - ) - val revised = - new munit.diff.Chunk[T]( - janchor, - copyOfRange(rev, janchor, j) - ) + new munit.diff.Chunk[T](ianchor, copyOfRange(orig, ianchor, i)) + val revised = new munit.diff.Chunk[T](janchor, copyOfRange(rev, janchor, j)) val delta: munit.diff.Delta[T] = - if (original.size == 0 && revised.size != 0) { + if (original.size == 0 && revised.size != 0) new munit.diff.InsertDelta[T](original, revised) - } else if (original.size > 0 && revised.size == 0) { + else if (original.size > 0 && revised.size == 0) new munit.diff.DeleteDelta[T](original, revised) - } else { - new munit.diff.ChangeDelta[T](original, revised) - } + else new munit.diff.ChangeDelta[T](original, revised) patch.addDelta(delta) - if (path.isSnake) { - path = path.prev - } + if (path.isSnake) path = path.prev } patch } @@ -68,10 +50,7 @@ class MyersDiff[T](equalizer: Equalizer[T]) private def copyOfRange(original: util.List[T], fromIndex: Int, to: Int) = new util.ArrayList[T](original.subList(fromIndex, to)) - def buildPath( - orig: util.List[T], - rev: util.List[T] - ): PathNode = { + def buildPath(orig: util.List[T], rev: util.List[T]): PathNode = { val N = orig.size() val M = rev.size() @@ -91,7 +70,7 @@ class MyersDiff[T](equalizer: Equalizer[T]) val kminus = kmiddle - 1 var prev: PathNode = null var i = 0 - if ((k == -d) || (k != d && diagonal(kminus).i < diagonal(kplus).i)) { + if (k == -d || k != d && diagonal(kminus).i < diagonal(kplus).i) { i = diagonal(kplus).i prev = diagonal(kplus) } else { @@ -105,21 +84,13 @@ class MyersDiff[T](equalizer: Equalizer[T]) // orig and rev are zero-based // but the algorithm is one-based // that's why there's no +1 when indexing the sequences - while ( - i < N && - j < M && - equalizer.equals(orig.get(i), rev.get(j)) - ) { + while (i < N && j < M && equalizer.equals(orig.get(i), rev.get(j))) { i += 1 j += 1 } - if (i > node.i) { - node = new Snake(i, j, node) - } + if (i > node.i) node = new Snake(i, j, node) diagonal(kmiddle) = node - if (i >= N && j >= M) { - return diagonal(kmiddle) - } + if (i >= N && j >= M) return diagonal(kmiddle) k += 2 } diff --git a/munit-diff/shared/src/main/scala/munit/diff/Patch.scala b/munit-diff/shared/src/main/scala/munit/diff/Patch.scala index 5045f780..99d176a0 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/Patch.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/Patch.scala @@ -1,17 +1,16 @@ package munit.diff import java.util -import java.util.{Collections, Comparator} +import java.util.Collections +import java.util.Comparator class Patch[T] { private val deltas: util.List[Delta[T]] = new util.ArrayList() private val comparator: Comparator[Delta[T]] = new Comparator[Delta[T]] { - override def compare(o1: Delta[T], o2: Delta[T]): Int = - o1.getOriginal.getPosition.compareTo(o2.getOriginal.getPosition) - } - def addDelta(delta: Delta[T]): Unit = { - deltas.add(delta) + override def compare(o1: Delta[T], o2: Delta[T]): Int = o1.getOriginal + .getPosition.compareTo(o2.getOriginal.getPosition) } + def addDelta(delta: Delta[T]): Unit = deltas.add(delta) def getDeltas: util.List[Delta[T]] = { Collections.sort(deltas, comparator) deltas diff --git a/munit-diff/shared/src/main/scala/munit/diff/PathNode.scala b/munit-diff/shared/src/main/scala/munit/diff/PathNode.scala index 92d04771..6e286f86 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/PathNode.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/PathNode.scala @@ -3,14 +3,11 @@ package munit.diff sealed abstract class PathNode(val i: Int, val j: Int, val prev: PathNode) { def isSnake: Boolean - final def isBootstrap: Boolean = { - i < 0 || j < 0 - } - final def previousSnake: PathNode = { + final def isBootstrap: Boolean = i < 0 || j < 0 + final def previousSnake: PathNode = if (isBootstrap) null else if (!isSnake && prev != null) prev.previousSnake else this - } override def toString: String = { val buf = new StringBuffer("[") diff --git a/munit-diff/shared/src/main/scala/munit/diff/Printer.scala b/munit-diff/shared/src/main/scala/munit/diff/Printer.scala index 7d5e713b..0bf30834 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/Printer.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/Printer.scala @@ -12,8 +12,7 @@ trait Printer { */ def print(value: Any, out: StringBuilder, indent: Int): Boolean def height: Int = Printer.defaultHeight - def isMultiline(string: String): Boolean = - string.contains('\n') + def isMultiline(string: String): Boolean = string.contains('\n') /** * Combine two printers into a single printer. @@ -48,12 +47,8 @@ trait Printer { val h = this.height val p: (Any, StringBuilder, Int) => Boolean = this.print new Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = - p.apply(value, out, indent) || other.print( - value, - out, - indent - ) + def print(value: Any, out: StringBuilder, indent: Int): Boolean = p + .apply(value, out, indent) || other.print(value, out, indent) override def height: Int = h.max(other.height) } } @@ -69,14 +64,13 @@ object Printer { )(partialPrint: PartialFunction[Any, String]): Printer = { val h = height new Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = { + def print(value: Any, out: StringBuilder, indent: Int): Boolean = partialPrint.lift.apply(value) match { case Some(string) => out.append(string) true case None => false } - } override def height: Int = h } diff --git a/munit-diff/shared/src/main/scala/munit/diff/console/AnsiColors.scala b/munit-diff/shared/src/main/scala/munit/diff/console/AnsiColors.scala index f9a15918..20733ae2 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/console/AnsiColors.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/console/AnsiColors.scala @@ -15,20 +15,16 @@ object AnsiColors { val GREEN = "\u001B[32m" val DarkGrey = "\u001B[90m" - val noColor: Boolean = - Option(System.getenv("NO_COLOR")).exists(_ != "") + val noColor: Boolean = Option(System.getenv("NO_COLOR")).exists(_ != "") - def use(colorSequence: String): String = - if (noColor) "" else colorSequence + def use(colorSequence: String): String = if (noColor) "" else colorSequence def c(s: String, colorSequence: String): String = - if (colorSequence == null || noColor) s - else colorSequence + s + Reset + if (colorSequence == null || noColor) s else colorSequence + s + Reset - def filterAnsi(s: String): String = { - if (s == null) { - null - } else { + def filterAnsi(s: String): String = + if (s == null) null + else { val len = s.length val r = new java.lang.StringBuilder(len) var i = 0 @@ -37,13 +33,10 @@ object AnsiColors { if (c == '\u001B') { i += 1 while (i < len && s.charAt(i) != 'm') i += 1 - } else { - r.append(c) - } + } else r.append(c) i += 1 } r.toString() } - } } diff --git a/munit-diff/shared/src/main/scala/munit/diff/console/Printers.scala b/munit-diff/shared/src/main/scala/munit/diff/console/Printers.scala index 4e9c9ed6..a5173bad 100644 --- a/munit-diff/shared/src/main/scala/munit/diff/console/Printers.scala +++ b/munit-diff/shared/src/main/scala/munit/diff/console/Printers.scala @@ -1,6 +1,7 @@ package munit.diff.console -import munit.diff.{EmptyPrinter, Printer} +import munit.diff.EmptyPrinter +import munit.diff.Printer import scala.annotation.switch @@ -15,7 +16,7 @@ object Printers { def printString( string: String, out: StringBuilder, - printer: Printer + printer: Printer, ): Unit = { val isMultiline = printer.isMultiline(string) if (isMultiline) { @@ -40,20 +41,19 @@ object Printers { def printChar( c: Char, sb: StringBuilder, - isEscapeUnicode: Boolean = true - ): Unit = - (c: @switch) match { - case '"' => sb.append("\\\"") - case '\\' => sb.append("\\\\") - case '\b' => sb.append("\\b") - case '\f' => sb.append("\\f") - case '\n' => sb.append("\\n") - case '\r' => sb.append("\\r") - case '\t' => sb.append("\\t") - case c => - val isNonReadableAscii = c < ' ' || (c > '~' && isEscapeUnicode) - if (isNonReadableAscii && !Character.isLetter(c)) - sb.append("\\u%04x".format(c.toInt)) - else sb.append(c) - } + isEscapeUnicode: Boolean = true, + ): Unit = (c: @switch) match { + case '"' => sb.append("\\\"") + case '\\' => sb.append("\\\\") + case '\b' => sb.append("\\b") + case '\f' => sb.append("\\f") + case '\n' => sb.append("\\n") + case '\r' => sb.append("\\r") + case '\t' => sb.append("\\t") + case c => + val isNonReadableAscii = c < ' ' || c > '~' && isEscapeUnicode + if (isNonReadableAscii && !Character.isLetter(c)) sb + .append("\\u%04x".format(c.toInt)) + else sb.append(c) + } } diff --git a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitGcpListener.scala b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitGcpListener.scala index f072c19e..f4bbab18 100644 --- a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitGcpListener.scala +++ b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitGcpListener.scala @@ -1,56 +1,51 @@ package munit.sbtmunit -import com.google.cloud.storage.StorageOptions -import com.google.cloud.storage.BucketInfo -import com.google.gson.Gson +import munit.sbtmunit.MUnitTestReport.Summary + +import sbt.util.Logger + import java.nio.charset.StandardCharsets + import com.google.cloud.storage.Bucket.BlobTargetOption +import com.google.cloud.storage.BucketInfo import com.google.cloud.storage.Storage.PredefinedAcl import com.google.cloud.storage.StorageException -import sbt.util.Logger -import munit.sbtmunit.MUnitTestReport.Summary +import com.google.cloud.storage.StorageOptions +import com.google.gson.Gson class MUnitGcpListener( val reportName: String, val bucketName: String, val maxRetries: Int = 100, - logger: Logger = sbt.ConsoleLogger() + logger: Logger = sbt.ConsoleLogger(), ) extends MUnitReportListener { private lazy val storage = StorageOptions.getDefaultInstance().getService() - private lazy val bucket = Option(storage.get(bucketName)).getOrElse { - storage.create(BucketInfo.of(bucketName)) - } + private lazy val bucket = Option(storage.get(bucketName)) + .getOrElse(storage.create(BucketInfo.of(bucketName))) def onReport(report: Summary): Unit = synchronized { - val suffixes = Stream - .from(0) - .map { - case 0 => ".json" - case n => s"-$n.json" - } - .take(maxRetries) + val suffixes = Stream.from(0).map { + case 0 => ".json" + case n => s"-$n.json" + }.take(maxRetries) val bytes = new Gson().toJson(report).getBytes(StandardCharsets.UTF_8) val success = suffixes.find { suffix => - val name = s"${report.repository}/${reportName}$suffix" + val name = s"${report.repository}/$reportName$suffix" try { val blob = bucket.create( name, bytes, "application/json", BlobTargetOption.predefinedAcl(PredefinedAcl.PUBLIC_READ), - BlobTargetOption.doesNotExist() - ) - logger.info( - s"uploaded test report: gs://${blob.getBucket()}/${blob.getBlobId().getName()}" + BlobTargetOption.doesNotExist(), ) + logger.info(s"uploaded test report: gs://${blob.getBucket()}/${blob.getBlobId().getName()}") true } catch { case e: StorageException - if Option(e.getMessage()).contains("Precondition Failed") => - false + if Option(e.getMessage()).contains("Precondition Failed") => false } } - if (success.isEmpty) { - logger.error(s"warn: failed to upload report after $maxRetries retries.") - } + if (success.isEmpty) logger + .error(s"warn: failed to upload report after $maxRetries retries.") } } diff --git a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitLocalListener.scala b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitLocalListener.scala index 0ec53a10..cdb9fb0f 100644 --- a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitLocalListener.scala +++ b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitLocalListener.scala @@ -1,18 +1,20 @@ package munit.sbtmunit -import java.nio.file.Path -import java.nio.file.Paths import sbt.util.Logger -import com.google.gson.Gson + import java.nio.charset.StandardCharsets import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths import java.nio.file.StandardOpenOption +import com.google.gson.Gson + class MUnitLocalListener( - path: Path = - Paths.get(".").toAbsolutePath().normalize().resolve("test-report.json"), + path: Path = Paths.get(".").toAbsolutePath().normalize() + .resolve("test-report.json"), maxRetries: Int = 100, - logger: Logger = sbt.ConsoleLogger() + logger: Logger = sbt.ConsoleLogger(), ) extends MUnitReportListener { def onReport(report: MUnitTestReport.Summary): Unit = { val bytes = new Gson().toJson(report).getBytes(StandardCharsets.UTF_8) @@ -20,7 +22,7 @@ class MUnitLocalListener( path, bytes, StandardOpenOption.CREATE, - StandardOpenOption.TRUNCATE_EXISTING + StandardOpenOption.TRUNCATE_EXISTING, ) logger.info(s"wrote test report: $path") } diff --git a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitPlugin.scala b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitPlugin.scala index e057d197..0659900f 100644 --- a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitPlugin.scala +++ b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitPlugin.scala @@ -1,40 +1,33 @@ package munit.sbtmunit -import sbt._ import sbt.Keys._ +import sbt._ import sbt.plugins._ -import java.nio.file.Paths + import java.nio.file.Files -import java.{util => ju} -import java.time.format.DateTimeFormatter +import java.nio.file.Paths import java.time.LocalDate +import java.time.format.DateTimeFormatter +import java.{util => ju} object MUnitPlugin extends AutoPlugin { override def trigger = allRequirements override def requires = JvmPlugin object autoImport { - val munitBucketName: SettingKey[Option[String]] = - settingKey[Option[String]]( - "The Google Cloud Storage bucket name, defaults to 'munit-test-reports'." - ) - val munitRepository: SettingKey[Option[String]] = - settingKey[Option[String]]( - "The repository of this project, for example GitHub URL." - ) + val munitBucketName: SettingKey[Option[String]] = settingKey[Option[String]]( + "The Google Cloud Storage bucket name, defaults to 'munit-test-reports'." + ) + val munitRepository: SettingKey[Option[String]] = settingKey[Option[String]]( + "The repository of this project, for example GitHub URL." + ) val munitRef: SettingKey[Option[String]] = - settingKey[Option[String]]( - "The git branch or tag reference from where this report was created, for example 'refs/heads/master'." - ) + settingKey[Option[String]]("The git branch or tag reference from where this report was created, for example 'refs/heads/master'.") val munitSha: SettingKey[Option[String]] = - settingKey[Option[String]]( - "The git commit SHA from where this report was created, for example 'f32a4ab1cf8685f47837f07bb52f515b48fd4ecb'." - ) + settingKey[Option[String]]("The git commit SHA from where this report was created, for example 'f32a4ab1cf8685f47837f07bb52f515b48fd4ecb'.") val munitReportName: SettingKey[Option[String]] = settingKey[Option[String]]("The filename for this test report.") val munitReportListener: SettingKey[Option[MUnitReportListener]] = - settingKey[Option[MUnitReportListener]]( - "The listener to handle reports." - ) + settingKey[Option[MUnitReportListener]]("The listener to handle reports.") } import autoImport._ @@ -42,7 +35,7 @@ object MUnitPlugin extends AutoPlugin { munitBucketName := Some("munit-test-reports"), munitRepository := Option(System.getenv("GITHUB_REPOSITORY")), munitRef := Option(System.getenv("GITHUB_REF")), - munitSha := Option(System.getenv("GITHUB_SHA")) + munitSha := Option(System.getenv("GITHUB_SHA")), ) override val projectSettings: Seq[Def.Setting[_]] = List( @@ -58,8 +51,7 @@ object MUnitPlugin extends AutoPlugin { Files.createDirectories(path.getParent()) Files.write(path, json) true - case _ => - false + case _ => false } } bucketName <- munitBucketName.value @@ -74,7 +66,7 @@ object MUnitPlugin extends AutoPlugin { project = thisProject.value.id scala = scalaVersion.value jvm = System.getProperty("java.version", "unknown") - } yield s"${date}/$ref/$sha/$project/$scala/$jvm" + } yield s"$date/$ref/$sha/$project/$scala/$jvm" }, testListeners ++= { for { @@ -90,8 +82,8 @@ object MUnitPlugin extends AutoPlugin { ref, sha, scalaVersion.value, - thisProject.value.id + thisProject.value.id, ) - } + }, ) } diff --git a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitReportPlugin.scala b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitReportPlugin.scala index 1ac615e8..3f9f1d4e 100644 --- a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitReportPlugin.scala +++ b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitReportPlugin.scala @@ -1,7 +1,8 @@ package munit.sbtmunit -import sbt._ import sbt.Keys._ +import sbt._ + import MUnitPlugin.autoImport._ object MUnitReportPlugin extends AutoPlugin { @@ -12,17 +13,13 @@ object MUnitReportPlugin extends AutoPlugin { else List("org.scalameta" %% "munit-docs" % BuildInfo.munitVersion) }, Compile / resourceGenerators += Def.task[List[File]] { - val out = - (Compile / managedResourceDirectories).value.head / "munit.properties" + val out = (Compile / managedResourceDirectories).value.head / + "munit.properties" val props = new java.util.Properties() - munitRepository.value.foreach { repo => - props.put("munitRepository", repo) - } - munitBucketName.value.foreach { repo => - props.put("munitBucketName", repo) - } + munitRepository.value.foreach(repo => props.put("munitRepository", repo)) + munitBucketName.value.foreach(repo => props.put("munitBucketName", repo)) IO.write(props, "MUnit properties", out) List(out) - } + }, ) } diff --git a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestReport.scala b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestReport.scala index 1150818e..5c8e4f55 100644 --- a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestReport.scala +++ b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestReport.scala @@ -10,13 +10,9 @@ object MUnitTestReport { projectName: String, javaVersion: String, os: String, - groups: Array[Group] - ) - case class Group( - name: String, - result: String, - events: Array[TestEvent] + groups: Array[Group], ) + case class Group(name: String, result: String, events: Array[TestEvent]) case class TestEvent( status: String, name: String, @@ -24,12 +20,12 @@ object MUnitTestReport { // but then all numbers get formatted as `2.0` with a redundant `.0` // suffix. duration: Long, - exception: TestException + exception: TestException, ) case class TestException( className: String, message: String, stack: Array[String], - cause: TestException + cause: TestException, ) } diff --git a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestsListener.scala b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestsListener.scala index 6196efc6..e9f0ceed 100644 --- a/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestsListener.scala +++ b/munit-sbt/src/main/scala/munit/sbtmunit/MUnitTestsListener.scala @@ -1,13 +1,15 @@ package munit.sbtmunit import sbt._ -import scala.collection.JavaConverters._ +import sbt.testing.Event +import sbt.testing.Status + +import java.text.SimpleDateFormat import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue -import sbt.testing.Status -import sbt.testing.Event import java.{util => ju} -import java.text.SimpleDateFormat + +import scala.collection.JavaConverters._ class MUnitTestsListener( listener: MUnitReportListener, @@ -16,35 +18,29 @@ class MUnitTestsListener( ref: String, sha: String, scalaVersion: String, - projectName: String + projectName: String, ) extends TestsListener { private val groups = new ConcurrentHashMap[String, ConcurrentLinkedQueue[TestEvent]] @volatile private var currentGroup: String = "unknown" - def startGroup(name: String): Unit = { - currentGroup = name - } + def startGroup(name: String): Unit = currentGroup = name def testEvent(event: TestEvent): Unit = { val group = groups.computeIfAbsent( currentGroup, - (_: String) => new ConcurrentLinkedQueue[TestEvent]() + (_: String) => new ConcurrentLinkedQueue[TestEvent](), ) group.add(event) } def endGroup(name: String, t: Throwable): Unit = {} def endGroup(name: String, result: TestResult): Unit = {} - def doInit(): Unit = { - groups.clear() - } - def doComplete(finalResult: TestResult): Unit = { - listener.onReport(newReport(finalResult)) - } + def doInit(): Unit = groups.clear() + def doComplete(finalResult: TestResult): Unit = listener + .onReport(newReport(finalResult)) - val ISO_8601 = - new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", ju.Locale.US); - private def newReport(testResult: TestResult): MUnitTestReport.Summary = { + val ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", ju.Locale.US); + private def newReport(testResult: TestResult): MUnitTestReport.Summary = MUnitTestReport.Summary( repository = repository, ref = ref, @@ -58,27 +54,23 @@ class MUnitTestsListener( MUnitTestReport.Group( name = group, result = overallResult(events.asScala).toString, - events = events.asScala.iterator - .flatMap(_.detail) - .map(newTestEvent) - .toArray + events = events.asScala.iterator.flatMap(_.detail).map(newTestEvent) + .toArray, ) - }.toArray + }.toArray, ) - } - private def newTestEvent(event: Event): MUnitTestReport.TestEvent = { + private def newTestEvent(event: Event): MUnitTestReport.TestEvent = MUnitTestReport.TestEvent( status = event.status().toString(), name = event.fullyQualifiedName(), duration = event.duration(), exception = if (event.throwable().isEmpty()) null - else newTestException(event.throwable().get()) + else newTestException(event.throwable().get()), ) - } - private def newTestException(ex: Throwable): MUnitTestReport.TestException = { + private def newTestException(ex: Throwable): MUnitTestReport.TestException = if (ex == null) null else { val plainMessage = Option(ex.getMessage()).map(filterAnsi).getOrElse("") @@ -91,29 +83,21 @@ class MUnitTestsListener( val colon = plainMessage.indexOf(": ") val space = plainMessage.indexOf(' ') val customClassNameHasSpace = space >= 0 && space < colon - if (colon < 0 || customClassNameHasSpace) { + if (colon < 0 || customClassNameHasSpace) (plainClassName, plainMessage) - } else { - ( - plainMessage.substring(0, colon), - plainMessage.substring(colon + 2) - ) - } - } else { - (plainClassName, plainMessage) - } + else + (plainMessage.substring(0, colon), plainMessage.substring(colon + 2)) + } else (plainClassName, plainMessage) MUnitTestReport.TestException( className = className, message = message, stack = Option(ex.getStackTrace()).getOrElse(Array()).map(_.toString), - cause = newTestException(ex.getCause()) + cause = newTestException(ex.getCause()), ) } - } - private def filterAnsi(s: String): String = { - if (s == null) { - null - } else { + private def filterAnsi(s: String): String = + if (s == null) null + else { var r: String = "" val len = s.length var i = 0 @@ -122,25 +106,20 @@ class MUnitTestsListener( if (c == '\u001B') { i += 1 while (i < len && s.charAt(i) != 'm') i += 1 - } else { - r += c - } + } else r += c i += 1 } r } - } - private def overallResult(events: Iterable[TestEvent]): TestResult = { - events.iterator - .flatMap(_.detail) - .foldLeft(TestResult.Passed: TestResult) { (sum, event) => - (sum, event.status) match { - case (TestResult.Error, _) => TestResult.Error - case (_, Status.Error) => TestResult.Error - case (TestResult.Failed, _) => TestResult.Failed - case (_, Status.Failure) => TestResult.Failed - case _ => TestResult.Passed - } + private def overallResult(events: Iterable[TestEvent]): TestResult = events + .iterator.flatMap(_.detail) + .foldLeft(TestResult.Passed: TestResult)((sum, event) => + (sum, event.status) match { + case (TestResult.Error, _) => TestResult.Error + case (_, Status.Error) => TestResult.Error + case (TestResult.Failed, _) => TestResult.Failed + case (_, Status.Failure) => TestResult.Failed + case _ => TestResult.Passed } - } + ) } diff --git a/munit/js-native/src/main/scala/munit/Framework.scala b/munit/js-native/src/main/scala/munit/Framework.scala index e994efe4..d1494760 100644 --- a/munit/js-native/src/main/scala/munit/Framework.scala +++ b/munit/js-native/src/main/scala/munit/Framework.scala @@ -8,9 +8,6 @@ class Framework extends JUnitFramework { override def name(): String = "munit" val munitFingerprint = new CustomFingerprint("munit.Suite", _isModule = false) val customRunners = new CustomRunners( - List( - munitFingerprint, - new CustomFingerprint("munit.Suite", _isModule = true) - ) + List(munitFingerprint, new CustomFingerprint("munit.Suite", _isModule = true)) ) } diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomFingerprint.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomFingerprint.scala index 1d845208..c9fe6b8f 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomFingerprint.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomFingerprint.scala @@ -2,10 +2,8 @@ package munit.internal.junitinterface import sbt.testing.SubclassFingerprint -class CustomFingerprint( - val suite: String, - _isModule: Boolean -) extends SubclassFingerprint { +class CustomFingerprint(val suite: String, _isModule: Boolean) + extends SubclassFingerprint { override def isModule(): Boolean = _isModule override def superclassName(): String = suite override def requireNoArgConstructor(): Boolean = true diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomRunners.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomRunners.scala index 84731da2..ad5d1037 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomRunners.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/CustomRunners.scala @@ -1,6 +1,7 @@ package munit.internal.junitinterface -import sbt.testing.{Fingerprint, SubclassFingerprint} +import sbt.testing.Fingerprint +import sbt.testing.SubclassFingerprint class CustomRunners(val runners: List[CustomFingerprint]) { private val superclasses = runners.iterator.map(_.suite).toSet @@ -8,7 +9,7 @@ class CustomRunners(val runners: List[CustomFingerprint]) { def matchesFingerprint(fingerprint: Fingerprint): Boolean = fingerprint match { case s: SubclassFingerprint => superclasses.contains(s.superclassName()) - case _ => false + case _ => false } } diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/IncludeFilter.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/IncludeFilter.scala index ab9e2cb7..2b219a18 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/IncludeFilter.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/IncludeFilter.scala @@ -3,11 +3,9 @@ package munit.internal.junitinterface import org.junit.runner.Description import org.junit.runner.manipulation.Filter -class TagsFilter( - val include: Set[String], - val exclude: Set[String] -) extends Filter { - override def shouldRun(description: Description): Boolean = { +class TagsFilter(val include: Set[String], val exclude: Set[String]) + extends Filter { + override def shouldRun(description: Description): Boolean = if (include.isEmpty && exclude.isEmpty) true else { var isIncluded = include.isEmpty @@ -20,5 +18,4 @@ class TagsFilter( } isIncluded && !isExcluded } - } } diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitEvent.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitEvent.scala index cf033e85..3df23d6b 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitEvent.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitEvent.scala @@ -12,7 +12,7 @@ final class JUnitEvent( _status: Status, _selector: Selector, _throwable: OptionalThrowable = new OptionalThrowable, - _duration: Long = -1L + _duration: Long = -1L, ) extends Event { override def status(): Status = _status override def selector(): Selector = _selector diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitFramework.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitFramework.scala index c35d0192..ed4642ef 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitFramework.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitFramework.scala @@ -12,38 +12,32 @@ abstract class JUnitFramework extends Framework { def customRunners: CustomRunners - def fingerprints(): Array[Fingerprint] = { - customRunners.runners.toArray - } + def fingerprints(): Array[Fingerprint] = customRunners.runners.toArray def runner( args: Array[String], remoteArgs: Array[String], - testClassLoader: ClassLoader - ): Runner = { - new JUnitRunner( - args, - remoteArgs, - parseRunSettings(args), - testClassLoader, - customRunners - ) - } + testClassLoader: ClassLoader, + ): Runner = new JUnitRunner( + args, + remoteArgs, + parseRunSettings(args), + testClassLoader, + customRunners, + ) def slaveRunner( args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader, - send: String => Unit - ): Runner = { - new JUnitRunner( - args, - remoteArgs, - parseRunSettings(args), - testClassLoader, - customRunners - ) - } + send: String => Unit, + ): Runner = new JUnitRunner( + args, + remoteArgs, + parseRunSettings(args), + testClassLoader, + customRunners, + ) private def parseRunSettings(args: Array[String]): RunSettings = { val defaults = Settings.defaults() @@ -56,60 +50,56 @@ abstract class JUnitFramework extends Framework { var trimStackTraces = defaults.trimStackTraces var includeTags = Set.empty[String] var excludeTags = Set.empty[String] - for (str <- args) { - str match { - case "-v" => verbose = true - case "-n" => noColor = true - case "-s" => decodeScalaNames = true - case "-a" => logAssert = true - case "-c" => notLogExceptionClass = true + for (str <- args) str match { + case "-v" => verbose = true + case "-n" => noColor = true + case "-s" => decodeScalaNames = true + case "-a" => logAssert = true + case "-c" => notLogExceptionClass = true - case s if s.startsWith("-tests=") => - throw new UnsupportedOperationException("-tests") + case s if s.startsWith("-tests=") => + throw new UnsupportedOperationException("-tests") - case s if s.startsWith("--tests=") => - throw new UnsupportedOperationException("--tests") + case s if s.startsWith("--tests=") => + throw new UnsupportedOperationException("--tests") - case s if s.startsWith("--ignore-runners=") => - throw new UnsupportedOperationException("--ignore-runners") + case s if s.startsWith("--ignore-runners=") => + throw new UnsupportedOperationException("--ignore-runners") - case s if s.startsWith("--run-listener=") => - throw new UnsupportedOperationException("--run-listener") + case s if s.startsWith("--run-listener=") => + throw new UnsupportedOperationException("--run-listener") - case s if s.startsWith("--exclude-tags=") => - excludeTags += s.stripPrefix("--exclude-tags=") + case s if s.startsWith("--exclude-tags=") => + excludeTags += s.stripPrefix("--exclude-tags=") - case s if s.startsWith("--include-tags=") => - includeTags += s.stripPrefix("--include-tags=") + case s if s.startsWith("--include-tags=") => + includeTags += s.stripPrefix("--include-tags=") - case s if s.startsWith("--include-categories=") => - throw new UnsupportedOperationException("--include-categories") + case s if s.startsWith("--include-categories=") => + throw new UnsupportedOperationException("--include-categories") - case s if s.startsWith("--exclude-categories=") => - throw new UnsupportedOperationException("--exclude-categories") + case s if s.startsWith("--exclude-categories=") => + throw new UnsupportedOperationException("--exclude-categories") - case s if s.startsWith("-D") && s.contains("=") => - throw new UnsupportedOperationException("-Dkey=value") + case s if s.startsWith("-D") && s.contains("=") => + throw new UnsupportedOperationException("-Dkey=value") - case s if !s.startsWith("-") && !s.startsWith("+") => - throw new UnsupportedOperationException(s) + case s if !s.startsWith("-") && !s.startsWith("+") => + throw new UnsupportedOperationException(s) - case _ => - } + case _ => } - for (s <- args) { - s match { - case "+v" => verbose = false - case "+n" => noColor = false - case "+s" => decodeScalaNames = false - case "+a" => logAssert = false - case "+c" => notLogExceptionClass = false - case "+l" => useSbtLoggers = true - case "-l" => useSbtLoggers = false - case "+F" => trimStackTraces = true - case "-F" => trimStackTraces = false - case _ => - } + for (s <- args) s match { + case "+v" => verbose = false + case "+n" => noColor = false + case "+s" => decodeScalaNames = false + case "+a" => logAssert = false + case "+c" => notLogExceptionClass = false + case "+l" => useSbtLoggers = true + case "-l" => useSbtLoggers = false + case "+F" => trimStackTraces = true + case "-F" => trimStackTraces = false + case _ => } new RunSettings( color = !noColor, @@ -119,7 +109,7 @@ abstract class JUnitFramework extends Framework { notLogExceptionClass = notLogExceptionClass, useSbtLoggers = useSbtLoggers, trimStackTraces = trimStackTraces, - tags = new TagsFilter(includeTags, excludeTags) + tags = new TagsFilter(includeTags, excludeTags), ) } } diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala index fcedafe9..cb47561b 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitReporter.scala @@ -5,47 +5,41 @@ package munit.internal.junitinterface import munit.diff.console.AnsiColors -import sbt.testing._ import munit.internal.PlatformCompat +import sbt.testing._ + final class JUnitReporter( eventHandler: EventHandler, loggers: Array[Logger], settings: RunSettings, - taskDef: TaskDef + taskDef: TaskDef, ) { - private val isAnsiSupported = - loggers.forall(_.ansiCodesSupported()) && settings.color + private val isAnsiSupported = loggers.forall(_.ansiCodesSupported()) && + settings.color - def reportTestSuiteStarted(): Unit = { - log( - Info, - AnsiColors.c(s"${taskDef.fullyQualifiedName()}:", AnsiColors.GREEN) - ) - } - def reportTestStarted(method: String): Unit = { - if (settings.verbose) { - log(Info, s"$method started") - } - } + def reportTestSuiteStarted(): Unit = + log(Info, AnsiColors.c(s"${taskDef.fullyQualifiedName()}:", AnsiColors.GREEN)) + def reportTestStarted(method: String): Unit = + if (settings.verbose) log(Info, s"$method started") def reportTestIgnored( method: String, elapsedMillis: Double, - suffix: String + suffix: String, ): Unit = { - val suffixed = if (suffix.isEmpty) "" else s" ${suffix}" + val suffixed = if (suffix.isEmpty) "" else s" $suffix" log( Info, AnsiColors.c(s"==> i $method$suffixed ignored", AnsiColors.YELLOW) + " " + - formatTime(elapsedMillis) + formatTime(elapsedMillis), ) emitEvent(method, Status.Ignored) } def reportAssumptionViolation( method: String, timeInSeconds: Double, - e: Throwable + e: Throwable, ): Unit = { log(Info, AnsiColors.c(s"==> s $method skipped", AnsiColors.YELLOW)) emitEvent(method, Status.Skipped, new OptionalThrowable(e)) @@ -54,96 +48,74 @@ final class JUnitReporter( log( Info, AnsiColors.c(s" + $method", AnsiColors.GREEN) + " " + - formatTime(elapsedMillis) + formatTime(elapsedMillis), ) emitEvent(method, Status.Success) } def reportTestFailed( method: String, ex: Throwable, - elapsedMillis: Double + elapsedMillis: Double, ): Unit = { log( Info, - new StringBuilder() - .append( - AnsiColors.c( - s"==> X ${taskDef.fullyQualifiedName()}.$method", - AnsiColors.LightRed - ) - ) - .append(" ") - .append(formatTime(elapsedMillis)) - .append(" ") - .append(ex.getClass().getName()) - .append(": ") - .append(ex.getMessage()) - .toString() + new StringBuilder().append(AnsiColors.c( + s"==> X ${taskDef.fullyQualifiedName()}.$method", + AnsiColors.LightRed, + )).append(" ").append(formatTime(elapsedMillis)).append(" ") + .append(ex.getClass().getName()).append(": ").append(ex.getMessage()) + .toString(), ) emitEvent(method, Status.Failure, new OptionalThrowable(ex)) } - private def trace(t: Throwable): Unit = { - if (!t.isInstanceOf[AssertionError] || settings.logAssert) { - logTrace(t) - } - } + private def trace(t: Throwable): Unit = + if (!t.isInstanceOf[AssertionError] || settings.logAssert) logTrace(t) private def emitEvent( method: String, status: Status, - throwable: OptionalThrowable = new OptionalThrowable + throwable: OptionalThrowable = new OptionalThrowable, ): Unit = { - val testName = - taskDef.fullyQualifiedName() + "." + - settings.decodeName(method) + val testName = taskDef.fullyQualifiedName() + "." + + settings.decodeName(method) val selector = new TestSelector(testName) - eventHandler.handle( - new JUnitEvent(taskDef, testName, status, selector, throwable) - ) + eventHandler + .handle(new JUnitEvent(taskDef, testName, status, selector, throwable)) } - private def log(level: Level, s: String): Unit = { - if (settings.useSbtLoggers) { - for (l <- loggers) { - val msg = filterAnsiIfNeeded(l, s) - level match { - case Debug => l.debug(msg) - case Info => l.info(msg) - case Warn => l.warn(msg) - case Error => l.error(msg) - case _ => l.error(msg) - } - } - } else { + private def log(level: Level, s: String): Unit = + if (settings.useSbtLoggers) for (l <- loggers) { + val msg = filterAnsiIfNeeded(l, s) level match { - case Debug | Trace if !settings.verbose => - case _ => - println(filterAnsiIfNeeded(isAnsiSupported, s)) + case Debug => l.debug(msg) + case Info => l.info(msg) + case Warn => l.warn(msg) + case Error => l.error(msg) + case _ => l.error(msg) } } - } + else level match { + case Debug | Trace if !settings.verbose => + case _ => println(filterAnsiIfNeeded(isAnsiSupported, s)) + } private def filterAnsiIfNeeded(l: Logger, s: String): String = filterAnsiIfNeeded(l.ansiCodesSupported(), s) private def filterAnsiIfNeeded(isColorSupported: Boolean, s: String): String = - if (isColorSupported && settings.color) s - else AnsiColors.filterAnsi(s) + if (isColorSupported && settings.color) s else AnsiColors.filterAnsi(s) private def logTrace(t: Throwable): Unit = { - val trace = t.getStackTrace.dropWhile { p => + val trace = t.getStackTrace.dropWhile(p => p.getFileName != null && { p.getFileName.contains("StackTrace.scala") || p.getFileName.contains("Throwables.scala") } - } - val testFileName = { - if (settings.color) findTestFileName(trace) - else null - } - val i = trace.indexWhere { p => + ) + val testFileName = if (settings.color) findTestFileName(trace) else null + val i = trace.indexWhere(p => p.getFileName != null && p.getFileName.contains("JUnitExecuteTest.scala") - } - 1 + ) - 1 val m = if (i > 0) i else trace.length - 1 logStackTracePart(trace, m, trace.length - m - 1, t, testFileName) } @@ -153,7 +125,7 @@ final class JUnitReporter( m: Int, framesInCommon: Int, t: Throwable, - testFileName: String + testFileName: String, ): Unit = { val m0 = m var m2 = m @@ -163,10 +135,9 @@ final class JUnitReporter( if ( trace(i).toString.startsWith("org.junit.") || trace(i).toString.startsWith("org.hamcrest.") - ) { - if (i == top) { - top += 1 - } else { + ) + if (i == top) top += 1 + else { m2 = i - 1 var break = false while (m2 > top && !break) { @@ -174,100 +145,75 @@ final class JUnitReporter( if ( !s.startsWith("java.lang.reflect.") && !s.startsWith("sun.reflect.") - ) { - break = true - } else { - m2 -= 1 - } + ) break = true + else m2 -= 1 } i = m2 // break } - } i += 1 } - for (i <- top to m2) { + for (i <- top to m2) log(Error, stackTraceElementToString(trace(i), testFileName)) - } - if (m0 != m2) { + if (m0 != m2) // skip junit-related frames log(Error, " ...") - } else if (framesInCommon != 0) { + else if (framesInCommon != 0) // skip frames that were in the previous trace too log(Error, " ... " + framesInCommon + " more") - } logStackTraceAsCause(trace, t.getCause, testFileName) } private def logStackTraceAsCause( causedTrace: Array[StackTraceElement], t: Throwable, - testFileName: String - ): Unit = { - if (t != null) { - val trace = t.getStackTrace - var m = trace.length - 1 - var n = causedTrace.length - 1 - while (m >= 0 && n >= 0 && trace(m) == causedTrace(n)) { - m -= 1 - n -= 1 - } - log(Error, "Caused by: " + t) - logStackTracePart(trace, m, trace.length - 1 - m, t, testFileName) + testFileName: String, + ): Unit = if (t != null) { + val trace = t.getStackTrace + var m = trace.length - 1 + var n = causedTrace.length - 1 + while (m >= 0 && n >= 0 && trace(m) == causedTrace(n)) { + m -= 1 + n -= 1 } + log(Error, "Caused by: " + t) + logStackTracePart(trace, m, trace.length - 1 - m, t, testFileName) } - private def findTestFileName(trace: Array[StackTraceElement]): String = - trace - .find(_.getClassName == taskDef.fullyQualifiedName()) - .map(_.getFileName) - .orNull + private def findTestFileName(trace: Array[StackTraceElement]): String = trace + .find(_.getClassName == taskDef.fullyQualifiedName()).map(_.getFileName) + .orNull private def stackTraceElementToString( e: StackTraceElement, - testFileName: String + testFileName: String, ): String = { val highlight = settings.color && { // This logic assumes that users have configured Scala.js sourcemaps. - e.getFileName() != null && - e.getFileName().contains("file:/") + e.getFileName() != null && e.getFileName().contains("file:/") } val canHighlight = !PlatformCompat.isNative - new StringBuilder() - .append(AnsiColors.use(AnsiColors.Reset)) - .append( - if (!canHighlight) "" - else if (highlight) AnsiColors.use(AnsiColors.Bold) - else AnsiColors.use(AnsiColors.DarkGrey) - ) - .append(" at ") + new StringBuilder().append(AnsiColors.use(AnsiColors.Reset)).append( + if (!canHighlight) "" + else if (highlight) AnsiColors.use(AnsiColors.Bold) + else AnsiColors.use(AnsiColors.DarkGrey) + ).append(" at ") .append(settings.decodeName(e.getClassName + '.' + e.getMethodName)) - .append('(') - .append( - if (e.isNativeMethod()) { - "Native Method" - } else if (e.getFileName() == null) { - "Unknown Source" - } else { + .append('(').append( + if (e.isNativeMethod()) "Native Method" + else if (e.getFileName() == null) "Unknown Source" + else { val file = e.getFileName().indexOf("file:/") - val https = - if (file >= 0) file else e.getFileName().indexOf("https:/") + val https = if (file >= 0) file else e.getFileName().indexOf("https:/") val filename = - if (https >= 0) e.getFileName().substring(https) - else e.getFileName() - if (e.getLineNumber() >= 0) { - s"${filename}:${e.getLineNumber()}" - } else { - filename - } + if (https >= 0) e.getFileName().substring(https) else e.getFileName() + if (e.getLineNumber() >= 0) s"$filename:${e.getLineNumber()}" + else filename } - ) - .append(')') - .append(AnsiColors.use(AnsiColors.Reset)) - .toString() + ).append(')').append(AnsiColors.use(AnsiColors.Reset)).toString() } - private def formatTime(elapsedMillis: Double): String = - AnsiColors.c("%.3fs".format(elapsedMillis / 1000.0), AnsiColors.DarkGrey) + private def formatTime(elapsedMillis: Double): String = AnsiColors + .c("%.3fs".format(elapsedMillis / 1000.0), AnsiColors.DarkGrey) private val Trace = 0 private val Debug = 1 private val Info = 2 diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala index 59cef135..dd0ae86c 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/JUnitRunner.scala @@ -4,36 +4,35 @@ package munit.internal.junitinterface -import sbt.testing._ import munit.internal.PlatformCompat +import sbt.testing._ + final class JUnitRunner( val args: Array[String], _remoteArgs: Array[String], runSettings: RunSettings, classLoader: ClassLoader, - customRunners: CustomRunners + customRunners: CustomRunners, ) extends Runner { PlatformCompat.setThisClassLoader(classLoader) override def remoteArgs(): Array[String] = _remoteArgs - override def tasks(taskDefs: Array[TaskDef]): Array[Task] = - taskDefs.map(new JUnitTask(_, runSettings, classLoader)) + override def tasks(taskDefs: Array[TaskDef]): Array[Task] = taskDefs + .map(new JUnitTask(_, runSettings, classLoader)) override def done(): String = "" override def serializeTask( task: Task, - serializer: TaskDef => String - ): String = - serializer(task.taskDef()) + serializer: TaskDef => String, + ): String = serializer(task.taskDef()) override def deserializeTask( task: String, - deserializer: String => TaskDef - ): Task = - new JUnitTask(deserializer(task), runSettings, classLoader) + deserializer: String => TaskDef, + ): Task = new JUnitTask(deserializer(task), runSettings, classLoader) override def receiveMessage(msg: String): Option[String] = None } diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/MUnitRunNotifier.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/MUnitRunNotifier.scala index ec4092dc..f718bd2e 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/MUnitRunNotifier.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/MUnitRunNotifier.scala @@ -1,18 +1,18 @@ package munit.internal.junitinterface -import org.junit.runner.{Description, notification} -import org.junit.runner.notification.RunNotifier - import scala.collection.mutable +import org.junit.runner.Description +import org.junit.runner.notification +import org.junit.runner.notification.RunNotifier + class MUnitRunNotifier(reporter: JUnitReporter) extends RunNotifier { var ignored = 0 var total = 0 var startedTimestamp = 0L val isReported: mutable.Set[Description] = mutable.Set.empty[Description] - override def fireTestSuiteStarted(description: Description): Unit = { + override def fireTestSuiteStarted(description: Description): Unit = reporter.reportTestSuiteStarted() - } override def fireTestStarted(description: Description): Unit = { startedTimestamp = System.nanoTime() reporter.reportTestStarted(description.getMethodName) @@ -26,48 +26,36 @@ class MUnitRunNotifier(reporter: JUnitReporter) extends RunNotifier { isReported += description val pendingSuffixes = { val annotations = description.getAnnotations - val isPending = annotations.collect { case munit.Pending => - "PENDING" - }.distinct - val pendingComments = annotations.collect { - case tag: munit.PendingComment => tag.value - } + val isPending = annotations.collect { case munit.Pending => "PENDING" } + .distinct + val pendingComments = annotations + .collect { case tag: munit.PendingComment => tag.value } isPending ++ pendingComments } reporter.reportTestIgnored( description.getMethodName, elapsedMillis(), - pendingSuffixes.mkString(" ") + pendingSuffixes.mkString(" "), ) } - override def fireTestAssumptionFailed( - failure: notification.Failure - ): Unit = { + override def fireTestAssumptionFailed(failure: notification.Failure): Unit = { isReported += failure.description reporter.reportAssumptionViolation( failure.description.getMethodName, elapsedMillis(), - failure.ex + failure.ex, ) } override def fireTestFailure(failure: notification.Failure): Unit = { val methodName = failure.description.getMethodName isReported += failure.description - reporter.reportTestFailed( - methodName, - failure.ex, - elapsedMillis() - ) + reporter.reportTestFailed(methodName, failure.ex, elapsedMillis()) } override def fireTestFinished(description: Description): Unit = { val methodName = description.getMethodName total += 1 - if (!isReported(description)) { - reporter.reportTestPassed( - methodName, - elapsedMillis() - ) - } + if (!isReported(description)) reporter + .reportTestPassed(methodName, elapsedMillis()) } override def fireTestSuiteFinished(description: Description): Unit = {} } diff --git a/munit/js-native/src/main/scala/munit/internal/junitinterface/RunSettings.scala b/munit/js-native/src/main/scala/munit/internal/junitinterface/RunSettings.scala index df708be2..4c033051 100644 --- a/munit/js-native/src/main/scala/munit/internal/junitinterface/RunSettings.scala +++ b/munit/js-native/src/main/scala/munit/internal/junitinterface/RunSettings.scala @@ -14,11 +14,10 @@ final class RunSettings( val notLogExceptionClass: Boolean, val useSbtLoggers: Boolean, val trimStackTraces: Boolean, - val tags: TagsFilter + val tags: TagsFilter, ) extends Settings { - def decodeName(name: String): String = { - if (decodeScalaNames) - Try(scala.reflect.NameTransformer.decode(name)).getOrElse(name) + def decodeName(name: String): String = + if (decodeScalaNames) Try(scala.reflect.NameTransformer.decode(name)) + .getOrElse(name) else name - } } diff --git a/munit/js-native/src/main/scala/org/junit/runner/Description.scala b/munit/js-native/src/main/scala/org/junit/runner/Description.scala index 69461ef5..89a01551 100644 --- a/munit/js-native/src/main/scala/org/junit/runner/Description.scala +++ b/munit/js-native/src/main/scala/org/junit/runner/Description.scala @@ -6,7 +6,7 @@ class Description( cls: Option[Class[_]] = None, methodName: Option[String] = None, annotations: List[Annotation] = Nil, - children: List[Description] = Nil + children: List[Description] = Nil, ) { def addChild(description: Description): Description = new Description(cls, methodName, annotations, description :: children) @@ -17,22 +17,16 @@ class Description( object Description { def createSuiteDescription(cls: Class[_]): Description = - new Description( - cls = Some(cls) - ) + new Description(cls = Some(cls)) def createTestDescription( cls: Class[_], name: String, annotation: Annotation* - ): Description = - new Description( - cls = Some(cls), - methodName = Some(name), - annotations = annotation.toList - ) + ): Description = new Description( + cls = Some(cls), + methodName = Some(name), + annotations = annotation.toList, + ) def createTestDescription(cls: Class[_], name: String): Description = - new Description( - cls = Some(cls), - methodName = Some(name) - ) + new Description(cls = Some(cls), methodName = Some(name)) } diff --git a/munit/js/src/main/scala/munit/internal/PlatformCompat.scala b/munit/js/src/main/scala/munit/internal/PlatformCompat.scala index 7a1ac67b..d1039078 100644 --- a/munit/js/src/main/scala/munit/internal/PlatformCompat.scala +++ b/munit/js/src/main/scala/munit/internal/PlatformCompat.scala @@ -1,29 +1,31 @@ package munit.internal -import scala.scalajs.reflect.Reflect -import sbt.testing.TaskDef import munit.MUnitRunner -import scala.concurrent.Future -import sbt.testing.Task + import sbt.testing.EventHandler import sbt.testing.Logger -import scala.concurrent.Promise -import scala.concurrent.duration.Duration +import sbt.testing.Task +import sbt.testing.TaskDef + +import java.util.concurrent.TimeoutException + import scala.concurrent.Await import scala.concurrent.Awaitable import scala.concurrent.ExecutionContext +import scala.concurrent.Future +import scala.concurrent.Promise +import scala.concurrent.duration.Duration import scala.scalajs.js.timers -import java.util.concurrent.TimeoutException +import scala.scalajs.reflect.Reflect object PlatformCompat { - def awaitResult[T](awaitable: Awaitable[T]): T = { - Await.result(awaitable, Duration.Inf) - } + def awaitResult[T](awaitable: Awaitable[T]): T = Await + .result(awaitable, Duration.Inf) def executeAsync( task: Task, eventHandler: EventHandler, - loggers: Array[Logger] + loggers: Array[Logger], ): Future[Unit] = { val p = Promise[Unit]() task.execute(eventHandler, loggers, _ => p.success(())) @@ -33,25 +35,20 @@ object PlatformCompat { def waitAtMost[T]( startFuture: () => Future[T], duration: Duration, - ec: ExecutionContext + ec: ExecutionContext, ): Future[T] = { val onComplete = Promise[T]() val timeoutHandle = - if (duration.isFinite) - Some(timers.setTimeout(duration.toMillis) { - onComplete.tryFailure( - new TimeoutException(s"test timed out after $duration") - ) - }) - else - None + if (duration.isFinite) Some(timers.setTimeout(duration.toMillis)( + onComplete + .tryFailure(new TimeoutException(s"test timed out after $duration")) + )) + else None ec.execute(new Runnable { - def run(): Unit = { - startFuture().onComplete { result => - onComplete.tryComplete(result) - timeoutHandle.foreach(timers.clearTimeout(_)) - }(ec) - } + def run(): Unit = startFuture().onComplete { result => + onComplete.tryComplete(result) + timeoutHandle.foreach(timers.clearTimeout(_)) + }(ec) }) onComplete.future } @@ -71,17 +68,14 @@ object PlatformCompat { def newRunner( taskDef: TaskDef, - classLoader: ClassLoader - ): Option[MUnitRunner] = { - Reflect - .lookupInstantiatableClass(taskDef.fullyQualifiedName()) - .map(cls => - new MUnitRunner( - cls.runtimeClass.asInstanceOf[Class[_ <: munit.Suite]], - () => cls.newInstance().asInstanceOf[munit.Suite] - ) + classLoader: ClassLoader, + ): Option[MUnitRunner] = Reflect + .lookupInstantiatableClass(taskDef.fullyQualifiedName()).map(cls => + new MUnitRunner( + cls.runtimeClass.asInstanceOf[Class[_ <: munit.Suite]], + () => cls.newInstance().asInstanceOf[munit.Suite], ) - } + ) private var myClassLoader: ClassLoader = _ def setThisClassLoader(loader: ClassLoader): Unit = myClassLoader = loader def getThisClassLoader: ClassLoader = myClassLoader diff --git a/munit/js/src/main/scala/munit/internal/io/File.scala b/munit/js/src/main/scala/munit/internal/io/File.scala index 73d6936e..896214e6 100644 --- a/munit/js/src/main/scala/munit/internal/io/File.scala +++ b/munit/js/src/main/scala/munit/internal/io/File.scala @@ -4,75 +4,54 @@ import java.net.URI // obtained implementation by experimentation on the JDK. class File(path: String) { - def this(parent: String, child: String) = - this(parent + File.separator + child) - def this(parent: File, child: String) = - this(parent.getPath, child) - def this(uri: URI) = - this( - if (uri.getScheme != "file") { - throw new IllegalArgumentException("URI scheme is not \"file\"") - } else { - uri.getPath - } - ) - def toPath: MunitPath = - MunitPath(path) + def this(parent: String, child: String) = this(parent + File.separator + child) + def this(parent: File, child: String) = this(parent.getPath, child) + def this(uri: URI) = this( + if (uri.getScheme != "file") + throw new IllegalArgumentException("URI scheme is not \"file\"") + else uri.getPath + ) + def toPath: MunitPath = MunitPath(path) def toURI: URI = { val file = getAbsoluteFile.toString val uripath = - if (file.startsWith("/")) file - else "/" + file.replace(File.separator, "/") + if (file.startsWith("/")) file else "/" + file.replace(File.separator, "/") val withslash = if (isDirectory && !uripath.endsWith("/")) uripath + "/" else uripath new URI("file", null, withslash, null) } - def getAbsoluteFile: File = - toPath.toAbsolutePath.toFile - def getAbsolutePath: String = - getAbsoluteFile.toString - def getParentFile: File = - toPath.getParent.toFile - def mkdirs(): Unit = - throw new UnsupportedOperationException( - "mkdirs() is not supported in Scala.js" - ) - def getPath: String = - path - def exists(): Boolean = - JSIO.exists(path) - def isFile: Boolean = - JSIO.isFile(path) - def isDirectory: Boolean = - JSIO.isDirectory(path) - override def toString: String = - path + def getAbsoluteFile: File = toPath.toAbsolutePath.toFile + def getAbsolutePath: String = getAbsoluteFile.toString + def getParentFile: File = toPath.getParent.toFile + def mkdirs(): Unit = throw new UnsupportedOperationException( + "mkdirs() is not supported in Scala.js" + ) + def getPath: String = path + def exists(): Boolean = JSIO.exists(path) + def isFile: Boolean = JSIO.isFile(path) + def isDirectory: Boolean = JSIO.isDirectory(path) + override def toString: String = path } object File { - def listRoots(): Array[File] = Array( - new File( - JSIO.path match { - case Some(p) => p.parse(p.resolve()).root.asInstanceOf[String] - case None => "/" - } - // if (JSIO.isNode) JSPath.parse(JSPath.resolve()).root - // else "/" - ) - ) - - def separatorChar: Char = - separator.charAt(0) - - def separator: String = + def listRoots(): Array[File] = Array(new File( JSIO.path match { - case Some(p) => p.sep.asInstanceOf[String] - case None => "/" + case Some(p) => p.parse(p.resolve()).root.asInstanceOf[String] + case None => "/" } + // if (JSIO.isNode) JSPath.parse(JSPath.resolve()).root + // else "/" + )) - def pathSeparator: String = - JSIO.path match { - case Some(p) => p.delimeter.asInstanceOf[String] - case None => ":" - } + def separatorChar: Char = separator.charAt(0) + + def separator: String = JSIO.path match { + case Some(p) => p.sep.asInstanceOf[String] + case None => "/" + } + + def pathSeparator: String = JSIO.path match { + case Some(p) => p.delimeter.asInstanceOf[String] + case None => ":" + } } diff --git a/munit/js/src/main/scala/munit/internal/io/Files.scala b/munit/js/src/main/scala/munit/internal/io/Files.scala index 94d64267..06a80f5b 100644 --- a/munit/js/src/main/scala/munit/internal/io/Files.scala +++ b/munit/js/src/main/scala/munit/internal/io/Files.scala @@ -1,10 +1,10 @@ package munit.internal.io -import scala.scalajs.js -import java.{util => ju} import java.nio.charset.StandardCharsets +import java.{util => ju} import scala.collection.JavaConverters._ +import scala.scalajs.js object Files { def readAllLines(path: MunitPath): ju.List[String] = { @@ -14,8 +14,7 @@ object Files { } def readAllBytes(path: MunitPath): Array[Byte] = { val jsArray = JSIO.fs match { - case Some(fs) => - fs.readFileSync(path.toString).asInstanceOf[js.Array[Int]] + case Some(fs) => fs.readFileSync(path.toString).asInstanceOf[js.Array[Int]] case None => new js.Array[Int](0) } val len = jsArray.length @@ -27,6 +26,5 @@ object Files { } result } - def exists(path: MunitPath): Boolean = - JSIO.exists(path.toString) + def exists(path: MunitPath): Boolean = JSIO.exists(path.toString) } diff --git a/munit/js/src/main/scala/munit/internal/io/JSIO.scala b/munit/js/src/main/scala/munit/internal/io/JSIO.scala index 466c4ae8..6447280d 100644 --- a/munit/js/src/main/scala/munit/internal/io/JSIO.scala +++ b/munit/js/src/main/scala/munit/internal/io/JSIO.scala @@ -5,38 +5,34 @@ import scala.util.Try object JSIO { - private def require(module: String): Option[js.Dynamic] = { + private def require(module: String): Option[js.Dynamic] = Try(js.Dynamic.global.require(module)) // Node.js .orElse( // JSDOM Try(js.Dynamic.global.Node.constructor("return require")()(module)) - ) - .toOption - } + ).toOption val process: Option[js.Dynamic] = require("process") val path: Option[js.Dynamic] = require("path") val fs: Option[js.Dynamic] = require("fs") - def cwd(): String = - process match { - case Some(p) => p.cwd().asInstanceOf[String] - case None => "/" - } + def cwd(): String = process match { + case Some(p) => p.cwd().asInstanceOf[String] + case None => "/" + } - def exists(path: String): Boolean = - fs match { - case Some(f) => f.existsSync(path).asInstanceOf[Boolean] - case None => false - } + def exists(path: String): Boolean = fs match { + case Some(f) => f.existsSync(path).asInstanceOf[Boolean] + case None => false + } - def isFile(path: String): Boolean = - exists(path) && (fs match { + def isFile(path: String): Boolean = exists(path) && + (fs match { case Some(f) => f.lstatSync(path).isFile().asInstanceOf[Boolean] - case None => false + case None => false }) - def isDirectory(path: String): Boolean = - exists(path) && (fs match { + def isDirectory(path: String): Boolean = exists(path) && + (fs match { case Some(f) => f.lstatSync(path).isDirectory().asInstanceOf[Boolean] - case None => false + case None => false }) } diff --git a/munit/js/src/main/scala/munit/internal/io/MunitPath.scala b/munit/js/src/main/scala/munit/internal/io/MunitPath.scala index de1302ed..b94aec61 100644 --- a/munit/js/src/main/scala/munit/internal/io/MunitPath.scala +++ b/munit/js/src/main/scala/munit/internal/io/MunitPath.scala @@ -8,142 +8,96 @@ import scala.collection.JavaConverters._ // Rough implementation of java.nio.Path, should work similarly for the happy // path but has undefined behavior for error handling. case class MunitPath(filename: String) { - private[this] val escapedSeparator = - java.util.regex.Pattern.quote(File.separator) + private[this] val escapedSeparator = java.util.regex.Pattern + .quote(File.separator) - private def adjustIndex(idx: Int): Int = - if (isAbsolute) idx + 1 else idx - def subpath(beginIndex: Int, endIndex: Int): MunitPath = - MunitPath( - filename - .split(escapedSeparator) - .slice(adjustIndex(beginIndex), adjustIndex(endIndex)) - .mkString - ) - def toFile: File = - new File(filename) + private def adjustIndex(idx: Int): Int = if (isAbsolute) idx + 1 else idx + def subpath(beginIndex: Int, endIndex: Int): MunitPath = MunitPath( + filename.split(escapedSeparator) + .slice(adjustIndex(beginIndex), adjustIndex(endIndex)).mkString + ) + def toFile: File = new File(filename) def isAbsolute: Boolean = JSIO.path match { case Some(path) => path.isAbsolute(filename).asInstanceOf[Boolean] - case None => filename.startsWith(File.separator) + case None => filename.startsWith(File.separator) + } + def getName(index: Int): MunitPath = MunitPath( + filename.split(escapedSeparator).lift(adjustIndex(index)) + .getOrElse(throw new IllegalArgumentException) + ) + def getParent: MunitPath = JSIO.path match { + case Some(path) => MunitPath(path.dirname(filename).asInstanceOf[String]) + case None => throw new UnsupportedOperationException( + "Path.getParent() is only supported in Node.js" + ) } - def getName(index: Int): MunitPath = - MunitPath( - filename - .split(escapedSeparator) - .lift(adjustIndex(index)) - .getOrElse(throw new IllegalArgumentException) - ) - def getParent: MunitPath = - JSIO.path match { - case Some(path) => - MunitPath(path.dirname(filename).asInstanceOf[String]) - case None => - throw new UnsupportedOperationException( - "Path.getParent() is only supported in Node.js" - ) - } def toAbsolutePath: MunitPath = - if (isAbsolute) this - else MunitPath.workingDirectory.resolve(this) - def relativize(other: MunitPath): MunitPath = - JSIO.path match { - case Some(path) => - MunitPath( - path.relative(filename, other.toString()).asInstanceOf[String] - ) - case None => - throw new UnsupportedOperationException( - "Path.relativize() is only supported in Node.js" - ) - } + if (isAbsolute) this else MunitPath.workingDirectory.resolve(this) + def relativize(other: MunitPath): MunitPath = JSIO.path match { + case Some(path) => + MunitPath(path.relative(filename, other.toString()).asInstanceOf[String]) + case None => throw new UnsupportedOperationException( + "Path.relativize() is only supported in Node.js" + ) + } def getNameCount: Int = { val strippeddrive = - if ((filename.length > 1) && (filename(1) == ':')) filename.substring(2) + if (filename.length > 1 && filename(1) == ':') filename.substring(2) else filename - val (first, remaining) = - strippeddrive.split(escapedSeparator + "+").span(_.isEmpty) - if (remaining.isEmpty) first.length - else remaining.length + val (first, remaining) = strippeddrive.split(escapedSeparator + "+") + .span(_.isEmpty) + if (remaining.isEmpty) first.length else remaining.length } def toUri: URI = toFile.toURI - def getFileName(): MunitPath = - JSIO.path match { - case Some(path) => - MunitPath(path.basename(filename).asInstanceOf[String]) - case None => - throw new UnsupportedOperationException( - "Path.getFileName() is only supported in Node.js" - ) - } - def getRoot: MunitPath = - if (!isAbsolute) null - else MunitPath(File.separator) - def normalize(): MunitPath = - JSIO.path match { - case Some(path) => - MunitPath(path.normalize(filename).asInstanceOf[String]) - case None => - throw new UnsupportedOperationException( - "Path.normalize() is only supported in Node.js" - ) - } - def endsWith(other: MunitPath): Boolean = - endsWith(other.toString) - def endsWith(other: String): Boolean = - paths(filename).endsWith(paths(other)) + def getFileName(): MunitPath = JSIO.path match { + case Some(path) => MunitPath(path.basename(filename).asInstanceOf[String]) + case None => throw new UnsupportedOperationException( + "Path.getFileName() is only supported in Node.js" + ) + } + def getRoot: MunitPath = if (!isAbsolute) null else MunitPath(File.separator) + def normalize(): MunitPath = JSIO.path match { + case Some(path) => MunitPath(path.normalize(filename).asInstanceOf[String]) + case None => throw new UnsupportedOperationException( + "Path.normalize() is only supported in Node.js" + ) + } + def endsWith(other: MunitPath): Boolean = endsWith(other.toString) + def endsWith(other: String): Boolean = paths(filename).endsWith(paths(other)) // JSPath.resolve(relpath, relpath) produces an absolute path from cwd. // This method turns the generated absolute path back into a relative path. private def adjustResolvedPath(resolved: MunitPath): MunitPath = - if (isAbsolute) resolved - else MunitPath.workingDirectory.relativize(resolved) + if (isAbsolute) resolved else MunitPath.workingDirectory.relativize(resolved) def resolveSibling(other: MunitPath): MunitPath = resolveSibling(other.toString) - def resolveSibling(other: String): MunitPath = - JSIO.path match { - case Some(path) => - adjustResolvedPath( - MunitPath( - path - .resolve(path.dirname(filename).asInstanceOf[String], other) - .asInstanceOf[String] - ) - ) - case None => - throw new UnsupportedOperationException( - "Path.normalize() is only supported in Node.js" - ) - } - def resolve(other: MunitPath): MunitPath = - resolve(other.toString) - def resolve(other: String): MunitPath = - JSIO.path match { - case Some(path) => - adjustResolvedPath( - MunitPath(path.resolve(filename, other).asInstanceOf[String]) - ) - case None => - throw new UnsupportedOperationException( - "Path.normalize() is only supported in Node.js" - ) - } - def startsWith(other: MunitPath): Boolean = - startsWith(other.toString) - def startsWith(other: String): Boolean = - paths(filename).startsWith(paths(other)) - private def paths(name: String) = - name.split(escapedSeparator) - override def toString: String = - filename - def iterator(): util.Iterator[MunitPath] = - filename - .split(File.separator) - .iterator - .map(name => MunitPath(name): MunitPath) - .asJava + def resolveSibling(other: String): MunitPath = JSIO.path match { + case Some(path) => adjustResolvedPath(MunitPath( + path.resolve(path.dirname(filename).asInstanceOf[String], other) + .asInstanceOf[String] + )) + case None => throw new UnsupportedOperationException( + "Path.normalize() is only supported in Node.js" + ) + } + def resolve(other: MunitPath): MunitPath = resolve(other.toString) + def resolve(other: String): MunitPath = JSIO.path match { + case Some(path) => adjustResolvedPath( + MunitPath(path.resolve(filename, other).asInstanceOf[String]) + ) + case None => throw new UnsupportedOperationException( + "Path.normalize() is only supported in Node.js" + ) + } + def startsWith(other: MunitPath): Boolean = startsWith(other.toString) + def startsWith(other: String): Boolean = paths(filename) + .startsWith(paths(other)) + private def paths(name: String) = name.split(escapedSeparator) + override def toString: String = filename + def iterator(): util.Iterator[MunitPath] = filename.split(File.separator) + .iterator.map(name => MunitPath(name): MunitPath).asJava } object MunitPath { - def workingDirectory: MunitPath = - MunitPath(JSIO.cwd()) + def workingDirectory: MunitPath = MunitPath(JSIO.cwd()) } diff --git a/munit/js/src/main/scala/munit/internal/io/Paths.scala b/munit/js/src/main/scala/munit/internal/io/Paths.scala index cf04e689..127afe3c 100644 --- a/munit/js/src/main/scala/munit/internal/io/Paths.scala +++ b/munit/js/src/main/scala/munit/internal/io/Paths.scala @@ -21,7 +21,7 @@ object Paths { val parts = uripath.split('/').toList val (leading, trailing) = parts.span(_ == "") trailing match { - case drive :: path if (drive.length == 2 && drive(1) == ':') => + case drive :: path if drive.length == 2 && drive(1) == ':' => MunitPath(trailing.mkString("\\")) case _ => MunitPath(uripath) } diff --git a/munit/js/src/main/scala/munit/internal/io/PlatformIO.scala b/munit/js/src/main/scala/munit/internal/io/PlatformIO.scala index 695dc6bb..b1ea7ad6 100644 --- a/munit/js/src/main/scala/munit/internal/io/PlatformIO.scala +++ b/munit/js/src/main/scala/munit/internal/io/PlatformIO.scala @@ -7,10 +7,9 @@ object PlatformIO { } object Files { - def readAllLines(path: Path): java.util.List[String] = - munit.internal.io.Files.readAllLines(path) - def exists(path: Path): Boolean = - munit.internal.io.Files.exists(path) + def readAllLines(path: Path): java.util.List[String] = munit.internal.io + .Files.readAllLines(path) + def exists(path: Path): Boolean = munit.internal.io.Files.exists(path) } type Path = MunitPath diff --git a/munit/js/src/main/scala/munit/internal/junitinterface/JUnitTask.scala b/munit/js/src/main/scala/munit/internal/junitinterface/JUnitTask.scala index 780b768f..eba4b009 100644 --- a/munit/js/src/main/scala/munit/internal/junitinterface/JUnitTask.scala +++ b/munit/js/src/main/scala/munit/internal/junitinterface/JUnitTask.scala @@ -5,10 +5,13 @@ package munit.internal.junitinterface import munit.internal.PlatformCompat -import org.junit.runner.notification.RunNotifier + import sbt.testing._ + import scala.concurrent.ExecutionContext.Implicits.global +import org.junit.runner.notification.RunNotifier + /* Implementation note: In JUnitTask we use Future[Try[Unit]] instead of simply * Future[Unit]. This is to prevent Scala's Future implementation to box/wrap * fatal errors (most importantly AssertionError) in ExecutionExceptions. We @@ -18,16 +21,13 @@ import scala.concurrent.ExecutionContext.Implicits.global final class JUnitTask( _taskDef: TaskDef, runSettings: RunSettings, - classLoader: ClassLoader + classLoader: ClassLoader, ) extends Task { override def taskDef(): TaskDef = _taskDef override def tags(): Array[String] = Array.empty - def execute( - eventHandler: EventHandler, - loggers: Array[Logger] - ): Array[Task] = { + def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[Task] = { execute(eventHandler, loggers, _ => ()) Array() } @@ -35,17 +35,15 @@ final class JUnitTask( def execute( eventHandler: EventHandler, loggers: Array[Logger], - continuation: Array[Task] => Unit - ): Unit = { - PlatformCompat.newRunner(taskDef(), classLoader) match { - case None => - case Some(runner) => - runner.filter(runSettings.tags) - val reporter = - new JUnitReporter(eventHandler, loggers, runSettings, taskDef()) - val notifier: RunNotifier = new MUnitRunNotifier(reporter) - runner.runAsync(notifier).foreach(_ => continuation(Array())) - } + continuation: Array[Task] => Unit, + ): Unit = PlatformCompat.newRunner(taskDef(), classLoader) match { + case None => + case Some(runner) => + runner.filter(runSettings.tags) + val reporter = + new JUnitReporter(eventHandler, loggers, runSettings, taskDef()) + val notifier: RunNotifier = new MUnitRunNotifier(reporter) + runner.runAsync(notifier).foreach(_ => continuation(Array())) } } diff --git a/munit/jvm/src/main/scala/munit/Framework.scala b/munit/jvm/src/main/scala/munit/Framework.scala index d965875f..e7ddb304 100644 --- a/munit/jvm/src/main/scala/munit/Framework.scala +++ b/munit/jvm/src/main/scala/munit/Framework.scala @@ -1,16 +1,14 @@ package munit -import sbt.testing.Fingerprint - import munit.internal.junitinterface.CustomFingerprint import munit.internal.junitinterface.CustomRunners + +import sbt.testing.Fingerprint import sbt.testing.SubclassFingerprint class Framework extends munit.internal.junitinterface.JUnitFramework { - val munitFingerprint: CustomFingerprint = CustomFingerprint.of( - "munit.Suite", - "munit.MUnitRunner" - ) + val munitFingerprint: CustomFingerprint = CustomFingerprint + .of("munit.Suite", "munit.MUnitRunner") override val name = "munit" override val fingerprints: Array[Fingerprint] = Array( munitFingerprint, @@ -18,8 +16,7 @@ class Framework extends munit.internal.junitinterface.JUnitFramework { def isModule(): Boolean = true def superclassName(): String = "munit.Suite" def requireNoArgConstructor(): Boolean = true - } + }, ) - override val customRunners: CustomRunners = - CustomRunners.of(munitFingerprint) + override val customRunners: CustomRunners = CustomRunners.of(munitFingerprint) } diff --git a/munit/jvm/src/main/scala/munit/internal/PlatformCompat.scala b/munit/jvm/src/main/scala/munit/internal/PlatformCompat.scala index 14718747..bc78ee7d 100644 --- a/munit/jvm/src/main/scala/munit/internal/PlatformCompat.scala +++ b/munit/jvm/src/main/scala/munit/internal/PlatformCompat.scala @@ -1,26 +1,25 @@ package munit.internal -import scala.concurrent.Future -import sbt.testing.Task import sbt.testing.EventHandler import sbt.testing.Logger +import sbt.testing.Task + +import java.util.concurrent.Executors +import java.util.concurrent.ThreadFactory +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException +import java.util.concurrent.atomic.AtomicInteger -import scala.concurrent.duration.Duration -import java.util.concurrent.{ - Executors, - ThreadFactory, - TimeUnit, - TimeoutException -} import scala.concurrent.Await import scala.concurrent.Awaitable -import scala.concurrent.Promise import scala.concurrent.ExecutionContext -import java.util.concurrent.atomic.AtomicInteger +import scala.concurrent.Future +import scala.concurrent.Promise +import scala.concurrent.duration.Duration object PlatformCompat { - private val sh = Executors.newSingleThreadScheduledExecutor( - new ThreadFactory { + private val sh = Executors + .newSingleThreadScheduledExecutor(new ThreadFactory { val counter = new AtomicInteger def threadNumber() = counter.incrementAndGet() def newThread(r: Runnable) = @@ -28,17 +27,15 @@ object PlatformCompat { setDaemon(true) setPriority(Thread.NORM_PRIORITY) } - } - ) + }) - def awaitResult[T](awaitable: Awaitable[T]): T = { - Await.result(awaitable, Duration.Inf) - } + def awaitResult[T](awaitable: Awaitable[T]): T = Await + .result(awaitable, Duration.Inf) def executeAsync( task: Task, eventHandler: EventHandler, - loggers: Array[Logger] + loggers: Array[Logger], ): Future[Unit] = { task.execute(eventHandler, loggers) Future.successful(()) @@ -47,46 +44,35 @@ object PlatformCompat { def waitAtMost[T]( startFuture: () => Future[T], duration: Duration, - ec: ExecutionContext + ec: ExecutionContext, ): Future[T] = { val onComplete = Promise[T]() val timeout = - if (duration.isFinite) - Some( - sh.schedule[Unit]( - () => - onComplete.tryFailure( - new TimeoutException(s"test timed out after $duration") - ), - duration.toMillis, - TimeUnit.MILLISECONDS - ) - ) - else - None + if (duration.isFinite) Some(sh.schedule[Unit]( + () => + onComplete + .tryFailure(new TimeoutException(s"test timed out after $duration")), + duration.toMillis, + TimeUnit.MILLISECONDS, + )) + else None ec.execute(new Runnable { - def run(): Unit = { - startFuture().onComplete { result => - onComplete.tryComplete(result) - timeout.foreach(_.cancel(false)) - }(ec) - } + def run(): Unit = startFuture().onComplete { result => + onComplete.tryComplete(result) + timeout.foreach(_.cancel(false)) + }(ec) }) onComplete.future } def setTimeout(ms: Int)(body: => Unit): () => Unit = { - val scheduled = sh.schedule[Unit]( - () => body, - ms, - TimeUnit.MILLISECONDS - ) + val scheduled = sh.schedule[Unit](() => body, ms, TimeUnit.MILLISECONDS) () => scheduled.cancel(false) } - def isIgnoreSuite(cls: Class[_]): Boolean = - cls.getAnnotationsByType(classOf[munit.IgnoreSuite]).nonEmpty + def isIgnoreSuite(cls: Class[_]): Boolean = cls + .getAnnotationsByType(classOf[munit.IgnoreSuite]).nonEmpty def isJVM: Boolean = true def isJS: Boolean = false def isNative: Boolean = false diff --git a/munit/jvm/src/main/scala/munit/internal/io/PlatformIO.scala b/munit/jvm/src/main/scala/munit/internal/io/PlatformIO.scala index 4f7a623b..d4dd37e8 100644 --- a/munit/jvm/src/main/scala/munit/internal/io/PlatformIO.scala +++ b/munit/jvm/src/main/scala/munit/internal/io/PlatformIO.scala @@ -7,10 +7,9 @@ object PlatformIO { } object Files { - def readAllLines(path: Path): java.util.List[String] = - java.nio.file.Files.readAllLines(path) - def exists(path: Path): Boolean = - java.nio.file.Files.exists(path) + def readAllLines(path: Path): java.util.List[String] = java.nio.file.Files + .readAllLines(path) + def exists(path: Path): Boolean = java.nio.file.Files.exists(path) } type Path = java.nio.file.Path diff --git a/munit/native/src/main/scala/munit/internal/PlatformCompat.scala b/munit/native/src/main/scala/munit/internal/PlatformCompat.scala index 7bf177db..c76cb165 100644 --- a/munit/native/src/main/scala/munit/internal/PlatformCompat.scala +++ b/munit/native/src/main/scala/munit/internal/PlatformCompat.scala @@ -1,55 +1,53 @@ package munit.internal -import sbt.testing.TaskDef import munit.MUnitRunner -import scala.concurrent.Future -import scala.scalanative.reflect.Reflect -import sbt.testing.Task + import sbt.testing.EventHandler import sbt.testing.Logger +import sbt.testing.Task +import sbt.testing.TaskDef + +import java.util.concurrent.Executors +import java.util.concurrent.ThreadFactory +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException +import java.util.concurrent.atomic.AtomicInteger + import scala.concurrent.Await import scala.concurrent.Awaitable +import scala.concurrent.ExecutionContext +import scala.concurrent.Future import scala.concurrent.Promise import scala.concurrent.duration.Duration -import scala.concurrent.ExecutionContext -import java.util.concurrent.{ - Executors, - ThreadFactory, - TimeoutException, - TimeUnit -} -import java.util.concurrent.atomic.AtomicInteger import scala.scalanative.meta.LinktimeInfo.isMultithreadingEnabled +import scala.scalanative.reflect.Reflect // Delay reachability of multithreading capability // Would not force multithreading support unless explicitly configured by the user // or if using threads in the tests private object LazyMultithreadingSupport { - val sh = Executors.newSingleThreadScheduledExecutor( - new ThreadFactory { - val counter = new AtomicInteger - def threadNumber() = counter.incrementAndGet() - def newThread(r: Runnable) = - new Thread(r, s"munit-scheduler-${threadNumber()}") { - setDaemon(true) - setPriority(Thread.NORM_PRIORITY) - } - } - ) + val sh = Executors.newSingleThreadScheduledExecutor(new ThreadFactory { + val counter = new AtomicInteger + def threadNumber() = counter.incrementAndGet() + def newThread(r: Runnable) = + new Thread(r, s"munit-scheduler-${threadNumber()}") { + setDaemon(true) + setPriority(Thread.NORM_PRIORITY) + } + }) } object PlatformCompat { import LazyMultithreadingSupport._ def awaitResult[T](awaitable: Awaitable[T]): T = { - if (!isMultithreadingEnabled) - Thread.`yield`() // invokes SN 0.4 scalanative.runtime.loop() + if (!isMultithreadingEnabled) Thread.`yield`() // invokes SN 0.4 scalanative.runtime.loop() Await.result(awaitable, Duration.Inf) } def executeAsync( task: Task, eventHandler: EventHandler, - loggers: Array[Logger] + loggers: Array[Logger], ): Future[Unit] = { task.execute(eventHandler, loggers) Future.successful(()) @@ -58,52 +56,39 @@ object PlatformCompat { def waitAtMost[T]( startFuture: () => Future[T], duration: Duration, - ec: ExecutionContext - ): Future[T] = { + ec: ExecutionContext, + ): Future[T] = if (!isMultithreadingEnabled) startFuture() else { val onComplete = Promise[T]() val timeout = - if (duration.isFinite) - Some( - sh.schedule[Unit]( - () => - onComplete.tryFailure( - new TimeoutException(s"test timed out after $duration") - ), - duration.toMillis, - TimeUnit.MILLISECONDS - ) - ) - else - None + if (duration.isFinite) Some(sh.schedule[Unit]( + () => + onComplete + .tryFailure(new TimeoutException(s"test timed out after $duration")), + duration.toMillis, + TimeUnit.MILLISECONDS, + )) + else None ec.execute(new Runnable { - def run(): Unit = { - startFuture().onComplete { result => - onComplete.tryComplete(result) - timeout.foreach(_.cancel(false)) - }(ec) - } + def run(): Unit = startFuture().onComplete { result => + onComplete.tryComplete(result) + timeout.foreach(_.cancel(false)) + }(ec) }) onComplete.future } - } - def setTimeout(ms: Int)(body: => Unit): () => Unit = { + def setTimeout(ms: Int)(body: => Unit): () => Unit = if (!isMultithreadingEnabled) { // Thread.sleep(ms) body () => () } else { - val scheduled = sh.schedule[Unit]( - () => body, - ms, - TimeUnit.MILLISECONDS - ) + val scheduled = sh.schedule[Unit](() => body, ms, TimeUnit.MILLISECONDS) () => scheduled.cancel(false) } - } // Scala Native does not support looking up annotations at runtime. def isIgnoreSuite(cls: Class[_]): Boolean = false @@ -114,17 +99,14 @@ object PlatformCompat { def newRunner( taskDef: TaskDef, - classLoader: ClassLoader - ): Option[MUnitRunner] = { - Reflect - .lookupInstantiatableClass(taskDef.fullyQualifiedName()) - .map(cls => - new MUnitRunner( - cls.runtimeClass.asInstanceOf[Class[_ <: munit.Suite]], - () => cls.newInstance().asInstanceOf[munit.Suite] - ) + classLoader: ClassLoader, + ): Option[MUnitRunner] = Reflect + .lookupInstantiatableClass(taskDef.fullyQualifiedName()).map(cls => + new MUnitRunner( + cls.runtimeClass.asInstanceOf[Class[_ <: munit.Suite]], + () => cls.newInstance().asInstanceOf[munit.Suite], ) - } + ) private var myClassLoader: ClassLoader = _ def setThisClassLoader(loader: ClassLoader): Unit = myClassLoader = loader def getThisClassLoader: ClassLoader = myClassLoader diff --git a/munit/native/src/main/scala/munit/internal/io/PlatformIO.scala b/munit/native/src/main/scala/munit/internal/io/PlatformIO.scala index 4f7a623b..d4dd37e8 100644 --- a/munit/native/src/main/scala/munit/internal/io/PlatformIO.scala +++ b/munit/native/src/main/scala/munit/internal/io/PlatformIO.scala @@ -7,10 +7,9 @@ object PlatformIO { } object Files { - def readAllLines(path: Path): java.util.List[String] = - java.nio.file.Files.readAllLines(path) - def exists(path: Path): Boolean = - java.nio.file.Files.exists(path) + def readAllLines(path: Path): java.util.List[String] = java.nio.file.Files + .readAllLines(path) + def exists(path: Path): Boolean = java.nio.file.Files.exists(path) } type Path = java.nio.file.Path diff --git a/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala b/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala index 791ae277..81dde414 100644 --- a/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala +++ b/munit/native/src/main/scala/munit/internal/junitinterface/JUnitTask.scala @@ -5,10 +5,13 @@ package munit.internal.junitinterface import munit.internal.PlatformCompat -import org.junit.runner.notification.RunNotifier + import sbt.testing._ + import scala.concurrent.ExecutionContext.Implicits.global +import org.junit.runner.notification.RunNotifier + /* Implementation note: In JUnitTask we use Future[Try[Unit]] instead of simply * Future[Unit]. This is to prevent Scala's Future implementation to box/wrap * fatal errors (most importantly AssertionError) in ExecutionExceptions. We @@ -18,16 +21,13 @@ import scala.concurrent.ExecutionContext.Implicits.global final class JUnitTask( _taskDef: TaskDef, runSettings: RunSettings, - classLoader: ClassLoader + classLoader: ClassLoader, ) extends Task { override def taskDef(): TaskDef = _taskDef override def tags(): Array[String] = Array.empty - def execute( - eventHandler: EventHandler, - loggers: Array[Logger] - ): Array[Task] = { + def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[Task] = { PlatformCompat.newRunner(taskDef(), classLoader) match { case None => case Some(runner) => diff --git a/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala b/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala index e0606348..e568dbb1 100644 --- a/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala +++ b/munit/shared/src/main/scala-2.13/munit/internal/Compat.scala @@ -3,8 +3,7 @@ package munit.internal object Compat { type LazyList[+T] = scala.LazyList[T] val LazyList = scala.LazyList - def productElementNames(p: Product): Iterator[String] = - p.productElementNames - def collectionClassName(i: Iterable[_]): String = - i.asInstanceOf[{ def collectionClassName: String }].collectionClassName + def productElementNames(p: Product): Iterator[String] = p.productElementNames + def collectionClassName(i: Iterable[_]): String = i + .asInstanceOf[{ def collectionClassName: String }].collectionClassName } diff --git a/munit/shared/src/main/scala-3/munit/internal/Compat.scala b/munit/shared/src/main/scala-3/munit/internal/Compat.scala index 7e489e23..1b56be6e 100644 --- a/munit/shared/src/main/scala-3/munit/internal/Compat.scala +++ b/munit/shared/src/main/scala-3/munit/internal/Compat.scala @@ -5,9 +5,7 @@ import scala.reflect.Selectable.reflectiveSelectable object Compat { type LazyList[+T] = scala.LazyList[T] val LazyList = scala.LazyList - def productElementNames(p: Product): Iterator[String] = - p.productElementNames - def collectionClassName(i: Iterable[_]): String = { - i.asInstanceOf[{ def collectionClassName: String }].collectionClassName - } + def productElementNames(p: Product): Iterator[String] = p.productElementNames + def collectionClassName(i: Iterable[_]): String = i + .asInstanceOf[{ def collectionClassName: String }].collectionClassName } diff --git a/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala b/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala index ffbf1fdb..9e4f4eff 100644 --- a/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala +++ b/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala @@ -2,38 +2,36 @@ package munit.internal import munit.Clue import munit.Location -import scala.quoted._ + import scala.language.experimental.macros +import scala.quoted._ object MacroCompat { private val workingDirectory: String = { val sep = java.io.File.separator val cwd = sys.props("user.dir") - if (cwd.endsWith(sep)) cwd - else cwd + sep + if (cwd.endsWith(sep)) cwd else cwd + sep } trait LocationMacro { - inline implicit def generate: Location = ${ locationImpl() } + implicit inline def generate: Location = ${ locationImpl() } implicit def generate: Location = macro MacroCompatScala2.locationImpl } def locationImpl()(using Quotes): Expr[Location] = { import quotes.reflect._ val pos = Position.ofMacroExpansion - val path0 = pos.sourceFile.getJPath - .map(_.toString()) + val path0 = pos.sourceFile.getJPath.map(_.toString()) .getOrElse(pos.sourceFile.path) val relativePath = - if (path0.startsWith(workingDirectory)) - path0.drop(workingDirectory.length) + if (path0.startsWith(workingDirectory)) path0.drop(workingDirectory.length) else path0 val startLine = pos.startLine + 1 '{ new Location(${ Expr(relativePath) }, ${ Expr(startLine) }) } } trait ClueMacro { - inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) } + implicit inline def generate[T](value: T): Clue[T] = ${ clueImpl('value) } implicit def generate[T](value: T): Clue[T] = macro MacroCompatScala2.clueImpl } @@ -48,19 +46,13 @@ object MacroCompat { trait CompileErrorMacro { transparent inline def compileErrors(inline code: String): String = { val errors = scala.compiletime.testing.typeCheckErrors(code) - errors - .map { error => - val indent = " " * (error.column - 1) - val trimMessage = error.message.linesIterator - .map { line => - if (line.matches(" +")) "" - else line - } - .mkString("\n") - val separator = if (error.message.contains('\n')) "\n" else " " - s"error:${separator}${trimMessage}\n${error.lineContent}\n${indent}^" - } - .mkString("\n") + errors.map { error => + val indent = " " * (error.column - 1) + val trimMessage = error.message.linesIterator + .map(line => if (line.matches(" +")) "" else line).mkString("\n") + val separator = if (error.message.contains('\n')) "\n" else " " + s"error:$separator$trimMessage\n${error.lineContent}\n$indent^" + }.mkString("\n") } def compileErrors(code: String): String = macro MacroCompatScala2.compileErrorsImpl diff --git a/munit/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala b/munit/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala index cadb0ab8..c9efada4 100644 --- a/munit/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala +++ b/munit/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala @@ -3,8 +3,7 @@ package munit.internal object Compat { type LazyList[+T] = Stream[T] val LazyList = scala.Stream - def productElementNames(p: Product): Iterator[String] = - Iterator.continually("") - def collectionClassName(i: Iterable[_]): String = - i.stringPrefix + def productElementNames(p: Product): Iterator[String] = Iterator + .continually("") + def collectionClassName(i: Iterable[_]): String = i.stringPrefix } diff --git a/munit/shared/src/main/scala/munit/AfterEach.scala b/munit/shared/src/main/scala/munit/AfterEach.scala index 74b8d234..0ba4fcc4 100644 --- a/munit/shared/src/main/scala/munit/AfterEach.scala +++ b/munit/shared/src/main/scala/munit/AfterEach.scala @@ -1,5 +1,3 @@ package munit -class AfterEach( - val test: Test -) extends Serializable +class AfterEach(val test: Test) extends Serializable diff --git a/munit/shared/src/main/scala/munit/Assertions.scala b/munit/shared/src/main/scala/munit/Assertions.scala index cd03f472..481c3b40 100644 --- a/munit/shared/src/main/scala/munit/Assertions.scala +++ b/munit/shared/src/main/scala/munit/Assertions.scala @@ -1,16 +1,18 @@ package munit -import munit.internal.console.{Lines, StackTraces} -import munit.internal.console.Printers -import munit.diff.Printer import munit.diff.EmptyPrinter +import munit.diff.Printer +import munit.diff.console.AnsiColors +import munit.internal.MacroCompat +import munit.internal.console.Lines +import munit.internal.console.Printers +import munit.internal.console.StackTraces +import scala.collection.mutable import scala.reflect.ClassTag import scala.util.control.NonFatal -import scala.collection.mutable -import munit.diff.console.AnsiColors + import org.junit.AssumptionViolatedException -import munit.internal.MacroCompat object Assertions extends Assertions trait Assertions extends MacroCompat.CompileErrorMacro { @@ -20,47 +22,31 @@ trait Assertions extends MacroCompat.CompileErrorMacro { def munitAnsiColors: Boolean = true private def munitFilterAnsi(message: String): String = - if (munitAnsiColors) message - else AnsiColors.filterAnsi(message) + if (munitAnsiColors) message else AnsiColors.filterAnsi(message) - def assert( - cond: => Boolean, - clue: => Any = "assertion failed" - )(implicit loc: Location): Unit = { - StackTraces.dropInside { - val (isTrue, clues) = munitCaptureClues(cond) - if (!isTrue) { - fail(munitPrint(clue), clues) - } - } + def assert(cond: => Boolean, clue: => Any = "assertion failed")(implicit + loc: Location + ): Unit = StackTraces.dropInside { + val (isTrue, clues) = munitCaptureClues(cond) + if (!isTrue) fail(munitPrint(clue), clues) } - def assume( - cond: Boolean, - clue: => Any = "assumption failed" - )(implicit loc: Location): Unit = { - StackTraces.dropInside { - if (!cond) { - throw new AssumptionViolatedException(munitPrint(clue)) - } - } - } + def assume(cond: Boolean, clue: => Any = "assumption failed")(implicit + loc: Location + ): Unit = StackTraces + .dropInside(if (!cond) throw new AssumptionViolatedException(munitPrint(clue))) def assertNoDiff( obtained: String, expected: String, - clue: => Any = "diff assertion failed" - )(implicit loc: Location): Unit = { - StackTraces.dropInside { - Diffs.assertNoDiff( - obtained, - expected, - exceptionHandlerFromAssertions(this, Clues.empty), - munitPrint(clue), - printObtainedAsStripMargin = true - ) - } - } + clue: => Any = "diff assertion failed", + )(implicit loc: Location): Unit = StackTraces.dropInside(Diffs.assertNoDiff( + obtained, + expected, + exceptionHandlerFromAssertions(this, Clues.empty), + munitPrint(clue), + printObtainedAsStripMargin = true, + )) /** * Asserts that two elements are not equal according to the `Compare[A, B]` type-class. @@ -70,18 +56,14 @@ trait Assertions extends MacroCompat.CompileErrorMacro { def assertNotEquals[A, B]( obtained: A, expected: B, - clue: => Any = "values are the same" - )(implicit loc: Location, compare: Compare[A, B]): Unit = { - StackTraces.dropInside { - if (compare.isEqual(obtained, expected)) { - failComparison( - s"${munitPrint(clue)}, expected 2 different values: $expected is equal to $obtained", - obtained, - expected - ) - } - } - } + clue: => Any = "values are the same", + )(implicit loc: Location, compare: Compare[A, B]): Unit = StackTraces.dropInside( + if (compare.isEqual(obtained, expected)) failComparison( + s"${munitPrint(clue)}, expected 2 different values: $expected is equal to $obtained", + obtained, + expected, + ) + ) /** * Asserts that two elements are equal according to the `Compare[A, B]` type-class. @@ -91,9 +73,9 @@ trait Assertions extends MacroCompat.CompileErrorMacro { def assertEquals[A, B]( obtained: A, expected: B, - clue: => Any = "values are not the same" - )(implicit loc: Location, compare: Compare[A, B]): Unit = { - StackTraces.dropInside { + clue: => Any = "values are not the same", + )(implicit loc: Location, compare: Compare[A, B]): Unit = StackTraces + .dropInside { if (!compare.isEqual(obtained, expected)) { (obtained, expected) match { case (a: Array[_], b: Array[_]) if a.sameElements(b) => @@ -111,14 +93,13 @@ trait Assertions extends MacroCompat.CompileErrorMacro { "Convert the arrays to a non-Array collection if you intend to assert the two arrays have the same elements. " + "For example, `assertEquals(a.toSeq, b.toSeq)", obtained, - expected + expected, ) case _ => } compare.failEqualsComparison(obtained, expected, clue, loc, this) } } - } /** * Asserts that two doubles are equal to within a positive delta. @@ -129,19 +110,15 @@ trait Assertions extends MacroCompat.CompileErrorMacro { obtained: Double, expected: Double, delta: Double, - clue: => Any = "values are not the same" - )(implicit loc: Location): Unit = { - StackTraces.dropInside { - val exactlyTheSame = java.lang.Double.compare(expected, obtained) == 0 - val almostTheSame = Math.abs(expected - obtained) <= delta - if (!exactlyTheSame && !almostTheSame) { - failComparison( - s"${munitPrint(clue)} expected: $expected but was: $obtained", - obtained, - expected - ) - } - } + clue: => Any = "values are not the same", + )(implicit loc: Location): Unit = StackTraces.dropInside { + val exactlyTheSame = java.lang.Double.compare(expected, obtained) == 0 + val almostTheSame = Math.abs(expected - obtained) <= delta + if (!exactlyTheSame && !almostTheSame) failComparison( + s"${munitPrint(clue)} expected: $expected but was: $obtained", + obtained, + expected, + ) } /** @@ -153,19 +130,15 @@ trait Assertions extends MacroCompat.CompileErrorMacro { obtained: Float, expected: Float, delta: Float, - clue: => Any = "values are not the same" - )(implicit loc: Location): Unit = { - StackTraces.dropInside { - val exactlyTheSame = java.lang.Float.compare(expected, obtained) == 0 - val almostTheSame = Math.abs(expected - obtained) <= delta - if (!exactlyTheSame && !almostTheSame) { - failComparison( - s"${munitPrint(clue)} expected: $expected but was: $obtained", - obtained, - expected - ) - } - } + clue: => Any = "values are not the same", + )(implicit loc: Location): Unit = StackTraces.dropInside { + val exactlyTheSame = java.lang.Float.compare(expected, obtained) == 0 + val almostTheSame = Math.abs(expected - obtained) <= delta + if (!exactlyTheSame && !almostTheSame) failComparison( + s"${munitPrint(clue)} expected: $expected but was: $obtained", + obtained, + expected, + ) } /** @@ -173,22 +146,19 @@ trait Assertions extends MacroCompat.CompileErrorMacro { */ def intercept[T <: Throwable]( body: => Any - )(implicit T: ClassTag[T], loc: Location): T = { - runIntercept(None, body) - } + )(implicit T: ClassTag[T], loc: Location): T = runIntercept(None, body) /** * Evalutes the given expression and asserts that an exception of type T with the expected message is thrown. */ - def interceptMessage[T <: Throwable](expectedExceptionMessage: String)( - body: => Any - )(implicit T: ClassTag[T], loc: Location): T = { + def interceptMessage[T <: Throwable]( + expectedExceptionMessage: String + )(body: => Any)(implicit T: ClassTag[T], loc: Location): T = runIntercept(Some(expectedExceptionMessage), body) - } private def runIntercept[T <: Throwable]( expectedExceptionMessage: Option[String], - body: => Any + body: => Any, )(implicit T: ClassTag[T], loc: Location): T = { val expectedExceptionMsg = s"expected exception of type '${T.runtimeClass.getName()}' but body evaluated successfully" @@ -197,34 +167,32 @@ trait Assertions extends MacroCompat.CompileErrorMacro { fail(expectedExceptionMsg) } catch { case e: FailExceptionLike[_] - if !T.runtimeClass.isAssignableFrom(e.getClass()) => - throw e + if !T.runtimeClass.isAssignableFrom(e.getClass()) => throw e case e: FailExceptionLike[_] - if e.getMessage.contains(expectedExceptionMsg) => - throw e + if e.getMessage.contains(expectedExceptionMsg) => throw e case NonFatal(e) => - if (T.runtimeClass.isAssignableFrom(e.getClass())) { + if (T.runtimeClass.isAssignableFrom(e.getClass())) if ( - expectedExceptionMessage.isEmpty || e.getMessage == expectedExceptionMessage.get - ) - e.asInstanceOf[T] + expectedExceptionMessage.isEmpty || + e.getMessage == expectedExceptionMessage.get + ) e.asInstanceOf[T] else { val obtained = e.getClass().getName() throw new FailException( s"intercept failed, exception '$obtained' had message '${e.getMessage}', which was different from expected message '${expectedExceptionMessage.get}'", cause = e, isStackTracesEnabled = false, - location = loc + location = loc, ) } - } else { + else { val obtained = e.getClass().getName() val expected = T.runtimeClass.getName() throw new FailException( s"intercept failed, exception '$obtained' is not a subtype of '$expected", cause = e, isStackTracesEnabled = false, - location = loc + location = loc, ) } } @@ -233,29 +201,23 @@ trait Assertions extends MacroCompat.CompileErrorMacro { /** * Unconditionally fails this test with the given message and exception marked as the cause. */ - def fail(message: String, cause: Throwable)(implicit - loc: Location - ): Nothing = { + def fail(message: String, cause: Throwable)(implicit loc: Location): Nothing = throw new FailException( munitFilterAnsi(munitLines.formatLine(loc, message)), cause, isStackTracesEnabled = true, - location = loc + location = loc, ) - } /** * Unconditionally fails this test with the given message and optional clues. */ - def fail( - message: String, - clues: Clues = new Clues(Nil) - )(implicit loc: Location): Nothing = { - throw new FailException( - munitFilterAnsi(munitLines.formatLine(loc, message, clues)), - loc - ) - } + def fail(message: String, clues: Clues = new Clues(Nil))(implicit + loc: Location + ): Nothing = throw new FailException( + munitFilterAnsi(munitLines.formatLine(loc, message, clues)), + loc, + ) /** * Unconditionally fails this test due to result of comparing two values. @@ -268,53 +230,45 @@ trait Assertions extends MacroCompat.CompileErrorMacro { message: String, obtained: Any, expected: Any, - clues: Clues = new Clues(Nil) - )(implicit loc: Location): Nothing = { - throw new ComparisonFailException( - munitFilterAnsi(munitLines.formatLine(loc, message, clues)), - obtained, - expected, - loc, - isStackTracesEnabled = true - ) - } + clues: Clues = new Clues(Nil), + )(implicit loc: Location): Nothing = throw new ComparisonFailException( + munitFilterAnsi(munitLines.formatLine(loc, message, clues)), + obtained, + expected, + loc, + isStackTracesEnabled = true, + ) /** * Unconditionally fail this test case and cancel all the subsequent tests in this suite. */ - def failSuite( - message: String, - clues: Clues = new Clues(Nil) - )(implicit loc: Location): Nothing = { - throw new FailSuiteException( - munitFilterAnsi(munitLines.formatLine(loc, message, clues)), - loc - ) - } + def failSuite(message: String, clues: Clues = new Clues(Nil))(implicit + loc: Location + ): Nothing = throw new FailSuiteException( + munitFilterAnsi(munitLines.formatLine(loc, message, clues)), + loc, + ) private def exceptionHandlerFromAssertions( assertions: Assertions, - clues: => Clues - ): ComparisonFailExceptionHandler = - new ComparisonFailExceptionHandler { - def handle( - message: String, - obtained: String, - expected: String, - loc: Location - ): Nothing = { - assertions.failComparison(message, obtained, expected, clues)(loc) - } - } + clues: => Clues, + ): ComparisonFailExceptionHandler = new ComparisonFailExceptionHandler { + def handle( + message: String, + obtained: String, + expected: String, + loc: Location, + ): Nothing = assertions + .failComparison(message, obtained, expected, clues)(loc) + } private val munitCapturedClues: mutable.ListBuffer[Clue[_]] = mutable.ListBuffer.empty - def munitCaptureClues[T](thunk: => T): (T, Clues) = - synchronized { - munitCapturedClues.clear() - val result = thunk - (result, new Clues(munitCapturedClues.toList)) - } + def munitCaptureClues[T](thunk: => T): (T, Clues) = synchronized { + munitCapturedClues.clear() + val result = thunk + (result, new Clues(munitCapturedClues.toList)) + } def clue[T](c: Clue[T]): T = synchronized { munitCapturedClues += c @@ -324,11 +278,9 @@ trait Assertions extends MacroCompat.CompileErrorMacro { def printer: Printer = EmptyPrinter - def munitPrint(clue: => Any): String = { - clue match { - case message: String => message - case value => Printers.print(value, printer) - } + def munitPrint(clue: => Any): String = clue match { + case message: String => message + case value => Printers.print(value, printer) } } diff --git a/munit/shared/src/main/scala/munit/BeforeEach.scala b/munit/shared/src/main/scala/munit/BeforeEach.scala index 99c8406b..b432a26c 100644 --- a/munit/shared/src/main/scala/munit/BeforeEach.scala +++ b/munit/shared/src/main/scala/munit/BeforeEach.scala @@ -1,5 +1,3 @@ package munit -class BeforeEach( - val test: Test -) extends Serializable +class BeforeEach(val test: Test) extends Serializable diff --git a/munit/shared/src/main/scala/munit/Clue.scala b/munit/shared/src/main/scala/munit/Clue.scala index 2621155d..e7ebf15c 100644 --- a/munit/shared/src/main/scala/munit/Clue.scala +++ b/munit/shared/src/main/scala/munit/Clue.scala @@ -2,14 +2,10 @@ package munit import munit.internal.MacroCompat -class Clue[+T]( - val source: String, - val value: T, - val valueType: String -) extends Serializable { +class Clue[+T](val source: String, val value: T, val valueType: String) + extends Serializable { override def toString(): String = s"Clue($source, $value)" } object Clue extends MacroCompat.ClueMacro { - def fromValue[T](value: T): Clue[T] = - new Clue("", value, "") + def fromValue[T](value: T): Clue[T] = new Clue("", value, "") } diff --git a/munit/shared/src/main/scala/munit/Compare.scala b/munit/shared/src/main/scala/munit/Compare.scala index 62e6aa95..8d6af568 100644 --- a/munit/shared/src/main/scala/munit/Compare.scala +++ b/munit/shared/src/main/scala/munit/Compare.scala @@ -42,20 +42,15 @@ trait Compare[A, B] { expected: B, title: Any, loc: Location, - assertions: Assertions + assertions: Assertions, ): Nothing = { val diffHandler = new ComparisonFailExceptionHandler { override def handle( message: String, _obtained: String, _expected: String, - loc: Location - ): Nothing = - assertions.failComparison( - message, - obtained, - expected - )(loc) + loc: Location, + ): Nothing = assertions.failComparison(message, obtained, expected)(loc) } // Attempt 1: custom pretty-printer that produces multiline output, which is // optimized for line-by-line diffing. @@ -64,7 +59,7 @@ trait Compare[A, B] { assertions.munitPrint(expected), diffHandler, title = assertions.munitPrint(title), - printObtainedAsStripMargin = false + printObtainedAsStripMargin = false, )(loc) // Attempt 2: try with `.toString` in case `munitPrint()` produces identical @@ -74,30 +69,28 @@ trait Compare[A, B] { expected.toString(), diffHandler, title = assertions.munitPrint(title), - printObtainedAsStripMargin = false + printObtainedAsStripMargin = false, )(loc) // Attempt 3: string comparison is not working, unconditionally fail the test. - if (obtained.toString() == expected.toString()) - assertions.failComparison( - s"values are not equal even if they have the same `toString()`: $obtained", - obtained, - expected - )(loc) - else - assertions.failComparison( - s"values are not equal, even if their text representation only differs in leading/trailing whitespace and ANSI escape characters: $obtained", - obtained, - expected - )(loc) + if (obtained.toString() == expected.toString()) assertions.failComparison( + s"values are not equal even if they have the same `toString()`: $obtained", + obtained, + expected, + )(loc) + else assertions.failComparison( + s"values are not equal, even if their text representation only differs in leading/trailing whitespace and ANSI escape characters: $obtained", + obtained, + expected, + )(loc) } } object Compare extends ComparePriority1 { private val anyEquality: Compare[Any, Any] = _ == _ - def defaultCompare[A, B]: Compare[A, B] = - anyEquality.asInstanceOf[Compare[A, B]] + def defaultCompare[A, B]: Compare[A, B] = anyEquality + .asInstanceOf[Compare[A, B]] } /** Allows comparison between A and B when A is a subtype of B */ diff --git a/munit/shared/src/main/scala/munit/ComparisonFailException.scala b/munit/shared/src/main/scala/munit/ComparisonFailException.scala index 74eb75c7..ded7e503 100644 --- a/munit/shared/src/main/scala/munit/ComparisonFailException.scala +++ b/munit/shared/src/main/scala/munit/ComparisonFailException.scala @@ -25,7 +25,7 @@ class ComparisonFailException( val expected: Any, val expectedString: String, val location: Location, - val isStackTracesEnabled: Boolean + val isStackTracesEnabled: Boolean, ) extends ComparisonFailure(message, expectedString, obtainedString) with FailExceptionLike[ComparisonFailException] { def this( @@ -33,7 +33,7 @@ class ComparisonFailException( obtained: Any, expected: Any, location: Location, - isStackTracesEnabled: Boolean + isStackTracesEnabled: Boolean, ) = this( message, obtained, @@ -41,7 +41,7 @@ class ComparisonFailException( expected, s"$expected", location, - isStackTracesEnabled + isStackTracesEnabled, ) override def getMessage: String = message def withMessage(newMessage: String): ComparisonFailException = @@ -52,13 +52,12 @@ class ComparisonFailException( expected, expectedString, location, - isStackTracesEnabled + isStackTracesEnabled, ) override def fillInStackTrace(): Throwable = { val result = super.fillInStackTrace() - if (!isStackTracesEnabled) { - result.setStackTrace(result.getStackTrace().slice(0, 1)) - } + if (!isStackTracesEnabled) result + .setStackTrace(result.getStackTrace().slice(0, 1)) result } } diff --git a/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala b/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala index 7f9ba7f6..c2bf7c9a 100644 --- a/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala +++ b/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala @@ -5,6 +5,6 @@ trait ComparisonFailExceptionHandler { message: String, obtained: String, expected: String, - location: Location + location: Location, ): Nothing } diff --git a/munit/shared/src/main/scala/munit/Diffs.scala b/munit/shared/src/main/scala/munit/Diffs.scala index c0252ac3..71a5fb4b 100644 --- a/munit/shared/src/main/scala/munit/Diffs.scala +++ b/munit/shared/src/main/scala/munit/Diffs.scala @@ -9,25 +9,22 @@ object Diffs { expected: String, handler: ComparisonFailExceptionHandler, title: String, - printObtainedAsStripMargin: Boolean + printObtainedAsStripMargin: Boolean, )(implicit loc: Location): Boolean = { if (obtained.isEmpty && !expected.isEmpty) { - val msg = - s"""|Obtained empty output! - |=> Expected: - |$expected""".stripMargin + val msg = s"""|Obtained empty output! + |=> Expected: + |$expected""".stripMargin handler.handle(msg, obtained, expected, loc) } val diff = new Diff(obtained, expected) if (diff.isEmpty) true - else { - handler.handle( - diff.createReport(title, printObtainedAsStripMargin), - obtained, - expected, - loc - ) - } + else handler.handle( + diff.createReport(title, printObtainedAsStripMargin), + obtained, + expected, + loc, + ) } } diff --git a/munit/shared/src/main/scala/munit/Exceptions.scala b/munit/shared/src/main/scala/munit/Exceptions.scala index 11709a5d..00b3f0e4 100644 --- a/munit/shared/src/main/scala/munit/Exceptions.scala +++ b/munit/shared/src/main/scala/munit/Exceptions.scala @@ -4,6 +4,7 @@ import munit.internal.PlatformCompat.InvocationTargetException import munit.internal.PlatformCompat.UndeclaredThrowableException import java.util.concurrent.ExecutionException + import scala.annotation.tailrec object Exceptions { @@ -14,8 +15,7 @@ object Exceptions { def rootCause(x: Throwable): Throwable = x match { case _: InvocationTargetException | _: ExceptionInInitializerError | _: UndeclaredThrowableException | _: ExecutionException - if x.getCause != null => - rootCause(x.getCause) + if x.getCause != null => rootCause(x.getCause) case _ => x } } diff --git a/munit/shared/src/main/scala/munit/FailException.scala b/munit/shared/src/main/scala/munit/FailException.scala index 67414893..d36ecdef 100644 --- a/munit/shared/src/main/scala/munit/FailException.scala +++ b/munit/shared/src/main/scala/munit/FailException.scala @@ -4,32 +4,25 @@ class FailException( val message: String, val cause: Throwable, val isStackTracesEnabled: Boolean, - val location: Location -) extends AssertionError(message, cause) - with FailExceptionLike[FailException] { + val location: Location, +) extends AssertionError(message, cause) with FailExceptionLike[FailException] { def this(message: String, location: Location) = this(message, null, isStackTracesEnabled = true, location) - def this(message: String, cause: Throwable, location: Location) = this( - message, - cause, - isStackTracesEnabled = true, - location - ) - def withMessage(newMessage: String): FailException = - copy(message = newMessage) + def this(message: String, cause: Throwable, location: Location) = + this(message, cause, isStackTracesEnabled = true, location) + def withMessage(newMessage: String): FailException = copy(message = newMessage) private[munit] def copy( message: String = this.message, cause: Throwable = this.cause, isStackTracesEnabled: Boolean = this.isStackTracesEnabled, - location: Location = this.location + location: Location = this.location, ): FailException = new FailException(message, cause, isStackTracesEnabled, location) override def fillInStackTrace(): Throwable = { val result = super.fillInStackTrace() - if (!isStackTracesEnabled) { - result.setStackTrace(result.getStackTrace().slice(0, 1)) - } + if (!isStackTracesEnabled) result + .setStackTrace(result.getStackTrace().slice(0, 1)) result } diff --git a/munit/shared/src/main/scala/munit/FailSuiteException.scala b/munit/shared/src/main/scala/munit/FailSuiteException.scala index 4167b7dd..bcd304e3 100644 --- a/munit/shared/src/main/scala/munit/FailSuiteException.scala +++ b/munit/shared/src/main/scala/munit/FailSuiteException.scala @@ -2,5 +2,5 @@ package munit class FailSuiteException( override val message: String, - override val location: Location + override val location: Location, ) extends FailException(message, location) diff --git a/munit/shared/src/main/scala/munit/FunFixtures.scala b/munit/shared/src/main/scala/munit/FunFixtures.scala index 646d8826..4494a5d9 100644 --- a/munit/shared/src/main/scala/munit/FunFixtures.scala +++ b/munit/shared/src/main/scala/munit/FunFixtures.scala @@ -3,56 +3,50 @@ package munit import munit.internal.FutureCompat._ import scala.concurrent.Future -import scala.util.Success import scala.util.Failure +import scala.util.Success -trait FunFixtures { self: BaseFunSuite => +trait FunFixtures { + self: BaseFunSuite => class FunFixture[T] private ( val setup: TestOptions => Future[T], - val teardown: T => Future[Unit] - )(implicit dummy: DummyImplicit) { fixture => + val teardown: T => Future[Unit], + )(implicit dummy: DummyImplicit) { + fixture => - def test(name: String)( - body: T => Any - )(implicit loc: Location): Unit = { + def test(name: String)(body: T => Any)(implicit loc: Location): Unit = fixture.test(TestOptions(name))(body) - } - def test(options: TestOptions)( - body: T => Any - )(implicit loc: Location): Unit = { - self.test(options) { - implicit val ec = munitExecutionContext - // the setup, test and teardown need to keep the happens-before execution order - setup(options).flatMap { argument => - munitValueTransform(body(argument)) - .transformWithCompat(testValue => - teardown(argument).transformCompat { - case Success(_) => testValue - case teardownFailure @ Failure(teardownException) => - testValue match { - case testFailure @ Failure(testException) => - testException.addSuppressed(teardownException) - testFailure - case _ => - teardownFailure - } + def test( + options: TestOptions + )(body: T => Any)(implicit loc: Location): Unit = self.test(options) { + implicit val ec = munitExecutionContext + // the setup, test and teardown need to keep the happens-before execution order + setup(options).flatMap(argument => + munitValueTransform(body(argument)).transformWithCompat(testValue => + teardown(argument).transformCompat { + case Success(_) => testValue + case teardownFailure @ Failure(teardownException) => testValue match { + case testFailure @ Failure(testException) => + testException.addSuppressed(teardownException) + testFailure + case _ => teardownFailure } - ) - } - }(loc) - } + } + ) + ) + }(loc) } object FunFixture { def apply[T]( setup: TestOptions => T, - teardown: T => Unit + teardown: T => Unit, ): FunFixture[T] = { implicit val ec = munitExecutionContext async[T]( - options => Future { setup(options) }, - argument => Future { teardown(argument) } + options => Future(setup(options)), + argument => Future(teardown(argument)), ) } def async[T](setup: TestOptions => Future[T], teardown: T => Future[Unit]) = @@ -71,41 +65,35 @@ trait FunFixtures { self: BaseFunSuite => }, teardown = { case (argumentA, argumentB) => implicit val ec = munitExecutionContext - Future - .sequence(List(a.teardown(argumentA), b.teardown(argumentB))) + Future.sequence(List(a.teardown(argumentA), b.teardown(argumentB))) .map(_ => ()) - } + }, ) def map3[A, B, C]( a: FunFixture[A], b: FunFixture[B], - c: FunFixture[C] - ): FunFixture[(A, B, C)] = - FunFixture.async[(A, B, C)]( - setup = { options => - implicit val ec = munitExecutionContext - val setupA = a.setup(options) - val setupB = b.setup(options) - val setupC = c.setup(options) - for { - argumentA <- setupA - argumentB <- setupB - argumentC <- setupC - } yield (argumentA, argumentB, argumentC) - }, - teardown = { case (argumentA, argumentB, argumentC) => - implicit val ec = munitExecutionContext - Future - .sequence( - List( - a.teardown(argumentA), - b.teardown(argumentB), - c.teardown(argumentC) - ) - ) - .map(_ => ()) - } - ) + c: FunFixture[C], + ): FunFixture[(A, B, C)] = FunFixture.async[(A, B, C)]( + setup = { options => + implicit val ec = munitExecutionContext + val setupA = a.setup(options) + val setupB = b.setup(options) + val setupC = c.setup(options) + for { + argumentA <- setupA + argumentB <- setupB + argumentC <- setupC + } yield (argumentA, argumentB, argumentC) + }, + teardown = { case (argumentA, argumentB, argumentC) => + implicit val ec = munitExecutionContext + Future.sequence(List( + a.teardown(argumentA), + b.teardown(argumentB), + c.teardown(argumentC), + )).map(_ => ()) + }, + ) } } diff --git a/munit/shared/src/main/scala/munit/FunSuite.scala b/munit/shared/src/main/scala/munit/FunSuite.scala index 97b10629..cb146391 100644 --- a/munit/shared/src/main/scala/munit/FunSuite.scala +++ b/munit/shared/src/main/scala/munit/FunSuite.scala @@ -1,12 +1,14 @@ package munit +import munit.internal.PlatformCompat + +import java.util.concurrent.TimeUnit + import scala.collection.mutable import scala.concurrent.Future -import scala.util.control.NonFatal -import munit.internal.PlatformCompat import scala.concurrent.duration.Duration import scala.concurrent.duration.FiniteDuration -import java.util.concurrent.TimeUnit +import scala.util.control.NonFatal abstract class FunSuite extends BaseFunSuite @@ -17,37 +19,28 @@ trait BaseFunSuite with TestOptionsConversions with TestTransforms with SuiteTransforms - with ValueTransforms { self => + with ValueTransforms { + self => - final val munitTestsBuffer: mutable.ListBuffer[Test] = - mutable.ListBuffer.empty[Test] - def munitTests(): Seq[Test] = { - munitSuiteTransform(munitTestsBuffer.toList) - } + final val munitTestsBuffer: mutable.ListBuffer[Test] = mutable.ListBuffer + .empty[Test] + def munitTests(): Seq[Test] = munitSuiteTransform(munitTestsBuffer.toList) - def test(name: String)(body: => Any)(implicit loc: Location): Unit = { + def test(name: String)(body: => Any)(implicit loc: Location): Unit = test(new TestOptions(name))(body) - } - def test(options: TestOptions)(body: => Any)(implicit loc: Location): Unit = { - munitTestsBuffer += munitTestTransform( - new Test( - options.name, - { () => - try { - waitForCompletion(() => munitValueTransform(body)) - } catch { - case NonFatal(e) => - Future.failed(e) - } - }, - options.tags.toSet, - loc - ) - ) - } + def test(options: TestOptions)(body: => Any)(implicit loc: Location): Unit = + munitTestsBuffer += munitTestTransform(new Test( + options.name, + { () => + try waitForCompletion(() => munitValueTransform(body)) + catch { case NonFatal(e) => Future.failed(e) } + }, + options.tags.toSet, + loc, + )) def munitTimeout: Duration = new FiniteDuration(30, TimeUnit.SECONDS) - private final def waitForCompletion[T](f: () => Future[T]) = - PlatformCompat.waitAtMost(f, munitTimeout, munitExecutionContext) + private final def waitForCompletion[T](f: () => Future[T]) = PlatformCompat + .waitAtMost(f, munitTimeout, munitExecutionContext) } diff --git a/munit/shared/src/main/scala/munit/FutureFixture.scala b/munit/shared/src/main/scala/munit/FutureFixture.scala index c38a6181..98039f90 100644 --- a/munit/shared/src/main/scala/munit/FutureFixture.scala +++ b/munit/shared/src/main/scala/munit/FutureFixture.scala @@ -18,12 +18,8 @@ import scala.concurrent.Future * `beforeAll()` or `afterAll()` fail. */ abstract class FutureFixture[T](name: String) extends AnyFixture[T](name) { - override def beforeAll(): Future[Unit] = - Future.successful(()) - override def beforeEach(context: BeforeEach): Future[Unit] = - Future.successful(()) - override def afterEach(context: AfterEach): Future[Unit] = - Future.successful(()) - override def afterAll(): Future[Unit] = - Future.successful(()) + override def beforeAll(): Future[Unit] = Future.successful(()) + override def beforeEach(context: BeforeEach): Future[Unit] = Future.successful(()) + override def afterEach(context: AfterEach): Future[Unit] = Future.successful(()) + override def afterAll(): Future[Unit] = Future.successful(()) } diff --git a/munit/shared/src/main/scala/munit/Location.scala b/munit/shared/src/main/scala/munit/Location.scala index ca0fd517..7e9eccc5 100644 --- a/munit/shared/src/main/scala/munit/Location.scala +++ b/munit/shared/src/main/scala/munit/Location.scala @@ -1,39 +1,29 @@ package munit +import munit.internal.MacroCompat +import munit.internal.io.PlatformIO.File + import java.lang.annotation.Annotation + import scala.runtime.Statics -import munit.internal.io.PlatformIO.File -import munit.internal.MacroCompat object Location extends MacroCompat.LocationMacro { def empty: Location = new Location("", 0) } -final class Location( - val path: String, - val line: Int -) extends Annotation - with Serializable { +final class Location(val path: String, val line: Int) + extends Annotation with Serializable { def filename: String = { val sep = path.lastIndexOf(File.separatorChar) - if (sep < 0) path - else path.substring(math.min(sep + 1, path.length() - 1)) - } - override def annotationType(): Class[Annotation] = { - classOf[Annotation] + if (sep < 0) path else path.substring(math.min(sep + 1, path.length() - 1)) } - override def toString: String = { - path + ":" + line - } - override def equals(obj: Any): Boolean = { - obj.asInstanceOf[AnyRef].eq(this) || (obj match { - case l: Location => - l.path == path && - l.line == line - case _ => - false + override def annotationType(): Class[Annotation] = classOf[Annotation] + override def toString: String = path + ":" + line + override def equals(obj: Any): Boolean = obj.asInstanceOf[AnyRef].eq(this) || + (obj match { + case l: Location => l.path == path && l.line == line + case _ => false }) - } override def hashCode(): Int = { var acc = -889275714 acc = Statics.mix(acc, Statics.anyHash(path)) diff --git a/munit/shared/src/main/scala/munit/MUnitRunner.scala b/munit/shared/src/main/scala/munit/MUnitRunner.scala index 9f5a3919..c55af6c1 100644 --- a/munit/shared/src/main/scala/munit/MUnitRunner.scala +++ b/munit/shared/src/main/scala/munit/MUnitRunner.scala @@ -6,15 +6,9 @@ import munit.internal.console.Printers import munit.internal.console.StackTraces import munit.internal.junitinterface.Configurable import munit.internal.junitinterface.Settings -import org.junit.AssumptionViolatedException -import org.junit.runner.Description -import org.junit.runner.Runner -import org.junit.runner.manipulation.Filter -import org.junit.runner.manipulation.Filterable -import org.junit.runner.notification.Failure -import org.junit.runner.notification.RunNotifier import java.lang.reflect.Modifier + import scala.collection.mutable import scala.concurrent.ExecutionContext import scala.concurrent.Future @@ -23,10 +17,16 @@ import scala.util.Success import scala.util.Try import scala.util.control.NonFatal +import org.junit.AssumptionViolatedException +import org.junit.runner.Description +import org.junit.runner.Runner +import org.junit.runner.manipulation.Filter +import org.junit.runner.manipulation.Filterable +import org.junit.runner.notification.Failure +import org.junit.runner.notification.RunNotifier + class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) - extends Runner - with Filterable - with Configurable { + extends Runner with Filterable with Configurable { def this(cls: Class[_ <: Suite]) = this(MUnitRunner.ensureEligibleConstructor(cls), () => cls.newInstance()) @@ -35,77 +35,63 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) private implicit val ec: ExecutionContext = suite.munitExecutionContext - @volatile private var settings: Settings = Settings.defaults() - @volatile private var suiteAborted: Boolean = false + @volatile + private var settings: Settings = Settings.defaults() + @volatile + private var suiteAborted: Boolean = false - private val descriptions: mutable.Map[Test, Description] = - mutable.Map.empty[Test, Description] - private val testNames: mutable.Set[String] = - mutable.Set.empty[String] + private val descriptions: mutable.Map[Test, Description] = mutable.Map + .empty[Test, Description] + private val testNames: mutable.Set[String] = mutable.Set.empty[String] - private lazy val munitTests: mutable.ArrayBuffer[Test] = - mutable.ArrayBuffer[Test](suite.munitTests(): _*) + private lazy val munitTests: mutable.ArrayBuffer[Test] = mutable + .ArrayBuffer[Test](suite.munitTests(): _*) // Suite fixtures are implemented as regular fixtures // We split up the before*/after* methods so we can order them explicitly private val suiteFixtureBefore = new Fixture[Unit](cls.getName()) { def apply(): Unit = () - override def beforeAll(): Unit = - suite.beforeAll() - override def beforeEach(context: BeforeEach): Unit = - suite.beforeEach(context) + override def beforeAll(): Unit = suite.beforeAll() + override def beforeEach(context: BeforeEach): Unit = suite + .beforeEach(context) } private val suiteFixtureAfter = new Fixture[Unit](cls.getName()) { def apply(): Unit = () - override def afterEach(context: AfterEach): Unit = - suite.afterEach(context) - override def afterAll(): Unit = - suite.afterAll() + override def afterEach(context: AfterEach): Unit = suite.afterEach(context) + override def afterAll(): Unit = suite.afterAll() } - private lazy val munitFixtures: List[AnyFixture[_]] = - suiteFixtureBefore :: (suite.munitFixtures.toList ::: suiteFixtureAfter :: Nil) + private lazy val munitFixtures: List[AnyFixture[_]] = suiteFixtureBefore :: + suite.munitFixtures.toList ::: suiteFixtureAfter :: Nil override def filter(filter: Filter): Unit = { - val newTests = munitTests.filter { t => - filter.shouldRun(createTestDescription(t)) - } + val newTests = munitTests + .filter(t => filter.shouldRun(createTestDescription(t))) munitTests.clear() munitTests ++= newTests } - override def configure(settings: Settings): Unit = { - this.settings = settings - } + override def configure(settings: Settings): Unit = this.settings = settings - private def createTestDescription(test: Test): Description = { - descriptions.getOrElseUpdate( + private def createTestDescription(test: Test): Description = descriptions + .getOrElseUpdate( test, { val escapedName = Printers.escapeNonVisible(test.name) - val testName = munit.internal.Compat.LazyList - .from(0) - .map { - case 0 => escapedName - case n => s"${escapedName}-${n}" - } - .find(candidate => !testNames.contains(candidate)) - .head + val testName = munit.internal.Compat.LazyList.from(0).map { + case 0 => escapedName + case n => s"$escapedName-$n" + }.find(candidate => !testNames.contains(candidate)).head testNames += testName - val desc = Description.createTestDescription( - cls, - testName, - test.annotations: _* - ) + val desc = Description + .createTestDescription(cls, testName, test.annotations: _*) desc - } + }, ) - } override def getDescription(): Description = { val description = Description.createSuiteDescription(cls) try { val suiteTests = StackTraces.dropOutside(munitTests) - suiteTests.iterator - .map(createTestDescription) + suiteTests.iterator.map(createTestDescription) .foreach(description.addChild) } catch { case ex: Throwable => @@ -117,9 +103,8 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) description } - override def run(notifier: RunNotifier): Unit = { - PlatformCompat.awaitResult(runAsync(notifier)) - } + override def run(notifier: RunNotifier): Unit = PlatformCompat + .awaitResult(runAsync(notifier)) def runAsync(notifier: RunNotifier): Future[Unit] = { val description = getDescription() if (PlatformCompat.isIgnoreSuite(cls) || munitTests.isEmpty) { @@ -127,24 +112,18 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) Future.successful(()) } else { notifier.fireTestSuiteStarted(description) - runAll(notifier) - .transformCompat[Unit](result => { - result.failed.foreach(ex => - fireFailedHiddenTest(notifier, "unexpected error running tests", ex) - ) - notifier.fireTestSuiteFinished(description) - util.Success(()) - }) + runAll(notifier).transformCompat[Unit] { result => + result.failed.foreach(ex => + fireFailedHiddenTest(notifier, "unexpected error running tests", ex) + ) + notifier.fireTestSuiteFinished(description) + util.Success(()) + } } } - private def runTests( - notifier: RunNotifier - ): Future[List[Try[Boolean]]] = { - sequenceFutures( - munitTests.iterator.map(t => runTest(notifier, t)) - ) - } + private def runTests(notifier: RunNotifier): Future[List[Try[Boolean]]] = + sequenceFutures(munitTests.iterator.map(t => runTest(notifier, t))) // Similar `Future.sequence` but with cleaner stack traces for non-async code. private def sequenceFutures[A]( @@ -152,65 +131,54 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) ): Future[List[Try[A]]] = { def loop( it: Iterator[Future[A]], - acc: mutable.ListBuffer[Try[A]] + acc: mutable.ListBuffer[Try[A]], ): Future[List[Try[A]]] = - if (!it.hasNext) { - Future.successful(acc.toList) - } else { + if (!it.hasNext) Future.successful(acc.toList) + else { val future = it.next() future.value match { case Some(value) => acc += value // use tail-recursive call if possible to keep stack traces clean. loop(it, acc) - case None => - future.flatMap(t => { + case None => future.flatMap { t => acc += util.Success(t) loop(it, acc) - }) + } } } loop(futures, mutable.ListBuffer.empty) } - private def munitTimeout(): Option[Duration] = { - suite match { - case funSuite: FunSuite => Some(funSuite.munitTimeout) - case _ => None - } + private def munitTimeout(): Option[Duration] = suite match { + case funSuite: FunSuite => Some(funSuite.munitTimeout) + case _ => None } - private def runAll(notifier: RunNotifier): Future[Unit] = { - for { - beforeAll <- runBeforeAll(notifier) - _ <- { - if (beforeAll.isSuccess) { - runTests(notifier) - } else { - Future.successful(Nil) - } - } - _ <- runAfterAll(notifier, beforeAll) - } yield () - } + private def runAll(notifier: RunNotifier): Future[Unit] = for { + beforeAll <- runBeforeAll(notifier) + _ <- { + if (beforeAll.isSuccess) runTests(notifier) else Future.successful(Nil) + } + _ <- runAfterAll(notifier, beforeAll) + } yield () private[munit] class BeforeAllResult( val isSuccess: Boolean, val loadedFixtures: List[AnyFixture[_]], - val errors: List[Throwable] + val errors: List[Throwable], ) private def runBeforeAll(notifier: RunNotifier): Future[BeforeAllResult] = { - val result: Future[List[Try[(AnyFixture[_], Boolean)]]] = - sequenceFutures( - munitFixtures.iterator.map(f => - runHiddenTest( - notifier, - s"beforeAll(${f.fixtureName})", - () => f.beforeAll() - ).map(isSuccess => f -> isSuccess) - ) + val result: Future[List[Try[(AnyFixture[_], Boolean)]]] = sequenceFutures( + munitFixtures.iterator.map(f => + runHiddenTest( + notifier, + s"beforeAll(${f.fixtureName})", + () => f.beforeAll(), + ).map(isSuccess => f -> isSuccess) ) + ) result.map { results => val loadedFixtures = results.collect { case Success((fixture, true)) => fixture @@ -223,33 +191,23 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) private def runAfterAll( notifier: RunNotifier, - beforeAll: BeforeAllResult - ): Future[Unit] = { - sequenceFutures[Boolean]( - beforeAll.loadedFixtures.iterator.map(f => - runHiddenTest( - notifier, - s"afterAll(${f.fixtureName})", - () => f.afterAll() - ) - ) - ).map(_ => ()) - } + beforeAll: BeforeAllResult, + ): Future[Unit] = + sequenceFutures[Boolean](beforeAll.loadedFixtures.iterator.map(f => + runHiddenTest(notifier, s"afterAll(${f.fixtureName})", () => f.afterAll()) + )).map(_ => ()) private[munit] class BeforeEachResult( val error: Option[Throwable], - val loadedFixtures: List[AnyFixture[_]] + val loadedFixtures: List[AnyFixture[_]], ) - private def runBeforeEach( - test: Test - ): Future[BeforeAllResult] = { + private def runBeforeEach(test: Test): Future[BeforeAllResult] = { val context = new BeforeEach(test) val fixtures = mutable.ListBuffer.empty[AnyFixture[_]] sequenceFutures( - munitFixtures.iterator.map(f => - valueTransform(() => f.beforeEach(context)).map(_ => f) - ) + munitFixtures.iterator + .map(f => valueTransform(() => f.beforeEach(context)).map(_ => f)) ).map { results => val loadedFixtures = results.collect { case Success(f) => f } val errors = results.collect { case util.Failure(ex) => ex } @@ -260,7 +218,7 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) private def runAfterEach( test: Test, - fixtures: List[AnyFixture[_]] + fixtures: List[AnyFixture[_]], ): Future[Unit] = { val context = new AfterEach(test) sequenceFutures( @@ -268,19 +226,14 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) ).map(_ => ()) } - private def runTest( - notifier: RunNotifier, - test: Test - ): Future[Boolean] = { + private def runTest(notifier: RunNotifier, test: Test): Future[Boolean] = { val description = createTestDescription(test) if (suiteAborted) { - notifier.fireTestAssumptionFailed( - new Failure( - description, - new FailSuiteException("Suite has been aborted", test.location) - ) - ) + notifier.fireTestAssumptionFailed(new Failure( + description, + new FailSuiteException("Suite has been aborted", test.location), + )) return Future.successful(false) } @@ -295,13 +248,12 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) val cause = Exceptions.rootCause(ex) val failure = new Failure(description, cause) cause match { - case _: AssumptionViolatedException => - notifier.fireTestAssumptionFailed(failure) + case _: AssumptionViolatedException => notifier + .fireTestAssumptionFailed(failure) case _: FailSuiteException => suiteAborted = true notifier.fireTestFailure(failure) - case _ => - notifier.fireTestFailure(failure) + case _ => notifier.fireTestFailure(failure) } Future.successful(()) } @@ -311,10 +263,8 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) trimStackTrace(ex) notifier.fireTestAssumptionFailed(new Failure(description, ex)) Future.successful(()) - case NonFatal(ex) => - handleNonFatalOrStackOverflow(ex) - case ex: StackOverflowError => - handleNonFatalOrStackOverflow(ex) + case NonFatal(ex) => handleNonFatalOrStackOverflow(ex) + case ex: StackOverflowError => handleNonFatalOrStackOverflow(ex) case ex => suiteAborted = true notifier.fireTestFailure(new Failure(description, ex)) @@ -331,91 +281,72 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) private def futureFromAny(any: Any): Future[Any] = any match { case f: Future[_] => f - case _ => Future.successful(any) + case _ => Future.successful(any) } private def runTestBody( notifier: RunNotifier, description: Description, - test: Test + test: Test, ): Future[Unit] = { - val result: Future[Any] = - runBeforeEach(test).flatMap[Any] { beforeEach => - beforeEach.errors match { - case Nil => - StackTraces - .dropOutside(test.body()) - .transformWithCompat(result => - runAfterEach(test, beforeEach.loadedFixtures) - .transformCompat(_ => result) - ) - case error :: errors => - errors.foreach(err => error.addSuppressed(err)) - try runAfterEach(test, beforeEach.loadedFixtures) - finally throw error - } + val result: Future[Any] = runBeforeEach(test).flatMap[Any](beforeEach => + beforeEach.errors match { + case Nil => StackTraces.dropOutside(test.body()) + .transformWithCompat(result => + runAfterEach(test, beforeEach.loadedFixtures) + .transformCompat(_ => result) + ) + case error :: errors => + errors.foreach(err => error.addSuppressed(err)) + try runAfterEach(test, beforeEach.loadedFixtures) + finally throw error } + ) result.map { case f: TestValues.FlakyFailure => trimStackTrace(f) notifier.fireTestAssumptionFailed(new Failure(description, f)) - case TestValues.Ignore => - notifier.fireTestIgnored(description) - case _ if test.tags(Pending) => - notifier.fireTestIgnored(description) - case _ => - () + case TestValues.Ignore => notifier.fireTestIgnored(description) + case _ if test.tags(Pending) => notifier.fireTestIgnored(description) + case _ => () } } private def runHiddenTest( notifier: RunNotifier, name: String, - thunk: () => Any - ): Future[Boolean] = { - try { - StackTraces.dropOutside { - valueTransform(thunk) - .transformCompat { - case util.Success(value) => - util.Success(true) - case util.Failure(exception) => - fireFailedHiddenTest(notifier, name, exception) - util.Success(false) - } - } - } catch { + thunk: () => Any, + ): Future[Boolean] = + try StackTraces.dropOutside(valueTransform(thunk).transformCompat { + case util.Success(value) => util.Success(true) + case util.Failure(exception) => + fireFailedHiddenTest(notifier, name, exception) + util.Success(false) + }) + catch { case ex: Throwable => fireFailedHiddenTest(notifier, name, ex) Future.successful(false) } - } private def fireFailedHiddenTest( notifier: RunNotifier, name: String, - ex: Throwable + ex: Throwable, ): Unit = { val test = new Test(name, () => ???, Set.empty, Location.empty) val description = createTestDescription(test) notifier.fireTestStarted(description) trimStackTrace(ex) - notifier.fireTestFailure( - new Failure(description, Exceptions.rootCause(ex)) - ) + notifier.fireTestFailure(new Failure(description, Exceptions.rootCause(ex))) notifier.fireTestFinished(description) } - private def trimStackTrace(ex: Throwable): Unit = { - if (settings.trimStackTraces) { - StackTraces.trimStackTrace(ex) - } - } + private def trimStackTrace(ex: Throwable): Unit = + if (settings.trimStackTraces) StackTraces.trimStackTrace(ex) - private def valueTransform(thunk: () => Any): Future[Any] = { - suite match { - case funSuite: FunSuite => funSuite.munitValueTransform(thunk()) - case _ => futureFromAny(thunk()) - } + private def valueTransform(thunk: () => Any): Future[Any] = suite match { + case funSuite: FunSuite => funSuite.munitValueTransform(thunk()) + case _ => futureFromAny(thunk()) } } @@ -425,18 +356,13 @@ object MUnitRunner { ): Class[_ <: Suite] = { require( hasEligibleConstructor(cls), - s"Class '${cls.getName}' is missing a public empty argument constructor" + s"Class '${cls.getName}' is missing a public empty argument constructor", ) cls } - private def hasEligibleConstructor(cls: Class[_ <: Suite]): Boolean = { + private def hasEligibleConstructor(cls: Class[_ <: Suite]): Boolean = try { - val constructor = cls.getConstructor( - new Array[java.lang.Class[_]](0): _* - ) + val constructor = cls.getConstructor(new Array[java.lang.Class[_]](0): _*) Modifier.isPublic(constructor.getModifiers) - } catch { - case nsme: NoSuchMethodException => false - } - } + } catch { case nsme: NoSuchMethodException => false } } diff --git a/munit/shared/src/main/scala/munit/Suite.scala b/munit/shared/src/main/scala/munit/Suite.scala index ab856aa3..90333f80 100644 --- a/munit/shared/src/main/scala/munit/Suite.scala +++ b/munit/shared/src/main/scala/munit/Suite.scala @@ -1,9 +1,10 @@ package munit -import org.junit.runner.RunWith import scala.concurrent.ExecutionContext import scala.concurrent.Future +import org.junit.runner.RunWith + /** * The base class for all test suites. * Extend this class if you don't need the functionality in FunSuite. diff --git a/munit/shared/src/main/scala/munit/SuiteTransforms.scala b/munit/shared/src/main/scala/munit/SuiteTransforms.scala index ca47b1f9..190413b2 100644 --- a/munit/shared/src/main/scala/munit/SuiteTransforms.scala +++ b/munit/shared/src/main/scala/munit/SuiteTransforms.scala @@ -3,7 +3,8 @@ package munit import scala.concurrent.Future import scala.util.control.NonFatal -trait SuiteTransforms { this: BaseFunSuite => +trait SuiteTransforms { + this: BaseFunSuite => final class SuiteTransform(val name: String, fn: List[Test] => List[Test]) extends Function1[List[Test], List[Test]] { @@ -11,60 +12,34 @@ trait SuiteTransforms { this: BaseFunSuite => } def munitSuiteTransforms: List[SuiteTransform] = - List( - munitIgnoreSuiteTransform, - munitOnlySuiteTransform - ) + List(munitIgnoreSuiteTransform, munitOnlySuiteTransform) - final def munitSuiteTransform(tests: List[Test]): List[Test] = { - try { - munitSuiteTransforms.foldLeft(tests) { case (ts, fn) => - fn(ts) - } - } catch { - case NonFatal(e) => - List( - new Test( - "munitSuiteTransform", - () => Future.failed(e) - )(Location.empty) + final def munitSuiteTransform(tests: List[Test]): List[Test] = + try munitSuiteTransforms.foldLeft(tests) { case (ts, fn) => fn(ts) } + catch { + case NonFatal(e) => List( + new Test("munitSuiteTransform", () => Future.failed(e))(Location.empty) ) } - } def munitIgnore: Boolean = false final def munitIgnoreSuiteTransform: SuiteTransform = - new SuiteTransform( - "munitIgnore", - { tests => - if (munitIgnore) Nil - else tests - } - ) + new SuiteTransform("munitIgnore", { tests => if (munitIgnore) Nil else tests }) def isCI: Boolean = "true" == System.getenv("CI") - final def munitOnlySuiteTransform: SuiteTransform = - new SuiteTransform( - "only", - { tests => - val onlySuite = tests.filter(_.tags(Only)) - if (onlySuite.nonEmpty) { - if (!isCI) { - onlySuite - } else { - onlySuite.map(t => - if (t.tags(Only)) { - t.withBody(() => - fail("'Only' tag is not allowed when `isCI=true`")(t.location) - ) - } else { - t - } - ) - } - } else { - tests - } - } - ) + final def munitOnlySuiteTransform: SuiteTransform = new SuiteTransform( + "only", + { tests => + val onlySuite = tests.filter(_.tags(Only)) + if (onlySuite.nonEmpty) + if (!isCI) onlySuite + else onlySuite.map(t => + if (t.tags(Only)) t.withBody(() => + fail("'Only' tag is not allowed when `isCI=true`")(t.location) + ) + else t + ) + else tests + }, + ) } diff --git a/munit/shared/src/main/scala/munit/Tag.scala b/munit/shared/src/main/scala/munit/Tag.scala index e1ca68a3..0225e02d 100644 --- a/munit/shared/src/main/scala/munit/Tag.scala +++ b/munit/shared/src/main/scala/munit/Tag.scala @@ -1,6 +1,7 @@ package munit import java.lang.annotation.Annotation + import scala.runtime.Statics class Tag(val value: String) @@ -10,7 +11,7 @@ class Tag(val value: String) // Not a case class so that it possible to override these. override def equals(obj: Any): Boolean = obj match { case t: Tag => t.value == value - case _ => false + case _ => false } override def hashCode(): Int = { var acc = -889275714 diff --git a/munit/shared/src/main/scala/munit/Test.scala b/munit/shared/src/main/scala/munit/Test.scala index 74d9ff8c..1ea4715e 100644 --- a/munit/shared/src/main/scala/munit/Test.scala +++ b/munit/shared/src/main/scala/munit/Test.scala @@ -1,6 +1,7 @@ package munit import java.lang.annotation.Annotation + import scala.collection.mutable import scala.concurrent.Future @@ -15,20 +16,15 @@ final class Test( val name: String, val body: () => Future[Any], val tags: Set[Tag], - val location: Location + val location: Location, ) extends Serializable { def this(name: String, body: () => Future[Any])(implicit loc: Location) = this(name, body, Set.empty, loc) - def withName(newName: String): Test = - copy(name = newName) - def withBody(newBody: () => Future[Any]): Test = - copy(body = newBody) - def withTags(newTags: Set[Tag]): Test = - copy(tags = newTags) - def tag(newTag: Tag): Test = - withTags(tags + newTag) - def withLocation(newLocation: Location): Test = - copy(location = newLocation) + def withName(newName: String): Test = copy(name = newName) + def withBody(newBody: () => Future[Any]): Test = copy(body = newBody) + def withTags(newTags: Set[Tag]): Test = copy(tags = newTags) + def tag(newTag: Tag): Test = withTags(tags + newTag) + def withLocation(newLocation: Location): Test = copy(location = newLocation) def withBodyMap(newBody: Future[Any] => Future[Any]): Test = withBody(() => newBody(body())) @@ -37,10 +33,8 @@ final class Test( name: String = this.name, body: () => Future[Any] = this.body, tags: Set[Tag] = this.tags, - location: Location = this.location - ): Test = { - new Test(name, body, tags, location) - } + location: Location = this.location, + ): Test = new Test(name, body, tags, location) override def toString(): String = s"Test($name, $tags, $location)" // NOTE(olafur): tests have reference equality because there's no reasonable // structural equality that we can use to compare the test body function. diff --git a/munit/shared/src/main/scala/munit/TestOptions.scala b/munit/shared/src/main/scala/munit/TestOptions.scala index a9805fa5..f0b5155b 100644 --- a/munit/shared/src/main/scala/munit/TestOptions.scala +++ b/munit/shared/src/main/scala/munit/TestOptions.scala @@ -10,15 +10,13 @@ package munit final class TestOptions( val name: String, val tags: Set[Tag], - val location: Location + val location: Location, ) extends Serializable { def this(name: String)(implicit loc: munit.Location) = this(name, Set.empty, loc) - def withName(newName: String): TestOptions = - copy(name = newName) - def withTags(newTags: Set[Tag]): TestOptions = - copy(tags = newTags) + def withName(newName: String): TestOptions = copy(name = newName) + def withTags(newTags: Set[Tag]): TestOptions = copy(tags = newTags) def withLocation(newLocation: Location): TestOptions = copy(location = newLocation) @@ -26,20 +24,16 @@ final class TestOptions( def flaky: TestOptions = tag(Flaky) def ignore: TestOptions = tag(Ignore) def pending: TestOptions = tag(Pending) - def pending(comment: String): TestOptions = - pending.tag(PendingComment(comment)) + def pending(comment: String): TestOptions = pending.tag(PendingComment(comment)) def only: TestOptions = tag(Only) def tag(t: Tag): TestOptions = copy(tags = tags + t) private[this] def copy( name: String = this.name, tags: Set[Tag] = this.tags, - location: Location = this.location - ): TestOptions = { - new TestOptions(name, tags, location) - } + location: Location = this.location, + ): TestOptions = new TestOptions(name, tags, location) - override def toString: String = - s"TestOptions($name, $tags, $location)" + override def toString: String = s"TestOptions($name, $tags, $location)" } object TestOptions extends TestOptionsConversions { @@ -53,8 +47,7 @@ trait TestOptionsConversions { * Implicitly create a TestOptions given a test name. * This allows writing `test("name") { ... }` even if `test` accepts a `TestOptions` */ - implicit def testOptionsFromString( - name: String - )(implicit loc: Location): TestOptions = - new TestOptions(name, Set.empty, loc) + implicit def testOptionsFromString(name: String)(implicit + loc: Location + ): TestOptions = new TestOptions(name, Set.empty, loc) } diff --git a/munit/shared/src/main/scala/munit/TestTransforms.scala b/munit/shared/src/main/scala/munit/TestTransforms.scala index ca7f7ccc..08ba6c90 100644 --- a/munit/shared/src/main/scala/munit/TestTransforms.scala +++ b/munit/shared/src/main/scala/munit/TestTransforms.scala @@ -1,12 +1,14 @@ package munit import munit.internal.FutureCompat._ -import scala.util.Success -import scala.util.Failure + import scala.concurrent.Future +import scala.util.Failure +import scala.util.Success import scala.util.control.NonFatal -trait TestTransforms { this: BaseFunSuite => +trait TestTransforms { + this: BaseFunSuite => final class TestTransform(val name: String, fn: Test => Test) extends Function1[Test, Test] { @@ -14,69 +16,46 @@ trait TestTransforms { this: BaseFunSuite => } def munitTestTransforms: List[TestTransform] = - List( - munitFailTransform, - munitFlakyTransform - ) + List(munitFailTransform, munitFlakyTransform) - final def munitTestTransform(test: Test): Test = { - try { - munitTestTransforms.foldLeft(test) { case (t, fn) => - fn(t) - } - } catch { - case NonFatal(e) => - test.withBody(() => Future.failed(e)) - } - } + final def munitTestTransform(test: Test): Test = + try munitTestTransforms.foldLeft(test) { case (t, fn) => fn(t) } + catch { case NonFatal(e) => test.withBody(() => Future.failed(e)) } - final def munitFailTransform: TestTransform = - new TestTransform( - "fail", - { t => - if (t.tags(Fail)) { - t.withBodyMap( - _.transformCompat { - case Success(value) => - Failure( - throw new FailException( - munitLines.formatLine( - t.location, - "expected failure but test passed" - ), - t.location - ) - ) - case Failure(exception) => - Success(()) - }(munitExecutionContext) - ) - } else { - t - } - } - ) + final def munitFailTransform: TestTransform = new TestTransform( + "fail", + { t => + if (t.tags(Fail)) t.withBodyMap( + _.transformCompat { + case Success(value) => Failure( + throw new FailException( + munitLines + .formatLine(t.location, "expected failure but test passed"), + t.location, + ) + ) + case Failure(exception) => Success(()) + }(munitExecutionContext) + ) + else t + }, + ) def munitFlakyOK: Boolean = "true" == System.getenv("MUNIT_FLAKY_OK") - final def munitFlakyTransform: TestTransform = - new TestTransform( - "flaky", - { t => - if (t.tags(Flaky)) { - t.withBodyMap(_.transformCompat { - case Success(value) => Success(value) - case Failure(exception) => - if (munitFlakyOK) { - Success(new TestValues.FlakyFailure(exception)) - } else { - throw exception - } - }(munitExecutionContext)) - } else { - t - } - } - ) + final def munitFlakyTransform: TestTransform = new TestTransform( + "flaky", + { t => + if (t.tags(Flaky)) t.withBodyMap( + _.transformCompat { + case Success(value) => Success(value) + case Failure(exception) => + if (munitFlakyOK) Success(new TestValues.FlakyFailure(exception)) + else throw exception + }(munitExecutionContext) + ) + else t + }, + ) /** * Optionally augment a failure with additional information. @@ -85,32 +64,29 @@ trait TestTransforms { this: BaseFunSuite => */ def munitAppendToFailureMessage( buildSuffix: Test => Option[String] - ): TestTransform = - new TestTransform( - "failureSuffix", - { t => - t.withBodyMap( - _.transformCompat { - case s @ Success(_) => s - case f @ Failure(exception) => - buildSuffix(t).fold(f) { suffix => - def append(existing: String): String = - if (existing.endsWith("\n")) s"$existing$suffix\n" - else s"$existing\n$suffix" + ): TestTransform = new TestTransform( + "failureSuffix", + { t => + t.withBodyMap { + _.transformCompat { + case s @ Success(_) => s + case f @ Failure(exception) => buildSuffix(t).fold(f) { suffix => + def append(existing: String): String = + if (existing.endsWith("\n")) s"$existing$suffix\n" + else s"$existing\n$suffix" - Failure(Exceptions.rootCause(exception) match { - case fel: FailExceptionLike[_] => fel.updateMessage(append) - case e => - new FailException( - message = append(e.getMessage), - cause = e, - isStackTracesEnabled = false, - location = t.location - ) - }) - } - }(munitExecutionContext) - ) + Failure(Exceptions.rootCause(exception) match { + case fel: FailExceptionLike[_] => fel.updateMessage(append) + case e => new FailException( + message = append(e.getMessage), + cause = e, + isStackTracesEnabled = false, + location = t.location, + ) + }) + } + }(munitExecutionContext) } - ) + }, + ) } diff --git a/munit/shared/src/main/scala/munit/TestValues.scala b/munit/shared/src/main/scala/munit/TestValues.scala index e8a5d419..5d3caf50 100644 --- a/munit/shared/src/main/scala/munit/TestValues.scala +++ b/munit/shared/src/main/scala/munit/TestValues.scala @@ -9,11 +9,7 @@ object TestValues { /** The test failed with the given exception but was ignored but its marked as flaky */ class FlakyFailure(error: Throwable) - extends FailException( - "ignoring flaky test failure", - error, - Location.empty - ) + extends FailException("ignoring flaky test failure", error, Location.empty) with NoStackTrace with Serializable diff --git a/munit/shared/src/main/scala/munit/ValueTransforms.scala b/munit/shared/src/main/scala/munit/ValueTransforms.scala index d6a3bea2..7571ce08 100644 --- a/munit/shared/src/main/scala/munit/ValueTransforms.scala +++ b/munit/shared/src/main/scala/munit/ValueTransforms.scala @@ -1,35 +1,33 @@ package munit -import scala.concurrent.Future import munit.internal.FutureCompat._ -import scala.util.Try import munit.internal.console.StackTraces -trait ValueTransforms { this: BaseFunSuite => +import scala.concurrent.Future +import scala.util.Try + +trait ValueTransforms { + this: BaseFunSuite => final class ValueTransform( val name: String, - fn: PartialFunction[Any, Future[Any]] + fn: PartialFunction[Any, Future[Any]], ) extends Function1[Any, Option[Future[Any]]] { def apply(v1: Any): Option[Future[Any]] = fn.lift(v1) } - def munitValueTransforms: List[ValueTransform] = - List( - munitFutureTransform - ) + def munitValueTransforms: List[ValueTransform] = List(munitFutureTransform) final def munitValueTransform(testValue: => Any): Future[Any] = { // Takes an arbitrarily nested future `Future[Future[Future[...]]]` and // returns a `Future[T]` where `T` is not a `Future`. def flattenFuture(future: Future[_]): Future[_] = { val nested: Future[Future[Any]] = future.map { value => - val transformed = munitValueTransforms.iterator - .map(fn => fn(value)) + val transformed = munitValueTransforms.iterator.map(fn => fn(value)) .collectFirst { case Some(future) => future } transformed match { case Some(f) => flattenFuture(f) - case None => Future.successful(value) + case None => Future.successful(value) } }(munitExecutionContext) nested.flattenCompat(munitExecutionContext) diff --git a/munit/shared/src/main/scala/munit/internal/FutureCompat.scala b/munit/shared/src/main/scala/munit/internal/FutureCompat.scala index 1581f51e..640b6b4d 100644 --- a/munit/shared/src/main/scala/munit/internal/FutureCompat.scala +++ b/munit/shared/src/main/scala/munit/internal/FutureCompat.scala @@ -1,24 +1,19 @@ package munit.internal +import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.util.Try -import scala.concurrent.ExecutionContext object FutureCompat { implicit class ExtensionFuture[T](f: Future[T]) { - def flattenCompat[S]( + def flattenCompat[S](ec: ExecutionContext)(implicit + ev: T <:< Future[S] + ): Future[S] = f.flatten + def transformCompat[B](fn: Try[T] => Try[B])(implicit + ec: ExecutionContext + ): Future[B] = f.transform(fn) + def transformWithCompat[B](fn: Try[T] => Future[B])(implicit ec: ExecutionContext - )(implicit ev: T <:< Future[S]): Future[S] = - f.flatten - def transformCompat[B]( - fn: Try[T] => Try[B] - )(implicit ec: ExecutionContext): Future[B] = { - f.transform(fn) - } - def transformWithCompat[B]( - fn: Try[T] => Future[B] - )(implicit ec: ExecutionContext): Future[B] = { - f.transformWith(fn) - } + ): Future[B] = f.transformWith(fn) } } diff --git a/munit/shared/src/main/scala/munit/internal/MacroCompatScala2.scala b/munit/shared/src/main/scala/munit/internal/MacroCompatScala2.scala index 641ff3e8..0588f2bd 100644 --- a/munit/shared/src/main/scala/munit/internal/MacroCompatScala2.scala +++ b/munit/shared/src/main/scala/munit/internal/MacroCompatScala2.scala @@ -2,21 +2,21 @@ package munit.internal import munit.Clue import munit.Location -import scala.reflect.macros.blackbox.Context -import scala.reflect.macros.TypecheckException + import scala.reflect.macros.ParseException +import scala.reflect.macros.TypecheckException +import scala.reflect.macros.blackbox.Context object MacroCompatScala2 { def locationImpl(c: Context): c.Tree = { import c.universe._ - val workingDirectory: String = - sys.props("user.dir") + java.io.File.separator + val workingDirectory: String = sys.props("user.dir") + + java.io.File.separator val line = Literal(Constant(c.enclosingPosition.line)) val path0 = c.enclosingPosition.source.path val relativePath = - if (path0.startsWith(workingDirectory)) - path0.drop(workingDirectory.length) + if (path0.startsWith(workingDirectory)) path0.drop(workingDirectory.length) else path0 val path = Literal(Constant(relativePath)) New(c.mirror.staticClass(classOf[Location].getName()), path, line) @@ -30,17 +30,11 @@ object MacroCompatScala2 { val start = value.pos.start val end = value.pos.end if ( - end > start && - start >= 0 && start < chars.length && - end >= 0 && end < chars.length - ) { - new String(chars, start, end - start) - } else { - "" - } - } else { - "" - } + end > start && start >= 0 && start < chars.length && end >= 0 && + end < chars.length + ) new String(chars, start, end - start) + else "" + } else "" def simplifyType(tpe: Type): Type = tpe match { case TypeRef(ThisType(pre), sym, args) if pre == sym.owner => simplifyType(c.internal.typeRef(NoPrefix, sym, args)) @@ -55,11 +49,11 @@ object MacroCompatScala2 { c.internal.typeRef( NoPrefix, c.mirror.staticClass(classOf[Clue[_]].getName()), - List(value.tpe.widen) + List(value.tpe.widen), ), source, value, - valueType + valueType, ) } @@ -67,35 +61,26 @@ object MacroCompatScala2 { import c.universe._ val toParse: String = code match { case Literal(Constant(literal: String)) => literal - case _ => - c.abort( + case _ => c.abort( code.pos, "cannot compile dynamic expressions, only constant literals.\n" + - "To fix this problem, pass in a string literal in double quotes \"...\"" + "To fix this problem, pass in a string literal in double quotes \"...\"", ) } def formatError(message: String, pos: scala.reflect.api.Position): String = - new StringBuilder() - .append("error:") - .append(if (message.contains('\n')) "\n" else " ") - .append(message) - .append("\n") - .append(pos.lineContent) - .append("\n") - .append(" " * (pos.column - 1)) - .append("^") - .toString() + new StringBuilder().append("error:") + .append(if (message.contains('\n')) "\n" else " ").append(message) + .append("\n").append(pos.lineContent).append("\n") + .append(" " * (pos.column - 1)).append("^").toString() val message: String = try { c.typecheck(c.parse(s"{\n$toParse\n}")) "" } catch { - case e: ParseException => - formatError(e.getMessage(), e.pos) - case e: TypecheckException => - formatError(e.getMessage(), e.pos) + case e: ParseException => formatError(e.getMessage(), e.pos) + case e: TypecheckException => formatError(e.getMessage(), e.pos) } Literal(Constant(message)) } diff --git a/munit/shared/src/main/scala/munit/internal/console/Lines.scala b/munit/shared/src/main/scala/munit/internal/console/Lines.scala index 62aab3b7..8ef1472d 100644 --- a/munit/shared/src/main/scala/munit/internal/console/Lines.scala +++ b/munit/shared/src/main/scala/munit/internal/console/Lines.scala @@ -1,31 +1,28 @@ package munit.internal.console -import munit.internal.io.PlatformIO.{Files, Path, Paths} +import munit.Clues import munit.Location +import munit.internal.io.PlatformIO.Files +import munit.internal.io.PlatformIO.Path +import munit.internal.io.PlatformIO.Paths import scala.collection.JavaConverters._ import scala.collection.mutable import scala.util.control.NonFatal -import munit.Clues class Lines extends Serializable { private val filecache = mutable.Map.empty[Path, Array[String]] - def formatLine(location: Location, message: String): String = { + def formatLine(location: Location, message: String): String = formatLine(location, message, new Clues(Nil)) - } - def formatPath(location: Location): String = - location.path + def formatPath(location: Location): String = location.path def findPath(cwd: String, path: String, max: Int): Path = { val p = Paths.get(cwd).resolve(path) def getParentPath(somePath: String, sep: String): String = { val somePath1 = - if (somePath.endsWith(sep)) somePath.dropRight(sep.length) - else somePath - val sep1 = - if (sep == "\\") "\\\\" - else sep + if (somePath.endsWith(sep)) somePath.dropRight(sep.length) else somePath + val sep1 = if (sep == "\\") "\\\\" else sep somePath1.split(sep1).dropRight(1).mkString(sep) } if (Files.exists(p)) p @@ -35,64 +32,37 @@ class Lines extends Serializable { else findPath(getParentPath(cwd, "/"), path, max - 1) } - def formatLine(location: Location, message: String, clues: Clues): String = { + def formatLine(location: Location, message: String, clues: Clues): String = try { val path = findPath(Path.workingDirectory.toString, location.path, 3) - val lines = filecache.getOrElseUpdate( - path, { - Files.readAllLines(path).asScala.toArray - } - ) + val lines = filecache + .getOrElseUpdate(path, Files.readAllLines(path).asScala.toArray) val slice = lines.slice(location.line - 2, location.line + 1) val out = new StringBuilder() if (slice.length >= 2) { val width = (location.line + 1).toString().length() + 1 - def format(n: Int): String = { - s"$n:".padTo(width, ' ') - } + def format(n: Int): String = s"$n:".padTo(width, ' ') val isMultilineMessage = message.contains('\n') - out - .append(formatPath(location)) - .append(':') + out.append(formatPath(location)).append(':') .append(location.line.toString()) - if (message.length() > 0 && !isMultilineMessage) { - out.append(" ").append(message) - } - out - .append('\n') - .append(format(location.line - 1)) - .append(slice(0)) - .append('\n') - .append( - munit.diff.console.AnsiColors - .use(munit.diff.console.AnsiColors.Reversed) - ) - .append(format(location.line)) - .append(slice(1)) - .append( - munit.diff.console.AnsiColors - .use(munit.diff.console.AnsiColors.Reset) - ) - if (slice.length >= 3) - out - .append('\n') - .append(format(location.line + 1)) - .append(slice(2)) - if (isMultilineMessage) { - out.append('\n').append(message) - } - if (clues.values.nonEmpty) { - out.append('\n').append(Printers.print(clues)) - } + if (message.length() > 0 && !isMultilineMessage) out.append(" ") + .append(message) + out.append('\n').append(format(location.line - 1)).append(slice(0)) + .append('\n').append(munit.diff.console.AnsiColors.use( + munit.diff.console.AnsiColors.Reversed + )).append(format(location.line)).append(slice(1)) + .append(munit.diff.console.AnsiColors.use( + munit.diff.console.AnsiColors.Reset + )) + if (slice.length >= 3) out.append('\n').append(format(location.line + 1)) + .append(slice(2)) + if (isMultilineMessage) out.append('\n').append(message) + if (clues.values.nonEmpty) out.append('\n').append(Printers.print(clues)) } out.toString() } catch { case NonFatal(_) => - if (clues.values.isEmpty) { - message - } else { - message + "\n" + Printers.print(clues) - } + if (clues.values.isEmpty) message + else message + "\n" + Printers.print(clues) } - } } diff --git a/munit/shared/src/main/scala/munit/internal/console/Printers.scala b/munit/shared/src/main/scala/munit/internal/console/Printers.scala index b952de6c..dc3885fe 100644 --- a/munit/shared/src/main/scala/munit/internal/console/Printers.scala +++ b/munit/shared/src/main/scala/munit/internal/console/Printers.scala @@ -1,12 +1,12 @@ // Adaptation of https://github.com/lihaoyi/PPrint/blob/e6a918c259ed7ae1998bbf58c360334a3f0157ca/pprint/src/pprint/Walker.scala package munit.internal.console +import munit.Clues import munit.Location -import munit.diff.Printer +import munit.Printable import munit.diff.EmptyPrinter +import munit.diff.Printer import munit.diff.console.{Printers => DiffPrinters} -import munit.Clues -import munit.Printable import munit.internal.Compat object Printers { @@ -33,98 +33,77 @@ object Printers { } val nextIndent = indent + indentStep val isDone = printer.print(a, out, indent) - if (!isDone) { - a match { - case null => out.append("null") - case x: Printable => x.print(out, indent) - case x: Char => - out.append('\'') - if (x == '\'') out.append("\\'") - else printChar(x, out) - out.append('\'') - case x: Byte => out.append(x.toString()) - case x: Short => out.append(x.toString()) - case x: Int => out.append(x.toString()) - case x: Long => out.append(x.toString()) - case x: Float => out.append(x.toString()) - case x: Double => out.append(x.toString()) - case x: String => printString(x, out, printer) - case x: Clues => - printApply( - "Clues", - x.values.iterator, - out, - indent, - nextIndent, - open = " {", - close = "}", - comma = "" - ) { clue => - if (clue.source.nonEmpty) { - out.append(clue.source) - } - if (clue.valueType.nonEmpty) { - out.append(": ").append(clue.valueType) - } - out.append(" = ") - loop(clue.value, nextIndent) - } - case None => - out.append("None") - case Nil => - out.append("Nil") - case x: Map[_, _] => - printApply( - Compat.collectionClassName(x), - x.iterator, - out, - indent, - nextIndent - ) { case (key, value) => - loop(key, nextIndent) - out.append(" -> ") - loop(value, nextIndent) - } - case x: Iterable[_] => - printApply( - Compat.collectionClassName(x), - x.iterator, - out, - indent, - nextIndent - ) { value => loop(value, nextIndent) } - case x: Array[_] => - printApply( - "Array", - x.iterator, - out, - indent, - nextIndent - ) { value => loop(value, nextIndent) } - case it: Iterator[_] => - if (it.isEmpty) out.append("empty iterator") - else out.append("non-empty iterator") - case p: Product => - val elementNames = Compat.productElementNames(p) - val infiniteElementNames = Iterator.continually { - if (elementNames.hasNext) elementNames.next() - else "" - } - printApply( - p.productPrefix, - p.productIterator.zip(infiniteElementNames), - out, - indent, - nextIndent - ) { case (value, key) => - if (key.nonEmpty) { - out.append(key).append(" = ") - } - loop(value, nextIndent) - } - case _ => - out.append(a.toString()) - } + if (!isDone) a match { + case null => out.append("null") + case x: Printable => x.print(out, indent) + case x: Char => + out.append('\'') + if (x == '\'') out.append("\\'") else printChar(x, out) + out.append('\'') + case x: Byte => out.append(x.toString()) + case x: Short => out.append(x.toString()) + case x: Int => out.append(x.toString()) + case x: Long => out.append(x.toString()) + case x: Float => out.append(x.toString()) + case x: Double => out.append(x.toString()) + case x: String => printString(x, out, printer) + case x: Clues => printApply( + "Clues", + x.values.iterator, + out, + indent, + nextIndent, + open = " {", + close = "}", + comma = "", + ) { clue => + if (clue.source.nonEmpty) out.append(clue.source) + if (clue.valueType.nonEmpty) out.append(": ").append(clue.valueType) + out.append(" = ") + loop(clue.value, nextIndent) + } + case None => out.append("None") + case Nil => out.append("Nil") + case x: Map[_, _] => printApply( + Compat.collectionClassName(x), + x.iterator, + out, + indent, + nextIndent, + ) { case (key, value) => + loop(key, nextIndent) + out.append(" -> ") + loop(value, nextIndent) + } + case x: Iterable[_] => printApply( + Compat.collectionClassName(x), + x.iterator, + out, + indent, + nextIndent, + )(value => loop(value, nextIndent)) + case x: Array[_] => + printApply("Array", x.iterator, out, indent, nextIndent)(value => + loop(value, nextIndent) + ) + case it: Iterator[_] => + if (it.isEmpty) out.append("empty iterator") + else out.append("non-empty iterator") + case p: Product => + val elementNames = Compat.productElementNames(p) + val infiniteElementNames = Iterator + .continually(if (elementNames.hasNext) elementNames.next() else "") + printApply( + p.productPrefix, + p.productIterator.zip(infiniteElementNames), + out, + indent, + nextIndent, + ) { case (value, key) => + if (key.nonEmpty) out.append(key).append(" = ") + loop(value, nextIndent) + } + case _ => out.append(a.toString()) } } loop(any, indent = 0) @@ -139,7 +118,7 @@ object Printers { nextIndent: Int, open: String = "(", close: String = ")", - comma: String = "," + comma: String = ",", )(fn: T => Unit): Unit = { out.append(prefix) out.append(open) @@ -151,9 +130,7 @@ object Printers { if (it.hasNext) { out.append(comma) printNewline(out, nextIndent) - } else { - printNewline(out, indent) - } + } else printNewline(out, indent) } } out.append(close) @@ -189,7 +166,7 @@ object Printers { val ch = string.charAt(i) ch match { case '"' | '\'' => out.append(ch) - case _ => printChar(ch, out, isEscapeUnicode = false) + case _ => printChar(ch, out, isEscapeUnicode = false) } i += 1 } diff --git a/munit/shared/src/main/scala/munit/internal/console/StackTraces.scala b/munit/shared/src/main/scala/munit/internal/console/StackTraces.scala index d6b3ce80..c640afa4 100644 --- a/munit/shared/src/main/scala/munit/internal/console/StackTraces.scala +++ b/munit/shared/src/main/scala/munit/internal/console/StackTraces.scala @@ -12,17 +12,12 @@ object StackTraces { def dropOutside[T](t: => T): T = t def trimStackTrace(ex: Throwable): ex.type = { - val isVisited = ju.Collections.newSetFromMap( - new ju.IdentityHashMap[Throwable, java.lang.Boolean]() - ) - def loop(e: Throwable): Unit = { - if (e != null && isVisited.add(e)) { - val stack = e.getStackTrace() - if (stack != null) { - e.setStackTrace(filterCallStack(stack)) - } - loop(e.getCause()) - } + val isVisited = ju.Collections + .newSetFromMap(new ju.IdentityHashMap[Throwable, java.lang.Boolean]()) + def loop(e: Throwable): Unit = if (e != null && isVisited.add(e)) { + val stack = e.getStackTrace() + if (stack != null) e.setStackTrace(filterCallStack(stack)) + loop(e.getCause()) } loop(ex) ex @@ -32,30 +27,27 @@ object StackTraces { stack: Array[StackTraceElement] ): Array[StackTraceElement] = { val droppedInside = stack.lastIndexWhere(x => - x.getClassName == className && - x.getMethodName == "dropInside" + x.getClassName == className && x.getMethodName == "dropInside" ) val droppedOutside = stack.indexWhere(x => - x.getClassName == className && - x.getMethodName == "dropOutside" + x.getClassName == className && x.getMethodName == "dropOutside" ) val stack1 = stack.slice( droppedInside match { case -1 => 0 - case n => n + 3 + case n => n + 3 }, droppedOutside match { case -1 => stack.length - case n => n - } + case n => n + }, ) - val lastNonLMFIndex = - stack1.lastIndexWhere(x => !x.getClassName.contains("$$Lambda$")) + val lastNonLMFIndex = stack1 + .lastIndexWhere(x => !x.getClassName.contains("$$Lambda$")) - if (lastNonLMFIndex < 0) stack1 - else stack1.take(lastNonLMFIndex + 1) + if (lastNonLMFIndex < 0) stack1 else stack1.take(lastNonLMFIndex + 1) } } diff --git a/munit/shared/src/main/scala/munit/package.scala b/munit/shared/src/main/scala/munit/package.scala index fc4be115..390f753f 100644 --- a/munit/shared/src/main/scala/munit/package.scala +++ b/munit/shared/src/main/scala/munit/package.scala @@ -1,9 +1,9 @@ -import munit.internal.junitinterface.{PendingCommentTag, PendingTag} +import munit.internal.junitinterface.PendingCommentTag +import munit.internal.junitinterface.PendingTag package object munit { case class PendingComment(override val value: String) - extends Tag(value) - with PendingCommentTag + extends Tag(value) with PendingCommentTag val Ignore = new Tag("Ignore") val Only = new Tag("Only") diff --git a/tests/js/src/test/scala/munit/AsyncJSSuite.scala b/tests/js/src/test/scala/munit/AsyncJSSuite.scala index c3e8043f..6d6fec80 100644 --- a/tests/js/src/test/scala/munit/AsyncJSSuite.scala +++ b/tests/js/src/test/scala/munit/AsyncJSSuite.scala @@ -5,17 +5,14 @@ import scala.concurrent.Promise class AsyncJSSuite extends FunSuite { test("async-ok") { val p = Promise[Unit]() - scala.scalajs.js.timers.setTimeout(100) { - p.success(()) - } + scala.scalajs.js.timers.setTimeout(100)(p.success(())) p.future } test("async-error".fail) { val p = Promise[Unit]() - scala.scalajs.js.timers.setTimeout(100) { - p.failure(new RuntimeException("boom")) - } + scala.scalajs.js.timers + .setTimeout(100)(p.failure(new RuntimeException("boom"))) p.future } } diff --git a/tests/js/src/test/scala/munit/TimeoutSuite.scala b/tests/js/src/test/scala/munit/TimeoutSuite.scala index 83b373f2..0b96d755 100644 --- a/tests/js/src/test/scala/munit/TimeoutSuite.scala +++ b/tests/js/src/test/scala/munit/TimeoutSuite.scala @@ -1,23 +1,19 @@ package munit -import scala.scalajs.js.timers._ import scala.concurrent.Promise import scala.concurrent.duration.Duration +import scala.scalajs.js.timers._ class TimeoutSuite extends BaseSuite { override def munitTimeout: Duration = Duration(3, "ms") test("setTimeout-exceeds".fail) { val promise = Promise[Unit]() - setTimeout(1000) { - promise.success(()) - } + setTimeout(1000)(promise.success(())) promise.future } test("setTimeout-passes") { val promise = Promise[Unit]() - setTimeout(1) { - promise.success(()) - } + setTimeout(1)(promise.success(())) promise.future } diff --git a/tests/jvm/src/main/scala/munit/ThrottleCpu.scala b/tests/jvm/src/main/scala/munit/ThrottleCpu.scala index 474f9e96..f763013d 100644 --- a/tests/jvm/src/main/scala/munit/ThrottleCpu.scala +++ b/tests/jvm/src/main/scala/munit/ThrottleCpu.scala @@ -1,18 +1,13 @@ package munit object ThrottleCpu { - def run(): Unit = { - while (true) { - // Some computationally intensive calculation - 1.to(1000).foreach(i => fib(i)) - println("Loop") - } + def run(): Unit = while (true) { + // Some computationally intensive calculation + 1.to(1000).foreach(i => fib(i)) + println("Loop") } - private final def fib(n: Int): Int = { - if (n < 1) 0 - else if (n == 1) n - else fib(n - 1) + fib(n - 2) - } + private final def fib(n: Int): Int = + if (n < 1) 0 else if (n == 1) n else fib(n - 1) + fib(n - 2) } diff --git a/tests/jvm/src/test/scala/munit/AsyncFixtureSuite.scala b/tests/jvm/src/test/scala/munit/AsyncFixtureSuite.scala index d1784dd1..656505c7 100644 --- a/tests/jvm/src/test/scala/munit/AsyncFixtureSuite.scala +++ b/tests/jvm/src/test/scala/munit/AsyncFixtureSuite.scala @@ -1,22 +1,19 @@ package munit -import scala.concurrent.Promise import java.util.concurrent.Executors +import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.TimeUnit + import scala.concurrent.ExecutionContext -import java.util.concurrent.ScheduledExecutorService +import scala.concurrent.Promise class AsyncFixtureSuite extends BaseSuite { case class PromiseWrapper(name: String, promise: Promise[_]) override def munitValueTransforms: List[ValueTransform] = - super.munitValueTransforms ++ List( - new ValueTransform( - "PromiseWrapper", - { case p: PromiseWrapper => - p.promise.future - } - ) - ) + super.munitValueTransforms ++ List(new ValueTransform( + "PromiseWrapper", + { case p: PromiseWrapper => p.promise.future }, + )) class ScheduledMessage() extends AnyFixture[String]("AsyncFixture") { val sh: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor() @@ -32,7 +29,7 @@ class AsyncFixtureSuite extends BaseSuite { setBeforeAllBit.success(()) }, timeout, - TimeUnit.MILLISECONDS + TimeUnit.MILLISECONDS, ) PromiseWrapper("beforeAll", setBeforeAllBit) } @@ -40,16 +37,13 @@ class AsyncFixtureSuite extends BaseSuite { assertEquals( promise.future.value, None, - "promise did not get reset from afterEach" - ) - assert( - didBeforeAllEvaluateAsync, - "beforeAll promise did not complete yet" + "promise did not get reset from afterEach", ) + assert(didBeforeAllEvaluateAsync, "beforeAll promise did not complete yet") sh.schedule[Unit]( () => promise.success(s"beforeEach-${context.test.name}"), timeout, - TimeUnit.MILLISECONDS + TimeUnit.MILLISECONDS, ) PromiseWrapper("beforeEach", promise) } @@ -61,38 +55,33 @@ class AsyncFixtureSuite extends BaseSuite { resetPromise.success(()) }, timeout, - TimeUnit.MILLISECONDS + TimeUnit.MILLISECONDS, ) PromiseWrapper("afterEach", resetPromise) } override def afterAll(): PromiseWrapper = { val shutdownPromise = Promise[Unit]() - ExecutionContext.global.execute(() => { + ExecutionContext.global.execute { () => Thread.sleep(timeout) val runningJobs = sh.shutdownNow() assert(runningJobs.isEmpty(), runningJobs) shutdownPromise.success(()) - }) + } PromiseWrapper("afterAll", shutdownPromise) } } val message = new ScheduledMessage() val latest: Fixture[Unit] = new Fixture[Unit]("latest") { def apply(): Unit = () - override def afterAll(): Unit = { - assert( - message.sh.isShutdown(), - "message.afterAll did not complete yet. " + - "We may want to remove this assertion in the future if we allow fixtures to load in parallel." - ) - } + override def afterAll(): Unit = assert( + message.sh.isShutdown(), + "message.afterAll did not complete yet. " + + "We may want to remove this assertion in the future if we allow fixtures to load in parallel.", + ) } override def munitFixtures: Seq[AnyFixture[_]] = List(message, latest) - 1.to(3).foreach { i => - test(s"test-$i") { - assertEquals(message(), s"beforeEach-test-$i") - } - } + 1.to(3) + .foreach(i => test(s"test-$i")(assertEquals(message(), s"beforeEach-test-$i"))) } diff --git a/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala b/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala index c6eda50b..e0c0167d 100644 --- a/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala +++ b/tests/jvm/src/test/scala/munit/AsyncFunFixtureOrderSuite.scala @@ -12,10 +12,8 @@ class AsyncFunFixtureOrderSuite extends FunSuite { setup = { test => Future.successful(test.name) }, teardown = { name => implicit val ec = munitExecutionContext - Future { - completedFromTeardown = Some(latch.trySuccess(())); - } - } + Future { completedFromTeardown = Some(latch.trySuccess(())); } + }, ) override def afterAll(): Unit = { diff --git a/tests/jvm/src/test/scala/munit/FutureSuite.scala b/tests/jvm/src/test/scala/munit/FutureSuite.scala index 54463350..68e10d65 100644 --- a/tests/jvm/src/test/scala/munit/FutureSuite.scala +++ b/tests/jvm/src/test/scala/munit/FutureSuite.scala @@ -4,16 +4,14 @@ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future class FutureSuite extends FunSuite { - test("nested".fail) { + test("nested".fail)(Future { + Thread.sleep(2) Future { Thread.sleep(2) Future { Thread.sleep(2) - Future { - Thread.sleep(2) - ??? - } + ??? } } - } + }) } diff --git a/tests/jvm/src/test/scala/munit/TestSelectorSuite.scala b/tests/jvm/src/test/scala/munit/TestSelectorSuite.scala index 79ac82f9..cdf2578a 100644 --- a/tests/jvm/src/test/scala/munit/TestSelectorSuite.scala +++ b/tests/jvm/src/test/scala/munit/TestSelectorSuite.scala @@ -2,26 +2,23 @@ package munit import sbt.testing.Event import sbt.testing.EventHandler +import sbt.testing.Runner import sbt.testing.Selector import sbt.testing.Status import sbt.testing.SuiteSelector import sbt.testing.TaskDef import sbt.testing.TestSelector + import scala.collection.mutable -import sbt.testing.Runner /** * Dummy test suite which is needed by TestSelectorSuite */ class MyTestSuite extends FunSuite { - test("testFoo") { - assert(true, "Test should pass") - } + test("testFoo")(assert(true, "Test should pass")) - test("testBar") { - assert(true, "Test should pass") - } + test("testBar")(assert(true, "Test should pass")) } /** @@ -30,11 +27,8 @@ class MyTestSuite extends FunSuite { */ class TestSelectorSuite extends FunSuite { val framework = new Framework(); - val runner: Runner = framework.runner( - Array.empty, - Array.empty, - this.getClass().getClassLoader() - ); + val runner: Runner = framework + .runner(Array.empty, Array.empty, this.getClass().getClassLoader()); val fingerprint = framework.munitFingerprint @@ -45,27 +39,19 @@ class TestSelectorSuite extends FunSuite { private def getEventHandler(): (mutable.ListBuffer[String], EventHandler) = { val executedItems = new mutable.ListBuffer[String] val eventHandler = new EventHandler { - override def handle(event: Event) = - if (event.status() == Status.Success) { - executedItems += event.fullyQualifiedName() - } + override def handle(event: Event) = if (event.status() == Status.Success) + executedItems += event.fullyQualifiedName() } (executedItems, eventHandler) } - private def getTaskDefs(selectors: Array[Selector]): Array[TaskDef] = { - Array( - new TaskDef("munit.MyTestSuite", fingerprint, false, selectors) - ) - } + private def getTaskDefs(selectors: Array[Selector]): Array[TaskDef] = + Array(new TaskDef("munit.MyTestSuite", fingerprint, false, selectors)) test("runAllViaSuiteSelector") { - val selectors = Array[Selector]( - new SuiteSelector - ) - val taskDefs = Array( - new TaskDef("munit.MyTestSuite", fingerprint, false, selectors) - ) + val selectors = Array[Selector](new SuiteSelector) + val taskDefs = + Array(new TaskDef("munit.MyTestSuite", fingerprint, false, selectors)) val tasks = runner.tasks(taskDefs) assertEquals(tasks.size, 1) @@ -76,15 +62,13 @@ class TestSelectorSuite extends FunSuite { task.execute(eventHandler, Nil.toArray) assertEquals( executedItems.toSet, - Set("munit.MyTestSuite.testBar", "munit.MyTestSuite.testFoo") + Set("munit.MyTestSuite.testBar", "munit.MyTestSuite.testFoo"), ) } test("runAllViaTestSelectors") { - val selectors = Array[Selector]( - new TestSelector("testFoo"), - new TestSelector("testBar") - ) + val selectors = + Array[Selector](new TestSelector("testFoo"), new TestSelector("testBar")) val taskDefs = getTaskDefs(selectors) val tasks = runner.tasks(taskDefs) @@ -96,14 +80,12 @@ class TestSelectorSuite extends FunSuite { task.execute(eventHandler, Nil.toArray) assertEquals( executedItems.toSet, - Set("munit.MyTestSuite.testBar", "munit.MyTestSuite.testFoo") + Set("munit.MyTestSuite.testBar", "munit.MyTestSuite.testFoo"), ) } test("runOnlyOne") { - val selectors = Array[Selector]( - new TestSelector("testFoo") - ) + val selectors = Array[Selector](new TestSelector("testFoo")) val taskDefs = getTaskDefs(selectors) val tasks = runner.tasks(taskDefs) @@ -113,10 +95,7 @@ class TestSelectorSuite extends FunSuite { val (executedItems, eventHandler) = getEventHandler() task.execute(eventHandler, Nil.toArray) - assertEquals( - executedItems.toSet, - Set("munit.MyTestSuite.testFoo") - ) + assertEquals(executedItems.toSet, Set("munit.MyTestSuite.testFoo")) } } diff --git a/tests/jvm/src/test/scala/munit/TimeoutSuite.scala b/tests/jvm/src/test/scala/munit/TimeoutSuite.scala index e82bf8de..61a87bb1 100644 --- a/tests/jvm/src/test/scala/munit/TimeoutSuite.scala +++ b/tests/jvm/src/test/scala/munit/TimeoutSuite.scala @@ -1,49 +1,23 @@ package munit -import scala.concurrent.duration.Duration -import scala.concurrent.Future +import scala.concurrent.ExecutionContext import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future +import scala.concurrent.duration.Duration import scala.concurrent.duration.FiniteDuration -import scala.concurrent.ExecutionContext class TimeoutSuite extends munit.FunSuite { override val munitTimeout: FiniteDuration = Duration(100, "ms") override def munitExecutionContext: ExecutionContext = global - test("fast-1") { - Future { - Thread.sleep(1) - } - } - test("slow".fail) { - Future { - Thread.sleep(1000) - } - } - test("fast-2") { - Future { - Thread.sleep(1) - } - } - test("infinite-loop".fail) { - Future { - ThrottleCpu.run() - } - } - test("fast-3") { - Future { - Thread.sleep(1) - } - } + test("fast-1")(Future(Thread.sleep(1))) + test("slow".fail)(Future(Thread.sleep(1000))) + test("fast-2")(Future(Thread.sleep(1))) + test("infinite-loop".fail)(Future(ThrottleCpu.run())) + test("fast-3")(Future(Thread.sleep(1))) // NOTE(olafurpg): The test below times out on CI but not on my local Macbook // test("slow-non-future".fail) { // ThrottleCpu.run() // } - test("slow-non-future-sleep".fail) { - Thread.sleep(1000) - } - test("fast-4") { - Future { - Thread.sleep(1) - } - } + test("slow-non-future-sleep".fail)(Thread.sleep(1000)) + test("fast-4")(Future(Thread.sleep(1))) } diff --git a/tests/shared/src/main/scala/munit/AssertionsFrameworkSuite.scala b/tests/shared/src/main/scala/munit/AssertionsFrameworkSuite.scala index 377e85be..16c170ee 100644 --- a/tests/shared/src/main/scala/munit/AssertionsFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/AssertionsFrameworkSuite.scala @@ -35,9 +35,9 @@ class AssertionsFrameworkSuite extends FunSuite { assertEquals[Any, Any](a.A(), b.A()) } - test("toString-has-different-whitespace") { + test("toString-has-different-whitespace")( assertEquals[Any, Any]("foo", "foo ") - } + ) } object AssertionsFrameworkSuite @@ -62,8 +62,8 @@ object AssertionsFrameworkSuite |-a.A() |+b.B() |==> failure munit.AssertionsFrameworkSuite.toString-has-different-whitespace - tests/shared/src/main/scala/munit/AssertionsFrameworkSuite.scala:39 values are not equal, even if their text representation only differs in leading/trailing whitespace and ANSI escape characters: foo - |38: test("toString-has-different-whitespace") { + |38: test("toString-has-different-whitespace")( |39: assertEquals[Any, Any]("foo", "foo ") - |40: } - |""".stripMargin + |40: ) + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/AsyncFixtureTeardownFrameworkSuite.scala b/tests/shared/src/main/scala/munit/AsyncFixtureTeardownFrameworkSuite.scala index b50a773c..9b363a9c 100644 --- a/tests/shared/src/main/scala/munit/AsyncFixtureTeardownFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/AsyncFixtureTeardownFrameworkSuite.scala @@ -3,24 +3,23 @@ package munit import scala.concurrent.Future class AsyncFixtureTeardownFrameworkSuite extends FunSuite { - @volatile var cleanedUp: Boolean = _ + @volatile + var cleanedUp: Boolean = _ val cleanupInTeardown: FunFixture[Unit] = FunFixture.async[Unit]( _ => { cleanedUp = false; Future.successful(()) }, - _ => { cleanedUp = true; Future.successful(()) } + _ => { cleanedUp = true; Future.successful(()) }, ) - override def afterAll(): Unit = { - assert(cleanedUp) - } + override def afterAll(): Unit = assert(cleanedUp) - cleanupInTeardown.test("calls teardown when test throws") { _ => + cleanupInTeardown.test("calls teardown when test throws")(_ => throw new Error("failure in test") - } + ) - cleanupInTeardown.test("calls teardown when test returns failed Future") { - _ => Future.failed(new Error("failure in test")) - } + cleanupInTeardown.test("calls teardown when test returns failed Future")(_ => + Future.failed(new Error("failure in test")) + ) } object AsyncFixtureTeardownFrameworkSuite @@ -28,5 +27,5 @@ object AsyncFixtureTeardownFrameworkSuite classOf[AsyncFixtureTeardownFrameworkSuite], """|==> failure munit.AsyncFixtureTeardownFrameworkSuite.calls teardown when test throws - failure in test |==> failure munit.AsyncFixtureTeardownFrameworkSuite.calls teardown when test returns failed Future - failure in test - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/AsyncFunFixtureFrameworkSuite.scala b/tests/shared/src/main/scala/munit/AsyncFunFixtureFrameworkSuite.scala index c401b2ee..994a4ec9 100644 --- a/tests/shared/src/main/scala/munit/AsyncFunFixtureFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/AsyncFunFixtureFrameworkSuite.scala @@ -5,48 +5,40 @@ import scala.concurrent.Future class AsyncFunFixtureFrameworkSuite extends FunSuite { val failingSetup: FunFixture[Unit] = FunFixture.async[Unit]( _ => Future.failed(new Error("failure in setup")), - _ => Future.successful(()) + _ => Future.successful(()), ) val failingTeardown: FunFixture[Unit] = FunFixture.async[Unit]( _ => Future.successful(()), - _ => Future.failed(new Error("failure in teardown")) + _ => Future.failed(new Error("failure in teardown")), ) - val unitFixture: FunFixture[Unit] = FunFixture.async[Unit]( - _ => Future.successful(()), - _ => Future.successful(()) - ) + val unitFixture: FunFixture[Unit] = FunFixture + .async[Unit](_ => Future.successful(()), _ => Future.successful(())) - failingSetup.test("fail when setup fails") { _ => + failingSetup.test("fail when setup fails")(_ => fail("failing setup did not fail the test") - } + ) - failingTeardown.test("fail when teardown fails") { _ => () } + failingTeardown.test("fail when teardown fails")(_ => ()) - failingTeardown.test("fail when test and teardown fail") { _ => - fail("failure in test") - } + failingTeardown + .test("fail when test and teardown fail")(_ => fail("failure in test")) - FunFixture - .map2(unitFixture, failingSetup) - .test("fail when mapped setup fails") { _ => - fail("failing setup did not fail the test") - } + FunFixture.map2(unitFixture, failingSetup).test("fail when mapped setup fails")( + _ => fail("failing setup did not fail the test") + ) - FunFixture - .map3(unitFixture, unitFixture, failingSetup) - .test("fail when even more nested mapped setup fails") { _ => + FunFixture.map3(unitFixture, unitFixture, failingSetup) + .test("fail when even more nested mapped setup fails")(_ => fail("failing setup did not fail the test") - } + ) - FunFixture - .map2(unitFixture, failingTeardown) - .test("fail when mapped teardown fails") { _ => () } + FunFixture.map2(unitFixture, failingTeardown) + .test("fail when mapped teardown fails")(_ => ()) - FunFixture - .map3(unitFixture, unitFixture, failingTeardown) - .test("fail when even more nested mapped teardown fails") { _ => () } + FunFixture.map3(unitFixture, unitFixture, failingTeardown) + .test("fail when even more nested mapped teardown fails")(_ => ()) } object AsyncFunFixtureFrameworkSuite @@ -54,13 +46,13 @@ object AsyncFunFixtureFrameworkSuite classOf[AsyncFunFixtureFrameworkSuite], """|==> failure munit.AsyncFunFixtureFrameworkSuite.fail when setup fails - failure in setup |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when teardown fails - failure in teardown - |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when test and teardown fail - tests/shared/src/main/scala/munit/AsyncFunFixtureFrameworkSuite.scala:28 failure in test - |27: failingTeardown.test("fail when test and teardown fail") { _ => - |28: fail("failure in test") - |29: } + |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when test and teardown fail - tests/shared/src/main/scala/munit/AsyncFunFixtureFrameworkSuite.scala:26 failure in test + |25: failingTeardown + |26: .test("fail when test and teardown fail")(_ => fail("failure in test")) + |27: |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when mapped setup fails - failure in setup |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when even more nested mapped setup fails - failure in setup |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when mapped teardown fails - failure in teardown |==> failure munit.AsyncFunFixtureFrameworkSuite.fail when even more nested mapped teardown fails - failure in teardown - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/BaseFrameworkSuite.scala b/tests/shared/src/main/scala/munit/BaseFrameworkSuite.scala index 76ac72e2..308a2301 100644 --- a/tests/shared/src/main/scala/munit/BaseFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/BaseFrameworkSuite.scala @@ -1,117 +1,85 @@ package munit -import java.io.ByteArrayOutputStream -import sbt.testing.TaskDef -import sbt.testing.EventHandler +import munit.diff.console.AnsiColors +import munit.internal.PlatformCompat + import sbt.testing.Event +import sbt.testing.EventHandler +import sbt.testing.Logger +import sbt.testing.TaskDef + +import java.io.ByteArrayOutputStream import java.io.PrintStream import java.nio.charset.StandardCharsets -import sbt.testing.Logger -import scala.util.control.NonFatal import java.util.regex.Pattern -import munit.diff.console.AnsiColors -import munit.internal.PlatformCompat + import scala.concurrent.Future +import scala.util.control.NonFatal abstract class BaseFrameworkSuite extends BaseSuite { val systemOut = System.out override def munitIgnore: Boolean = !BuildInfo.scalaVersion.startsWith("2.13") - def exceptionMessage(ex: Throwable): String = { + def exceptionMessage(ex: Throwable): String = if (ex.getMessage() == null) "null" - else { - ex.getMessage() - .replace( - BuildInfo.sourceDirectory.toString(), - "" - ) - .replace('\\', '/') - } - } + else ex.getMessage().replace(BuildInfo.sourceDirectory.toString(), "") + .replace('\\', '/') - def check(t: FrameworkTest): Unit = { - test(t.cls.getSimpleName().withTags(t.tags)) { - val baos = new ByteArrayOutputStream() - val out = new PrintStream(baos) - val logger = new Logger { - def ansiCodesSupported(): Boolean = false - def error(x: String): Unit = out.println(x) - def warn(x: String): Unit = out.println(x) - def info(x: String): Unit = out.println(x) - def debug(x: String): Unit = () // ignore debugging output - def trace(x: Throwable): Unit = out.println(x) - } - val framework = new Framework - val runner = framework.runner( - t.arguments ++ Array("+l"), // use sbt loggers - Array(), - PlatformCompat.getThisClassLoader - ) - val tasks = runner.tasks( - Array( - new TaskDef( - t.cls.getName(), - framework.munitFingerprint, - false, - Array() - ) - ) - ) - val events = new StringBuilder() - val eventHandler = new EventHandler { - def handle(event: Event): Unit = { - try { - events.append(t.onEvent(event)) - val status = event.status().toString().toLowerCase() - val name = event.fullyQualifiedName() - events - .append("==> ") - .append(status) - .append(" ") - .append(name) - if (event.throwable().isDefined()) { - events - .append(" - ") - .append(exceptionMessage(event.throwable().get())) - } - events.append("\n") - } catch { - case NonFatal(e) => - e.printStackTrace() - events.append(s"unexpected error: $e") - } - } - } - implicit val ec = munitExecutionContext - val elapsedTimePattern = Pattern.compile(" ? \\d+\\.\\d+s ?") - TestingConsole.out = out - TestingConsole.err = out - for { - _ <- tasks.foldLeft(Future.successful(())) { case (base, task) => - base.flatMap(_ => - PlatformCompat.executeAsync( - task, - eventHandler, - Array(logger) - ) - ) + def check(t: FrameworkTest): Unit = test(t.cls.getSimpleName().withTags(t.tags)) { + val baos = new ByteArrayOutputStream() + val out = new PrintStream(baos) + val logger = new Logger { + def ansiCodesSupported(): Boolean = false + def error(x: String): Unit = out.println(x) + def warn(x: String): Unit = out.println(x) + def info(x: String): Unit = out.println(x) + def debug(x: String): Unit = () // ignore debugging output + def trace(x: Throwable): Unit = out.println(x) + } + val framework = new Framework + val runner = framework.runner( + t.arguments ++ Array("+l"), // use sbt loggers + Array(), + PlatformCompat.getThisClassLoader, + ) + val tasks = runner.tasks(Array( + new TaskDef(t.cls.getName(), framework.munitFingerprint, false, Array()) + )) + val events = new StringBuilder() + val eventHandler = new EventHandler { + def handle(event: Event): Unit = + try { + events.append(t.onEvent(event)) + val status = event.status().toString().toLowerCase() + val name = event.fullyQualifiedName() + events.append("==> ").append(status).append(" ").append(name) + if (event.throwable().isDefined()) events.append(" - ") + .append(exceptionMessage(event.throwable().get())) + events.append("\n") + } catch { + case NonFatal(e) => + e.printStackTrace() + events.append(s"unexpected error: $e") } - } yield { - val stdout = - AnsiColors.filterAnsi(baos.toString(StandardCharsets.UTF_8.name())) - val obtained = AnsiColors.filterAnsi( - t.format match { - case SbtFormat => - events.toString().replace("\"\"\"", "'''") - case StdoutFormat => - elapsedTimePattern.matcher(stdout).replaceAll(" ") - } + } + implicit val ec = munitExecutionContext + val elapsedTimePattern = Pattern.compile(" ? \\d+\\.\\d+s ?") + TestingConsole.out = out + TestingConsole.err = out + for { + _ <- tasks.foldLeft(Future.successful(())) { case (base, task) => + base.flatMap(_ => + PlatformCompat.executeAsync(task, eventHandler, Array(logger)) ) - assertNoDiff( - obtained, - t.expected, - stdout - )(t.location) } - }(t.location) - } + } yield { + val stdout = AnsiColors + .filterAnsi(baos.toString(StandardCharsets.UTF_8.name())) + val obtained = AnsiColors.filterAnsi(t.format match { + case SbtFormat => events.toString().replace("\"\"\"", "'''") + case StdoutFormat => elapsedTimePattern.matcher(stdout) + .replaceAll(" ") + }) + assertNoDiff(obtained, t.expected, stdout)(t.location) + } + }(t.location) } diff --git a/tests/shared/src/main/scala/munit/BaseSuite.scala b/tests/shared/src/main/scala/munit/BaseSuite.scala index dddc0336..6f435860 100644 --- a/tests/shared/src/main/scala/munit/BaseSuite.scala +++ b/tests/shared/src/main/scala/munit/BaseSuite.scala @@ -4,30 +4,21 @@ import munit.internal.PlatformCompat class BaseSuite extends FunSuite { - def isDotty: Boolean = - !BuildInfo.scalaVersion.startsWith("2.") - def is213: Boolean = - BuildInfo.scalaVersion.startsWith("2.13") || isDotty + def isDotty: Boolean = !BuildInfo.scalaVersion.startsWith("2.") + def is213: Boolean = BuildInfo.scalaVersion.startsWith("2.13") || isDotty - override def munitTestTransforms: List[TestTransform] = - super.munitTestTransforms ++ List( - new TestTransform( - "BaseSuite", - { test => - if (test.tags(NoDotty) && isDotty) { - test.tag(Ignore) - } else if (test.tags(Only213) && !is213) { - test.tag(Ignore) - } else if (test.tags(OnlyJVM) && !PlatformCompat.isJVM) { - test.tag(Ignore) - } else if (test.tags(NoJVM) && PlatformCompat.isJVM) { - test.tag(Ignore) - } else if (test.tags(NoNative) && PlatformCompat.isNative) { - test.tag(Ignore) - } else { - test - } - } - ) + override def munitTestTransforms + : List[TestTransform] = super.munitTestTransforms ++ List( + new TestTransform( + "BaseSuite", + { test => + if (test.tags(NoDotty) && isDotty) test.tag(Ignore) + else if (test.tags(Only213) && !is213) test.tag(Ignore) + else if (test.tags(OnlyJVM) && !PlatformCompat.isJVM) test.tag(Ignore) + else if (test.tags(NoJVM) && PlatformCompat.isJVM) test.tag(Ignore) + else if (test.tags(NoNative) && PlatformCompat.isNative) test.tag(Ignore) + else test + }, ) + ) } diff --git a/tests/shared/src/main/scala/munit/BoxedFrameworkSuite.scala b/tests/shared/src/main/scala/munit/BoxedFrameworkSuite.scala index 59c98879..4d5ebf22 100644 --- a/tests/shared/src/main/scala/munit/BoxedFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/BoxedFrameworkSuite.scala @@ -10,7 +10,7 @@ class BoxedFrameworkSuite extends FunSuite { val values = Array( Outer(Seq(Inner(1), Inner(2), Inner(10))), Outer(Seq(Inner(1), Inner(2), Inner(10))), - Outer(Seq(Inner(1), Inner(2), Inner(10))) + Outer(Seq(Inner(1), Inner(2), Inner(10))), ) assert(values.exists(outer => outer.data.exists(inner => inner.value > 90))) } @@ -24,5 +24,5 @@ object BoxedFrameworkSuite |14: ) |15: assert(values.exists(outer => outer.data.exists(inner => inner.value > 90))) |16: } - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/CiOnlyFrameworkSuite.scala b/tests/shared/src/main/scala/munit/CiOnlyFrameworkSuite.scala index c89691c4..be0f78d5 100644 --- a/tests/shared/src/main/scala/munit/CiOnlyFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/CiOnlyFrameworkSuite.scala @@ -2,12 +2,8 @@ package munit class CiOnlyFrameworkSuite extends FunSuite { override def isCI: Boolean = true - test("only".only) { - println("pass") - } - test("boom") { - ??? - } + test("only".only)(println("pass")) + test("boom")(???) } object CiOnlyFrameworkSuite @@ -15,7 +11,7 @@ object CiOnlyFrameworkSuite classOf[CiOnlyFrameworkSuite], """|==> failure munit.CiOnlyFrameworkSuite.only - tests/shared/src/main/scala/munit/CiOnlyFrameworkSuite.scala:5 'Only' tag is not allowed when `isCI=true` |4: override def isCI: Boolean = true - |5: test("only".only) { - |6: println("pass") - |""".stripMargin + |5: test("only".only)(println("pass")) + |6: test("boom")(???) + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/CustomCompare.scala b/tests/shared/src/main/scala/munit/CustomCompare.scala index 0cd62cdd..2e254835 100644 --- a/tests/shared/src/main/scala/munit/CustomCompare.scala +++ b/tests/shared/src/main/scala/munit/CustomCompare.scala @@ -7,16 +7,12 @@ trait CustomCompare[A, B] { object CustomCompare { implicit val optionEquality: CustomCompare[Some[Int], Option[Int]] = new CustomCompare[Some[Int], Option[Int]] { - def isEqual(a: Some[Int], b: Option[Int]): Boolean = { - if (a.contains(42)) sys.error("boom") - else a == b - } + def isEqual(a: Some[Int], b: Option[Int]): Boolean = + if (a.contains(42)) sys.error("boom") else a == b } implicit def fromCustomEquality[A, B](implicit my: CustomCompare[A, B] - ): Compare[A, B] = { - new Compare[A, B] { - def isEqual(a: A, b: B) = my.isEqual(a, b) - } + ): Compare[A, B] = new Compare[A, B] { + def isEqual(a: A, b: B) = my.isEqual(a, b) } } diff --git a/tests/shared/src/main/scala/munit/DiffProductFrameworkSuite.scala b/tests/shared/src/main/scala/munit/DiffProductFrameworkSuite.scala index 676a9d5e..6265e4de 100644 --- a/tests/shared/src/main/scala/munit/DiffProductFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/DiffProductFrameworkSuite.scala @@ -34,5 +34,5 @@ object DiffProductFrameworkSuite | friends = List( |+ 1, | 2 - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala b/tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala index 05e86b91..3ce286f8 100644 --- a/tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala @@ -1,10 +1,7 @@ package munit class DuplicateNameFrameworkSuite extends FunSuite { - def check(name: String)(body: () => Any): Unit = - test(name) { - body() - } + def check(name: String)(body: () => Any): Unit = test(name)(body()) check("a")(() => ()) check("a")(() => fail("boom")) check("a")(() => fail("boom")) @@ -18,16 +15,16 @@ object DuplicateNameFrameworkSuite extends FrameworkTest( classOf[DuplicateNameFrameworkSuite], """|==> success munit.DuplicateNameFrameworkSuite.a - |==> failure munit.DuplicateNameFrameworkSuite.a-1 - tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala:9 boom - |8: check("a")(() => ()) - |9: check("a")(() => fail("boom")) - |10: check("a")(() => fail("boom")) - |==> failure munit.DuplicateNameFrameworkSuite.a-2 - tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala:10 boom - |9: check("a")(() => fail("boom")) - |10: check("a")(() => fail("boom")) - |11: check("a")(() => ()) + |==> failure munit.DuplicateNameFrameworkSuite.a-1 - tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala:6 boom + |5: check("a")(() => ()) + |6: check("a")(() => fail("boom")) + |7: check("a")(() => fail("boom")) + |==> failure munit.DuplicateNameFrameworkSuite.a-2 - tests/shared/src/main/scala/munit/DuplicateNameFrameworkSuite.scala:7 boom + |6: check("a")(() => fail("boom")) + |7: check("a")(() => fail("boom")) + |8: check("a")(() => ()) |==> success munit.DuplicateNameFrameworkSuite.a-3 |==> success munit.DuplicateNameFrameworkSuite.POST -> /[type]/[id] |==> success munit.DuplicateNameFrameworkSuite.POST -> /[type]/[id]-1 - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/FailFrameworkSuite.scala b/tests/shared/src/main/scala/munit/FailFrameworkSuite.scala index 9da75914..2723c107 100644 --- a/tests/shared/src/main/scala/munit/FailFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/FailFrameworkSuite.scala @@ -4,9 +4,7 @@ class FailFrameworkSuite extends FunSuite { test("pass".fail) { // println("pass") } - test("fail".fail) { - ??? - } + test("fail".fail)(???) } object FailFrameworkSuite @@ -17,5 +15,5 @@ object FailFrameworkSuite |4: test("pass".fail) { |5: // println("pass") |==> success munit.FailFrameworkSuite.fail - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/FailSuiteFrameworkSuite.scala b/tests/shared/src/main/scala/munit/FailSuiteFrameworkSuite.scala index bcaec610..934e631b 100644 --- a/tests/shared/src/main/scala/munit/FailSuiteFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/FailSuiteFrameworkSuite.scala @@ -4,9 +4,7 @@ class FailSuiteFrameworkSuite extends FunSuite { test("pass") { // println("pass") } - test("fail") { - failSuite("Oops, can not do anything.") - } + test("fail")(failSuite("Oops, can not do anything.")) test(name = "not gonna run") { // println("not pass") } @@ -16,10 +14,10 @@ object FailSuiteFrameworkSuite extends FrameworkTest( classOf[FailSuiteFrameworkSuite], """|==> success munit.FailSuiteFrameworkSuite.pass - |==> failure munit.FailSuiteFrameworkSuite.fail - tests/shared/src/main/scala/munit/FailSuiteFrameworkSuite.scala:8 Oops, can not do anything. - |7: test("fail") { - |8: failSuite("Oops, can not do anything.") - |9: } + |==> failure munit.FailSuiteFrameworkSuite.fail - tests/shared/src/main/scala/munit/FailSuiteFrameworkSuite.scala:7 Oops, can not do anything. + |6: } + |7: test("fail")(failSuite("Oops, can not do anything.")) + |8: test(name = "not gonna run") { |==> skipped munit.FailSuiteFrameworkSuite.not gonna run - Suite has been aborted - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/FixtureOrderFrameworkSuite.scala b/tests/shared/src/main/scala/munit/FixtureOrderFrameworkSuite.scala index 2f1d3465..43f1a66c 100644 --- a/tests/shared/src/main/scala/munit/FixtureOrderFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/FixtureOrderFrameworkSuite.scala @@ -4,42 +4,24 @@ class FixtureOrderFrameworkSuite extends FunSuite { def println(msg: String): Unit = TestingConsole.out.println(msg) private def fixture(name: String) = new Fixture[Int](name) { def apply(): Int = 1 - override def beforeAll(): Unit = { - println(s"beforeAll($name)") - } - override def beforeEach(context: BeforeEach): Unit = { + override def beforeAll(): Unit = println(s"beforeAll($name)") + override def beforeEach(context: BeforeEach): Unit = println(s"beforeEach($name, ${context.test.name})") - } - override def afterEach(context: AfterEach): Unit = { + override def afterEach(context: AfterEach): Unit = println(s"afterEach($name, ${context.test.name})") - } - override def afterAll(): Unit = { - println(s"afterAll($name)") - } + override def afterAll(): Unit = println(s"afterAll($name)") } private val a = fixture("a") private val b = fixture("b") private val adhoc = fixture("ad-hoc") override val munitFixtures: List[Fixture[Int]] = List(a, b) - override def beforeAll(): Unit = { - adhoc.beforeAll() - } - override def beforeEach(context: BeforeEach): Unit = { - adhoc.beforeEach(context) - } - override def afterEach(context: AfterEach): Unit = { - adhoc.afterEach(context) - } - override def afterAll(): Unit = { - adhoc.afterAll() - } + override def beforeAll(): Unit = adhoc.beforeAll() + override def beforeEach(context: BeforeEach): Unit = adhoc.beforeEach(context) + override def afterEach(context: AfterEach): Unit = adhoc.afterEach(context) + override def afterAll(): Unit = adhoc.afterAll() - 1.to(3).foreach { i => - test(i.toString()) { - println(s"test($i)") - } - } + 1.to(3).foreach(i => test(i.toString())(println(s"test($i)"))) } object FixtureOrderFrameworkSuite @@ -77,5 +59,5 @@ object FixtureOrderFrameworkSuite |afterAll(b) |afterAll(ad-hoc) |""".stripMargin, - format = StdoutFormat + format = StdoutFormat, ) diff --git a/tests/shared/src/main/scala/munit/FrameworkTest.scala b/tests/shared/src/main/scala/munit/FrameworkTest.scala index 2c6084f4..f1dc1ece 100644 --- a/tests/shared/src/main/scala/munit/FrameworkTest.scala +++ b/tests/shared/src/main/scala/munit/FrameworkTest.scala @@ -9,7 +9,7 @@ class FrameworkTest( val tags: Set[Tag] = Set.empty, val format: FrameworkTestFormat = SbtFormat, val arguments: Array[String] = Array(), - val onEvent: Event => String = _ => "" + val onEvent: Event => String = _ => "", )(implicit val location: Location) sealed abstract class FrameworkTestFormat diff --git a/tests/shared/src/main/scala/munit/InterceptFrameworkSuite.scala b/tests/shared/src/main/scala/munit/InterceptFrameworkSuite.scala index 1d10a97f..3588acf0 100644 --- a/tests/shared/src/main/scala/munit/InterceptFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/InterceptFrameworkSuite.scala @@ -2,15 +2,11 @@ package munit class InterceptException extends Exception("Foo") class InterceptFrameworkSuite extends FunSuite { - test("not-implemented") { - intercept[NotImplementedError](???) - } - test("type-mismatch") { - intercept[InterceptException](???) - } - test("intercept-message-match") { - interceptMessage[NotImplementedError]("boom") { ??? } - } + test("not-implemented")(intercept[NotImplementedError](???)) + test("type-mismatch")(intercept[InterceptException](???)) + test("intercept-message-match")( + interceptMessage[NotImplementedError]("boom")(???) + ) } object InterceptFrameworkSuite @@ -19,5 +15,5 @@ object InterceptFrameworkSuite """|==> success munit.InterceptFrameworkSuite.not-implemented |==> failure munit.InterceptFrameworkSuite.type-mismatch - intercept failed, exception 'scala.NotImplementedError' is not a subtype of 'munit.InterceptException |==> failure munit.InterceptFrameworkSuite.intercept-message-match - intercept failed, exception 'scala.NotImplementedError' had message 'an implementation is missing', which was different from expected message 'boom' - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/Issue179FrameworkSuite.scala b/tests/shared/src/main/scala/munit/Issue179FrameworkSuite.scala index 1576bdc9..f67e3862 100644 --- a/tests/shared/src/main/scala/munit/Issue179FrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/Issue179FrameworkSuite.scala @@ -1,18 +1,16 @@ package munit class Issue179FrameworkSuite extends FunSuite { - test("issue-179") { - assertNoDiff("\n", "A\n") - } + test("issue-179")(assertNoDiff("\n", "A\n")) } object Issue179FrameworkSuite extends FrameworkTest( classOf[Issue179FrameworkSuite], - """|==> failure munit.Issue179FrameworkSuite.issue-179 - tests/shared/src/main/scala/munit/Issue179FrameworkSuite.scala:5 - |4: test("issue-179") { - |5: assertNoDiff("/n", "A/n") - |6: } + """|==> failure munit.Issue179FrameworkSuite.issue-179 - tests/shared/src/main/scala/munit/Issue179FrameworkSuite.scala:4 + |3:class Issue179FrameworkSuite extends FunSuite { + |4: test("issue-179")(assertNoDiff("/n", "A/n")) + |5:} |diff assertion failed |=> Obtained | '''| @@ -20,5 +18,5 @@ object Issue179FrameworkSuite |=> Diff (- obtained, + expected) |- |+A - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/Issue285FrameworkSuite.scala b/tests/shared/src/main/scala/munit/Issue285FrameworkSuite.scala index bdb30490..b3e61ffe 100644 --- a/tests/shared/src/main/scala/munit/Issue285FrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/Issue285FrameworkSuite.scala @@ -1,41 +1,30 @@ package munit -import scala.concurrent.duration.Duration import munit.internal.PlatformCompat + import scala.concurrent.Promise +import scala.concurrent.duration.Duration class Issue285FrameworkSuite extends FunSuite { def println(msg: String): Unit = TestingConsole.out.println(msg) val hello: Fixture[Unit] = new Fixture[Unit]("hello") { def apply(): Unit = () - override def beforeAll(): Unit = { - println("beforeAll") - } - override def beforeEach(context: BeforeEach): Unit = { + override def beforeAll(): Unit = println("beforeAll") + override def beforeEach(context: BeforeEach): Unit = println("beforeEach - " + context.test.name) - } - override def afterEach(context: AfterEach): Unit = { + override def afterEach(context: AfterEach): Unit = println("afterEach - " + context.test.name) - } - override def afterAll(): Unit = { - println("afterAll") - } + override def afterAll(): Unit = println("afterAll") } override def munitFixtures: List[Fixture[Unit]] = List(hello) override def munitTimeout: Duration = Duration(5, "ms") - test("issue-285-ok") { - () - } + test("issue-285-ok")(()) test("issue-285-fail") { val promise = Promise[Unit]() - PlatformCompat.setTimeout(40) { - promise.trySuccess(()) - } + PlatformCompat.setTimeout(40)(promise.trySuccess(())) promise.future } - test("issue-285-ok") { - () - } + test("issue-285-ok")(()) } object Issue285FrameworkSuite @@ -54,5 +43,5 @@ object Issue285FrameworkSuite | + issue-285-ok-1 |afterAll |""".stripMargin, - format = StdoutFormat + format = StdoutFormat, ) diff --git a/tests/shared/src/main/scala/munit/Issue497FrameworkSuite.scala b/tests/shared/src/main/scala/munit/Issue497FrameworkSuite.scala index 483a8810..8a087c06 100644 --- a/tests/shared/src/main/scala/munit/Issue497FrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/Issue497FrameworkSuite.scala @@ -10,13 +10,9 @@ class Issue497FrameworkSuite extends FunSuite { val myFixture: Fixture[Unit] = new Fixture[Unit]("myFixture") { def apply(): Unit = println("### myFixture apply() ###") - override def beforeAll(): Unit = { - println("### beforeAll is running ###") - } + override def beforeAll(): Unit = println("### beforeAll is running ###") - override def afterAll(): Unit = { - println("### afterAll is running ###") - } + override def afterAll(): Unit = println("### afterAll is running ###") } override def munitFixtures: List[Fixture[Unit]] = List(myFixture) @@ -36,8 +32,6 @@ object Issue497FrameworkSuite classOf[Issue497FrameworkSuite], "", arguments = Array("--exclude-categories=munit.Slow"), - tags = Set( - OnlyJVM - ), - format = StdoutFormat + tags = Set(OnlyJVM), + format = StdoutFormat, ) diff --git a/tests/shared/src/main/scala/munit/Issue583FrameworkSuite.scala b/tests/shared/src/main/scala/munit/Issue583FrameworkSuite.scala index 1fbc3085..7b1ffcdb 100644 --- a/tests/shared/src/main/scala/munit/Issue583FrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/Issue583FrameworkSuite.scala @@ -1,17 +1,13 @@ package munit class Issue583FrameworkSuite extends FunSuite { - test("simple test") { - () - } + test("simple test")(()) test("infinite loop test") { def loop(x: Int): Int = loop(x) + loop(x) loop(0) } - test("another test") { - () - } + test("another test")(()) } object Issue583FrameworkSuite @@ -21,5 +17,5 @@ object Issue583FrameworkSuite |==> failure munit.Issue583FrameworkSuite.infinite loop test - null |==> success munit.Issue583FrameworkSuite.another test |""".stripMargin, - tags = Set(OnlyJVM) + tags = Set(OnlyJVM), ) diff --git a/tests/shared/src/main/scala/munit/ScalaVersionFrameworkSuite.scala b/tests/shared/src/main/scala/munit/ScalaVersionFrameworkSuite.scala index f48f1b91..07d65bf9 100644 --- a/tests/shared/src/main/scala/munit/ScalaVersionFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/ScalaVersionFrameworkSuite.scala @@ -4,23 +4,17 @@ class ScalaVersionFrameworkSuite extends munit.FunSuite { val scalaVersion = "2.12.100" override def munitTestTransforms: List[TestTransform] = - super.munitTestTransforms ++ List( - new TestTransform( - "append scala version", - { test => - test.withName(test.name + "-" + scalaVersion) - } - ) - ) + super.munitTestTransforms ++ List(new TestTransform( + "append scala version", + { test => test.withName(test.name + "-" + scalaVersion) }, + )) - test("foo") { - assertEquals(List(1).head, 1) - } + test("foo")(assertEquals(List(1).head, 1)) } object ScalaVersionFrameworkSuite extends FrameworkTest( classOf[ScalaVersionFrameworkSuite], """|==> success munit.ScalaVersionFrameworkSuite.foo-2.12.100 - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala b/tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala index b98bfd57..35d43038 100644 --- a/tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala @@ -6,46 +6,26 @@ class SkippedFrameworkSuite extends FunSuite { test("pass") { // println("pass") } - test("ignore".ignore) { - ??? - } - test("ignore.failed.pending".ignore.pending) { - assert(false) - } - test("ignore.failed.pending.comment".ignore.pending("comment")) { - assert(false) - } - test("assume(true)") { + test("ignore".ignore)(???) + test("ignore.failed.pending".ignore.pending)(assert(false)) + test("ignore.failed.pending.comment".ignore.pending("comment"))(assert(false)) + test("assume(true)")( assume(true, "assume it passes") // println("pass") - } - test("assume(false)") { - assume(false, "assume it fails") - } + ) + test("assume(false)")(assume(false, "assume it fails")) test("pending.empty.ignored".pending) { // } test("pending.empty.ignored.comment".pending("comment")) { // } - test("pending.successful.ignored".pending) { - assert(true) - } - test("pending.successful.ignored.comment".pending("comment")) { - assert(true) - } - test("pending.failed.not-ignored".pending) { - assert(false) - } - test("pending.failed.not-ignored.comment".pending("comment")) { - assert(false) - } - test("pending.failed.ignored".pending.ignore) { - assert(false) - } - test("pending.failed.ignored.comment".pending("comment").ignore) { - assert(false) - } + test("pending.successful.ignored".pending)(assert(true)) + test("pending.successful.ignored.comment".pending("comment"))(assert(true)) + test("pending.failed.not-ignored".pending)(assert(false)) + test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + test("pending.failed.ignored".pending.ignore)(assert(false)) + test("pending.failed.ignored.comment".pending("comment").ignore)(assert(false)) } object SkippedFrameworkSuite @@ -61,18 +41,18 @@ object SkippedFrameworkSuite |==> ignored munit.SkippedFrameworkSuite.pending.empty.ignored.comment |==> ignored munit.SkippedFrameworkSuite.pending.successful.ignored |==> ignored munit.SkippedFrameworkSuite.pending.successful.ignored.comment - |==> failure munit.SkippedFrameworkSuite.pending.failed.not-ignored - tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:38 assertion failed - |37: test("pending.failed.not-ignored".pending) { - |38: assert(false) - |39: } - |==> failure munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment - tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:41 assertion failed - |40: test("pending.failed.not-ignored.comment".pending("comment")) { - |41: assert(false) - |42: } + |==> failure munit.SkippedFrameworkSuite.pending.failed.not-ignored - tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:25 assertion failed + |24: test("pending.successful.ignored.comment".pending("comment"))(assert(true)) + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |==> failure munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment - tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:26 assertion failed + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |27: test("pending.failed.ignored".pending.ignore)(assert(false)) |==> ignored munit.SkippedFrameworkSuite.pending.failed.ignored |==> ignored munit.SkippedFrameworkSuite.pending.failed.ignored.comment |""".stripMargin, - format = SbtFormat + format = SbtFormat, ) object SkippedFrameworkStdoutJsNativeSuite @@ -89,19 +69,19 @@ object SkippedFrameworkStdoutJsNativeSuite |==> i pending.empty.ignored.comment PENDING comment ignored |==> i pending.successful.ignored PENDING ignored |==> i pending.successful.ignored.comment PENDING comment ignored - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:38 assertion failed - |37: test("pending.failed.not-ignored".pending) { - |38: assert(false) - |39: } - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:41 assertion failed - |40: test("pending.failed.not-ignored.comment".pending("comment")) { - |41: assert(false) - |42: } + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:25 assertion failed + |24: test("pending.successful.ignored.comment".pending("comment"))(assert(true)) + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:26 assertion failed + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |27: test("pending.failed.ignored".pending.ignore)(assert(false)) |==> i pending.failed.ignored PENDING ignored |==> i pending.failed.ignored.comment PENDING comment ignored |""".stripMargin.replace('/', File.separatorChar), format = StdoutFormat, - tags = Set(NoJVM) + tags = Set(NoJVM), ) object SkippedFrameworkStdoutJsNativeVerboseSuite @@ -126,21 +106,21 @@ object SkippedFrameworkStdoutJsNativeVerboseSuite |pending.successful.ignored.comment started |==> i pending.successful.ignored.comment PENDING comment ignored |pending.failed.not-ignored started - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:38 assertion failed - |37: test("pending.failed.not-ignored".pending) { - |38: assert(false) - |39: } + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:25 assertion failed + |24: test("pending.successful.ignored.comment".pending("comment"))(assert(true)) + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) |pending.failed.not-ignored.comment started - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:41 assertion failed - |40: test("pending.failed.not-ignored.comment".pending("comment")) { - |41: assert(false) - |42: } + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:26 assertion failed + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |27: test("pending.failed.ignored".pending.ignore)(assert(false)) |==> i pending.failed.ignored PENDING ignored |==> i pending.failed.ignored.comment PENDING comment ignored |""".stripMargin.replace('/', File.separatorChar), format = StdoutFormat, tags = Set(NoJVM), - arguments = Array("-v") + arguments = Array("-v"), ) object SkippedFrameworkStdoutJVMSuite @@ -157,23 +137,23 @@ object SkippedFrameworkStdoutJVMSuite |==> i munit.SkippedFrameworkSuite.pending.empty.ignored.comment PENDING comment ignored |==> i munit.SkippedFrameworkSuite.pending.successful.ignored PENDING ignored |==> i munit.SkippedFrameworkSuite.pending.successful.ignored.comment PENDING comment ignored - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:38 assertion failed - |37: test("pending.failed.not-ignored".pending) { - |38: assert(false) - |39: } - | at munit.FunSuite.assert(FunSuite.scala:11) - | at munit.SkippedFrameworkSuite.$anonfun$new$21(SkippedFrameworkSuite.scala:38) - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:41 assertion failed - |40: test("pending.failed.not-ignored.comment".pending("comment")) { - |41: assert(false) - |42: } - | at munit.FunSuite.assert(FunSuite.scala:11) - | at munit.SkippedFrameworkSuite.$anonfun$new$24(SkippedFrameworkSuite.scala:41) + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:25 assertion failed + |24: test("pending.successful.ignored.comment".pending("comment"))(assert(true)) + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + | at munit.FunSuite.assert(FunSuite.scala:13) + | at munit.SkippedFrameworkSuite.$anonfun$new$21(SkippedFrameworkSuite.scala:25) + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:26 assertion failed + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |27: test("pending.failed.ignored".pending.ignore)(assert(false)) + | at munit.FunSuite.assert(FunSuite.scala:13) + | at munit.SkippedFrameworkSuite.$anonfun$new$24(SkippedFrameworkSuite.scala:26) |==> i munit.SkippedFrameworkSuite.pending.failed.ignored PENDING ignored |==> i munit.SkippedFrameworkSuite.pending.failed.ignored.comment PENDING comment ignored |""".stripMargin.replace('/', File.separatorChar), format = StdoutFormat, - tags = Set(OnlyJVM) + tags = Set(OnlyJVM), ) object SkippedFrameworkStdoutJVMVerboseSuite @@ -199,24 +179,24 @@ object SkippedFrameworkStdoutJVMVerboseSuite |munit.SkippedFrameworkSuite.pending.successful.ignored.comment started |==> i munit.SkippedFrameworkSuite.pending.successful.ignored.comment PENDING comment ignored |munit.SkippedFrameworkSuite.pending.failed.not-ignored started - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:38 assertion failed - |37: test("pending.failed.not-ignored".pending) { - |38: assert(false) - |39: } - | at munit.FunSuite.assert(FunSuite.scala:11) - | at munit.SkippedFrameworkSuite.$anonfun$new$21(SkippedFrameworkSuite.scala:38) + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:25 assertion failed + |24: test("pending.successful.ignored.comment".pending("comment"))(assert(true)) + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + | at munit.FunSuite.assert(FunSuite.scala:13) + | at munit.SkippedFrameworkSuite.$anonfun$new$21(SkippedFrameworkSuite.scala:25) |munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment started - |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:41 assertion failed - |40: test("pending.failed.not-ignored.comment".pending("comment")) { - |41: assert(false) - |42: } - | at munit.FunSuite.assert(FunSuite.scala:11) - | at munit.SkippedFrameworkSuite.$anonfun$new$24(SkippedFrameworkSuite.scala:41) + |==> X munit.SkippedFrameworkSuite.pending.failed.not-ignored.comment munit.FailException: tests/shared/src/main/scala/munit/SkippedFrameworkSuite.scala:26 assertion failed + |25: test("pending.failed.not-ignored".pending)(assert(false)) + |26: test("pending.failed.not-ignored.comment".pending("comment"))(assert(false)) + |27: test("pending.failed.ignored".pending.ignore)(assert(false)) + | at munit.FunSuite.assert(FunSuite.scala:13) + | at munit.SkippedFrameworkSuite.$anonfun$new$24(SkippedFrameworkSuite.scala:26) |==> i munit.SkippedFrameworkSuite.pending.failed.ignored PENDING ignored |==> i munit.SkippedFrameworkSuite.pending.failed.ignored.comment PENDING comment ignored |Test run munit.SkippedFrameworkSuite finished: 2 failed, 9 ignored, 9 total, |""".stripMargin.replace('/', File.separatorChar), format = StdoutFormat, tags = Set(OnlyJVM), - arguments = Array("-v") + arguments = Array("-v"), ) diff --git a/tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala b/tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala index 8ba7522e..44c6e4e6 100644 --- a/tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala @@ -1,9 +1,7 @@ package munit class StackTraceFrameworkSuite extends FunSuite { - test("fail") { - assertNoDiff("a", "b") - } + test("fail")(assertNoDiff("a", "b")) } class BaseStackTraceFrameworkSuite(arguments: Array[String], expected: String) @@ -15,13 +13,10 @@ class BaseStackTraceFrameworkSuite(arguments: Array[String], expected: String) onEvent = { event => if (event.throwable().isDefined()) { val s = event.throwable().get().getStackTrace() - s.take(4) - .map(e => s" at ${e.getClassName()}:${e.getMethodName()}") + s.take(4).map(e => s" at ${e.getClassName()}:${e.getMethodName()}") .mkString("", "\n", "\n") - } else { - "" - } - } + } else "" + }, ) object FullStackTraceFrameworkSuite @@ -31,17 +26,17 @@ object FullStackTraceFrameworkSuite | at munit.Assertions:failComparison$ | at munit.FunSuite:failComparison | at munit.Assertions$$anon$1:handle - |==> failure munit.StackTraceFrameworkSuite.fail - tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala:5 - |4: test("fail") { - |5: assertNoDiff("a", "b") - |6: } + |==> failure munit.StackTraceFrameworkSuite.fail - tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala:4 + |3:class StackTraceFrameworkSuite extends FunSuite { + |4: test("fail")(assertNoDiff("a", "b")) + |5:} |diff assertion failed |=> Obtained |"a" |=> Diff (- obtained, + expected) |-a |+b - |""".stripMargin + |""".stripMargin, ) object SmallStackTraceFrameworkSuite @@ -50,15 +45,15 @@ object SmallStackTraceFrameworkSuite """|at munit.FunSuite:assertNoDiff | at munit.StackTraceFrameworkSuite:$anonfun$new$1 | at scala.runtime.java8.JFunction0$mcV$sp:apply - |==> failure munit.StackTraceFrameworkSuite.fail - tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala:5 - |4: test("fail") { - |5: assertNoDiff("a", "b") - |6: } + |==> failure munit.StackTraceFrameworkSuite.fail - tests/shared/src/main/scala/munit/StackTraceFrameworkSuite.scala:4 + |3:class StackTraceFrameworkSuite extends FunSuite { + |4: test("fail")(assertNoDiff("a", "b")) + |5:} |diff assertion failed |=> Obtained |"a" |=> Diff (- obtained, + expected) |-a |+b - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/SuiteTransformCrashFrameworkSuite.scala b/tests/shared/src/main/scala/munit/SuiteTransformCrashFrameworkSuite.scala index d25baec1..8d30189d 100644 --- a/tests/shared/src/main/scala/munit/SuiteTransformCrashFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/SuiteTransformCrashFrameworkSuite.scala @@ -1,9 +1,8 @@ package munit class SuiteTransformCrashFrameworkSuite extends munit.FunSuite { - override val munitSuiteTransforms: List[SuiteTransform] = List( - new SuiteTransform("boom", tests => ???) - ) + override val munitSuiteTransforms: List[SuiteTransform] = + List(new SuiteTransform("boom", tests => ???)) test("hello") {} } @@ -11,5 +10,5 @@ object SuiteTransformCrashFrameworkSuite extends FrameworkTest( classOf[SuiteTransformCrashFrameworkSuite], """|==> failure munit.SuiteTransformCrashFrameworkSuite.munitSuiteTransform - an implementation is missing - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/SuiteTransformFrameworkSuite.scala b/tests/shared/src/main/scala/munit/SuiteTransformFrameworkSuite.scala index a7102d0b..e19adce9 100644 --- a/tests/shared/src/main/scala/munit/SuiteTransformFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/SuiteTransformFrameworkSuite.scala @@ -2,10 +2,7 @@ package munit class SuiteTransformFrameworkSuite extends munit.FunSuite { override val munitSuiteTransforms: List[SuiteTransform] = List( - new SuiteTransform( - "hello", - tests => tests.filter(_.name.startsWith("hello")) - ) + new SuiteTransform("hello", tests => tests.filter(_.name.startsWith("hello"))) ) test("hello") {} @@ -18,5 +15,5 @@ object SuiteTransformFrameworkSuite classOf[SuiteTransformFrameworkSuite], """|==> success munit.SuiteTransformFrameworkSuite.hello |==> success munit.SuiteTransformFrameworkSuite.hello-yes - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/SwallowedExceptionSuite.scala b/tests/shared/src/main/scala/munit/SwallowedExceptionSuite.scala index 5428270a..eaf408d2 100644 --- a/tests/shared/src/main/scala/munit/SwallowedExceptionSuite.scala +++ b/tests/shared/src/main/scala/munit/SwallowedExceptionSuite.scala @@ -3,17 +3,11 @@ package munit import scala.util.control.NoStackTrace class SwallowedExceptionSuite extends FunSuite { - test("issue-51") { - throw new Exception("i am not reported") with NoStackTrace - } + test("issue-51")(throw new Exception("i am not reported") with NoStackTrace) - test("issue-650") { - throw new IllegalAccessError("i am reported") - } + test("issue-650")(throw new IllegalAccessError("i am reported")) - test("should not be executed") { - assertEquals(1, 1) - } + test("should not be executed")(assertEquals(1, 1)) } object SwallowedExceptionSuite extends FrameworkTest( @@ -21,5 +15,5 @@ object SwallowedExceptionSuite """|==> failure munit.SwallowedExceptionSuite.issue-51 - i am not reported |==> failure munit.SwallowedExceptionSuite.issue-650 - i am reported |==> skipped munit.SwallowedExceptionSuite.should not be executed - Suite has been aborted - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/TagsFrameworkSuite.scala b/tests/shared/src/main/scala/munit/TagsFrameworkSuite.scala index 7ecc54bf..cabd2ebc 100644 --- a/tests/shared/src/main/scala/munit/TagsFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/TagsFrameworkSuite.scala @@ -14,7 +14,7 @@ object TagsIncludeFramweworkSuite """|==> success munit.TagsFrameworkSuite.a |==> success munit.TagsFrameworkSuite.c |""".stripMargin, - arguments = Array("--include-tags=include") + arguments = Array("--include-tags=include"), ) object TagsIncludeExcludeFramweworkSuite @@ -22,7 +22,7 @@ object TagsIncludeExcludeFramweworkSuite classOf[TagsFrameworkSuite], """|==> success munit.TagsFrameworkSuite.a |""".stripMargin, - arguments = Array("--include-tags=include", "--exclude-tags=exclude") + arguments = Array("--include-tags=include", "--exclude-tags=exclude"), ) object TagsExcludeFramweworkSuite @@ -31,5 +31,5 @@ object TagsExcludeFramweworkSuite """|==> success munit.TagsFrameworkSuite.a |==> success munit.TagsFrameworkSuite.d |""".stripMargin, - arguments = Array("--exclude-tags=exclude") + arguments = Array("--exclude-tags=exclude"), ) diff --git a/tests/shared/src/main/scala/munit/TestNameFrameworkSuite.scala b/tests/shared/src/main/scala/munit/TestNameFrameworkSuite.scala index 931e83eb..8f6b1b18 100644 --- a/tests/shared/src/main/scala/munit/TestNameFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/TestNameFrameworkSuite.scala @@ -26,5 +26,5 @@ object TestNameFrameworkSuite |==> success munit.TestNameFrameworkSuite.substitute\\u001az |==> success munit.TestNameFrameworkSuite.emoji😆 |==> success munit.TestNameFrameworkSuite.red\\u001b[31m - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/TestTransformCrashFrameworkSuite.scala b/tests/shared/src/main/scala/munit/TestTransformCrashFrameworkSuite.scala index 52b7b3f5..fa6819f9 100644 --- a/tests/shared/src/main/scala/munit/TestTransformCrashFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/TestTransformCrashFrameworkSuite.scala @@ -1,9 +1,8 @@ package munit class TestTransformCrashFrameworkSuite extends munit.FunSuite { - override val munitTestTransforms: List[TestTransform] = List( - new TestTransform("boom", test => ???) - ) + override val munitTestTransforms: List[TestTransform] = + List(new TestTransform("boom", test => ???)) test("hello") {} } @@ -11,5 +10,5 @@ object TestTransformCrashFrameworkSuite extends FrameworkTest( classOf[TestTransformCrashFrameworkSuite], """|==> failure munit.TestTransformCrashFrameworkSuite.hello - an implementation is missing - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala b/tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala index e920a265..57e4be21 100644 --- a/tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala @@ -5,37 +5,33 @@ class TestTransformFrameworkSuite extends munit.FunSuite { new TestTransform( "ok", test => - if (test.name == "hello") test.withName(test.name + "-ok") else test + if (test.name == "hello") test.withName(test.name + "-ok") else test, ), munitAppendToFailureMessage(t => if (t.name.startsWith("suffix")) Some("==> extra info") else None - ) + ), ) test("hello") {} test("suffix-success") {} - test("suffix-fail") { - fail("boom") - } - test("suffix-assertEquals") { - assertEquals(0, 1) - } + test("suffix-fail")(fail("boom")) + test("suffix-assertEquals")(assertEquals(0, 1)) } object TestTransformFrameworkSuite extends FrameworkTest( classOf[TestTransformFrameworkSuite], """|==> success munit.TestTransformFrameworkSuite.hello-ok |==> success munit.TestTransformFrameworkSuite.suffix-success - |==> failure munit.TestTransformFrameworkSuite.suffix-fail - tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala:19 boom - |18: test("suffix-fail") { - |19: fail("boom") - |20: } + |==> failure munit.TestTransformFrameworkSuite.suffix-fail - tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala:18 boom + |17: test("suffix-success") {} + |18: test("suffix-fail")(fail("boom")) + |19: test("suffix-assertEquals")(assertEquals(0, 1)) |==> extra info - |==> failure munit.TestTransformFrameworkSuite.suffix-assertEquals - tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala:22 - |21: test("suffix-assertEquals") { - |22: assertEquals(0, 1) - |23: } + |==> failure munit.TestTransformFrameworkSuite.suffix-assertEquals - tests/shared/src/main/scala/munit/TestTransformFrameworkSuite.scala:19 + |18: test("suffix-fail")(fail("boom")) + |19: test("suffix-assertEquals")(assertEquals(0, 1)) + |20:} |values are not the same |=> Obtained |0 @@ -43,5 +39,5 @@ object TestTransformFrameworkSuite |-0 |+1 |==> extra info - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/ValueTransformCrashFrameworkSuite.scala b/tests/shared/src/main/scala/munit/ValueTransformCrashFrameworkSuite.scala index 8d6f89c7..c2de11ef 100644 --- a/tests/shared/src/main/scala/munit/ValueTransformCrashFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/ValueTransformCrashFrameworkSuite.scala @@ -1,17 +1,14 @@ package munit class ValueTransformCrashFrameworkSuite extends munit.FunSuite { - override val munitValueTransforms: List[ValueTransform] = List( - new ValueTransform("boom", { case "test-body" => ??? }) - ) + override val munitValueTransforms: List[ValueTransform] = + List(new ValueTransform("boom", { case "test-body" => ??? })) - test("hello") { - "test-body" - } + test("hello")("test-body") } object ValueTransformCrashFrameworkSuite extends FrameworkTest( classOf[ValueTransformCrashFrameworkSuite], """|==> failure munit.ValueTransformCrashFrameworkSuite.hello - an implementation is missing - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/main/scala/munit/ValueTransformFrameworkSuite.scala b/tests/shared/src/main/scala/munit/ValueTransformFrameworkSuite.scala index 1d399df7..905c276d 100644 --- a/tests/shared/src/main/scala/munit/ValueTransformFrameworkSuite.scala +++ b/tests/shared/src/main/scala/munit/ValueTransformFrameworkSuite.scala @@ -4,21 +4,16 @@ import scala.concurrent.Future class ValueTransformFrameworkSuite extends munit.FunSuite { override val munitValueTransforms: List[ValueTransform] = List( - new ValueTransform( - "number", - { case 42 => - Future.failed(new Exception("boom")) - } - ) + new ValueTransform("number", { case 42 => Future.failed(new Exception("boom")) }) ) - test("explode") { 42 } - test("ok") { 41 } + test("explode")(42) + test("ok")(41) } object ValueTransformFrameworkSuite extends FrameworkTest( classOf[ValueTransformFrameworkSuite], """|==> failure munit.ValueTransformFrameworkSuite.explode - boom |==> success munit.ValueTransformFrameworkSuite.ok - |""".stripMargin + |""".stripMargin, ) diff --git a/tests/shared/src/test/scala/munit/AssertionsSuite.scala b/tests/shared/src/test/scala/munit/AssertionsSuite.scala index 95f40d7f..ea8dc5ac 100644 --- a/tests/shared/src/test/scala/munit/AssertionsSuite.scala +++ b/tests/shared/src/test/scala/munit/AssertionsSuite.scala @@ -3,15 +3,12 @@ package munit import munit.internal.console.Printers class AssertionsSuite extends BaseSuite { - def check( - name: TestOptions, - cond: => Boolean, - expected: String - )(implicit loc: Location): Unit = - test(name) { - val (_, clues) = munitCaptureClues(cond) - assertNoDiff(Printers.print(clues), expected) - } + def check(name: TestOptions, cond: => Boolean, expected: String)(implicit + loc: Location + ): Unit = test(name) { + val (_, clues) = munitCaptureClues(cond) + assertNoDiff(Printers.print(clues), expected) + } val a = 42 val b = 43L @@ -23,7 +20,7 @@ class AssertionsSuite extends BaseSuite { | a: Int = 42 | b: Long = 43 |} - |""".stripMargin + |""".stripMargin, ) check( @@ -33,7 +30,7 @@ class AssertionsSuite extends BaseSuite { | a: Int = 42 | c.head: Int = 41 |} - |""".stripMargin + |""".stripMargin, ) check( @@ -45,7 +42,7 @@ class AssertionsSuite extends BaseSuite { | 41 | ) |} - |""".stripMargin + |""".stripMargin, ) test("subtype".tag(NoDotty)) { @@ -85,7 +82,7 @@ class AssertionsSuite extends BaseSuite { | Alternative 2: upcast either type into `Any` or a shared supertype |assertEquals(List(1), Vector(1)) | ^ - |""".stripMargin + |""".stripMargin, ) } @@ -127,7 +124,7 @@ assertEquals(new A, new B) | Alternative 2: upcast either type into `Any` or a shared supertype |assertEquals(new A, new B) | ^ - |""".stripMargin + |""".stripMargin, ) } @@ -162,19 +159,14 @@ assertEquals(new A, new B) | Alternative 2: upcast either type into `Any` or a shared supertype |assertEquals('a', 'a'.toInt) | ^ - |""".stripMargin + |""".stripMargin, ) } test("array-sameElements") { - val e = intercept[ComparisonFailException] { - assertEquals(Array(1, 2), Array(1, 2)) - } - assert( - clue(e).getMessage.contains( - "arrays have the same elements but different reference equality. Convert the arrays to a non-Array collection if you intend to assert the two arrays have the same elements. For example, `assertEquals(a.toSeq, b.toSeq)" - ) - ) + val e = + intercept[ComparisonFailException](assertEquals(Array(1, 2), Array(1, 2))) + assert(clue(e).getMessage.contains("arrays have the same elements but different reference equality. Convert the arrays to a non-Array collection if you intend to assert the two arrays have the same elements. For example, `assertEquals(a.toSeq, b.toSeq)")) } test("some-none-nokj") { @@ -208,7 +200,7 @@ assertEquals(new A, new B) | Alternative 2: upcast either type into `Any` or a shared supertype |assertEquals(None, Some(1)) | ^ - |""".stripMargin + |""".stripMargin, ) } diff --git a/tests/shared/src/test/scala/munit/ClueSuite.scala b/tests/shared/src/test/scala/munit/ClueSuite.scala index c2b6c17d..ba1ca175 100644 --- a/tests/shared/src/test/scala/munit/ClueSuite.scala +++ b/tests/shared/src/test/scala/munit/ClueSuite.scala @@ -3,11 +3,7 @@ package munit class ClueSuite extends BaseSuite { def check[T](options: TestOptions, clue: Clue[T], expected: String)(implicit loc: Location - ): Unit = { - test(options) { - assertEquals(clue.source, expected) - } - } + ): Unit = test(options)(assertEquals(clue.source, expected)) val a: List[Int] = List(1) @@ -16,11 +12,7 @@ class ClueSuite extends BaseSuite { check("comment", a /*comment*/ .head, "a /*comment*/ .head") // Disabled on Dotty because the starting position doesn't include opening "(" - check( - "lambda", - { (y: String) => y.head }, - "(y: String) => y.head" - ) + check("lambda", (y: String) => y.head, "(y: String) => y.head") checkPrint( "string-message", @@ -28,7 +20,7 @@ class ClueSuite extends BaseSuite { """|Clues { | "message": String = "message" |} - |""".stripMargin + |""".stripMargin, ) val x = 42 @@ -38,7 +30,7 @@ class ClueSuite extends BaseSuite { """|Clues { | x: Int = 42 |} - |""".stripMargin + |""".stripMargin, ) val y = 32 @@ -49,7 +41,7 @@ class ClueSuite extends BaseSuite { | x: Int = 42 | y: Int = 32 |} - |""".stripMargin + |""".stripMargin, ) val z: List[Int] = List(1) @@ -61,7 +53,7 @@ class ClueSuite extends BaseSuite { | 1 | ) |} - |""".stripMargin + |""".stripMargin, ) case class User(name: String, age: Int) @@ -75,18 +67,14 @@ class ClueSuite extends BaseSuite { | age = 34 | ) |} - |""".stripMargin + |""".stripMargin, ) - def checkPrint( - options: TestOptions, - clues: Clues, - expected: String - )(implicit loc: Location): Unit = { - test(options) { - val obtained = munitPrint(clues) - assertNoDiff(obtained, expected) - } + def checkPrint(options: TestOptions, clues: Clues, expected: String)(implicit + loc: Location + ): Unit = test(options) { + val obtained = munitPrint(clues) + assertNoDiff(obtained, expected) } } diff --git a/tests/shared/src/test/scala/munit/ComparisonFailExceptionSuite.scala b/tests/shared/src/test/scala/munit/ComparisonFailExceptionSuite.scala index b929bf41..e2628b4a 100644 --- a/tests/shared/src/test/scala/munit/ComparisonFailExceptionSuite.scala +++ b/tests/shared/src/test/scala/munit/ComparisonFailExceptionSuite.scala @@ -1,41 +1,35 @@ package munit -import org.junit.ComparisonFailure import munit.internal.console.Lines import munit.internal.io.PlatformIO.Paths +import org.junit.ComparisonFailure + class ComparisonFailExceptionSuite extends BaseSuite { override val munitLines: Lines = new Lines { - override def formatPath(location: Location): String = { - Paths.get(location.path).getFileName().toString() - } + override def formatPath(location: Location): String = Paths + .get(location.path).getFileName().toString() } test("comparison-failure") { - val e = intercept[ComparisonFailException] { + val e = intercept[ComparisonFailException]( assertEquals[Any, Any](List("1", "2", "3"), List(1, 2)) - } + ) assert(clue(e).isInstanceOf[ComparisonFailure]) assert(clue(e).isInstanceOf[Serializable]) // NOTE: assert that we use the `toString` of values in the // `org.junit.ComparisionFailure` exception. The stdout message in the // console still uses `munitPrint()`, which would have displayed `List("1", // "2", "3")` instead of `List(1, 2, 3)`. - assertNoDiff( - e.getActual(), - "List(1, 2, 3)" - ) - assertNoDiff( - e.getExpected(), - "List(1, 2)" - ) + assertNoDiff(e.getActual(), "List(1, 2, 3)") + assertNoDiff(e.getExpected(), "List(1, 2)") assertEquals(e.expected, List(1, 2)) assertEquals(e.obtained, List("1", "2", "3")) assertNoDiff( e.getMessage(), """|ComparisonFailExceptionSuite.scala:15 - |14: val e = intercept[ComparisonFailException] { + |14: val e = intercept[ComparisonFailException]( |15: assertEquals[Any, Any](List("1", "2", "3"), List(1, 2)) - |16: } + |16: ) |values are not the same |=> Obtained |List( @@ -51,24 +45,22 @@ class ComparisonFailExceptionSuite extends BaseSuite { |+ 1, |+ 2 | ) - |""".stripMargin + |""".stripMargin, ) } test("assert-no-diff-obtained-empty") { - val e = intercept[ComparisonFailException] { - assertNoDiff("", "Lorem ipsum") - } + val e = intercept[ComparisonFailException](assertNoDiff("", "Lorem ipsum")) assertNoDiff( e.getMessage(), - """|ComparisonFailExceptionSuite.scala:60 - |59: val e = intercept[ComparisonFailException] { - |60: assertNoDiff("", "Lorem ipsum") - |61: } + """|ComparisonFailExceptionSuite.scala:53 + |52: test("assert-no-diff-obtained-empty") { + |53: val e = intercept[ComparisonFailException](assertNoDiff("", "Lorem ipsum")) + |54: assertNoDiff( |Obtained empty output! |=> Expected: |Lorem ipsum - |""".stripMargin + |""".stripMargin, ) } diff --git a/tests/shared/src/test/scala/munit/CustomCompareSuite.scala b/tests/shared/src/test/scala/munit/CustomCompareSuite.scala index 3e7bf43b..57e734c1 100644 --- a/tests/shared/src/test/scala/munit/CustomCompareSuite.scala +++ b/tests/shared/src/test/scala/munit/CustomCompareSuite.scala @@ -2,20 +2,16 @@ package munit class CustomCompareSuite extends BaseSuite { import CustomCompare.fromCustomEquality - test("ok") { - assertEquals(Some(1), Option(1)) - } + test("ok")(assertEquals(Some(1), Option(1))) - test("boom") { - interceptMessage[RuntimeException]("boom")( - assertEquals(Some(42), Option(42)) - ) - } + test("boom")( + interceptMessage[RuntimeException]("boom")(assertEquals(Some(42), Option(42))) + ) - test("fallback-to-default") { + test("fallback-to-default")( // NOTE: Users who rely on custom equality won't get a compile error for // comparisons between supertype/subtype relationships. They only get a // compile error when comparing unrelated types (same as default behavior). assertEquals(List(1), collection.Seq(1)) - } + ) } diff --git a/tests/shared/src/test/scala/munit/DemoSuite.scala b/tests/shared/src/test/scala/munit/DemoSuite.scala index 2046c39f..7d62720a 100644 --- a/tests/shared/src/test/scala/munit/DemoSuite.scala +++ b/tests/shared/src/test/scala/munit/DemoSuite.scala @@ -27,14 +27,10 @@ abstract class DemoSuite extends FunSuite { assert(clue(a) < clue(b)) } - test("stack-traces".flaky) { - List(List(1, 2, 3).iterator).iterator.flatten.foreach { i => - require(i < 2, i) - } - } + test("stack-traces".flaky)( + List(List(1, 2, 3).iterator).iterator.flatten.foreach(i => require(i < 2, i)) + ) - test("flaky".flaky) { - ??? - } + test("flaky".flaky)(???) } diff --git a/tests/shared/src/test/scala/munit/DiffsSuite.scala b/tests/shared/src/test/scala/munit/DiffsSuite.scala index f8287268..ecc755c7 100644 --- a/tests/shared/src/test/scala/munit/DiffsSuite.scala +++ b/tests/shared/src/test/scala/munit/DiffsSuite.scala @@ -1,6 +1,7 @@ package munit -class DiffsSuite extends FunSuite { self => +class DiffsSuite extends FunSuite { + self => test("ansi") { val diff1 = munit.diff.Diffs.unifiedDiff("a", "b") val diff2 = munit.diff.Diffs.unifiedDiff("a", "c") @@ -12,20 +13,15 @@ class DiffsSuite extends FunSuite { self => """|-a |-+b |++c - |""".stripMargin + |""".stripMargin, ) } - def check( - name: String, - a: String, - b: String, - expected: String - )(implicit loc: Location): Unit = { - test(name) { - val obtained = munit.diff.Diffs.unifiedDiff(a, b) - assertNoDiff(obtained, expected) - } + def check(name: String, a: String, b: String, expected: String)(implicit + loc: Location + ): Unit = test(name) { + val obtained = munit.diff.Diffs.unifiedDiff(a, b) + assertNoDiff(obtained, expected) } check( @@ -35,14 +31,9 @@ class DiffsSuite extends FunSuite { self => """|-a |+a ∙ | b - |""".stripMargin + |""".stripMargin, ) - check( - "windows-crlf", - "a\r\nb", - "a\nb", - "" - ) + check("windows-crlf", "a\r\nb", "a\nb", "") } diff --git a/tests/shared/src/test/scala/munit/DoubleAssertionsFrameworkSuite.scala b/tests/shared/src/test/scala/munit/DoubleAssertionsFrameworkSuite.scala index c564c3ed..7c87e2d5 100644 --- a/tests/shared/src/test/scala/munit/DoubleAssertionsFrameworkSuite.scala +++ b/tests/shared/src/test/scala/munit/DoubleAssertionsFrameworkSuite.scala @@ -1,76 +1,60 @@ package munit class DoubleAssertionsFrameworkSuite extends BaseSuite { - test("Assert Equals NaN Fails".fail) { - assertEqualsDouble(1.234, Double.NaN, 0.0) - } + test("Assert Equals NaN Fails".fail)(assertEqualsDouble(1.234, Double.NaN, 0.0)) - test("Assert NaN Equals Fails".fail) { - assertEqualsDouble(Double.NaN, 1.234, 0.0) - } + test("Assert NaN Equals Fails".fail)(assertEqualsDouble(Double.NaN, 1.234, 0.0)) - test("Assert NaN Equals NaN") { - assertEqualsDouble(Double.NaN, Double.NaN, 0.0) - } + test("Assert NaN Equals NaN")(assertEqualsDouble(Double.NaN, Double.NaN, 0.0)) - test("Assert Pos Infinity Not Equals Neg Infinity".fail) { + test("Assert Pos Infinity Not Equals Neg Infinity".fail)( assertEqualsDouble(Double.PositiveInfinity, Double.NegativeInfinity, 0.0) - } + ) - test("Assert Pos Infinity Not Equals".fail) { + test("Assert Pos Infinity Not Equals".fail)( assertEqualsDouble(Double.PositiveInfinity, 1.23, 0.0) - } + ) - test("Assert Pos Infinity Equals Infinity") { + test("Assert Pos Infinity Equals Infinity")( assertEqualsDouble(Double.PositiveInfinity, Double.PositiveInfinity, 0.0) - } + ) - test("Assert Neg Infinity Equals Infinity") { + test("Assert Neg Infinity Equals Infinity")( assertEqualsDouble(Double.NegativeInfinity, Double.NegativeInfinity, 0.0) - } + ) - test("All Infinities") { - assertEqualsDouble( - Double.PositiveInfinity, - Double.NegativeInfinity, - Double.PositiveInfinity - ) - } + test("All Infinities")(assertEqualsDouble( + Double.PositiveInfinity, + Double.NegativeInfinity, + Double.PositiveInfinity, + )) // And now, the same with floats... - test("Assert Equals NaN Fails".fail) { - assertEqualsFloat(1.234f, Float.NaN, 0.0f) - } + test("Assert Equals NaN Fails".fail)(assertEqualsFloat(1.234f, Float.NaN, 0.0f)) - test("Assert NaN Equals Fails".fail) { - assertEqualsFloat(Float.NaN, 1.234f, 0.0f) - } + test("Assert NaN Equals Fails".fail)(assertEqualsFloat(Float.NaN, 1.234f, 0.0f)) - test("Assert NaN Equals NaN") { - assertEqualsFloat(Float.NaN, Float.NaN, 0.0f) - } + test("Assert NaN Equals NaN")(assertEqualsFloat(Float.NaN, Float.NaN, 0.0f)) - test("Assert Pos Infinity Not Equals Neg Infinity".fail) { + test("Assert Pos Infinity Not Equals Neg Infinity".fail)( assertEqualsFloat(Float.PositiveInfinity, Float.NegativeInfinity, 0.0f) - } + ) - test("Assert Pos Infinity Not Equals".fail) { + test("Assert Pos Infinity Not Equals".fail)( assertEqualsFloat(Float.PositiveInfinity, 1.23f, 0.0f) - } + ) - test("Assert Pos Infinity Equals Infinity") { + test("Assert Pos Infinity Equals Infinity")( assertEqualsFloat(Float.PositiveInfinity, Float.PositiveInfinity, 0.0f) - } + ) - test("Assert Neg Infinity Equals Infinity") { + test("Assert Neg Infinity Equals Infinity")( assertEqualsFloat(Float.NegativeInfinity, Float.NegativeInfinity, 0.0f) - } - - test("All Infinities") { - assertEqualsFloat( - Float.PositiveInfinity, - Float.NegativeInfinity, - Float.PositiveInfinity - ) - } + ) + + test("All Infinities")(assertEqualsFloat( + Float.PositiveInfinity, + Float.NegativeInfinity, + Float.PositiveInfinity, + )) } diff --git a/tests/shared/src/test/scala/munit/FailExceptionSuite.scala b/tests/shared/src/test/scala/munit/FailExceptionSuite.scala index 1c4ce12c..eeec7049 100644 --- a/tests/shared/src/test/scala/munit/FailExceptionSuite.scala +++ b/tests/shared/src/test/scala/munit/FailExceptionSuite.scala @@ -2,27 +2,16 @@ package munit class FailExceptionSuite extends BaseSuite { test("assertion-error") { - val e = intercept[AssertionError] { - fail("hello world!") - } + val e = intercept[AssertionError](fail("hello world!")) assert(clue(e).isInstanceOf[Serializable]) } - test("assertion-error-no-exception") { - try { - intercept[AssertionError] { - println("throwing no exception!") - } - throw new Exception("should not reach here") - } catch { - case e: FailException => - assert( - e.getMessage.contains( - "expected exception of type 'java.lang.AssertionError' but body evaluated successfully" - ) - ) - case _: Throwable => - fail("No FailException was thrown") - } - } + test("assertion-error-no-exception")(try { + intercept[AssertionError](println("throwing no exception!")) + throw new Exception("should not reach here") + } catch { + case e: FailException => + assert(e.getMessage.contains("expected exception of type 'java.lang.AssertionError' but body evaluated successfully")) + case _: Throwable => fail("No FailException was thrown") + }) } diff --git a/tests/shared/src/test/scala/munit/FrameworkSuite.scala b/tests/shared/src/test/scala/munit/FrameworkSuite.scala index 1257c3d3..0bed4f14 100644 --- a/tests/shared/src/test/scala/munit/FrameworkSuite.scala +++ b/tests/shared/src/test/scala/munit/FrameworkSuite.scala @@ -35,7 +35,7 @@ class FrameworkSuite extends BaseFrameworkSuite { SkippedFrameworkStdoutJsNativeSuite, SkippedFrameworkStdoutJVMSuite, SkippedFrameworkStdoutJsNativeVerboseSuite, - SkippedFrameworkStdoutJVMVerboseSuite + SkippedFrameworkStdoutJVMVerboseSuite, ) - tests.foreach { t => check(t) } + tests.foreach(t => check(t)) } diff --git a/tests/shared/src/test/scala/munit/FunFixtureSuite.scala b/tests/shared/src/test/scala/munit/FunFixtureSuite.scala index f3c75a09..bda41140 100644 --- a/tests/shared/src/test/scala/munit/FunFixtureSuite.scala +++ b/tests/shared/src/test/scala/munit/FunFixtureSuite.scala @@ -4,13 +4,11 @@ class FunFixtureSuite extends FunSuite { var tearDownName = "" val files: FunFixture[String] = FunFixture[String]( setup = { test => test.name + "-setup" }, - teardown = { name => tearDownName = name } + teardown = { name => tearDownName = name }, ) - override def afterAll(): Unit = { - assertEquals(tearDownName, "basic-setup") - } + override def afterAll(): Unit = assertEquals(tearDownName, "basic-setup") - files.test("basic") { name => assertEquals(name, "basic-setup") } + files.test("basic")(name => assertEquals(name, "basic-setup")) } diff --git a/tests/shared/src/test/scala/munit/LazyFutureSuite.scala b/tests/shared/src/test/scala/munit/LazyFutureSuite.scala index 5247e399..ef5d15ef 100644 --- a/tests/shared/src/test/scala/munit/LazyFutureSuite.scala +++ b/tests/shared/src/test/scala/munit/LazyFutureSuite.scala @@ -12,28 +12,16 @@ class LazyFutureSuite extends FunSuite { } override def munitValueTransforms: List[ValueTransform] = - super.munitValueTransforms ++ List( - new ValueTransform( - "LazyFuture", - { case LazyFuture(run) => - run() - } - ) - ) + super.munitValueTransforms ++ + List(new ValueTransform("LazyFuture", { case LazyFuture(run) => run() })) - test("ok-task".fail) { - LazyFuture { - // Test will fail because LazyFuture.run()` is automatically called - throw new RuntimeException("BOOM!") - } - } + test("ok-task".fail)(LazyFuture( + // Test will fail because LazyFuture.run()` is automatically called + throw new RuntimeException("BOOM!") + )) - test("nested".fail) { - LazyFuture { - LazyFuture { - // Test will fail because LazyFuture.run()` is automatically called - throw new RuntimeException("BOOM!") - } - } - } + test("nested".fail)(LazyFuture(LazyFuture( + // Test will fail because LazyFuture.run()` is automatically called + throw new RuntimeException("BOOM!") + ))) } diff --git a/tests/shared/src/test/scala/munit/PrintersSuite.scala b/tests/shared/src/test/scala/munit/PrintersSuite.scala index 4a692af4..6077d2dc 100644 --- a/tests/shared/src/test/scala/munit/PrintersSuite.scala +++ b/tests/shared/src/test/scala/munit/PrintersSuite.scala @@ -2,52 +2,27 @@ package munit import munit.internal.console.Printers -class PrintersSuite extends FunSuite { self => +class PrintersSuite extends FunSuite { + self => val isScala213: Boolean = BuildInfo.scalaVersion.startsWith("2.13") def check( options: TestOptions, original: Any, expected: String, - isEnabled: Boolean = true - ): Unit = { - test(options) { - assume(isEnabled, "disabled test") - val obtained = Printers.print(original) - assertNoDiff(obtained, expected) - } + isEnabled: Boolean = true, + ): Unit = test(options) { + assume(isEnabled, "disabled test") + val obtained = Printers.print(original) + assertNoDiff(obtained, expected) } - check( - "basic", - "a", - "\"a\"" - ) + check("basic", "a", "\"a\"") - check( - "multiline", - "a\n", - "\"\"\"a\n\"\"\"" - ) - check( - "single-quote", - '\'', - "'\\''" - ) - check( - "newline", - '\n', - "'\\n'" - ) - check( - "char-single-quote", - '\'', - "'\\''" - ) - check( - "string-single-quote", - "'a'", - "\"'a'\"" - ) + check("multiline", "a\n", "\"\"\"a\n\"\"\"") + check("single-quote", '\'', "'\\''") + check("newline", '\n', "'\\n'") + check("char-single-quote", '\'', "'\\''") + check("string-single-quote", "'a'", "\"'a'\"") check( "map", Map(1 -> 2, 3 -> 4, 5 -> Map(6 -> 7)), @@ -58,7 +33,7 @@ class PrintersSuite extends FunSuite { self => | 6 -> 7 | ) |) - |""".stripMargin + |""".stripMargin, ) check( @@ -77,7 +52,7 @@ class PrintersSuite extends FunSuite { self => | ) | ) |) - |""".stripMargin + |""".stripMargin, ) check( @@ -96,14 +71,14 @@ class PrintersSuite extends FunSuite { self => | ) | ) |) - |""".stripMargin + |""".stripMargin, ) case class User( name: String, age: Int, awesome: Boolean, - friends: List[User] = Nil + friends: List[User] = Nil, ) check( "user1", @@ -115,7 +90,7 @@ class PrintersSuite extends FunSuite { self => | friends = Nil |) |""".stripMargin, - isScala213 + isScala213, ) check( @@ -135,6 +110,6 @@ class PrintersSuite extends FunSuite { self => | ) |) |""".stripMargin, - isScala213 + isScala213, ) } diff --git a/tests/shared/src/test/scala/munit/SuiteLocalFixtureSuite.scala b/tests/shared/src/test/scala/munit/SuiteLocalFixtureSuite.scala index bbf37e0d..0899164f 100644 --- a/tests/shared/src/test/scala/munit/SuiteLocalFixtureSuite.scala +++ b/tests/shared/src/test/scala/munit/SuiteLocalFixtureSuite.scala @@ -19,9 +19,7 @@ class SuiteLocalFixtureSuite extends FunSuite { override def munitFixtures: Seq[Fixture[_]] = List(counter) - override def beforeAll(): Unit = { - assertEquals(counter(), 0) - } + override def beforeAll(): Unit = assertEquals(counter(), 0) override def beforeEach(context: BeforeEach): Unit = { val n = context.test.name.toInt @@ -33,13 +31,7 @@ class SuiteLocalFixtureSuite extends FunSuite { assertEquals(counter(), n * 3 + 1) } - override def afterAll(): Unit = { - assertEquals(counter(), -10) - } + override def afterAll(): Unit = assertEquals(counter(), -10) - 1.to(5).foreach { i => - test(i.toString()) { - assertEquals(counter(), 3 * i) - } - } + 1.to(5).foreach(i => test(i.toString())(assertEquals(counter(), 3 * i))) } diff --git a/tests/shared/src/test/scala/munit/TestLocalFixtureSuite.scala b/tests/shared/src/test/scala/munit/TestLocalFixtureSuite.scala index 88723142..35b35955 100644 --- a/tests/shared/src/test/scala/munit/TestLocalFixtureSuite.scala +++ b/tests/shared/src/test/scala/munit/TestLocalFixtureSuite.scala @@ -4,24 +4,19 @@ class TestLocalFixtureSuite extends FunSuite { val name: Fixture[String] = new Fixture[String]("name") { private var name = "" def apply() = name - override def beforeEach(context: BeforeEach): Unit = { + override def beforeEach(context: BeforeEach): Unit = name = context.test.name + "-before" - } - override def afterEach(context: AfterEach): Unit = { + override def afterEach(context: AfterEach): Unit = name = context.test.name + "-after" - } } val name2 = name - override def afterEach(context: AfterEach): Unit = { + override def afterEach(context: AfterEach): Unit = assertEquals(name(), context.test.name + "-after") - } override def munitFixtures: Seq[Fixture[_]] = List(name, name2) - test("basic") { - assertEquals(name(), "basic-before") - } + test("basic")(assertEquals(name(), "basic-before")) test("two") { assertEquals(name(), "two-before") diff --git a/tests/shared/src/test/scala/munit/TypeCheckSuite.scala b/tests/shared/src/test/scala/munit/TypeCheckSuite.scala index 3b92ca84..f4a44336 100644 --- a/tests/shared/src/test/scala/munit/TypeCheckSuite.scala +++ b/tests/shared/src/test/scala/munit/TypeCheckSuite.scala @@ -2,27 +2,19 @@ package munit class TypeCheckSuite extends FunSuite { - def check( - options: TestOptions, - obtained: String, - compat: Map[String, String] - )(implicit loc: Location): Unit = { - test(options) { - val split = BuildInfo.scalaVersion.split("\\.") - val binaryVersion = split.take(2).mkString(".") - val majorVersion = split.head match { - case "0" => "3" - case n => n - } - val expected = compat - .get(BuildInfo.scalaVersion) - .orElse(compat.get(binaryVersion)) - .orElse(compat.get(majorVersion)) - .getOrElse { - compat(BuildInfo.scalaVersion) - } - assertNoDiff(obtained, expected)(loc) + def check(options: TestOptions, obtained: String, compat: Map[String, String])( + implicit loc: Location + ): Unit = test(options) { + val split = BuildInfo.scalaVersion.split("\\.") + val binaryVersion = split.take(2).mkString(".") + val majorVersion = split.head match { + case "0" => "3" + case n => n } + val expected = compat.get(BuildInfo.scalaVersion) + .orElse(compat.get(binaryVersion)).orElse(compat.get(majorVersion)) + .getOrElse(compat(BuildInfo.scalaVersion)) + assertNoDiff(obtained, expected)(loc) } val msg = "Hello" @@ -30,11 +22,10 @@ class TypeCheckSuite extends FunSuite { "not a member", compileErrors("msg.foobar"), Map( - "2" -> - """|error: value foobar is not a member of String - |msg.foobar - | ^ - |""".stripMargin, + "2" -> """|error: value foobar is not a member of String + |msg.foobar + | ^ + |""".stripMargin, "3" -> """|error: |value foobar is not a member of String, but could be made available as an extension method. @@ -45,8 +36,8 @@ class TypeCheckSuite extends FunSuite { | |msg.foobar | ^ - |""".stripMargin - ) + |""".stripMargin, + ), ) check( @@ -57,26 +48,24 @@ class TypeCheckSuite extends FunSuite { |val x: = 2 | ^ |""".stripMargin, - "3" -> - """|error: an identifier expected, but '=' found - |val x: = 2 - | ^ - |""".stripMargin - ) + "3" -> """|error: an identifier expected, but '=' found + |val x: = 2 + | ^ + |""".stripMargin, + ), ) check( "type mismatch", compileErrors("val n: Int = msg"), Map( - "2" -> - """|error: - |type mismatch; - | found : String - | required: Int - |val n: Int = msg - | ^ - |""".stripMargin, + "2" -> """|error: + |type mismatch; + | found : String + | required: Int + |val n: Int = msg + | ^ + |""".stripMargin, "3" -> """|error: |Found: (TypeCheckSuite.this.msg : String) @@ -88,7 +77,7 @@ class TypeCheckSuite extends FunSuite { | |val n: Int = msg | ^ - |""".stripMargin - ) + |""".stripMargin, + ), ) }