5

一部のアプリケーション ドメイン (GameDev など) では、出力を生成するためにランダムな値を使用して多くの関数を作成する必要があります。例の 1 つを以下に示します。

def generate_key(monster_key_drop_coef):
    key_letters = string.ascii_uppercase
    rand = random.random()
    if monster_key_drop_coef < rand:
        return None

    button = {}
    button["type"] = random.choice([1,2,3])
    button["letter"] = random.choice(key_letters)
    return button

この関数は、いくつかのランダム操作に基づいてアイテムのドロップを生成します。この関数の正確性を自動的に検証したい場合、問題が発生します。生成された値は決定論的ではなく、回帰テストの作成は不可能のようです。

私の質問は次のとおりです。

  1. このタイプの関数に対して有用な回帰テストを作成することは可能ですか?
  2. この場合、他のタイプのテストを作成するための一般的なアプローチはありますか?
4

2 に答える 2

3

有用な単体テストの 1 つを以下に示します。

def test_generate_key():
    button_list = []
    for _ in range(1, 1000):
        button_list.append(generate_key(0.2))

    is_all_none = True
    is_not_none = False
    for key in button_list:
        is_all_none &= (key is None)
        is_not_none |= (key is not None)

    assert is_all_none == False
    assert is_not_none == True

関数の署名を検証し、関数のコードのすべての行をカバーし (良い確率で)、99.999% のケースで合格します。また、関数が 1000 から少なくとも 1 つのドロップを生成し、ドロップを生成しないこともあることが検証されました。アイテムがドロップする確率は 0.2 です。

于 2012-06-11T16:52:38.413 に答える
2

依存性注入を使用するように関数を書き直します(乱数ジェネレーターはパラメーターとして関数に渡されます)。次に、乱数ジェネレーターのモックを渡して、さまざまな決定論的な「ランダム」入力で関数をテストできます。

もちろん、ランダム呼び出しの結果に依存しないアサーションをテストすることもできます。そのような:

  • 関数は、Noneまたはキー「type」および「letter」を含むdictを返します。
  • ディクショナリが返される場合、値は適切なタイプと範囲です。

1000分の1であっても、非決定論的な結果をもたらす単体テストを作成することは決してありません。私はすべてのテストの失敗を気にします、そして確率論的な結果は不安になるでしょう。乱数ジェネレーターとは独立して関数をテストできるように、ランダム性をカプセル化することをお勧めします。

于 2012-06-24T16:20:44.510 に答える