2011-04-20 58 views

回答

2

接近基於模型的測試的一種方法是構建一個已知良好的實現並與之進行比較。實現這一目標的最佳策略之一是使用更高級的語言,以便簡短易懂的實現易於閱讀和推理。

我使用HaskellQuickCheck對查詢評估的基於模型的測試取得了巨大成功。我將查詢語言表示爲Haskell數據類型,然後簡單地將其作爲Arbitrary的實例。一旦完成,QuickCheck可以生成無限數量的查詢,然後我可以根據測試服務器和模型實現來評估這些查詢。

ScalaScala-Check可能允許您在JVM上執行相同的操作。

由於這是如何使用一個簡單的例子,這裏有一個快速和骯髒的例子:

import Test.QuickCheck 
import Control.Monad (liftM,liftM2) 

-- An simple expression data type. 
-- Expression is either (Add X Y, Minus X Y, Multiply X Y or just a plain value) 
-- where X and Y are further expressions 
data Expression = Add Expression Expression 
       | Minus Expression Expression 
       | Multiply Expression Expression 
       | Value Int 
        deriving Show 

-- This is my model-based approach, high level 
evaluate :: Expression -> Int     
evaluate (Value x) = x 
evaluate (Add lhs rhs) = evaluate lhs + evaluate rhs 
evaluate (Minus lhs rhs) = evaluate lhs - evaluate rhs 
evaluate (Multiply lhs rhs) = evaluate lhs * evaluate rhs 

這之後,我有一個已知的良好執行一個簡單的模型。只要通過檢查代碼,我可以確定這是做我認爲應該做的事情。現在我可以使用Arbitrary來生成任意複雜的表達式。下面的權重指示頻率(所以產生的表情的70%將是Value,10%將被適當Add報表等)

instance Arbitrary Expression where 
    arbitrary = frequency [ 
     (70,liftM Value arbitrary) 
    , (10,liftM2 Add arbitrary arbitrary) 
    , (10,liftM2 Minus arbitrary arbitrary) 
    , (10,liftM2 Multiply arbitrary arbitrary) 
    ] 

這個定義給出了快速檢查創建我任意表達式的權力。例如:

> sample (arbitrary :: Gen Expression) 
Multiply (Value 1) (Value 0) 
Value 1 
Add (Value (-3)) (Add (Value (-1)) (Minus (Value 3) (Value 0))) 
Value (-4) 
Value (-19) 
Add (Value (-49)) (Value (-55)) 
Minus (Value 50) (Value 103) 
Value 210 
Value (-172) 
Value (-907) 
Value (-2703) 

我覺得這已經很酷了(但也許我只是很奇怪)。真正強大的一點是,現在我可以指定保存在所有生成的值

prop_testAgainstModel :: Expression -> Bool 
prop_testAgainstModel expr = evaluate expr == evaluate' expr 

在這裏我們假設evaluate'是評估的事情,我想驗證對我的模式我的超級複雜的方式不變。然後QuickCheck將生成大量的任意表達式,並試圖反駁我的斷言。

下面是一個針對我的一個嘗試產生更復雜的評估函數的例子。

> quickCheck prop_testAgainstModel 
*** Failed! Falsifiable (after 28 tests): 
Multiply (Value (-53758)) (Value 125360) 

我用這種方法來測試用C++編寫的外部服務器。 Haskell模型的實現可能只有幾百行代碼,我可以將它與Web服務的結果進行比較,代碼不會比上述代碼多。

+0

我正在尋找Java或動態vm語言的東西 – 2011-04-20 14:24:37

+2

也許你可以使用Scala實現同樣的方法,它的QuickCheck版本(http://code.google.com/p/scalacheck/) – 2011-04-20 14:32:31

+0

可以你解釋了QuickCheck如何幫助MBT?我可以向它描述狀態轉換,以便它可以生成測試嗎? – 2011-04-20 17:28:48