diff --git a/build.sbt b/build.sbt index 6f2185958..df0ee03e5 100644 --- a/build.sbt +++ b/build.sbt @@ -234,7 +234,7 @@ lazy val scriptedSbtProj = (project in scriptedPath / "sbt") libraryDependencies ++= Seq(launcherInterface % "provided"), mimaSettings, ) - .configure(addSbtIO, addSbtUtilLogging, addSbtCompilerInterface, addSbtUtilScripted) + .configure(addSbtIO, addSbtUtilLogging, addSbtCompilerInterface, addSbtUtilScripted, addSbtLmCore) lazy val scriptedPluginProj = (project in scriptedPath / "plugin") .dependsOn(sbtProj) diff --git a/notes/1.1.0/filter-scripted-tests.md b/notes/1.1.0/filter-scripted-tests.md new file mode 100644 index 000000000..4f216e9c2 --- /dev/null +++ b/notes/1.1.0/filter-scripted-tests.md @@ -0,0 +1,14 @@ +[@jonas]: https://github.com/jonas + +[#3564]: https://github.com/sbt/sbt/issues/3564 +[#3566]: https://github.com/sbt/sbt/pull/3566 + +### Improvements + +- Filter scripted tests based on optional `project/build.properties`. [#3564]/[#3566] by [@jonas] + +### Filtering scripted tests using `project/build.properties`. + +For all scripted tests in which `project/build.properties` exist, the value of the `sbt.version` property is read. If its binary version is different from `sbtBinaryVersion in pluginCrossBuild` the test will be skipped and a message indicating this will be logged. + +This allows you to define scripted tests that track the minimum supported sbt versions, e.g. 0.13.9 and 1.0.0-RC2. diff --git a/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/Fail.scala b/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/Fail.scala new file mode 100644 index 000000000..f011d53a4 --- /dev/null +++ b/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/Fail.scala @@ -0,0 +1 @@ +object Skipped { diff --git a/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/build.properties b/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/build.properties new file mode 100644 index 000000000..a8c2f849b --- /dev/null +++ b/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/build.properties @@ -0,0 +1 @@ +sbt.version=0.12.0 diff --git a/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/test b/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/test new file mode 100644 index 000000000..4ed0b761f --- /dev/null +++ b/sbt/src/sbt-test/project/scripted-skip-incompatible/changes/test @@ -0,0 +1,2 @@ +$ copy-file changes/Fail.scala Skipped.scala +> compile diff --git a/sbt/src/sbt-test/project/scripted-skip-incompatible/project/plugins.sbt b/sbt/src/sbt-test/project/scripted-skip-incompatible/project/plugins.sbt new file mode 100644 index 000000000..529e7d656 --- /dev/null +++ b/sbt/src/sbt-test/project/scripted-skip-incompatible/project/plugins.sbt @@ -0,0 +1,3 @@ +libraryDependencies += { + "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value +} diff --git a/sbt/src/sbt-test/project/scripted-skip-incompatible/test b/sbt/src/sbt-test/project/scripted-skip-incompatible/test new file mode 100644 index 000000000..704535d5b --- /dev/null +++ b/sbt/src/sbt-test/project/scripted-skip-incompatible/test @@ -0,0 +1,17 @@ +# Setup failing test that should be skipped when tests are discovered +$ copy-file changes/Fail.scala src/sbt-test/group/skipped/changes/Fail.scala +$ copy-file changes/build.properties src/sbt-test/group/skipped/project/build.properties +$ copy-file changes/test src/sbt-test/group/skipped/test + +# Should fail when run explicitly +-> scripted group/skipped + +# Should be skipped when discovered +> scripted + +# Setup the same test without a project/build.properties file +$ copy-file changes/Fail.scala src/sbt-test/group/not-skipped/changes/Fail.scala +$ copy-file changes/test src/sbt-test/group/not-skipped/test + +# Running discovered tests should fail +-> scripted diff --git a/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala b/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala index 7094b8fb5..00781be92 100644 --- a/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala +++ b/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala @@ -6,6 +6,7 @@ package sbt package test import java.io.File +import java.util.Properties import scala.util.control.NonFatal import sbt.internal.scripted._ @@ -343,7 +344,9 @@ class ScriptedRunner { launchOpts: Array[String], prescripted: File => Unit): Unit = { val runner = new ScriptedTests(resourceBaseDirectory, bufferLog, bootProperties, launchOpts) - val allTests = get(tests, resourceBaseDirectory, logger) flatMap { + val sbtVersion = bootProperties.getName.dropWhile(!_.isDigit).dropRight(".jar".length) + val accept = isTestCompatible(resourceBaseDirectory, sbtVersion) _ + val allTests = get(tests, resourceBaseDirectory, accept, logger) flatMap { case ScriptedTest(group, name) => runner.singleScriptedTest(group, name, prescripted, logger) } @@ -399,17 +402,44 @@ class ScriptedRunner { reportErrors(tests.flatMap(test => test.apply().flatten.toSeq).toList) } + @deprecated("No longer used", "1.1.0") def get(tests: Seq[String], baseDirectory: File, log: Logger): Seq[ScriptedTest] = - if (tests.isEmpty) listTests(baseDirectory, log) else parseTests(tests) + get(tests, baseDirectory, _ => true, log) + def get(tests: Seq[String], + baseDirectory: File, + accept: ScriptedTest => Boolean, + log: Logger): Seq[ScriptedTest] = + if (tests.isEmpty) listTests(baseDirectory, accept, log) else parseTests(tests) + @deprecated("No longer used", "1.1.0") def listTests(baseDirectory: File, log: Logger): Seq[ScriptedTest] = - new ListTests(baseDirectory, _ => true, log).listTests + listTests(baseDirectory, _ => true, log) + def listTests(baseDirectory: File, + accept: ScriptedTest => Boolean, + log: Logger): Seq[ScriptedTest] = + (new ListTests(baseDirectory, accept, log)).listTests def parseTests(in: Seq[String]): Seq[ScriptedTest] = for (testString <- in) yield { val Array(group, name) = testString.split("/").map(_.trim) ScriptedTest(group, name) } + + private def isTestCompatible(resourceBaseDirectory: File, sbtVersion: String)( + test: ScriptedTest): Boolean = { + import sbt.internal.librarymanagement.cross.CrossVersionUtil.binarySbtVersion + val buildProperties = new Properties() + val testDir = new File(new File(resourceBaseDirectory, test.group), test.name) + val buildPropertiesFile = new File(new File(testDir, "project"), "build.properties") + + IO.load(buildProperties, buildPropertiesFile) + + Option(buildProperties.getProperty("sbt.version")) match { + case Some(version) => binarySbtVersion(version) == binarySbtVersion(sbtVersion) + case None => true + } + } + } final case class ScriptedTest(group: String, name: String) {