2011-11-19 46 views
14

Khi một giá trị không thực hiện được kiểm tra QuickCheck'd, tôi muốn sử dụng nó để gỡ lỗi. Có cách nào tôi có thể làm một cái gì đó như:Tìm giá trị không thành công để kiểm tra nhanh

let failValue = quickCheck' myTest 
in someStuff failValue 

Nếu dữ liệu của tôi là read thể sau đó tôi có lẽ có thể hack một số cách để có được nó từ IO, nhưng nó không phải.

Trả lời

9

Tôi không thể tìm thấy bất kỳ thứ gì trong API QuickCheck để thực hiện điều này một cách tốt đẹp, nhưng đây là điều tôi đã tấn công cùng nhau bằng API QuickCheck đơn thuần. Nó chặn và ghi lại các yếu tố đầu vào vào tài sản của bạn theo số IORef và giả định rằng nếu không thành công, mục cuối cùng là thủ phạm và trả lại số tiền đó theo số Just. Nếu thử nghiệm được thông qua, kết quả là Nothing. Điều này có thể được tinh chỉnh một chút nhưng đối với các thuộc tính một đối số đơn giản, nó sẽ thực hiện công việc.

import Control.Monad 
import Data.IORef 
import Test.QuickCheck 
import Test.QuickCheck.Monadic 

prop_failIfZero :: Int -> Bool 
prop_failIfZero n = n /= 0 

quickCheck' :: (Arbitrary a, Show a) => (a -> Bool) -> IO (Maybe a) 
quickCheck' prop = do input <- newIORef Nothing 
         result <- quickCheckWithResult args (logInput input prop) 
         case result of 
         Failure {} -> readIORef input 
         _ -> return Nothing 
    where 
    logInput input prop x = monadicIO $ do run $ writeIORef input (Just x) 
              assert (prop x) 
    args = stdArgs { chatty = False } 

main = do failed <- quickCheck' prop_failIfZero 
      case failed of 
       Just x -> putStrLn $ "The input that failed was: " ++ show x 
       Nothing -> putStrLn "The test passed" 
+0

rất thông minh, cảm ơn – Xodarap

+0

Mẹo nhỏ này đã làm cho trải nghiệm gỡ lỗi Haskell của tôi tốt hơn rất nhiều. Cảm ơn –

2

Một cách sẽ là sử dụng phương pháp sample', chạy thủ công kiểm tra và tìm các giá trị không thành công. Ví dụ, thử nghiệm một chức năng kép bị lỗi:

import Test.QuickCheck 

double :: Int -> Int 
double x | x < 10 = 2 * x 
     | otherwise = 13 

doubleTest :: Int -> Bool 
doubleTest x = x + x == double x 

tester :: IO() 
tester = do 
    values <- sample' arbitrary 
    let failedValues = filter (not . doubleTest) values 
    print failedValues 

Vấn đề duy nhất là sample' chỉ tạo ra 11 giá trị kiểm tra, có thể không đủ để kích hoạt lỗi.

Các vấn đề liên quan