tianwen / tests /test_core.py
liuyd-dev's picture
v0: zero is infinite
07c10da verified
Raw
History Blame Contribute Delete
3.74 kB
"""核心后端单测 (stdlib unittest, 免装依赖): 排盘 / 安全护栏 / 摇卦。
运行: python -m unittest discover -s tests
"""
import datetime as _dt
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from bazi.engine import compute_five_dim
from bazi.five_elements import ELEMENT_ORDER
from safety.intercept import check
from divination.coin import COIN_SUM_TO_LINE, LINE_VALUE_TO_NAME
from divination.hexagram import hex_from_six_lines, get_hexagram
class TestEngine(unittest.TestCase):
def setUp(self):
self.r = compute_five_dim(1990, 5, 15, 14, 30, 1).to_dict()
def test_four_pillars(self):
self.assertEqual(len(self.r["ming"]["pillars"]), 4)
for p in self.r["ming"]["pillars"]:
self.assertTrue(p["gan"] and p["zhi"])
def test_zodiac(self):
self.assertIn(self.r["ming"]["zodiac"], "鼠牛虎兔龙蛇马羊猴鸡狗猪")
def test_dayun_covers_0_to_120(self):
stages = self.r["yun"]["dayun_list"]
self.assertEqual(stages[0]["start_age"], 0) # 含童限
self.assertGreaterEqual(stages[-1]["end_age"], 120) # 外推至 120
cur = self.r["yun"]["current_index"]
self.assertTrue(0 <= cur < len(stages))
def test_element_scores(self):
scores = self.r["state"]["element_scores"]
self.assertEqual(set(scores), set(ELEMENT_ORDER))
for v in scores.values():
self.assertTrue(8 <= v <= 96)
def test_true_solar_time_shifts_hour(self):
# 偏离时区中央经线 (120°E) 会改变时辰 → 时柱可能不同
east = compute_five_dim(1990, 5, 15, 23, 50, 1, longitude=120).to_dict()
west = compute_five_dim(1990, 5, 15, 23, 50, 1, longitude=75).to_dict()
self.assertNotEqual(
east["birth"]["solar_corrected"], west["birth"]["solar_corrected"]
)
def test_southern_hemisphere_shifts_month(self):
north = compute_five_dim(1995, 6, 15, 12, 0, 1, southern=False).to_dict()
south = compute_five_dim(1995, 6, 15, 12, 0, 1, southern=True).to_dict()
self.assertNotEqual(
north["ming"]["pillars"][1]["zhi"], south["ming"]["pillars"][1]["zhi"]
)
class TestSafety(unittest.TestCase):
def test_crisis_blocked(self):
for txt in ("我不想活了", "感觉走投无路", "i want to die"):
hit, payload = check(txt)
self.assertTrue(hit, txt)
self.assertIn("热线", payload)
def test_normal_passes(self):
for txt in ("今天适合静心读书", "想换个工作", ""):
hit, _ = check(txt)
self.assertFalse(hit, txt)
def test_obfuscation_caught(self):
# 空格 / 标点穿透
hit, _ = check("我 想 死")
self.assertTrue(hit)
class TestDivination(unittest.TestCase):
def test_coin_sum_mapping(self):
# 三枚铜钱和 6-9 → 老阴/少阳/少阴/老阳
self.assertEqual(set(COIN_SUM_TO_LINE), {6, 7, 8, 9})
for s, v in COIN_SUM_TO_LINE.items():
self.assertIn(LINE_VALUE_TO_NAME[v], ("老阴", "少阳", "少阴", "老阳"))
def test_hex_code_range(self):
for bits in ([1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 1, 0]):
code = hex_from_six_lines(bits)
self.assertTrue(0 <= code <= 63)
hexagram = get_hexagram(code)
self.assertTrue(hexagram.name)
def test_qian_kun(self):
self.assertEqual(get_hexagram(hex_from_six_lines([1] * 6)).name, "乾为天")
self.assertEqual(get_hexagram(hex_from_six_lines([0] * 6)).name, "坤为地")
if __name__ == "__main__":
unittest.main()