2012-02-26 6 views
3

私はrandom.nextDouble()を使用するクラスをテストする必要があります。実行された出力を予知できるように、これらの数値をテストに提供するエレガントな方法はありますか?ランダムな値を使用するクラスをテストする

+3

モックRNGを注入しますか? –

+2

RNGシードを制御しますか? – trutheality

答えて

5

乱数ジェネレータを別のコンポーネントに埋め込み、クラスに注入することをおすすめします。このようにして、模擬インスタンスをテストに注入することができます。それは私の意見で最もエレガントなソリューションです。リフレクションを使っていくつかのトリックを行い、クラス本体内で作成されたランダムジェネレータをオーバーライドすることもできますが、これはまったくお勧めできません。

+0

+1:RNGを播種しても(@ Adamの答え)、IMOは隠れた状態を避けるため、より洗練されたソリューションです。 –

5

はい、あります:シードされた乱数を使用します。

クラスにプライベートコンストラクタを追加して、そのクラスがランダムにシードを取るようにする必要があります。代わりに

random = new Random(); 

を書くのコンストラクタでは、プライベートフィールドrandomを初期化するために

random = new Random(seed); 

を書きます。 creating a Random with a seedによって、ランダムの内部状態をシードから初期化します。 Randomは実際にはランダムではなく、次の戻り値を現在の状態に基づいた擬似乱数ジェネレータであるため、初期状態を設定することにより、一連の呼び出しによって返される数値のシーケンスをランダムに設定します。

デフォルトのコンストラクタではなく、この特別なパッケージプライベートテストコンストラクタを使用して、タイプFooの新しいオブジェクトを初期化します。テストするクラスが同じシードを渡すたびに同じシードを渡す限り毎回擬似乱数列を生成します。

0

あなたのテストは何を証明しようとしていますか?そのnextDoubleは実際に特定の値を返しますか?それは私にとって非常に有用なテストのようには見えません。

あなたがこの種の状況でできることは、あなたのコードを何回も実行すると、毎回違う乱数が得られることを証明することです。 1000のループでそれを実行し、何らかの種類の結果をSetに格納します。次に、Setのサイズがループを繰り返した回数と同じであることをアサートします。

これよりもうまくいくには、「ランダム」が意味するものを正確に数値化する必要があります。全体の本はこれに書かれており、単体テストで試してやるのは本当に有用なことではありません。

+0

なぜ(受理)確率的アルゴリズムが有用でないかをテストしていますか? – DaveFar

+0

私はあなたに尋ねられてうれしいです。 JUnitなどの自動化テストのポイントの1つは、非常に頻繁に実行でき、ソフトウェアが仕様に準拠していればテストが合格するということです。一連の乱数(例えば、少なくとも40%は許可された範囲の半分に収まる必要があります)に合致する条件は、合法的に失敗する可能性があります。実際には、プログラムが正常に動作する場合は失敗する必要があります。したがって、実行するたびにJUnitテストをパスしたい場合、JUnitテストで「これらの数値はランダムです」と表現する方法はありません。もちろん、数字が生成されたことをテストすることができます... –

+0

...( 'random.nextDouble'のような)特定のアルゴリズムによって、システムのビジネス要件を反映することはできません。したがって、あなたがテストしているものであってはなりません。唯一合理的なことは、 'Random'の周りにラッパーを置き、ラッパーをスタブし、生成された後に正しいことが乱数に起こっていることをテストすることです。 –

関連する問題