当 scalatest 检测到故障时如何忽略测试实用程序方法?
how to ignore test utility methods when scalatest detects failures?
我在测试中有这个方便的方法:
def assertFormat[T: SexpFormat](start: T, expect: Sexp): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
这基本上是 运行 我经常使用的断言模式的便利。
不可能将其重写为 Matcher
,因为对 SexpFormat[T]
的隐含要求(尽管我很想听听不需要我这样做的方法在foo should roundTrip[MyFormat](...)
)
中写入类型MyFormat
如果此实用程序方法中的任何测试失败,scalatest 会将 assertFormat
的内部标记为测试失败的原因。但是我真的想让scalatest检测到这个方法的caller是测试的原因。我该怎么做?
即当前输出为
[info] - should support custom missing value rules *** FAILED ***
[info] SexpNil did not equal SexpCons(SexpSymbol(:duck),SexpCons(SexpNil,SexpNil)) nil was not (:duck nil) (FormatSpec.scala:11)
[info] org.scalatest.exceptions.TestFailedException:
[info] at org.scalatest.Assertions$class.newAssertionFailedException(Assertions.scala:529)
[info] at org.scalatest.FlatSpec.newAssertionFailedException(FlatSpec.scala:1691)
[info] at org.scalatest.Assertions$AssertionsHelper.macroAssert(Assertions.scala:502)
[info] at org.ensime.sexp.formats.FormatSpec$class.assertFormat(FormatSpec.scala:11)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec.assertFormat(FamilyFormatsSpec.scala:151)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec.roundtrip(FamilyFormatsSpec.scala:156)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec$$anonfun.apply(FamilyFormatsSpec.scala:222)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec$$anonfun.apply(FamilyFormatsSpec.scala:221)
FormatSpec.scala:11
是定义我的 assertFormat
的地方。真正的失败是在 FamilyFormatsSpec.scala:222
(调用 另一个 便捷方法 FamilyFormatsSpec.scala:156
)
这在 ScalaTest 3.0 中是可能的,方法是在您的自定义断言中采用隐式 org.scalactic.source.Position
。每当您的 assertFormat
方法被调用时,该位置就会被计算(通过宏),并且该位置将由 assertFormat
内的断言和匹配器表达式选取。这是它的样子:
import org.scalactic.source
def assertFormat[T: SexpFormat](start: T, expect: Sexp)(implicit pos: source.Position): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
下面的例子说明了这一点。如果您在 class 路径上有 ScalaTest 3.0,只需:将以下文件加载到 Scala REPL 中:
:paste
import org.scalatest._
import org.scalactic._
import Matchers._
case class Sexp(o: Any) {
def compactPrint: String = o.toString
def convertTo[T: SexpFormat]: Sexp = implicitly[SexpFormat[T]].convertIt(o)
override def toString = "I'm too sexp for my shirt."
}
trait SexpFormat[T] {
def convertIt(o: Any): Sexp = new Sexp(o)
}
implicit class Sexpify(o: Any) {
def toSexp: Sexp = new Sexp(o)
}
implicit def universalSexpFormat[T]: SexpFormat[T] = new SexpFormat[T] {}
def assertFormat[T: SexpFormat](start: T, expect: Sexp): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
import org.scalatest.exceptions.TestFailedException
val before = intercept[TestFailedException] { assertFormat(1, new Sexp) }
println(s"${before.failedCodeStackDepth} - This stack depth points to the assert call inside assertFormat")
import org.scalactic.source
def betterAssertFormat[T: SexpFormat](start: T, expect: Sexp)(implicit pos: source.Position): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
val after = intercept[TestFailedException] { betterAssertFormat(1, new Sexp) }
println(s"${after.failedCodeStackDepth} - This stack depth is the betterAssertFormat call itself in your test code")
它将打印:
3 - This stack depth points to the assert call inside assertFormat
4 - This stack depth is the betterAssertFormat call itself in your test code
我在测试中有这个方便的方法:
def assertFormat[T: SexpFormat](start: T, expect: Sexp): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
这基本上是 运行 我经常使用的断言模式的便利。
不可能将其重写为 Matcher
,因为对 SexpFormat[T]
的隐含要求(尽管我很想听听不需要我这样做的方法在foo should roundTrip[MyFormat](...)
)
MyFormat
如果此实用程序方法中的任何测试失败,scalatest 会将 assertFormat
的内部标记为测试失败的原因。但是我真的想让scalatest检测到这个方法的caller是测试的原因。我该怎么做?
即当前输出为
[info] - should support custom missing value rules *** FAILED ***
[info] SexpNil did not equal SexpCons(SexpSymbol(:duck),SexpCons(SexpNil,SexpNil)) nil was not (:duck nil) (FormatSpec.scala:11)
[info] org.scalatest.exceptions.TestFailedException:
[info] at org.scalatest.Assertions$class.newAssertionFailedException(Assertions.scala:529)
[info] at org.scalatest.FlatSpec.newAssertionFailedException(FlatSpec.scala:1691)
[info] at org.scalatest.Assertions$AssertionsHelper.macroAssert(Assertions.scala:502)
[info] at org.ensime.sexp.formats.FormatSpec$class.assertFormat(FormatSpec.scala:11)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec.assertFormat(FamilyFormatsSpec.scala:151)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec.roundtrip(FamilyFormatsSpec.scala:156)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec$$anonfun.apply(FamilyFormatsSpec.scala:222)
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec$$anonfun.apply(FamilyFormatsSpec.scala:221)
FormatSpec.scala:11
是定义我的 assertFormat
的地方。真正的失败是在 FamilyFormatsSpec.scala:222
(调用 另一个 便捷方法 FamilyFormatsSpec.scala:156
)
这在 ScalaTest 3.0 中是可能的,方法是在您的自定义断言中采用隐式 org.scalactic.source.Position
。每当您的 assertFormat
方法被调用时,该位置就会被计算(通过宏),并且该位置将由 assertFormat
内的断言和匹配器表达式选取。这是它的样子:
import org.scalactic.source
def assertFormat[T: SexpFormat](start: T, expect: Sexp)(implicit pos: source.Position): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
下面的例子说明了这一点。如果您在 class 路径上有 ScalaTest 3.0,只需:将以下文件加载到 Scala REPL 中:
:paste
import org.scalatest._
import org.scalactic._
import Matchers._
case class Sexp(o: Any) {
def compactPrint: String = o.toString
def convertTo[T: SexpFormat]: Sexp = implicitly[SexpFormat[T]].convertIt(o)
override def toString = "I'm too sexp for my shirt."
}
trait SexpFormat[T] {
def convertIt(o: Any): Sexp = new Sexp(o)
}
implicit class Sexpify(o: Any) {
def toSexp: Sexp = new Sexp(o)
}
implicit def universalSexpFormat[T]: SexpFormat[T] = new SexpFormat[T] {}
def assertFormat[T: SexpFormat](start: T, expect: Sexp): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
import org.scalatest.exceptions.TestFailedException
val before = intercept[TestFailedException] { assertFormat(1, new Sexp) }
println(s"${before.failedCodeStackDepth} - This stack depth points to the assert call inside assertFormat")
import org.scalactic.source
def betterAssertFormat[T: SexpFormat](start: T, expect: Sexp)(implicit pos: source.Position): Unit = {
val sexp = start.toSexp
assert(sexp === expect, s"${sexp.compactPrint} was not ${expect.compactPrint}")
expect.convertTo[T] should be(start)
}
val after = intercept[TestFailedException] { betterAssertFormat(1, new Sexp) }
println(s"${after.failedCodeStackDepth} - This stack depth is the betterAssertFormat call itself in your test code")
它将打印:
3 - This stack depth points to the assert call inside assertFormat
4 - This stack depth is the betterAssertFormat call itself in your test code