2016-07-09 21 views
6

mam tej metody wygody moich testów:jak zignorować metody narzędzia testowego, gdy skalatest wykryje awarie?

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) 
    } 

, która jest w zasadzie wygoda dla prowadzenia wzór twierdzenie, że robię dużo.

To nie jest możliwe, aby przerobić to jako Matcher ze względu na niejawny zapotrzebowania na SexpFormat[T] (choć byłbym zainteresowany w rozprawie sposobów na to, że nie wymagają mi zrobić, aby zapisać typ MyFormat w foo should roundTrip[MyFormat](...))

Jeśli jakiekolwiek testy zakończą się niepowodzeniem w tej metodzie narzędzia, skalatest będzie oznaczać elementy wewnętrzne assertFormat jako przyczynę niepowodzenia testu. Ale naprawdę chcę, aby skalatest wykrył, że wywołanie tej metody jest przyczyną testu. Jak mogę to zrobić?

wyjście tj prąd

[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$12.apply(FamilyFormatsSpec.scala:222) 
[info] at org.ensime.sexp.formats.test.FamilyFormatsSpec$$anonfun$12.apply(FamilyFormatsSpec.scala:221) 

FormatSpec.scala:11 gdzie moja assertFormat jest zdefiniowana. Prawdziwa porażka jest w FamilyFormatsSpec.scala:222 (który dzwoni inna metoda wygoda FamilyFormatsSpec.scala:156)

Odpowiedz

2

Jest to możliwe w ScalaTest 3,0 biorąc niejawny org.scalactic.source.Position w niestandardowym twierdzenia. Pozycja zostanie obliczona (za pomocą makra) za każdym razem, gdy zostanie wywołana twoja metoda assertFormat, a ta pozycja zostanie pobrana przez wyrażenie assert i matcher wewnątrz assertFormat. Oto, jak to będzie wyglądać:

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) 
} 

Poniższy przykład ilustruje go. Jeśli masz ScalaTest 3,0 na ścieżce klasy, po prostu: załadować następujący plik do 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") 

To będzie drukować:

3 - This stack depth points to the assert call inside assertFormat 
4 - This stack depth is the betterAssertFormat call itself in your test code