23

文字列をエンコード/デコードする一連の簡単なデモ プログラムがあり、それらに対していくつかのquickCheckテストを生成したいが、テストを印刷可能な文字列のみに限定したい。生成されたテスト ケースと拒否されたテスト ケースが多すぎるため、ガードの使用は遅すぎて失敗するため、このドメイン用の安全なジェネレーターを作成したいと考えています。

私が見た this への参照は、(1) Charの独自のArbitraryインスタンスを定義し、それを使用して文字列の印刷可能な文字のみを生成するか、(2) 関数自体をnewtypeでラップしてArbitraryを記述する必要があることを示しています。そのためのインスタンス。

しかし、(1) これを実行しようとすると失敗します。Test.QuickCheck にこれの定義があるためです。これを行うにはどうすればよいでしょうか。新しい型のsafeCharジェネレーターを作成し、テストされた関数へのアダプターを再度作成する必要があります。 ? (これに関する RWH 本のセクションでは、この DIY Char 定義を推奨するのは時代遅れであると述べています。)

(2) を実行しようとすると、ローカライズされた単純な (しかし失敗する) テスト命題にガードを追加するか、新しいラッパーと関連するジェネレーターを作成することができますが、これは面倒に思えます。

明らかにこれは単純で (!)、すべてのツールが提供されていますが、誰かがこれが正しい分析であるかどうかをアドバイスし、これを行う最善の方法の例を挙げてもらえますか?

4

2 に答える 2

24

出発点は間違いなくgenSafeCharジェネレータであり、 type を持つことができますGen Char。例えば:

genSafeChar :: Gen Char
genSafeChar = elements ['a'..'z']

genSafeString次に、それをジェネレーターに組み込むことができます。たとえば、次のようにしlistOfます。

genSafeString :: Gen String
genSafeString = listOf genSafeChar

この時点で、合理的な選択肢がいくつかあります。newtype次のラッパーを作成しStringます。

newtype SafeString = SafeString { unwrapSafeString :: String }
    deriving Show

instance Arbitrary SafeString where
    arbitrary = SafeString <$> genSafeString

(この場合、 の定義をインライン化することができますgenSafeString)

そして、次のように使用できます。

testWibble (SafeString str) = str == str

または、forAll安全な文字列が必要な各ポイントで使用できます。

testWibble = forAll genSafeString $ \str -> str == str
于 2014-01-05T17:09:23.367 に答える
10

現在、 には のインスタンスもQuickCheckある型があります。つまり、次の方法で任意の文字列を簡単に生成できます。PrintableStringarbitrary

arbitraryPrintableString :: Gen String
arbitraryPrintableString = getPrintableString <$> arbitrary
于 2018-02-21T13:05:19.817 に答える