From 710d4a911ba6a486d4955d4292f642d73563d36b Mon Sep 17 00:00:00 2001 From: "E.G" <146701565+GlobalStar117@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:51:29 +1100 Subject: [PATCH] [2.x] test: Migrate TrackedSpec.scala to verify.BasicTestSuite (#8547) * test: Migrate TrackedSpec.scala to verify.BasicTestSuite Migrate TrackedSpec.scala from ScalaTest's AnyFlatSpec to verify.BasicTestSuite, following the pattern established by other test files in the sbt codebase. Changes: - Replace AnyFlatSpec class with BasicTestSuite object - Convert 'should ... in' syntax to 'test(...)' syntax - Use Scala 3 syntax with colon indentation - Change === to == for assertions (BasicTestSuite style) - Replace fail() with throw new AssertionError for explicit failures - Add 'end TrackedSpec' marker - Convert braces to colon-style for if expressions --- build.sbt | 6 +- project/HouseRulesPlugin.scala | 4 +- .../src/test/scala/sbt/util/TrackedSpec.scala | 129 +++++++----------- 3 files changed, 59 insertions(+), 80 deletions(-) diff --git a/build.sbt b/build.sbt index c7d60616e..80e29520c 100644 --- a/build.sbt +++ b/build.sbt @@ -384,7 +384,11 @@ lazy val utilTracking = (project in file("util-tracking")) .settings( utilCommonSettings, name := "Util Tracking", - libraryDependencies ++= Seq(scalatest % "test"), + libraryDependencies ++= Seq( + scalacheck % Test, + scalaVerify % Test, + hedgehog % Test, + ), mimaSettings, mimaBinaryIssueFilters ++= Seq( ) diff --git a/project/HouseRulesPlugin.scala b/project/HouseRulesPlugin.scala index dae33bc7a..a7b47999b 100644 --- a/project/HouseRulesPlugin.scala +++ b/project/HouseRulesPlugin.scala @@ -36,7 +36,9 @@ object HouseRulesPlugin extends AutoPlugin { case _ => Seq.empty } }, - scalacOptions ++= "-Xsource:3".ifScala2.value.toList + scalacOptions ++= "-Xsource:3".ifScala2.value.toList, + testFrameworks += TestFramework("hedgehog.sbt.Framework"), + testFrameworks += TestFramework("verify.runner.Framework"), ) ++ Seq(Compile, Test).flatMap(c => (c / console / scalacOptions) --= Seq("-Ywarn-unused-import", "-Xlint") ) diff --git a/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala b/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala index 2e5a77275..1dedbb1b5 100644 --- a/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala +++ b/util-tracking/src/test/scala/sbt/util/TrackedSpec.scala @@ -8,7 +8,7 @@ package sbt.util -import org.scalatest.flatspec.AnyFlatSpec +import verify.BasicTestSuite import sbt.io.IO import sbt.io.syntax.* import sbt.util.CacheImplicits.* @@ -16,8 +16,9 @@ import sjsonnew.{ Builder, JsonWriter } import scala.concurrent.Promise -class TrackedSpec extends AnyFlatSpec { - "lastOutput" should "store the last output" in { +object TrackedSpec extends BasicTestSuite: + + test("lastOutput should store the last output"): withStore { store => val value = 5 val otherValue = 10 @@ -25,45 +26,41 @@ class TrackedSpec extends AnyFlatSpec { val res0 = Tracked.lastOutput[Int, Int](store) { case (in, None) => - assert(in === value) + assert(in == value) in case (_, Some(_)) => - fail() + throw new AssertionError("Expected None but got Some") }(using implicitly)(value) - assert(res0 === value) + assert(res0 == value) val res1 = Tracked.lastOutput[Int, Int](store) { case (_, None) => - fail() + throw new AssertionError("Expected Some but got None") case (in, Some(read)) => - assert(in === otherValue) - assert(read === value) + assert(in == otherValue) + assert(read == value) read }(using implicitly)(otherValue) - assert(res1 === value) + assert(res1 == value) val res2 = Tracked.lastOutput[Int, Int](store) { case (_, None) => - fail() + throw new AssertionError("Expected Some but got None") case (in, Some(read)) => - assert(in === otherValue) - assert(read === value) + assert(in == otherValue) + assert(read == value) read }(using implicitly)(otherValue) - assert(res2 === value) - - () + assert(res2 == value) } - } - "inputChangedW" should "not require the input to have a JsonReader instance" in { + test("inputChangedW should not require the input to have a JsonReader instance"): case class Input(v: Int) - given JsonWriter[Input] = new JsonWriter[Input] { + given JsonWriter[Input] = new JsonWriter[Input]: override def write[J](obj: Input, builder: Builder[J]): Unit = builder.writeInt(obj.v) - } withStore { store => val input0 = Input(1) @@ -73,41 +70,35 @@ class TrackedSpec extends AnyFlatSpec { } val res0 = cachedFun(input0) - assert(res0 === input0.v) - () + assert(res0 == input0.v) } - } - - "inputChanged" should "detect that the input has not changed" in { + test("inputChanged should detect that the input has not changed"): withStore { store => val input0 = "foo" val res0 = Tracked.inputChanged[String, String](store) { case (true, in) => - assert(in === input0) + assert(in == input0) in case (false, _) => - fail() + throw new AssertionError("Expected changed=true but got false") }(using implicitly, implicitly)(input0) - assert(res0 === input0) + assert(res0 == input0) val res1 = Tracked.inputChanged[String, String](store) { case (true, _) => - fail() + throw new AssertionError("Expected changed=false but got true") case (false, in) => - assert(in === input0) + assert(in == input0) in }(using implicitly, implicitly)(input0) - assert(res1 === input0) - - () + assert(res1 == input0) } - } - it should "detect that the input has changed" in { + test("inputChanged should detect that the input has changed"): withStore { store => val input0 = 0 val input1 = 1 @@ -115,33 +106,29 @@ class TrackedSpec extends AnyFlatSpec { val res0 = Tracked.inputChanged[Int, Int](store) { case (true, in) => - assert(in === input0) + assert(in == input0) in case (false, _) => - fail() + throw new AssertionError("Expected changed=true but got false") }(using implicitly, implicitly)(input0) - assert(res0 === input0) + assert(res0 == input0) val res1 = Tracked.inputChanged[Int, Int](store) { case (true, in) => - assert(in === input1) + assert(in == input1) in case (false, _) => - fail() + throw new AssertionError("Expected changed=true but got false") }(using implicitly, implicitly)(input1) - assert(res1 === input1) - - () + assert(res1 == input1) } - } - "outputChangedW" should "not require the input to have a JsonReader instance" in { + test("outputChangedW should not require the input to have a JsonReader instance"): case class Input(v: Int) - given JsonWriter[Input] = new JsonWriter[Input] { + given JsonWriter[Input] = new JsonWriter[Input]: override def write[J](obj: Input, builder: Builder[J]): Unit = builder.writeInt(obj.v) - } withStore { store => val input0 = Input(1) @@ -151,76 +138,62 @@ class TrackedSpec extends AnyFlatSpec { } val res0 = cachedFun(() => input0) - assert(res0 === input0.v) - () + assert(res0 == input0.v) } - } - - "outputChanged" should "detect that the output has not changed" in { + test("outputChanged should detect that the output has not changed"): withStore { store => val beforeCompletion: String = "before-completion" val afterCompletion: String = "after-completion" val sideEffectCompleted = Promise[Unit]() - val p0: () => String = () => { - if (sideEffectCompleted.isCompleted) { - afterCompletion - } else { + val p0: () => String = () => + if sideEffectCompleted.isCompleted then afterCompletion + else sideEffectCompleted.success(()) beforeCompletion - } - } + val firstExpectedResult = "first-result" val secondExpectedResult = "second-result" val res0 = Tracked.outputChanged[String, String](store) { case (true, in) => - assert(in === beforeCompletion) + assert(in == beforeCompletion) firstExpectedResult case (false, _) => - fail() + throw new AssertionError("Expected changed=true but got false") }(using implicitly)(p0) - assert(res0 === firstExpectedResult) + assert(res0 == firstExpectedResult) val res1 = Tracked.outputChanged[String, String](store) { case (true, _) => - fail() + throw new AssertionError("Expected changed=false but got true") case (false, in) => - assert(in === afterCompletion) + assert(in == afterCompletion) secondExpectedResult }(using implicitly)(p0) - assert(res1 === secondExpectedResult) - - () + assert(res1 == secondExpectedResult) } - } - "tstamp tracker" should "have a timestamp of 0 on first invocation" in { + test("tstamp tracker should have a timestamp of 0 on first invocation"): withStore { store => Tracked.tstamp(store) { last => - assert(last === 0) + assert(last == 0) } - - () } - } - it should "provide the last time a function has been evaluated" in { + test("tstamp tracker should provide the last time a function has been evaluated"): withStore { store => Tracked.tstamp(store) { last => - assert(last === 0) + assert(last == 0) } Tracked.tstamp(store) { last => val difference = System.currentTimeMillis - last assert(difference < 1000) } - - () } - } private def withStore(f: CacheStore => Unit): Unit = IO.withTemporaryDirectory { tmp => @@ -228,4 +201,4 @@ class TrackedSpec extends AnyFlatSpec { f(store) } -} +end TrackedSpec