2012-09-28 29 views
14

我想提出我的ScalaCheck性能測試中我specs2測試套件確定性,暫時緩解調試。現在,每次重新運行測試套件時都會生成不同的值,這會使調試變得令人沮喪,因爲您不知道觀察到的行爲更改是由代碼更改引起的,還是僅由生成的不同數據引起。製作ScalaCheck測試確定性

我怎樣才能做到這一點?有沒有官方的方式來設置ScalaCheck使用的隨機種子?

我使用sbt運行測試套件。

獎金的問題:是否有打印出由ScalaCheck使用的隨機種子進行正式的方式,這樣就可以重現即使是非確定性的試運行?

+0

這個不斷變化的數據來自哪裏?一個數據庫?服務器? –

+0

@BrianAgnew不,它是由'ScalaCheck'隨機生成的。 –

回答

10

如果您使用純ScalaCheck性能,你應該能夠使用Test.Params類改變所使用的java.util.Random實例,並提供自己總是返回相同的一組值:

def check(params: Test.Parameters, p: Prop): Test.Result

[更新]

我剛剛出版了新specs2-1.12.2,快照,你可以使用下面的語法來指定您的隨機數發生器:

case class MyRandomGenerator() extends java.util.Random { 
    // implement a deterministic generator 
} 

"this is a specific property" ! prop { (a: Int, b: Int) => 
    (a + b) must_== (b + a) 
}.set(MyRandomGenerator(), minTestsOk -> 200, workers -> 3) 
+0

「使用純ScalaCheck屬性」是什麼意思?你的意思是,在那裏沒有使用任何specs2的東西? –

+0

我的意思是使用ScalaCheck規範:對象StringSpecification擴展了屬性(「String」),如ScalaCheck UserGuide所示:https://github.com/rickynils/scalacheck/wiki/User-Guide – Eric

1

作爲一般規則,在不確定性的輸入進行測試時,你應該嘗試呼應或保存在某個地方的投入時,有一個故障。

如果數據是小的,可以將其包含在該被示出給用戶的標籤或錯誤消息;例如,在一個的xUnit式測試:(因爲我是新來的Scala語法)

testLength(String x) { 
    assert(x.length > 10, "Length OK for '" + x + "'"); 
} 

如果數據是大的,例如自動生成的數據庫,你可能要麼將其存儲在非非易失性位置(​​例如。/ tmp帶有時間戳名稱)或顯示用於生成它的種子。

下一步很重要:採取價值,或種子,或什麼的,並把它添加到您的確定性的迴歸測試,以便它能夠從現在開始檢查每次。

你說你想ScalaCheck確定性「暫時」重現此問題;我說你已經找到了一個非常適合成爲單元測試的錯誤邊緣案例(可能經過一些手工簡化)。

0

對於scalacheck-1.12這種配置工作:

new Test.Parameters { 
    override val rng = new scala.util.Random(seed) 
} 

對於scalacheck-1.13因爲RNG方法刪除它不工作了。有什麼想法嗎?