init: AI培训与智能巡检系统
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,109 @@
|
||||
"""清洗规则单元测试 — 对应 T-1.2 UT。"""
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from app.etl import clean as cl
|
||||
|
||||
|
||||
class TestCleanCell(unittest.TestCase):
|
||||
def test_strip_newlines_and_spaces(self):
|
||||
self.assertEqual(cl.clean_cell("东\n\n\n风"), "东风")
|
||||
self.assertEqual(cl.clean_cell(" HXD1 型 "), "HXD1 型")
|
||||
|
||||
def test_none(self):
|
||||
self.assertEqual(cl.clean_cell(None), "")
|
||||
|
||||
def test_is_empty(self):
|
||||
for v in ["", "-", "——", "—", "/", None, "无"]:
|
||||
self.assertTrue(cl.is_empty(v), v)
|
||||
self.assertFalse(cl.is_empty("现役"))
|
||||
|
||||
|
||||
class TestParseValueUnit(unittest.TestCase):
|
||||
def test_plain_number(self):
|
||||
v, u, _ = cl.parse_value_unit("126.0", "t")
|
||||
self.assertEqual(v, 126.0)
|
||||
self.assertEqual(u, "t")
|
||||
|
||||
def test_with_unit_in_text(self):
|
||||
v, u, _ = cl.parse_value_unit("400km/h(试验)")
|
||||
self.assertEqual(v, 400.0)
|
||||
self.assertEqual(u, "km/h")
|
||||
|
||||
def test_speed_with_default_unit(self):
|
||||
v, u, _ = cl.parse_value_unit("160km/h", "km/h")
|
||||
self.assertEqual(v, 160.0)
|
||||
self.assertEqual(u, "km/h")
|
||||
|
||||
def test_axle_load_with_paren(self):
|
||||
v, u, _ = cl.parse_value_unit("23(25)", "t")
|
||||
self.assertEqual(v, 23.0)
|
||||
self.assertEqual(u, "t")
|
||||
|
||||
def test_composite_takes_first_number(self):
|
||||
v, u, _ = cl.parse_value_unit("2×92(100)", "t")
|
||||
self.assertEqual(v, 2.0) # 取第一个数值,原文保真在 raw_json
|
||||
|
||||
def test_empty_markers(self):
|
||||
for raw in ["——", "-", "", "/"]:
|
||||
v, u, txt = cl.parse_value_unit(raw, "t")
|
||||
self.assertIsNone(v)
|
||||
self.assertEqual(u, "")
|
||||
|
||||
def test_no_number(self):
|
||||
v, u, txt = cl.parse_value_unit("交-直-交传动", "")
|
||||
self.assertIsNone(v)
|
||||
self.assertEqual(txt, "交-直-交传动")
|
||||
|
||||
|
||||
class TestParseYear(unittest.TestCase):
|
||||
def test_year_with_char(self):
|
||||
self.assertEqual(cl.parse_year("1971 年"), 1971)
|
||||
|
||||
def test_year_datetime(self):
|
||||
self.assertEqual(cl.parse_year("2007-12-22 00:00:00"), 2007)
|
||||
|
||||
def test_year_plain(self):
|
||||
self.assertEqual(cl.parse_year("2006"), 2006)
|
||||
|
||||
def test_year_dashes(self):
|
||||
self.assertIsNone(cl.parse_year("——"))
|
||||
self.assertIsNone(cl.parse_year(""))
|
||||
|
||||
|
||||
class TestNormalizeStatus(unittest.TestCase):
|
||||
def test_mapping(self):
|
||||
self.assertEqual(cl.normalize_status("半封存"), "半封存")
|
||||
self.assertEqual(cl.normalize_status("封存"), "封存")
|
||||
self.assertEqual(cl.normalize_status("已淘汰"), "退役")
|
||||
self.assertEqual(cl.normalize_status("样车"), "试验")
|
||||
self.assertEqual(cl.normalize_status(""), "未知")
|
||||
|
||||
|
||||
class TestInferCountryType(unittest.TestCase):
|
||||
def test_default_domestic(self):
|
||||
self.assertEqual(cl.infer_country_type("大连机车车辆厂"), "国产")
|
||||
|
||||
def test_import(self):
|
||||
self.assertEqual(cl.infer_country_type("苏联引进"), "引进仿制")
|
||||
self.assertEqual(cl.infer_country_type("日本制造"), "进口")
|
||||
|
||||
def test_joint(self):
|
||||
self.assertEqual(cl.infer_country_type("中外合资生产"), "中外合资")
|
||||
|
||||
|
||||
class TestForwardFill(unittest.TestCase):
|
||||
def test_fill(self):
|
||||
self.assertEqual(
|
||||
cl.forward_fill(["东风", "", "", "韶山", ""]),
|
||||
["东风", "东风", "东风", "韶山", "韶山"])
|
||||
|
||||
def test_leading_empty(self):
|
||||
self.assertEqual(cl.forward_fill(["", "A"]), ["", "A"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,44 @@
|
||||
"""字段字典/映射单元测试 — 对应 T-1.1 UT。"""
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from app.etl import field_dict as fd
|
||||
|
||||
|
||||
class TestHeaderMapping(unittest.TestCase):
|
||||
def test_basic(self):
|
||||
self.assertEqual(fd.map_header("型号"), "model_code")
|
||||
self.assertEqual(fd.map_header("车号"), "car_number")
|
||||
self.assertEqual(fd.map_header("系列"), "series")
|
||||
|
||||
def test_with_spaces_and_newlines(self):
|
||||
self.assertEqual(fd.map_header("车体长度 /mm"), "length")
|
||||
self.assertEqual(fd.map_header("牵引力 (起动)/kN"), "tractive_start")
|
||||
self.assertEqual(fd.map_header("最高运营时速"), "max_speed")
|
||||
|
||||
def test_unknown(self):
|
||||
self.assertIsNone(fd.map_header("不存在的列"))
|
||||
|
||||
def test_normalize(self):
|
||||
self.assertEqual(fd.normalize_header("车体长度 /mm"), "车体长度/mm")
|
||||
self.assertEqual(fd.normalize_header("东\n风"), "东风")
|
||||
|
||||
|
||||
class TestConfig(unittest.TestCase):
|
||||
def test_all_12_sheets_configured(self):
|
||||
self.assertEqual(len(fd.CATEGORY_CONFIG), 12)
|
||||
|
||||
def test_grain_values(self):
|
||||
for cfg in fd.CATEGORY_CONFIG.values():
|
||||
self.assertIn(cfg["grain"], ("model", "unit"))
|
||||
|
||||
def test_numeric_fields_have_synonyms(self):
|
||||
for field in fd.NUMERIC_UNIT_FIELDS:
|
||||
self.assertIn(field, fd.FIELD_SYNONYMS, field)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,64 @@
|
||||
"""导入管线集成/幂等性测试 — 对应 T-1.2 UT/E2E。"""
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from app.etl import importer
|
||||
|
||||
|
||||
class TestHeaderDetection(unittest.TestCase):
|
||||
def test_find_header_row_skips_title(self):
|
||||
rows = [["全国电力机车型号表"], [], ["型号", "首产时间", "停产时间", "生产商"]]
|
||||
self.assertEqual(importer.find_header_row(rows), 2)
|
||||
|
||||
def test_build_column_map(self):
|
||||
header = ["系列", "型号", "首产时间", "未知列X"]
|
||||
cmap = importer.build_column_map(header)
|
||||
self.assertEqual(cmap[0], "series")
|
||||
self.assertEqual(cmap[1], "model_code")
|
||||
self.assertEqual(cmap[2], "first_year")
|
||||
self.assertTrue(cmap[3].startswith("raw::"))
|
||||
|
||||
|
||||
class TestFullImport(unittest.TestCase):
|
||||
"""跑真实 12 表导入,断言结果与幂等性。"""
|
||||
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.mkdtemp()
|
||||
self.db = os.path.join(self.tmp, "t.db")
|
||||
|
||||
def test_import_and_idempotent(self):
|
||||
if not os.path.isdir(importer.CSV_DIR):
|
||||
self.skipTest("CSV 目录不存在")
|
||||
r1 = importer.import_all(db_path=self.db)
|
||||
self.assertGreater(r1["models"], 0)
|
||||
self.assertGreater(r1["units"], 0)
|
||||
conn = sqlite3.connect(self.db)
|
||||
n1 = conn.execute("SELECT COUNT(*) FROM model").fetchone()[0]
|
||||
conn.close()
|
||||
# 再次导入:应重建而非翻倍(幂等)
|
||||
importer.import_all(db_path=self.db)
|
||||
conn = sqlite3.connect(self.db)
|
||||
n2 = conn.execute("SELECT COUNT(*) FROM model").fetchone()[0]
|
||||
conn.close()
|
||||
self.assertEqual(n1, n2)
|
||||
|
||||
def test_numeric_split_persisted(self):
|
||||
if not os.path.isdir(importer.CSV_DIR):
|
||||
self.skipTest("CSV 目录不存在")
|
||||
importer.import_all(db_path=self.db)
|
||||
conn = sqlite3.connect(self.db)
|
||||
row = conn.execute(
|
||||
"SELECT max_speed_value, max_speed_unit FROM model "
|
||||
"WHERE max_speed_value IS NOT NULL LIMIT 1").fetchone()
|
||||
conn.close()
|
||||
self.assertIsNotNone(row)
|
||||
self.assertIsInstance(row[0], float)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user