119 lines
4.6 KiB
Python
Executable File
119 lines
4.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Юнит-тесты правил классификации (без камеры)."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||
|
||
from classify import Category, classify_from_dims
|
||
|
||
|
||
def test_suitable_box():
|
||
r = classify_from_dims(120, 80, 40, circle_ratio=0.5)
|
||
assert r.category == Category.SUITABLE
|
||
assert r.category.zone == "B"
|
||
|
||
|
||
def test_oversize_priority_over_circle():
|
||
# Большой цилиндр: габариты важнее круга
|
||
r = classify_from_dims(500, 100, 100, circle_ratio=0.95)
|
||
assert r.category == Category.OVERSIZE
|
||
assert r.category.zone == "C"
|
||
|
||
|
||
def test_too_small():
|
||
r = classify_from_dims(5, 5, 5, circle_ratio=0.2)
|
||
assert r.category == Category.OVERSIZE
|
||
|
||
|
||
def test_need_pack_cylinder():
|
||
r = classify_from_dims(100, 50, 50, circle_ratio=0.85)
|
||
assert r.category == Category.NEED_PACK
|
||
assert r.category.zone == "D"
|
||
|
||
|
||
def test_lying_bottle_must_be_D_not_B():
|
||
"""ТЗ: круг в ЛЮБОМ сечении. Лежачая бутылка сверху не круг, но сечение круглое."""
|
||
# имитация: top-view низкий, но итоговый circle_ratio после 3D-срезов высокий
|
||
r = classify_from_dims(220, 70, 70, circle_ratio=0.86)
|
||
assert r.category == Category.NEED_PACK
|
||
assert r.category.zone == "D"
|
||
|
||
|
||
def test_strict_circle_boundary():
|
||
"""Официально: круг только при K > 0.8. K == 0.8 → B (не D)."""
|
||
below = classify_from_dims(100, 50, 50, circle_ratio=0.799999)
|
||
assert below.category == Category.SUITABLE
|
||
assert below.category.zone == "B"
|
||
assert below.is_circular is False
|
||
|
||
exact = classify_from_dims(100, 50, 50, circle_ratio=0.8)
|
||
assert exact.category == Category.SUITABLE
|
||
assert exact.category.zone == "B"
|
||
assert exact.is_circular is False
|
||
|
||
above = classify_from_dims(100, 50, 50, circle_ratio=0.800001)
|
||
assert above.category == Category.NEED_PACK
|
||
assert above.category.zone == "D"
|
||
assert above.is_circular is True
|
||
|
||
|
||
def test_normal_non_circular_B():
|
||
r = classify_from_dims(120, 80, 40, circle_ratio=0.5)
|
||
assert r.category == Category.SUITABLE
|
||
assert r.category.zone == "B"
|
||
|
||
|
||
def test_normal_circular_above_threshold_D():
|
||
r = classify_from_dims(100, 50, 50, circle_ratio=0.81)
|
||
assert r.category == Category.NEED_PACK
|
||
assert r.category.zone == "D"
|
||
|
||
|
||
def test_oversized_circular_still_C():
|
||
r = classify_from_dims(500, 100, 100, circle_ratio=0.95)
|
||
assert r.category == Category.OVERSIZE
|
||
assert r.category.zone == "C"
|
||
|
||
|
||
def test_border_dims_strict():
|
||
"""ТЗ: строго больше 10×10×10 и строго меньше 450×320×320."""
|
||
# ровно на максимуме → C
|
||
assert classify_from_dims(450, 320, 320, 0.3).category == Category.OVERSIZE
|
||
# ровно на минимуме → C
|
||
assert classify_from_dims(10, 10, 10, 0.3).category == Category.OVERSIZE
|
||
# чуть внутри границ → B
|
||
assert classify_from_dims(449, 319, 319, 0.3).category == Category.SUITABLE
|
||
assert classify_from_dims(11, 11, 11, 0.3).category == Category.SUITABLE
|
||
# 321 мм влезает вдоль оси 450 → B (сопоставление после сортировки)
|
||
assert classify_from_dims(100, 321, 100, 0.3).category == Category.SUITABLE
|
||
# а вот две стороны > 320 уже не влезают → C
|
||
assert classify_from_dims(400, 330, 100, 0.3).category == Category.OVERSIZE
|
||
|
||
|
||
def test_dims_order_independent():
|
||
"""Стороны сопоставляются после сортировки — порядок L/W/H не важен."""
|
||
assert classify_from_dims(319, 449, 318, 0.3).category == Category.SUITABLE
|
||
assert classify_from_dims(318, 319, 449, 0.3).category == Category.SUITABLE
|
||
# ровно 320 по строгому правилу «меньше» → C, в любом порядке
|
||
assert classify_from_dims(320, 449, 319, 0.3).category == Category.OVERSIZE
|
||
assert classify_from_dims(319, 320, 449, 0.3).category == Category.OVERSIZE
|
||
|
||
|
||
if __name__ == "__main__":
|
||
test_suitable_box()
|
||
test_oversize_priority_over_circle()
|
||
test_too_small()
|
||
test_need_pack_cylinder()
|
||
test_lying_bottle_must_be_D_not_B()
|
||
test_strict_circle_boundary()
|
||
test_normal_non_circular_B()
|
||
test_normal_circular_above_threshold_D()
|
||
test_oversized_circular_still_C()
|
||
test_border_dims_strict()
|
||
test_dims_order_independent()
|
||
print("OK: all classification tests passed")
|