3

私はいくつかの古いユニット テストをプロパティ ベース テスト (PBT) に置き換えようとしてscalascalatest - scalacheckます。テストしたいメソッドがある場合、単純化された状況は次のとおりです。

 def upcaseReverse(s:String) = s.toUpperCase.reverse

通常、次のような単体テストを作成します。

assertEquals("GNIRTS", upcaseReverse("string"))
assertEquals("", upcaseReverse(""))
// ... corner cases I could think of

したがって、テストごとに、期待する出力を書きますが、問題ありません。さて、PBT では、次のようになります。

property("strings are reversed and upper-cased") {
 forAll { (s: String) =>
   assert ( upcaseReverse(s) == ???) //this is the problem right here!
 }
}

すべての入力に対して true になるテストを作成しようとすると、テストでStringメソッドのロジックを再度作成する必要があることに気付きます。この場合、テストは次のようになります。

   assert ( upcaseReverse(s) == s.toUpperCase.reverse) 

つまり、出力が正しいことを確認するために、テストで実装を作成する必要がありました。これから抜け出す方法はありますか?私は PBT を誤解していますか?代わりに、次のような他のプロパティをテストする必要があります。

  • 「文字列はオリジナルと同じ長さでなければなりません」
  • 「文字列には元のすべての文字が含まれている必要があります」
  • 「文字列に小文字を含めないでください」...

それももっともらしいですが、かなり不自然で明確ではないように思えます。PBT の経験が豊富な人は、ここで光を当てることができますか?

編集: @Eric のソースをたどってこの投稿にたどり着きました。(カテゴリの適用でもう一度times): ( F#)内のメソッドをテストするために 、まさに私が意味することの例があります:

type Dollar(amount:int) =
member val Amount  = amount 
member this.Add add = 
    Dollar (amount + add)
member this.Times multiplier  = 
    Dollar (amount * multiplier)
static member Create amount  = 
    Dollar amount  

著者は、最終的に次のようなテストを作成します。

let ``create then times should be same as times then create`` start multiplier = 
let d0 = Dollar.Create start
let d1 = d0.Times(multiplier)
let d2 = Dollar.Create (start * multiplier)      // This ones duplicates the code of Times!
d1 = d2

したがって、そのメソッドをテストするために、メソッドのコードがテストで複製されます。この場合、乗算と同じくらい些細なことですが、より複雑なケースに推定されると思います。

4

2 に答える 2