japanese/tests/test_pinyin_checker.py
panli 2e4dcf8980 feat: 新增 jlearn 学习资料生成器 + 日语音变标注体系
新增学习资料生成器模块(learner),从权威库生成多维日语学习资料:
- 拼音/假名/汉字/熟字训四类索引,带拼音↔假名↔汉字交叉跳转
- 逐字音训分类(KANJIDIC2 精确查表 + 启发式回退 + 排序键)
- 音变标注体系:浊化(連濁)、半浊化、促音变(促音便)、连声(れんじょう)
  独立配色 + 合并逻辑 + 音变规律说明
- 显式标注表:rendaku_marks(连用形连浊)、renjou_marks(连声)
- 每索引独立例词数配置(jlearn.toml + --config)
- HTML 单页应用 + 静态 HTML + PDF(playwright)

清洗工具增强:
- 拼音校验器(pinyin_checker)集成到 jclean
- 多音字拼音校正、ます形サ変動詞转原型

数据:
- 权威库补充连声词(反応/天皇/陰陽/観音/因縁/三位/輪廻/安穏)
- KANJIDIC2 音训分类表、拼音校正字典

整理 .gitignore:忽略生成产物(output/study_materials)、词典数据库、
任务运行日志、备份文件
2026-09-09 15:44:50 +08:00

66 lines
2.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""拼音校验模块测试。"""
from pl_japanese.cleaner.pinyin_checker import (
check_line, check_segment, is_valid_syllable, _split_into_syllables,
)
class TestSyllableValidity:
def test_valid_syllables(self):
for py in ['xue', 'jue', 'que', 'lv', 'nv', 'yun', 'zhi', 'shi',
'bao', 'shang', 'hai', 'xian', 'er', 'n', 'ng']:
assert is_valid_syllable(py), f'{py} 应为合法音节'
def test_invalid_syllables(self):
for py in ['bap', 'ijao', 'qina', 'hue', 'xyz', 'blah']:
assert not is_valid_syllable(py), f'{py} 应为非法音节'
class TestSegmentCheck:
def test_illegal_syllable_flagged(self):
# 保 标成 bap非法音节
problem = check_segment('', 'bap')
assert problem is not None
assert 'bap' in problem
assert 'bao' in problem # 给出正确建议
def test_wrong_reading_flagged(self):
# 保 标成 xian合法音节但非该字读音
problem = check_segment('', 'xian')
assert problem is not None
assert 'bao' in problem
def test_correct_reading_passes(self):
assert check_segment('', 'bao') is None
assert check_segment('', 'zhong') is None
def test_non_hanzi_skipped(self):
# 假名/字母分段拼音为空,跳过
assert check_segment('める', '') is None
assert check_segment('Q', '') is None
class TestLineCheck:
def test_bad_line_flagged(self):
line = '上|海|保|険:シャン|ハイ|ほ|けん:shang|hai|bap|xian'
problems = check_line(line)
assert len(problems) == 1
assert 'bap' in problems[0]
def test_good_lines_pass(self):
for good in [
'学|生:がく|せい:xue|sheng',
'中|国:ちゅう|ごく:zhong|guo',
'決|める:き|める:jue|',
'血|液:けつ|えき:xue|ye',
]:
assert check_line(good) == [], f'{good} 不应有告警'
class TestSyllableSplit:
def test_connected_pinyin_splits(self):
assert _split_into_syllables('jinri') == ['jin', 'ri']
assert _split_into_syllables('nvjiang') == ['nv', 'jiang']
def test_unsplittable_returns_none(self):
assert _split_into_syllables('bapxian') is None