73 lines
2.9 KiB
Python
73 lines
2.9 KiB
Python
|
|
"""审批与方案版本化的纯函数单元测试(秒级,无需容器)。
|
|||
|
|
|
|||
|
|
守的是「方案内容是否真的变了」这一判定(``business_service._plan_changed``):
|
|||
|
|
它决定要不要新增一个方案版本行、要不要重提审批单。判错的后果是双向的——
|
|||
|
|
判成「变了」会刷出版本与审批留痕噪音,判成「没变」会让改过的方案
|
|||
|
|
沿用旧版本号,版本语义失真。
|
|||
|
|
|
|||
|
|
比较口径是**集合**(人员 ID + 其比例),与提交顺序无关:用户只是把行
|
|||
|
|
拖了个序,不该被算成方案变了。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from decimal import Decimal
|
|||
|
|
|
|||
|
|
import pytest
|
|||
|
|
|
|||
|
|
from app.models.business import SecondaryAllocation
|
|||
|
|
from app.services.business_service import _plan_changed
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _row(personnel_id: int, ratio: str) -> SecondaryAllocation:
|
|||
|
|
"""构造一个未入库的方案行(ORM 实例化不触数据库)。"""
|
|||
|
|
return SecondaryAllocation(
|
|||
|
|
business_id=1,
|
|||
|
|
version_no=1,
|
|||
|
|
personnel_id=personnel_id,
|
|||
|
|
personnel_name=f"t_人员{personnel_id}",
|
|||
|
|
ratio=Decimal(ratio),
|
|||
|
|
is_active=1,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestPlanChanged:
|
|||
|
|
"""方案内容比较。"""
|
|||
|
|
|
|||
|
|
def test_完全相同_判未变(self) -> None:
|
|||
|
|
old = [_row(1, "50.00"), _row(2, "30.00")]
|
|||
|
|
new = [_row(1, "50.00"), _row(2, "30.00")]
|
|||
|
|
assert _plan_changed(old, new) is False
|
|||
|
|
|
|||
|
|
def test_顺序不同_判未变(self) -> None:
|
|||
|
|
"""用户只是把行拖了个序 —— 送审快照按库内生效行顺序生成,
|
|||
|
|
按顺序比较会把这种编辑误判成「方案变了」。"""
|
|||
|
|
old = [_row(1, "50.00"), _row(2, "30.00")]
|
|||
|
|
new = [_row(2, "30.00"), _row(1, "50.00")]
|
|||
|
|
assert _plan_changed(old, new) is False
|
|||
|
|
|
|||
|
|
def test_比例变化_判已变(self) -> None:
|
|||
|
|
old = [_row(1, "50.00")]
|
|||
|
|
new = [_row(1, "80.00")]
|
|||
|
|
assert _plan_changed(old, new) is True
|
|||
|
|
|
|||
|
|
def test_参与人增减_判已变(self) -> None:
|
|||
|
|
old = [_row(1, "50.00")]
|
|||
|
|
assert _plan_changed(old, [_row(1, "50.00"), _row(2, "30.00")]) is True
|
|||
|
|
assert _plan_changed([_row(1, "50.00"), _row(2, "30.00")], [_row(1, "50.00")]) is True
|
|||
|
|
|
|||
|
|
def test_同一人的比例从一人换成另一人_判已变(self) -> None:
|
|||
|
|
"""参与人不同但比例相同:人员 ID 是比较键的一部分,不能只看比例。"""
|
|||
|
|
old = [_row(1, "50.00")]
|
|||
|
|
new = [_row(2, "50.00")]
|
|||
|
|
assert _plan_changed(old, new) is True
|
|||
|
|
|
|||
|
|
@pytest.mark.parametrize("written", ["50", "50.0", "50.00"])
|
|||
|
|
def test_比例写法不同_判未变(self, written: str) -> None:
|
|||
|
|
"""比例入参是字符串('50' 与 '50.00' 都合法),数值相同即未变。"""
|
|||
|
|
assert _plan_changed([_row(1, "50.00")], [_row(1, written)]) is False
|
|||
|
|
|
|||
|
|
def test_空方案与空方案_判未变(self) -> None:
|
|||
|
|
assert _plan_changed([], []) is False
|
|||
|
|
|
|||
|
|
def test_空方案与有方案_判已变(self) -> None:
|
|||
|
|
assert _plan_changed([], [_row(1, "50.00")]) is True
|