Jak wyświetlić niestandardowe komunikaty o błędach w ScalaTest?

86

Czy ktoś wie, jak wyświetlić niestandardowy komunikat o błędzie w ScalaTest?

Na przykład:

NumberOfElements() should equal (5)

W przypadku niepowodzenia wyświetla następujący komunikat:

10 nie równało się 5

Ale chcę bardziej opisowej wiadomości, takiej jak:

NumberOfElements powinno wynosić 5.

Udayakumar Rayala
źródło

Odpowiedzi:

101

Jesteś pierwszym, który prosi o taką funkcję. Jednym ze sposobów osiągnięcia tego jest withClue. Coś jak:

withClue("NumberOfElements: ") { NumberOfElements() should be (5) }

To powinno spowodować wyświetlenie tego komunikatu o błędzie:

NumberOfElements: 10 nie było równe 5

Jeśli chcesz całkowicie kontrolować wiadomość, możesz napisać niestandardowy element dopasowujący. Lub możesz użyć asercji, takiej jak ta:

assert(NumberOfElements() == 5, "NumberOfElements should be 5")

Czy możesz wyjaśnić, jaki jest Twój przypadek użycia? Dlaczego jest tak, że 10 nie równało się 5 nie pasuje do tabaki i jak często miałeś taką potrzebę?

Oto, o co prosisz:

scala> import org.scalatest.matchers.ShouldMatchers._
import org.scalatest.matchers.ShouldMatchers._

scala> withClue ("Hi:") { 1 + 1 should equal (3) }
org.scalatest.TestFailedException: Hi: 2 did not equal 3
at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:150)
at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2331)


scala> class AssertionHolder(f: => Any) {
     |   def withMessage(s: String) {
     |     withClue(s) { f }
     |   }
     | }
defined class AssertionHolder

scala> implicit def convertAssertion(f: => Any) = new AssertionHolder(f)
convertAssertion: (f: => Any)AssertionHolder

scala> { 1 + 1 should equal (3) } withMessage ("Ho:")
org.scalatest.TestFailedException: Ho: 2 did not equal 3
at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:150)
at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2331)

W ten sposób możesz napisać:

{ NumberOfElements() should be (5) } withMessage ("NumberOfElements:")
Bill Venners
źródło
1
Istnieją sytuacje, w których musiałem umieścić więcej niż jedno stwierdzenie w teście it () i jest więcej niż jedno porównanie liczb całkowitych. Patrząc na dzienniki, nie jest jasne, które stwierdzenie zawiodło.
Udayakumar Rayala
Ale sposób określania tego obiektu przez withClue jest nieczytelny. Czy nie ma sposobu, aby określić treść wiadomości na końcu?
Udayakumar Rayala
1
W końcu nie jest to wykonalne z DSL dopasowującego, ale możesz napisać metodę, która ustawia parametry withClue w odwrotnej kolejności. Do odpowiedzi dodam przykład.
Bill Venners
12

Nowy sposób od 2011 roku: Matchersi AppendedCluecechy. Ponadto w przypadku rozmiarów kolekcji istnieją komunikaty domyślne.

import org.scalatest.{AppendedClues, Matchers, WordSpec}

class SomeTest extends WordSpec with Matchers with AppendedClues {

  "Clues" should {
    "not be appended" when {
      "assertions pass" in {
        "hi" should equal ("hi") withClue "Greetings scala tester!"
      }
    }
    "be appended" when {
      "assertions fail"  in {
        1 + 1 should equal (3) withClue ", not even for large values of 1!"
      }
    }
    "not be needed" when {
      "looking at collection sizes" in {
        val list = List(1, 2, 3)
        list should have size 5
      }
    }
  }
}

Wynik wygląda następująco:

SomeTest:
Clues
  should not be appended
  - when assertions pass
  should be appended
  - when assertions fail *** FAILED ***
    2 did not equal 3, not even for large values of 1! (SomeTest.scala:15)
  should not be needed
  - when looking at collection sizes *** FAILED ***
    List(1, 2, 3) had size 3 instead of expected size 5 (SomeTest.scala:21)

Zwróć uwagę, że Listkomunikat o rozmiarze nie jest doskonały w przypadku list z długimi danymi .toStringwyjściowymi.

Więcej informacji można znaleźć w scaladoc .

tylda
źródło
3

Możesz także użyć withCluebez importowania czegokolwiek lub dodawania tego do klasy testowej:

withClue(s"Expecting distinct elements: ${elements.toList}") { elements.length shouldBe 3 }

To jest importowane z Assertionsklasy:org.scalatest.Assertions#withClue

Shubham Chaudhary
źródło