Wie zeige ich einen Grund für eine fehlgeschlagene Testeigenschaft mit QuickCheck an?

StackOverflow https://stackoverflow.com/questions/4772902

  •  23-10-2019
  •  | 
  •  

Frage

Was ist die beste Praxis, um Gründe für einen fehlgeschlagenen Immobilientest anzuzeigen, wenn er über QuickCheck getestet wird?

Betrachten Sie zum Beispiel:

prop a b = res /= []
   where
      (res, reason) = checkCode a b

Dann könnte die A -Sitzung aussehen:

> quickCheck prop
Falsifiable, after 48 tests:
42
23

Für das Debuggen wäre es jedoch sehr bequem, den Grund für das Scheitern als Teil des QuickCheck -Fälschungsberichts zu zeigen.

Ich habe es so gehackt:

prop a b = if res /= [] then traceShow reason False else True
   where
      (res, reason) = checkCode a b

Gibt es eine bessere/schönere oder schnellere Möglichkeit, dies zu tun?

War es hilfreich?

Lösung

Ich gehe davon aus, dass Ihre Variable "Grund" eine Art testspezifische Daten darüber enthält, was schief gelaufen ist. Sie können stattdessen ein "Ergebnis" zurückgeben, das sowohl Erfolg/Fail-/Ungültige Bedingungen enthält als auch eine Zeichenfolge, die erklärt, was schief gelaufen ist. Eigenschaften, die die Rückgabergebnisse von QuickCheck genauso wie Eigenschaften, die Bool zurückgeben, behandelt werden.

(bearbeiten) wie dieses:

module QtTest where 

import Test.QuickCheck
import Test.QuickCheck.Property as P


-- Always return success
prop_one :: Integer -> P.Result
prop_one _ = MkResult (Just True) True "always succeeds" False [] []


-- Always return failure
prop_two :: Integer -> P.Result
prop_two n = MkResult (Just False) True ("always fails: n = " ++ show n) False [] []

Beachten Sie, dass es sich um den in test.quickCheck.Property definierten "Ergebnis" -Typ handelt.

Es gibt auch einige Kombinatoren in test.quickCheck.property, die Ihnen helfen, das Ergebnis zu komponieren, anstatt den Konstruktor direkt aufzurufen, wie z.

prop_three :: Integer -> Property
prop_three n = printTestCase ("always fails: n = " ++ show n) False

Ich denke, es wäre ein besserer Stil, diese zu verwenden.

Andere Tipps

Da QuickCheck Ihnen die Eingänge für die Funktion gibt und der zu testende Code rein ist (oder?), Können Sie diese Eingaben einfach der Funktion übertragen und das Ergebnis erhalten. Dies ist flexibler, da Sie mit diesen Eingaben auch wiederholt mit Verbesserungen der ursprünglichen Funktion testen können, bis sie korrekt sind.

Dies ist meine Lösung (ich benutze counterexample Anstatt von printTestCase Da der spätere jetzt veraltet ist):

(<?>) :: (Testable p) => p -> String -> Property
(<?>) = flip (Test.QuickCheck.counterexample . ("Extra Info: " ++))
infixl 2 <?>

Verwendungszweck:

main :: IO ()
main = hspec $ do
  describe "math" $ do
    prop "sum-of-square-le-square-of-sum" $ do
      \(x :: Int) (y :: Int) ->
        x * x + y * y <= (x + y) * (x + y) <?> show (x * x, y * y, x + y)

Wenn also ein Testfall fehlschlägt, können Sie so etwas sehen wie:

   *** Failed! Falsifiable, Falsifiable (after 2 tests):
   1
   -1
   Extra Info: (1,1,0)

Sie können auch verwenden <?> zusammen mit .&&., .||., === und ==> etc.:

  describe "math" $ do
    prop "sum-of-square-le-square-of-sum" $ do
      \(x :: Int) (y :: Int) ->
        x * x + y * y <= (x + y) * (x + y) <?> show (x * x, y * y, x + y) .||. (1==0) <?> "haha"

Dies funktioniert auf die gleiche Weise wie die Antwort von Paul Johnson, ist aber prägnanter und robuster für Veränderungen in MkResult:

import Test.QuickCheck.Property (succeeded, failed, reason)

prop a b =
  if res /= []
    then succeeded
    else failed { reason = reason }
   where
      (res, reason) = checkCode a b
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top