From 9a44edcceb008ed1e9d7b972ea0e30ce52174561 Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 08:13:58 +0000 Subject: [PATCH 1/7] Update sbt-scalafmt to 2.5.5 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 2f6dd054..e565757c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -9,7 +9,7 @@ addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.8.0") addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.8.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.7.1") From 233b98110b1bdbd71cab33063b0e309784366619 Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 20:30:15 +0000 Subject: [PATCH 2/7] Update sbt, scripted-plugin to 1.11.3 --- project/build.properties | 2 +- scalafix/project/build.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project/build.properties b/project/build.properties index bbb0b608..c02c575f 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.2 +sbt.version=1.11.3 diff --git a/scalafix/project/build.properties b/scalafix/project/build.properties index bbb0b608..c02c575f 100644 --- a/scalafix/project/build.properties +++ b/scalafix/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.2 +sbt.version=1.11.3 From 7c3096f4043c1ba1d1690c1d1f8effaa3418b92f Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 20:15:05 +0000 Subject: [PATCH 3/7] Update cats-effect, cats-effect-testkit to 3.6.2 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ae75de73..70c20b75 100644 --- a/build.sbt +++ b/build.sbt @@ -36,7 +36,7 @@ ThisBuild / crossScalaVersions := Seq(scala212, scala213, "3.3.6") ThisBuild / scalaVersion := scala213 // the default Scala val Version = new { - val catsEffect = "3.6.1" + val catsEffect = "3.6.2" val catsLaws = "2.11.0" val discipline = "1.5.1" val fs2 = "3.12.0" From 3e8268a742f22203891ac51ca26630b85400c6be Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 16:10:21 +0000 Subject: [PATCH 4/7] Update sbt-mdoc to 2.7.2 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index e565757c..4afe3cba 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -11,6 +11,6 @@ addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.8.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") -addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.7.1") +addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.7.2") addSbtPlugin("io.get-coursier" % "sbt-shading" % "2.1.5") From f2190d8733ce5b823a7178810baf7a20ef00c086 Mon Sep 17 00:00:00 2001 From: zainab-ali Date: Wed, 9 Jul 2025 14:20:42 +0100 Subject: [PATCH 5/7] Add guide on asserting equality. --- build.sbt | 1 + docs/features/asserting_equality.md | 124 ++++++++++++++++++++++++++++ docs/features/directory.conf | 1 + docs/features/expectations.md | 108 +++++++++++------------- 4 files changed, 176 insertions(+), 58 deletions(-) create mode 100644 docs/features/asserting_equality.md diff --git a/build.sbt b/build.sbt index ae75de73..a20a0bc5 100644 --- a/build.sbt +++ b/build.sbt @@ -212,6 +212,7 @@ lazy val docs = project .settings( moduleName := "weaver-docs", name := "Weaver documentation", + mdocExtraArguments += "--allowCodeFenceIndented", watchSources += (ThisBuild / baseDirectory).value / "docs", libraryDependencies ++= Seq( "org.http4s" %% "http4s-ember-client" % Version.http4s, diff --git a/docs/features/asserting_equality.md b/docs/features/asserting_equality.md new file mode 100644 index 00000000..015509d1 --- /dev/null +++ b/docs/features/asserting_equality.md @@ -0,0 +1,124 @@ +# Asserting equality + +```scala mdoc:invisible +import weaver.Expectations.Helpers._ +val expected = 1 +val found = 2 +``` + +Weaver offers two approaches for asserting equality: `expect.eql` and `expect.same`. + +`expect.eql` is the better approach, but you may need to write some extra code to use it. + +## `expect.eql` (recommended) + +```scala mdoc:compile-only +expect.eql(expected, found) +``` + +`expect.eql` asserts for strict equality. + +If you accidentally compare the wrong types of data, your code will not compile: + +```scala mdoc:fail +expect.eql(1, "one") +``` + +The data types you compare must have an [Eq](https://typelevel.org/cats/typeclasses/eq.html) typeclass instance. You can declare one, or derive one using [kittens](https://github.com/typelevel/kittens). + +```scala mdoc:compile-only +case class Pet(name: String) + +// A cats.Eq instance is needed +import cats.Eq +implicit val petEq: Eq[Pet] = Eq.by(_.name) + +expect.eql(Pet("Maru"), Pet("Fido")) +``` + +## `expect.same` + +```scala mdoc:compile-only +expect.same(expected, found) +``` + +`expect.same` asserts using universal equality. + +If you accidentally compare the wrong types of data, your code will compile. Your test will fail later, when it is run: + +```scala +// This compiles +expect.same(1, "one") +``` + + +`expect.same` doesn't require an `Eq` instance. + +```scala mdoc:compile-only +case class Dog(name: String) // No Eq instance defined + +expect.same(Dog("Maru"), Dog("Fido")) +``` + +## Do not use `expect` + +You can assert for equality using `expect`. + +```scala mdoc:compile-only +expect(1 == 2) +``` + +This is discouraged because its failure messages are poorer than `expect.eql` or `expect.same`. It does not display a diff of the values on the left and right side of the equality. + +Use `expect` along with `clue` when you have other assertions. For example to assert for `>` + +```scala mdoc:invisible +val x = 1 +``` + +```scala mdoc:compile-only +expect(clue(x) > 2) +``` + +## Should I use `expect.same` or `expect.eql`? + +- Use `expect.eql` for Scala standard datatypes such as `Int` and `String`. These have `Eq` instances, so don't need any extra code. +- Use `expect.eql` for your own data types if you prefer compile time errors at the expense of extra code. +- Use `expect.same` for your own data types if you prefer runtime test failures instead of extra code. + +These are described in the suite below. + +### Example suite + +```scala mdoc +import weaver._ + +object ExpectationsSuite extends SimpleIOSuite { + + pureTest("expect.eql for standard data types") { + expect.eql(1, 2) + } + + import cats.Eq + case class Pet(name: String) + implicit val eqPet: Eq[Pet] = Eq.by[Pet, String](_.name) + + pureTest("expect.eql for user-defined data types") { + expect.same(Pet("Maru"), Pet("Fido")) + } + + // Note that we don't have an instance of Eq[Dog] + // anywhere in scope + case class Dog(name: String) + + pureTest("expect.same relaxed equality comparison") { + expect.same(Dog("Maru"), Dog("Fido")) + } +} +``` + +### Example suite report + +```scala mdoc:passthrough +println(weaver.docs.Output.runSuites(ExpectationsSuite)) +``` diff --git a/docs/features/directory.conf b/docs/features/directory.conf index 744f56e8..690dca9f 100644 --- a/docs/features/directory.conf +++ b/docs/features/directory.conf @@ -1,6 +1,7 @@ laika.title = Features laika.navigationOrder = [ expectations.md, + asserting_equality.md, tracing_failures.md, resources.md, global_resources.md, diff --git a/docs/features/expectations.md b/docs/features/expectations.md index cbd0c365..85c7d195 100644 --- a/docs/features/expectations.md +++ b/docs/features/expectations.md @@ -7,40 +7,58 @@ The easiest way to construct expectactions is to call the `expect` macro. The `c ## TL;DR -- Assert on boolean values using `expect`: - - ```scala mdoc:compile-only - expect(myVar == 25 && list.size == 4) - ``` +```scala mdoc:invisible +import weaver.Expectations.Helpers._ +import cats.effect.IO +val list = List(1) +``` + +- Assert on boolean values using `expect`: + + ```scala mdoc:compile-only + expect(list.size > 4) + ``` - Investigate failures using `clue`: ```scala mdoc:compile-only - expect(clue(myVar) == 25 && clue(list).size == 4) + expect(clue(list).size > 4) ``` +- Compare values using `expect.eql` (needs an `Eq` instance) + + ```scala mdoc:compile-only + expect.eql(List(1, 2, 3), (1 to 3).toList) + ``` + +- Compare values with relaxed equality using `expect.same` (no `Eq` instance needed) + + ```scala mdoc:compile-only + expect.same(List(1, 2, 3), (1 to 3).toList) + ``` + - Compose expectations using `and`/`or` - + ```scala mdoc:compile-only - (expect(1 == 1) and expect(2 > 1)) or expect(5 == 5) + (expect(1 > 0) and expect(2 > 1)) or expect(5 < 6) ``` - ... or their symbolic aliases `&&`/`||` ```scala mdoc:compile-only - (expect(1 == 1) && expect(2 > 1)) || expect(5 == 5) + (expect(1 > 0) && expect(2 > 1)) || expect(5 < 6) ``` - Compose expectations using `xor` ```scala mdoc:compile-only - expect(1 == 1) xor expect(2 == 2) + expect(1 > 0) xor expect(2 > 1) ``` - Use varargs short form for asserting on all boolean values ```scala mdoc:compile-only - expect.all(1 == 1, 2 == 2, 3 > 2) + expect.all(1 > 0, 2 > 1, 3 > 2) ``` - Use `forEach` to test every element of a collection (or anything that @@ -76,25 +94,6 @@ The easiest way to construct expectactions is to call the `expect` macro. The `c } ``` -- Use `expect.eql` for strict equality comparison (types that implement `Eq` - typeclass) and string representation diffing (using `Show` typeclass, fall - back to `toString` if no instance found) in - case of failure - - ```scala mdoc:compile-only - expect.eql(List(1, 2, 3), (1 to 3).toList) - ``` - - See below how the output looks in case of failure - -- Use `expect.same` for relaxed equality comparison (if no `Eq` instance is - found, fall back to universal equality) and relaxed string diffing (fall - back to `toString` implementation) - - ```scala mdoc:compile-only - expect.same(List(1, 2, 3), (1 to 3).toList) - ``` - - Use `success` or `failure` to create succeeding/failing expectations without conditions @@ -107,9 +106,9 @@ The easiest way to construct expectactions is to call the `expect` macro. The `c ```scala mdoc:compile-only for { x <- IO("hello") - _ <- expect(x.length == 4).failFast + _ <- expect(x.length < 4).failFast[IO] y = x + "bla" - _ <- expect(y.size > x.size).failFast + _ <- expect(y.size > x.size).failFast[IO] } yield expect(y.contains(x)) ``` @@ -121,54 +120,47 @@ import cats.effect.IO object ExpectationsSuite extends SimpleIOSuite { - object A { - object B { - object C { - def test(a: Int) = a + 5 - } - } - } + def test(a: Int) = a + 5 pureTest("Simple expectations (success)") { val z = 15 - - expect(A.B.C.test(z) == z + 5) + + expect(test(z) < z + 6) } - + pureTest("Simple expectations (failure)") { val z = 15 - - expect(clue(A.B.C.test(z)) % 7 == 0) - } + expect(clue(test(z)) > z + 6) + } pureTest("And/Or composition (success)") { expect(1 != 2) and expect(2 != 1) or expect(2 != 3) } pureTest("And/Or composition (failure)") { - (expect(1 != clue(2)) and expect(2 == clue(1))) or expect(2 == clue(3)) + (expect(1 != clue(2)) and expect(2 < clue(1))) or expect(2 > clue(3)) } pureTest("Varargs composition (success)") { - // expect(1 + 1 == 2) && expect (2 + 2 == 4) && expect(4 * 2 == 8) - expect.all(1 + 1 == 2, 2 + 2 == 4, 4 * 2 == 8) + // expect(1 + 1 < 3) && expect(2 + 2 < 5) && expect(4 * 2 < 9) + expect.all(1 + 1 < 3, 2 + 2 < 5, 4 * 2 < 9) } pureTest("Varargs composition (failure)") { - // expect(1 + 1 == 2) && expect (2 + 2 == 4) && expect(4 * 2 == 8) - expect.all(clue(1 + 1) == 2, clue(2 + 2) == 5, clue(4 * 2) == 8) + // expect(1 + 1 < 3) && expect(clue(2 + 2) > 5) && expect(4 * 2 < 9) + expect.all(1 + 1 < 3, clue(2 + 2) > 5, 4 * 2 < 9) } pureTest("Working with collections (success)") { forEach(List(1, 2, 3))(i => expect(i < 5)) and - forEach(Option("hello"))(msg => expect.same(msg, "hello")) and - exists(List("a", "b", "c"))(i => expect(i == "c")) and - exists(Vector(true, true, false))(i => expect(i == false)) + forEach(Option("hello"))(msg => expect.eql(msg, "hello")) and + exists(List("a", "b", "c"))(i => expect.eql(i, "c")) and + exists(Vector(true, true, false))(i => expect.eql(i, false)) } pureTest("Working with collections (failure 1)") { - forEach(Vector("hello", "world"))(msg => expect.same(msg, "hello")) + forEach(Vector("hello", "world"))(msg => expect.eql(msg, "hello")) } pureTest("Working with collections (failure 2)") { @@ -183,7 +175,7 @@ object ExpectationsSuite extends SimpleIOSuite { pureTest("Strict equality (success)") { expect.eql("hello", "hello") and expect.eql(List(1, 2, 3), List(1, 2, 3)) and - expect.eql(Test(25.0), Test(25.0)) + expect.eql(Test(25.0), Test(25.0)) } pureTest("Strict equality (failure 1)") { @@ -203,17 +195,17 @@ object ExpectationsSuite extends SimpleIOSuite { class Hello(val d: Double) { override def toString = s"Hello to $d" - override def equals(other: Any) = + override def equals(other: Any) = if(other != null && other.isInstanceOf[Hello]) other.asInstanceOf[Hello].d == this.d - else + else false } pureTest("Relaxed equality comparison (success)") { expect.same(new Hello(25.0), new Hello(25.0)) } - + pureTest("Relaxed equality comparison (failure)") { expect.same(new Hello(25.0), new Hello(50.0)) } From 275716804f2afbc38318d2a9381bc93669ff832b Mon Sep 17 00:00:00 2001 From: zainab-ali Date: Fri, 11 Jul 2025 15:49:23 +0100 Subject: [PATCH 6/7] Propagate source locations in expect macro. --- .../src/main/scala-2/weaver/ExpectMacro.scala | 30 ++++++++-------- .../src/main/scala-3/weaver/ExpectMacro.scala | 36 ++++++++++--------- .../shared/src/test/scala/DogFoodTests.scala | 18 +++++----- .../shared/src/test/scala/TracingTests.scala | 2 +- 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/modules/core/shared/src/main/scala-2/weaver/ExpectMacro.scala b/modules/core/shared/src/main/scala-2/weaver/ExpectMacro.scala index be4e8b1f..e637f6d8 100644 --- a/modules/core/shared/src/main/scala-2/weaver/ExpectMacro.scala +++ b/modules/core/shared/src/main/scala-2/weaver/ExpectMacro.scala @@ -10,14 +10,16 @@ private[weaver] trait ExpectMacro { * * Use the [[Expectations.Helpers.clue]] function to investigate any failures. */ - def apply(value: Boolean): Expectations = macro ExpectMacro.applyImpl + def apply(value: Boolean)(implicit loc: SourceLocation): Expectations = + macro ExpectMacro.applyImpl /** * Asserts that a boolean value is true and displays a failure message if not. * * Use the [[Expectations.Helpers.clue]] function to investigate any failures. */ - def apply(value: Boolean, message: => String): Expectations = + def apply(value: Boolean, message: => String)(implicit + loc: SourceLocation): Expectations = macro ExpectMacro.messageImpl /** @@ -25,7 +27,8 @@ private[weaver] trait ExpectMacro { * * Use the [[Expectations.Helpers.clue]] function to investigate any failures. */ - def all(values: Boolean*): Expectations = macro ExpectMacro.allImpl + def all(values: Boolean*)(implicit loc: SourceLocation): Expectations = + macro ExpectMacro.allImpl } private[weaver] object ExpectMacro { @@ -36,9 +39,9 @@ private[weaver] object ExpectMacro { * If any value evaluates to false, all generated clues are displayed as part * of the failed expectation. */ - def allImpl(c: blackbox.Context)(values: c.Tree*): c.Tree = { + def allImpl(c: blackbox.Context)(values: c.Tree*)( + loc: c.Tree): c.Tree = { import c.universe._ - val sourceLoc = new weaver.macros.Macros(c).fromContext.asInstanceOf[c.Tree] val clueMethodSymbol = getClueMethodSymbol(c) val allExpectations = values.toList.map { value => val (cluesName, cluesValDef) = makeClues(c) @@ -50,7 +53,7 @@ private[weaver] object ExpectMacro { makeExpectations(c)(cluesName = cluesName, cluesValDef = cluesValDef, value = transformedValue, - sourceLoc = sourceLoc, + loc = loc, sourceCode = sourceCode, message = q"None") } @@ -65,9 +68,8 @@ private[weaver] object ExpectMacro { */ def messageImpl(c: blackbox.Context)( value: c.Tree, - message: c.Tree): c.Tree = { + message: c.Tree)(loc: c.Tree): c.Tree = { import c.universe._ - val sourceLoc = new weaver.macros.Macros(c).fromContext.asInstanceOf[c.Tree] val sourcePos = c.enclosingPosition val sourceCode = new String(sourcePos.source.content.slice(sourcePos.start, sourcePos.end)) @@ -79,7 +81,7 @@ private[weaver] object ExpectMacro { makeExpectations(c)(cluesName = cluesName, cluesValDef = cluesValDef, value = transformedValue, - sourceLoc = sourceLoc, + loc = loc, sourceCode = sourceCode, message = q"Some($message)") } @@ -97,10 +99,10 @@ private[weaver] object ExpectMacro { * After the value is evaluated, the [[Clues]] collection is used to contruct * [[Expectations]]. */ - def applyImpl(c: blackbox.Context)(value: c.Tree): c.Tree = { + def applyImpl(c: blackbox.Context)(value: c.Tree)( + loc: c.Tree): c.Tree = { import c.universe._ - val sourceLoc = new weaver.macros.Macros(c).fromContext.asInstanceOf[c.Tree] val sourcePos = c.enclosingPosition val sourceCode = new String(sourcePos.source.content.slice(sourcePos.start, sourcePos.end)) @@ -113,7 +115,7 @@ private[weaver] object ExpectMacro { makeExpectations(c)(cluesName = cluesName, cluesValDef = cluesValDef, value = transformedValue, - sourceLoc = sourceLoc, + loc = loc, sourceCode = sourceCode, message = q"None") } @@ -123,12 +125,12 @@ private[weaver] object ExpectMacro { cluesName: c.TermName, cluesValDef: c.Tree, value: c.Tree, - sourceLoc: c.Tree, + loc: c.Tree, sourceCode: String, message: c.Tree): c.Tree = { import c.universe._ val block = - q"$cluesValDef; _root_.weaver.internals.Clues.toExpectations($sourceLoc, Some($sourceCode), $message, $cluesName, $value)" + q"$cluesValDef; _root_.weaver.internals.Clues.toExpectations($loc, Some($sourceCode), $message, $cluesName, $value)" val untyped = c.untypecheck(block) val retyped = c.typecheck(untyped, pt = c.typeOf[Expectations]) retyped diff --git a/modules/core/shared/src/main/scala-3/weaver/ExpectMacro.scala b/modules/core/shared/src/main/scala-3/weaver/ExpectMacro.scala index d7228af7..e651c4e2 100644 --- a/modules/core/shared/src/main/scala-3/weaver/ExpectMacro.scala +++ b/modules/core/shared/src/main/scala-3/weaver/ExpectMacro.scala @@ -13,8 +13,9 @@ private[weaver] trait ExpectMacro { * * Use the [[Expectations.Helpers.clue]] function to investigate any failures. */ - inline def apply(assertion: Clues ?=> Boolean): Expectations = - ${ ExpectMacro.applyImpl('assertion) } + inline def apply(assertion: Clues ?=> Boolean)(using + loc: SourceLocation): Expectations = + ${ ExpectMacro.applyImpl('assertion, 'loc) } /** * Asserts that a boolean value is true and displays a failure message if @@ -25,16 +26,17 @@ private[weaver] trait ExpectMacro { */ inline def apply( assertion: Clues ?=> Boolean, - message: => String): Expectations = - ${ ExpectMacro.applyMessageImpl('assertion, 'message) } + message: => String)(using loc: SourceLocation): Expectations = + ${ ExpectMacro.applyMessageImpl('assertion, 'message, 'loc) } /** * Asserts that boolean values are all true. * * Use the [[Expectations.Helpers.clue]] function to investigate any failures. */ - inline def all(inline assertions: (Clues ?=> Boolean)*): Expectations = - ${ ExpectMacro.allImpl('assertions) } + inline def all(inline assertions: (Clues ?=> Boolean)*)(using + loc: SourceLocation): Expectations = + ${ ExpectMacro.allImpl('assertions, 'loc) } } private[weaver] object ExpectMacro { @@ -49,10 +51,10 @@ private[weaver] object ExpectMacro { * After the assertion is evaluated, the [[Clues]] collection is used to * contruct [[Expectations]]. */ - def applyImpl[T: Type](assertion: Expr[Clues ?=> Boolean])(using - q: Quotes): Expr[Expectations] = { + def applyImpl[T: Type]( + assertion: Expr[Clues ?=> Boolean], + loc: Expr[SourceLocation])(using q: Quotes): Expr[Expectations] = { import q.reflect.* - val sourceLoc = weaver.macros.fromContextImpl(using q) // The compiler doesn't return the correct position information // for `assertion.asTerm.pos`. Use the position of the entire // expect statement instead. @@ -60,7 +62,7 @@ private[weaver] object ExpectMacro { '{ val clues = new Clues val result = ${ assertion }(using clues) - Clues.toExpectations($sourceLoc, + Clues.toExpectations($loc, sourceCode = $sourceCode, message = None, clues, @@ -76,14 +78,14 @@ private[weaver] object ExpectMacro { */ def applyMessageImpl[T: Type]( assertion: Expr[Clues ?=> Boolean], - message: => Expr[String])(using q: Quotes): Expr[Expectations] = { + message: => Expr[String], + loc: Expr[SourceLocation])(using q: Quotes): Expr[Expectations] = { import q.reflect.* - val sourceLoc = weaver.macros.fromContextImpl(using q) val sourceCode = Expr(Position.ofMacroExpansion.sourceCode) '{ val clues = new Clues val result = ${ assertion }(using clues) - Clues.toExpectations($sourceLoc, + Clues.toExpectations($loc, sourceCode = $sourceCode, message = Some($message), clues, @@ -97,10 +99,10 @@ private[weaver] object ExpectMacro { * If any assertion evaluates to false, all generated clues are displayed as * part of the failed expectation. */ - def allImpl[T: Type](assertions: Expr[Seq[(Clues ?=> Boolean)]])(using - q: Quotes): Expr[Expectations] = { + def allImpl[T: Type]( + assertions: Expr[Seq[(Clues ?=> Boolean)]], + loc: Expr[SourceLocation])(using q: Quotes): Expr[Expectations] = { import q.reflect.* - val sourceLoc = weaver.macros.fromContextImpl(using q) val sourceCodes: Expr[List[Option[String]]] = Expr(assertions match { case Varargs(exprs) => exprs.toList.map(_.asTerm.pos.sourceCode) case _ => Nil @@ -111,7 +113,7 @@ private[weaver] object ExpectMacro { val clues = new Clues val result = assertion(using clues) val sourceCode = ${ sourceCodes }.get(index).flatten - Clues.toExpectations($sourceLoc, + Clues.toExpectations($loc, sourceCode = sourceCode, message = None, clues, diff --git a/modules/framework-cats/shared/src/test/scala/DogFoodTests.scala b/modules/framework-cats/shared/src/test/scala/DogFoodTests.scala index 207bd3b1..89484754 100644 --- a/modules/framework-cats/shared/src/test/scala/DogFoodTests.scala +++ b/modules/framework-cats/shared/src/test/scala/DogFoodTests.scala @@ -181,7 +181,7 @@ object DogFoodTests extends IOSuite { | of | multiline | (failure) - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:34) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(clue(x) == y) | @@ -317,7 +317,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (failure) 0ms - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:83) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(clue(x) == clue(y)) | @@ -339,7 +339,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (nested) 0ms - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:89) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(clue(List(clue(x), clue(y))) == List(x, x)) | @@ -363,7 +363,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (map) 0ms - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:95) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(List(x, y).map(v => clue(v)) == List(x, x)) | @@ -384,7 +384,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (all) 0ms - | [0] assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:102) + | [0] assertion failed (src/main/DogFoodTests.scala:5) | [0] | [0] clue(x) == clue(y) | [0] @@ -393,7 +393,7 @@ object DogFoodTests extends IOSuite { | [0] y: Int = 2 | [0] } | - | [1] assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:102) + | [1] assertion failed (src/main/DogFoodTests.scala:5) | [1] | [1] clue(y) == clue(z) | [1] @@ -414,7 +414,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (show) 0ms - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:109) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(clue(x) == clue(y)) | @@ -437,7 +437,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (show-from-to-string) 0ms - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:119) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(clue(x) == clue(y)) | @@ -459,7 +459,7 @@ object DogFoodTests extends IOSuite { val expected = s""" |- (helpers) 0ms - | assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:128) + | assertion failed (src/main/DogFoodTests.scala:5) | | expect(CustomHelpers.clue(x) == otherclue(y) || x == clue(z)) | diff --git a/modules/framework-cats/shared/src/test/scala/TracingTests.scala b/modules/framework-cats/shared/src/test/scala/TracingTests.scala index b5acb9b8..f66baa1a 100644 --- a/modules/framework-cats/shared/src/test/scala/TracingTests.scala +++ b/modules/framework-cats/shared/src/test/scala/TracingTests.scala @@ -30,7 +30,7 @@ object TracingTests extends SimpleIOSuite { val locations = e.head.locations.toList val paths = locations.map(_.fileRelativePath).map(standardise) forEach(paths)(p => expect(p == thisFile)) && - expect(locations.map(_.line).distinct.size == 4) + expect(locations.map(_.line).distinct.size == 3) case Valid(_) => failure("Should have been invalid") } } From 909463880edf6eb1883e5841f74ec02fc533e0b4 Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 04:28:48 +0000 Subject: [PATCH 7/7] Update cats-effect, cats-effect-testkit to 3.6.3 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4ecfcb63..56813ec2 100644 --- a/build.sbt +++ b/build.sbt @@ -36,7 +36,7 @@ ThisBuild / crossScalaVersions := Seq(scala212, scala213, "3.3.6") ThisBuild / scalaVersion := scala213 // the default Scala val Version = new { - val catsEffect = "3.6.2" + val catsEffect = "3.6.3" val catsLaws = "2.11.0" val discipline = "1.5.1" val fs2 = "3.12.0"