- ruff profile in pyproject (E/W/F/I/B/RUF); clean src/ + tests/ - remove dead code: threaded_len/s/d/coat/first_rec_for_size, self.cat in gui - 59 public re-exports added to __all__ (sorted) - renamed l->ln (E741), zip(strict=True), split long lines, [*list, x] (RUF005) - CI: quality job (ruff), test runs tests/ -k 'not gen_all' w/ coverage - README rewritten (commands, API modules, tests/lint/coverage, CI) - docs/tasks.md: P4 recorded - 136 passed, 3 deselected (regen); ruff: all checks passed
118 lines
4.4 KiB
Python
118 lines
4.4 KiB
Python
"""Тесты для ведомости изделий (ГОСТ 2.119)."""
|
||
from __future__ import annotations
|
||
|
||
import io
|
||
|
||
from fastengen.catalog import ProductRecord
|
||
from fastengen.vedomost import (
|
||
Vedomost,
|
||
render_csv,
|
||
render_markdown,
|
||
render_markdown_full,
|
||
render_txt,
|
||
)
|
||
|
||
|
||
def _rec(standard, material, designation):
|
||
return ProductRecord(
|
||
id="x", designation=designation, type="bolt", category="Крепёж",
|
||
standard=standard, material=material, model_file="bolt_M6_20.step",
|
||
attributes={"диаметр": "6"}, created_at="",
|
||
)
|
||
|
||
|
||
def test_groups_sizes_into_single_position():
|
||
recs = [
|
||
_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 8.8 ГОСТ 7805-70"),
|
||
_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×25 8.8 ГОСТ 7805-70"),
|
||
_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М8×30 8.8 ГОСТ 7805-70"),
|
||
_rec("ГОСТ 5915-70", "Сталь 8", "Гайка М6 ГОСТ 5915-70"),
|
||
]
|
||
positions = Vedomost().build(recs)
|
||
# болты М6×20/25/8 - одна позиция (3 размера), гайка - вторая
|
||
assert len(positions) == 2
|
||
bolt = positions[0]
|
||
assert bolt.name == "Болт"
|
||
assert bolt.count == 3
|
||
assert bolt.standard == "ГОСТ 7805-70"
|
||
assert "M6" in bolt.size and "M8" in bolt.size
|
||
|
||
|
||
def test_sizes_handles_cyrillic_M():
|
||
recs = [_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М12×40 8.8 ГОСТ 7805-70")]
|
||
positions = Vedomost().build(recs)
|
||
assert positions[0].size == "M12"
|
||
|
||
|
||
def test_numbers_assigned_in_order():
|
||
recs = [
|
||
_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70"),
|
||
_rec("ГОСТ 5915-70", "Сталь 8", "Гайка М6 ГОСТ 5915-70"),
|
||
]
|
||
positions = Vedomost().build(recs)
|
||
assert [p.number for p in positions] == [1, 2]
|
||
|
||
|
||
def test_render_markdown_contains_header_and_rows():
|
||
recs = [_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70")]
|
||
md = render_markdown(Vedomost().build(recs))
|
||
assert "Ведомость" in md
|
||
assert "ГОСТ 7805-70" in md
|
||
assert md.count("|") >= 10 # заголовок + строки
|
||
|
||
|
||
def test_render_markdown_full_includes_okp_and_mass():
|
||
recs = [_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70")]
|
||
md = render_markdown_full(Vedomost().build(recs))
|
||
assert "ОКПД2" in md
|
||
assert "Масса" in md
|
||
assert "28.93.21.110" in md
|
||
|
||
|
||
def test_render_csv_has_header_and_row():
|
||
recs = [_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70")]
|
||
csv_text = render_csv(Vedomost().build(recs))
|
||
assert "№" in csv_text
|
||
assert "ГОСТ 7805-70" in csv_text
|
||
|
||
|
||
def test_render_txt_table():
|
||
recs = [_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70")]
|
||
txt = render_txt(Vedomost().build(recs))
|
||
assert "Болт" in txt
|
||
assert "ГОСТ 7805-70" in txt
|
||
|
||
|
||
def test_csv_is_parseable():
|
||
recs = [
|
||
_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70"),
|
||
_rec("ГОСТ 5915-70", "Сталь 8", "Гайка М6 ГОСТ 5915-70"),
|
||
]
|
||
csv_text = render_csv(Vedomost().build(recs))
|
||
rows = list(io.StringIO(csv_text))
|
||
assert len(rows) == 3 # заголовок + 2 позиции
|
||
|
||
|
||
def test_okp_code_autofilled_by_product_type():
|
||
recs = [
|
||
_rec("ГОСТ 7805-70", "Сталь 8.8", "Болт М6×20 ГОСТ 7805-70"),
|
||
_rec("ГОСТ 5915-70", "Сталь 8", "Гайка М6 ГОСТ 5915-70"),
|
||
_rec("ГОСТ 6402-70", "Сталь 65Г", "Шайба 6 ГОСТ 6402-70"),
|
||
]
|
||
positions = Vedomost().build(recs)
|
||
by_name = {p.name: p for p in positions}
|
||
assert by_name["Болт"].okp == "28.93.21.110"
|
||
assert by_name["Гайка"].okp == "28.93.21.210"
|
||
assert by_name["Шайба"].okp == "28.93.21.310"
|
||
# product_type заполнен (для ведомости ВЗ)
|
||
assert by_name["Болт"].product_type == "Болт"
|
||
|
||
|
||
def test_vz_type_field_populated():
|
||
recs = [_rec("ГОСТ 5915-70", "Сталь 8", "Гайка М12 ГОСТ 5915-70")]
|
||
positions = Vedomost().build(recs)
|
||
assert positions[0].product_type == "Гайка"
|
||
# в CSV колонка Тип присутствует
|
||
csv_text = render_csv(positions)
|
||
assert "ТИП" in csv_text
|