2017-07-25 13 views
2

私はScalaの初心者です。私は最初のScalacheckスイートを書いています。多くのケースを破棄してカスタムジェネレータが失敗したScalacheckテストはなぜですか?これを修正するにはどうすればよいですか?

私は(List[Double], List[Double])のような本質的には_1の各要素が_2の対応する要素よりも厳密に大きい場合にのみ整形式のデータ構造を持っています。

実際には少し複雑です(このMWEの目的のために、そこにすべてがあるとは思うかもしれませんが)、私はカスタム発電機を作成しました。

私は、その後のメッセージで、Gave up after only XX passed tests. YYY tests were discarded.

を2つの些細(すべての最も些細含め、1 == 1)テストとの両方のケースでのテストが失敗を追加なぜそれがある、と私はそれをどのように修正するのですか?

添付のテストスイートと出力です。


package com.foo.bar 

import org.scalacheck._ 
import Prop._ 
import Arbitrary._ 

object FooSpecification extends Properties("FooIntervals") { 

    type FooIntervals = (List[Double], List[Double]) 

    /* This is supposed to be a tuple of lists s.t. each element of _1 
    * is < the corresponding element of _2 
    * 
    * e.g. (List(1,3,5), List(2,4,6)) 
    */ 

    implicit def arbInterval : Arbitrary[FooIntervals] = 
    Arbitrary { 
     /** 
     * Yields a pair (low, high) s.t. low < high 
     */ 
     def GenPair : Gen[(Double, Double)] = for { 
     low <- arbitrary[Double] 
     high <- arbitrary[Double].suchThat(_ > low) 
     } yield (low, high) 

     /** 
     * Yields (List(x_1,...,x_n), List(y_1,...,y_n)) 
     * where x_i < y_i forall i and 1 <= n < 20 
     */ 
     for { 
     n <- Gen.choose(1,20) 
     pairs : List[(Double, Double)] <- Gen.containerOfN[List, (Double, Double)](n, GenPair) 
     } yield ((pairs.unzip._1, pairs.unzip._2)) 
    } 

    property("1 == 1") = forAll { 
    (b1: FooIntervals) 
    => 
    1 == 1 
    } 

    property("_1.head < _2.head") = forAll { 
    (b1: FooIntervals) 
    => 
    b1._1.head < b1._2.head 
    } 
} 

[info] ! FooIntervals.1 == 1: Gave up after only 32 passed tests. 501 tests were discarded. 
[info] ! FooIntervals._1.head < _2.head: Gave up after only 28 passed tests. 501 tests were discarded. 
[info] ScalaTest 
[info] Run completed in 1 second, 519 milliseconds. 
[info] Total number of tests run: 0 
[info] Suites: completed 0, aborted 0 
[info] Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0 
[info] No tests were executed. 
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0 
[error] Failed tests: 
[error]  com.foo.bar.FooSpecification 

答えて

1

arbitrary[Double].suchThat(_ > low)これはあなたの問題です。 suchThatは、条件がfalseのすべてのケースを破棄します。あなたは2つのランダムな値を取って、それらの値の1つが他の値よりも大きい場合をすべて破棄します。 suchThatの代わりにretryUntilを使用すると、値を破棄するのではなく条件が満たされるまで新しい値が生成されますが、これは潜在的に長い時間を要したり、条件が非常に悪い場合に永久にループするという欠点があります。 lowの高い値、あなたはと低く、最大の可能なdouble値を持っているのに十分な不運であれば、それより大きい高を取得するのに長い時間のためのループがかもしれない、あるいは永遠に。

働くだろう何をどの意志Gen.choose(low, Double.MaxValue)ですlowDouble.MaxValueの間の値を選択します(できるだけ大きい倍数)。

chooseまたはoneOfなどを使用してジェネレータを制限して、必要な値だけを選択し、任意の可能な任意の値を生成し、無効なケースを破棄または再試行するよりも良い場合があります。これは、可能性の合計と比較して条件に合わないケースがごくわずかであり、有効なケースがそれらのメソッドを使用して簡単に定義されない場合にのみ行われます。

+0

ああ、ありがとう、私は完全に誤解して、「そのようなこと」の意味を誤解していました。どうもありがとうございました。 –

関連する問題