3 回答

TA貢獻1829條經驗 獲得超9個贊
是的,假設聽起來是個好方法。例如:
from unittest import TestCase
from hypothesis import given
from hypothesis.strategies import integers
import hypothesis_random as undertest
class Test(TestCase):
@given(seed=integers())
def test_uses_random(self, seed):
undertest.uses_random(seed)
如果您的函數引發錯誤,您將獲得異常的回溯和來自假設的偽造示例,該示例觸發它作為測試的輸出,例如
Falsifying example: test_uses_random(
self=<test_hypothesis_random.Test testMethod=test_uses_random>, seed=-43,
)
Error
Traceback (most recent call last):
...

TA貢獻1864條經驗 獲得超6個贊
假設對于您的用例來說是一種極好的可能性——如果您使用得當的話。首先,為什么它有效:它不是隨機的,而是偽隨機的。當一個復雜示例的測試失敗時,它會降低復雜性,直到找到失敗的最小測試用例,然后給你那個。然后它還存儲失敗測試用例的數據庫,因此重放舊失敗是它嘗試的第一件事。
現在,缺點是構建測試用例通常需要很長時間,但好處是您可以真正確定您的代碼是健壯的。
我不知道你的代碼是什么樣的,只是為了給你一個模型:
from hypothesis import strategies as st
from hypothesis import assume
# In this example, damage and miss chance are based
# on the length of the name of the attack
samus = Character(health=100, attacks=['punch', 'shoot'])
wario = Character(health=70, attacks=['growl', 'punch'])
bowser = Character(health=250, attacks=['growl', 'kidnap_princess'])
st_character = st.sampled_from([samus, wario, bowser])
st_n_rounds = st.integer(min=0, max=10)
@st.composite
def fight_sequence(draw):
player_one = draw(st_character)
player_two = draw(st_character)
# don't test entire fights, just simulate one, record the steps,
# and check that the end state is what you expect
actions = [
dict(type='choose', player_number=1, player=player_one),
dict(type='choose', player_number=2, player=player_two)
]
# this filters out all test cases where players have the same character
assume(player_one != player_two)
n_rounds = draw(st_n_rounds)
both_alive = True
def _attack(player, other):
if not both_alive:
return
attack = draw(player.attacks)
response = draw(st.integers(min=0, max=len(attack)))
response_type = 'miss' if response == 0 else 'crit' if response == len(attack)) else 'hit'
actions.push(dict(type='attack', player=player, attack=attack, response=response_type))
if response_type == 'hit':
other.health -= len(attack)
elif response_type == 'crit':
other.health -= len(attack) * 2
if other.health <= 0:
actions.push(dict(type='ko', player=other))
for _ in range(n_rounds):
_attack(player_one, player_two)
_attack(player_two, player_one)
return actions
然后在您的測試用例中,將回放腳本提供給您的代碼并檢查結果是否一致。我希望你能以此為靈感。
添加回答
舉報