Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions tests/compact/testc_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,17 @@ def test_spell_word(self):
self.assertEqual(
spell_word("คนดี"), ["คอ", "นอ", "คน", "ดอ", "อี", "ดี", "คนดี"]
)
result = spell_word("คน")
self.assertIsInstance(result, list)
self.assertIn("คน", result)

# Edge cases: None and empty string
self.assertEqual(spell_word(None), [])
self.assertEqual(spell_word(""), [])

# multi-syllable: last element is the full word
result_multi = spell_word("คนดี")
self.assertEqual(result_multi[-1], "คนดี")

class UtilTestCaseC(unittest.TestCase):
def test_rhyme(self):
Expand All @@ -37,6 +44,14 @@ def test_thai_word_tone_detector(self):
self.assertEqual(
thai_word_tone_detector("ราคา"), [("รา", "m"), ("คา", "m")]
)
result = thai_word_tone_detector("คนดี")
self.assertIsInstance(result, list)
valid_tones = {"l", "m", "h", "r", "f", ""}
for syllable, tone in result:
self.assertIsInstance(syllable, str)
self.assertIn(tone, valid_tones)
self.assertIsInstance(thai_word_tone_detector("มือถือ"), list)

# Edge cases: None and empty string
self.assertEqual(thai_word_tone_detector(None), [])
self.assertEqual(thai_word_tone_detector(""), [])
Expand All @@ -63,3 +78,5 @@ def test_check_khuap_klam(self):

# Edge cases: empty string returns None
self.assertIsNone(check_khuap_klam(""))
for word in ["กลม", "จริง", "ตา"]:
self.assertIn(check_khuap_klam(word), (True, False, None))
141 changes: 141 additions & 0 deletions tests/core/test_khavee.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,144 @@ def test_check_aek_too(self):
self.assertTrue(
kv.check_aek_too(["หนม", "หน่ม", "หน้ม"]), [False, "aek", "too"]
)


class KhaveeCheckKaruLahuTestCase(unittest.TestCase):
"""Tests for KhaveeVerifier.check_karu_lahu"""

def setUp(self):
self.kv = KhaveeVerifier()

def test_dead_syllable_is_karu(self):
self.assertEqual(self.kv.check_karu_lahu("กด"), "karu")

def test_long_live_syllable_is_karu(self):
self.assertEqual(self.kv.check_karu_lahu("กา"), "karu")

def test_live_syllable_with_final_consonant_is_karu(self):
self.assertEqual(self.kv.check_karu_lahu("กาน"), "karu")

def test_bo_mai_ek_is_lahu(self):
self.assertEqual(self.kv.check_karu_lahu("บ่"), "lahu")

def test_no_short_word_is_lahu(self):
self.assertEqual(self.kv.check_karu_lahu("ณ"), "lahu")

def test_tho_short_word_is_lahu(self):
self.assertEqual(self.kv.check_karu_lahu("ธ"), "lahu")

def test_ko_mai_is_lahu(self):
self.assertEqual(self.kv.check_karu_lahu("ก็"), "lahu")


class KhaveeHandleKarunTestCase(unittest.TestCase):
"""Tests for KhaveeVerifier.handle_karun_sound_silence"""

def setUp(self):
self.kv = KhaveeVerifier()

def test_word_without_karun_unchanged(self):
self.assertEqual(self.kv.handle_karun_sound_silence("คน"), "คน")
self.assertEqual(self.kv.handle_karun_sound_silence("กา"), "กา")

def test_word_ending_with_karun_stripped(self):
# เกมส์ → drop ์ and the consonant before it (ส) → เกม
self.assertEqual(self.kv.handle_karun_sound_silence("เกมส์"), "เกม")

def test_word_ending_with_karun_stripped_2(self):
# รักษ์ → drop ์ + ษ → รัก
self.assertEqual(self.kv.handle_karun_sound_silence("รักษ์"), "รัก")

def test_returns_string(self):
self.assertIsInstance(self.kv.handle_karun_sound_silence("สวัสดี"), str)


class KhaveeCheckAekTooEdgeCasesTestCase(unittest.TestCase):
"""Edge-case tests for KhaveeVerifier.check_aek_too"""

def setUp(self):
self.kv = KhaveeVerifier()

def test_non_string_raises_type_error(self):
with self.assertRaises(TypeError):
self.kv.check_aek_too(123)

def test_dead_syllable_as_aek_flag(self):
self.assertEqual(self.kv.check_aek_too("บท", dead_syllable_as_aek=True), "aek")

def test_dead_syllable_without_flag_returns_false(self):
self.assertFalse(self.kv.check_aek_too("บท", dead_syllable_as_aek=False))

def test_list_with_non_string_element_raises(self):
with self.assertRaises(TypeError):
self.kv.check_aek_too(["ไก่", 42])

def test_both_tone_marks_returns_false(self):
# word with both ่ and ้ should return False
self.assertFalse(self.kv.check_aek_too("ก่้"))


class KhaveeCheckKlonExtendedTestCase(unittest.TestCase):
"""Tests for check_klon k_type=8 and invalid k_type"""

def setUp(self):
self.kv = KhaveeVerifier()

def test_invalid_k_type_returns_error_string(self):
result = self.kv.check_klon("บทกวีทดสอบ", k_type=99)
self.assertIsInstance(result, str)
self.assertIn("Something went wrong", result)

def test_incomplete_klon4_poem(self):
result = self.kv.check_klon("ฉันชื่อหมูกรอบ", k_type=4)
self.assertIsInstance(result, str)
self.assertIn("does not have 4 complete sentences", result)

def test_incomplete_klon8_poem(self):
result = self.kv.check_klon("ฉันชื่อหมูกรอบ", k_type=8)
self.assertIsInstance(result, str)

def test_check_klon8_correct_poem(self):
poem = (
"ฉันชื่อหมูกรอบ ฉันชอบกินไก่ แล้วก็วิ่งไล่ หมาชื่อนํ้าทอง "
"ลคคนเก่ง เอ๋งเอ๋งคะนอง มีคนจับจอง เขาชื่อน้องเธียร"
)
self.assertIsNotNone(self.kv.check_klon(poem, k_type=8))


class KhaveeCheckSaraEdgeCasesTestCase(unittest.TestCase):
"""Edge-case tests for KhaveeVerifier.check_sara"""

def setUp(self):
self.kv = KhaveeVerifier()

def test_bo_mai_ek_returns_oo(self):
self.assertEqual(self.kv.check_sara("บ่"), "ออ")

def test_special_word_เออ(self):
self.assertEqual(self.kv.check_sara("เออ"), "เออ")

def test_special_word_เอ(self):
self.assertEqual(self.kv.check_sara("เอ"), "เอ")

def test_special_word_เอะ(self):
self.assertEqual(self.kv.check_sara("เอะ"), "เอะ")

def test_special_word_เอา(self):
self.assertEqual(self.kv.check_sara("เอา"), "เอา")

def test_special_word_เอาะ(self):
self.assertEqual(self.kv.check_sara("เอาะ"), "เอาะ")

def test_ru_sara(self):
self.assertEqual(self.kv.check_sara("ฤ"), "อึ")

def test_ruea_sara(self):
# ฤา (ฤ + sara aa U+0E32) → อือ; note: ฤๅ uses lakkhangyao, not sara aa
self.assertEqual(self.kv.check_sara("ฤา"), "อือ")

def test_เอือ_sara(self):
self.assertEqual(self.kv.check_sara("เรือ"), "เอือ")

def test_returns_string(self):
self.assertIsInstance(self.kv.check_sara("เริง"), str)
76 changes: 76 additions & 0 deletions tests/core/test_tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,82 @@ def test_ner_locations(self):
)


class BlackboardPreProcessTestCase(unittest.TestCase):
"""Tests for pythainlp.tag.blackboard.pre_process"""

def setUp(self):
from pythainlp.tag.blackboard import pre_process

self.pre_process = pre_process

def test_space_is_escaped(self):
self.assertEqual(self.pre_process([" "]), ["_"])

def test_regular_words_unchanged(self):
self.assertEqual(self.pre_process(["ผม", "รัก", "คุณ"]), ["ผม", "รัก", "คุณ"])

def test_mixed_space_and_words(self):
self.assertEqual(self.pre_process(["ผม", " ", "คุณ"]), ["ผม", "_", "คุณ"])

def test_multiple_spaces(self):
self.assertEqual(self.pre_process([" ", " "]), ["_", "_"])

def test_empty_list(self):
self.assertEqual(self.pre_process([]), [])

def test_non_space_special_chars_unchanged(self):
self.assertEqual(self.pre_process(["_"]), ["_"]) # already escaped form

def test_single_thai_word(self):
self.assertEqual(self.pre_process(["สวัสดี"]), ["สวัสดี"])


class BlackboardPostProcessTestCase(unittest.TestCase):
"""Tests for pythainlp.tag.blackboard.post_process"""

def setUp(self):
from pythainlp.tag.blackboard import TO_UD, post_process

self.post_process = post_process
self.TO_UD = TO_UD

def test_unescape_underscore_to_space(self):
result = self.post_process([("_", "NN"), ("คน", "NN")])
self.assertEqual(result, [(" ", "NN"), ("คน", "NN")])

def test_regular_words_pass_through(self):
result = self.post_process([("ผม", "PPRS"), ("รัก", "VACT")])
self.assertEqual(result, [("ผม", "PPRS"), ("รัก", "VACT")])

def test_unescape_to_space_with_ud(self):
result = self.post_process([("_", "NN")], to_ud=True)
self.assertEqual(result, [(" ", "NOUN")])

def test_regular_word_to_ud(self):
result = self.post_process([("คน", "NN")], to_ud=True)
self.assertEqual(result, [("คน", "NOUN")])

def test_all_to_ud_mappings(self):
for bb_tag, ud_tag in self.TO_UD.items():
if bb_tag == "":
continue # skip empty-string sentinel
result = self.post_process([("word", bb_tag)], to_ud=True)
self.assertEqual(
result[0][1],
ud_tag,
f"TO_UD mapping failed for tag '{bb_tag}': "
f"expected '{ud_tag}', got '{result[0][1]}'",
)

def test_empty_list(self):
self.assertEqual(self.post_process([]), [])
self.assertEqual(self.post_process([], to_ud=True), [])

def test_no_ud_default_preserves_tag(self):
result = self.post_process([("คน", "VV")])
self.assertEqual(result[0][1], "VV")


class TagNNERTestCase(unittest.TestCase):
"""Test pythainlp.tag.thai_nner"""

Expand Down
69 changes: 69 additions & 0 deletions tests/core/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,23 @@
reign_year_to_ad,
remove_dangling,
remove_dup_spaces,
remove_repeat_vowels,
remove_spaces_before_marks,
remove_tone_ipa,
remove_tonemark,
remove_trailing_repeat_consonants,
remove_zw,
reorder_vowels,
sound_syllable,
spell_syllable,
spelling,
syllable_length,
syllable_open_close_detector,
text_to_arabic_digit,
text_to_num,
text_to_thai_digit,
th_zodiac,
thai_consonant_to_spelling,
thai_digit_to_arabic_digit,
thai_keyboard_dist,
thai_strftime,
Expand All @@ -65,6 +70,7 @@
to_idna,
to_lunar_date,
tone_detector,
tone_to_spelling,
words_to_num,
)
from pythainlp.util.morse import morse_decode, morse_encode
Expand Down Expand Up @@ -1048,3 +1054,66 @@ def test_analyze_thai_text(self):
analyze_thai_text("เล่น"),
{'สระ เอ': 1, 'ล': 1, 'ไม้เอก': 1, 'น': 1}
)

# ### pythainlp.util.pronounce

def test_thai_consonant_to_spelling(self):
self.assertEqual(thai_consonant_to_spelling("ก"), "กอ")
self.assertEqual(thai_consonant_to_spelling("ข"), "ขอ")
self.assertEqual(thai_consonant_to_spelling("น"), "นอ")
# multi-char strings and non-consonants pass through unchanged
self.assertEqual(thai_consonant_to_spelling("กา"), "กา")
self.assertEqual(thai_consonant_to_spelling("า"), "า")
self.assertEqual(thai_consonant_to_spelling("A"), "A")
self.assertEqual(thai_consonant_to_spelling(""), "")

def test_tone_to_spelling(self):
self.assertEqual(tone_to_spelling("่"), "ไม้เอก")
self.assertEqual(tone_to_spelling("้"), "ไม้โท")
self.assertEqual(tone_to_spelling("๊"), "ไม้ตรี")
self.assertEqual(tone_to_spelling("๋"), "ไม้จัตวา")
# non-tone-mark characters pass through unchanged
self.assertEqual(tone_to_spelling("ก"), "ก")
self.assertEqual(tone_to_spelling(""), "")

# ### pythainlp.util.spell_words

def test_spell_syllable(self):
result = spell_syllable("แมว")
self.assertIsInstance(result, list)
self.assertEqual(result[-1], "แมว")
result_kon = spell_syllable("คน")
self.assertGreater(len(result_kon), 0)
self.assertIn("คน", result_kon)

# ### pythainlp.util.normalize – remove_repeat_vowels,
# remove_spaces_before_marks, reorder_vowels

def test_remove_repeat_vowels(self):
self.assertEqual(remove_repeat_vowels(""), "")
self.assertEqual(remove_repeat_vowels("สวัสดี"), "สวัสดี")
self.assertEqual(remove_repeat_vowels("นานาา"), "นานา")
self.assertEqual(remove_repeat_vowels("ดีีีี"), "ดี")
# double sara E is reordered to sara Ae before repeat-removal
self.assertEqual(remove_repeat_vowels("เเปลก"), "แปลก")

def test_remove_spaces_before_marks(self):
self.assertEqual(remove_spaces_before_marks(""), "")
self.assertEqual(remove_spaces_before_marks("กิน"), "กิน")
self.assertEqual(remove_spaces_before_marks("ก ิ"), "กิ")
self.assertEqual(remove_spaces_before_marks("ก ุ"), "กุ")
self.assertEqual(remove_spaces_before_marks("ก ่า"), "ก่า")
# spaces between regular consonants are preserved
self.assertIn(" ", remove_spaces_before_marks("ก ข"))

def test_reorder_vowels(self):
self.assertEqual(reorder_vowels(""), "")
self.assertEqual(reorder_vowels("สวัสดี"), "สวัสดี")
# two sara E → sara Ae
self.assertEqual(reorder_vowels("เเปลก"), "แปลก")
# nikhahit (ํ) + sara aa (า) → sara am (ำ)
self.assertEqual(reorder_vowels("\u0e01\u0e4d\u0e32"), "\u0e01\u0e33")
# tone mark reorder: both characters still present after reorder
result = reorder_vowels("\u0e01\u0e32\u0e48")
self.assertIn("\u0e48", result)
self.assertIn("\u0e32", result)
Loading