forked from mttu-developers/konabot
67 lines
2.0 KiB
Python
67 lines
2.0 KiB
Python
import random
|
|
|
|
import pytest
|
|
|
|
from konabot.plugins.trpg_roll.core import RollError, roll_expression
|
|
|
|
|
|
class FakeRandom:
|
|
def __init__(self, randint_values: list[int] | None = None, choice_values: list[int] | None = None):
|
|
self._randint_values = list(randint_values or [])
|
|
self._choice_values = list(choice_values or [])
|
|
|
|
def randint(self, _a: int, _b: int) -> int:
|
|
assert self._randint_values
|
|
return self._randint_values.pop(0)
|
|
|
|
def choice(self, _seq):
|
|
assert self._choice_values
|
|
return self._choice_values.pop(0)
|
|
|
|
|
|
def test_roll_expression_basic():
|
|
rng = FakeRandom(randint_values=[2, 4, 5])
|
|
result = roll_expression("3d6", rng=rng)
|
|
|
|
assert result.total == 11
|
|
assert result.format() == "3d6 = 11\n+3d6=[2, 4, 5]"
|
|
|
|
|
|
def test_roll_expression_multiple_terms():
|
|
rng = FakeRandom(randint_values=[14, 3, 1])
|
|
result = roll_expression("d20+1d4-2", rng=rng)
|
|
|
|
assert result.total == 15
|
|
assert result.format() == "d20+1d4-2 = 15\n+1d20=[14] +1d4=[3] -2=2"
|
|
|
|
|
|
def test_roll_expression_df():
|
|
rng = FakeRandom(choice_values=[-1, 0, 1, 1])
|
|
result = roll_expression("4dF", rng=rng)
|
|
|
|
assert result.total == 1
|
|
assert result.format() == "4dF = 1\n+4dF=[-1, +0, +1, +1]"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("expr", "message"),
|
|
[
|
|
("", "请提供要掷的表达式"),
|
|
("abc", "无法解析表达式"),
|
|
("1d0", "骰子面数必须大于 0"),
|
|
("0d6", "骰子个数必须大于 0"),
|
|
("101d6", "单项最多只能掷 100 个骰子"),
|
|
("1d1001", "骰子面数不能超过 1000"),
|
|
("201d1", "单项最多只能掷 100 个骰子"),
|
|
("1d6*2", "表达式中含有无法识别的内容"),
|
|
],
|
|
)
|
|
def test_roll_expression_invalid(expr: str, message: str):
|
|
with pytest.raises(RollError, match=message):
|
|
roll_expression(expr, rng=random.Random(0))
|
|
|
|
|
|
def test_roll_expression_total_roll_limit():
|
|
with pytest.raises(RollError, match="一次最多只能实际掷 200 个骰子"):
|
|
roll_expression("100d6+100d6+1d6", rng=random.Random(0))
|