假设是您的用例的绝佳可能性 - 如果您正确使用它。首先,它为什么起作用:它不是随机的,而是伪随机的。当一个复杂示例的测试失败时,它会降低复杂性,直到找到失败的最小测试用例,并为您提供。然后它还存储失败测试用例的数据库,因此重放旧失败是它尝试的第一件事。
现在,缺点是构建测试用例通常需要很长时间,但好处是您可以真正确定您的代码是健壮的。
我不知道你的代码是什么样的,只是给你一个模型:
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
然后在您的测试用例中,将播放脚本提供给您的代码并检查结果是否对齐。我希望你能从中获得灵感。