2017-06-22 51 views
0

我想使用ScalaCheck的forAll與行爲功能,但我遇到問題。行爲的功能是這樣的:ScalaCheck的發電機與ScalaTest的行爲功能

def someBehaviour(args: FunArgs) 

其中FunArgs基本上是一個聯合類型,我想驗證的各種可能性。所以,有一個FunArgs1FunArgs2兩個從FunArgs繼承但具有不同的部件(例如,一個具有兩個Int小號而另一個具有String,一個LongInt)。我想測試的實際功能在內部處理這些不同情況。

sealed trait FunArgs 
final case class FunArgs1(a: Int, b: Int) extends FunArgs 
final case class FunArgs2(x: Long, y: Int, z: String) extends FunArgs 

sealed trait FunRes 
final case class FunRes1(...) extends FunRes 
final case class FunRes2(...) extends FunRes 

def someFun(args: FunArgs): FunRes = args match { 
    // do stuff and return some subclass of FunRes 
} 

trait SomeBehaviors { this: UnitSpec => 

    def someBehavior(args: FunArgs) { 

    it should "do stuff " in { 
     val result = someFun(args) // creates an instance of FunRes 
     ... 
     result should contain theSameElementsAs expected 
    } 

    it should "do more stuff" in { 
     // similar to before 
     ... 
     result should contain theSameElementsAs expected 
    } 
    } 
} 

裏面的行爲功能的多個in條款,因爲所有的功能需要滿足相同的行爲。

的問題是,我不能這樣做,因爲它會創建重複的測試名稱:

forAll { (a: Int, b: Int) => 
    someBehavior(FunArgs1(a, b)) 
} 

但我也不能這樣做,因爲「在」應該'這裏面:

"someFun1" should "do stuff" in { 
    forAll { (a: Int, b: Int) => 
    someBehaviour(FunArgs1(a, b)) 
    } 
} 

下面這行不會給我使用生成器的可能性,因爲我不得不將forAll放在行爲中,在這種行爲中我不一定知道參數有多少和什麼類型。

"someFun1" should behave like someBehaviour(MakeFunArgs1(a, b)) 

有沒有辦法做我想做的事?

+0

如果我正確理解你想要達到的目標,你應該定義一個自定義的'Gen [FunArgs]'生成器(名字叫funArgs')。然後,你可以很容易地寫出'forAll(funArgs){fa => someBehavior(fa)}'形式的屬性,它將覆蓋所有的'FunArgs'子類型,而不是爲每個子類型編寫一個屬性。 – Jubobs

回答

0

你可以做這樣的事情

trait SomeBehaviors { this: UnitSpec => 

    def someBehavior(index:Int, args: FunArgs) { 

    it should s"do stuff $index" in { 
     val result = someFun(args) // creates an instance of FunRes 
     ... 
     result should contain theSameElementsAs expected 
    } 

    it should "do more stuff $index" in { 
     // similar to before 
     ... 
     result should contain theSameElementsAs expected 
    } 
    } 
} 

你可以調用具有獨特testCaseName如下:

var index=0 
forAll { (a: Int, b: Int) => 
    someBehavior(index,FunArgs1(a, b)) 
    index = index+1 
} 

,而不是指數你也可以使用& b生成一個唯一的名稱,那會解決這個問題。

+0

這將創建一個潛在的巨大數量的子案例,即使他們應該在測試報告中只有一個條目也會被列出。畢竟他們都檢查同樣的事情,只是爲了不同的輸入。 –