Additional tests

This commit is contained in:
Patrick Elmer 2023-01-31 10:37:37 +09:00
parent 3a9ef9cae7
commit 2a63c37856
3 changed files with 69 additions and 16 deletions

View File

@ -1,7 +1,7 @@
import re
def apply(change, string, categories={}, apply=True):
def apply(change, string, categories={}, apply=True, zero_characters=['']):
"""Apply a sound change to a given string"""
if not apply:
@ -10,12 +10,11 @@ def apply(change, string, categories={}, apply=True):
# Check validity of change
if change.count('>') != 1:
raise ValueError(f"Change {change} is not a valid sound change. (Missing character '>')")
if change.count('/') > 1:
raise ValueError(f"Change {change} is not a valid sound change. (More than one '/' character)")
# Prepare change for regex
for k, v in {'{': '(', '}': ')', ',': '|'}.items():
for k, v in {' ': '', '{': '(', '}': ')', ',': '|'}.items():
change = change.replace(k, v)
# Replacements for categories
@ -30,15 +29,24 @@ def apply(change, string, categories={}, apply=True):
else:
environment = '_'
# Collaplse multiple underscores
environment = re.sub('(_+)', '_', environment)
if environment.count('_') != 1:
raise ValueError(f"Environment {environment} is not a valid environment. (Character '_' should exist exactly once)")
original, change_to = change.split('>')
before, after = environment.split('_')
n = before.count('(') + original.count('(') + 3
if not original:
raise ValueError(f"Nothing to change from.")
# Remove zero characters
for char in zero_characters:
change_to = change_to.replace(char, '')
pattern = f"({before})({original})({after})"
repl = f"\\1{change_to}\\{n}"
return re.sub(pattern, repl, f"#{string}#").strip('#')
last_group_index = pattern.count('(') - after.count('(')
replacement = f"\\1{change_to}\\{last_group_index}"
return re.sub(pattern, replacement, f"#{string}#").strip('#')

View File

@ -1,13 +1,43 @@
from soundchanger.change import apply
def test_apply_without_environment():
def test_without_environment():
assert apply('p>h', 'pana') == 'hana'
def test_apply_with_environment():
def test_with_environment():
assert apply('p>f/#_u', 'pune') == 'fune'
def test_apply_with_complex_environment():
def test_with_partial_environment():
assert apply('p>h/#_', 'pi') == 'hi'
assert apply('p>h/_i', 'pi') == 'hi'
def test_change_to_nothing():
assert apply('u>', 'fun') == 'fn'
def test_change_to_nothing_with_environment():
assert apply('u>/_n#', 'fun') == 'fn'
def test_change_to_zero_character_with_environment():
assert apply('w>∅', 'kawa') == 'kaa'
def test_custom_zero_character():
assert apply('w>-', 'kawa', zero_characters=['-']) == 'kaa'
def test_whitespace_in_change():
assert apply(' a > b / c _ d ', 'cad') == 'cbd'
def test_multiple_underscores_in_environment():
assert apply('a>b/c___d ', 'cad') == 'cbd'
def test_categories_as_string():
assert apply('V>o', 'ha', categories={'V': 'aiu'}) == 'ho'
assert apply('V>o', 'he', categories={'V': 'aiu'}) == 'he'
def test_categories_as_list():
assert apply('V>o', 'ha', categories={'V': ['a', 'i', 'u']}) == 'ho'
assert apply('V>o', 'he', categories={'V': ['a', 'i', 'u']}) == 'he'
def test_complex_environment():
inputs = ['pana', 'pina', 'puna', 'pama', 'pima', 'puma']
outputs = ['pana', 'hina', 'huna', 'pama', 'hima', 'huma']
for string, output in zip(inputs, outputs):
@ -17,14 +47,14 @@ def test_apply_with_complex_environment():
categories={'N': 'nm'}
) == output
def test_apply_with_complex_group_and_categories():
def test_complex_group_and_categories():
assert apply('e>i/{#,p,t,k}V{m,n,h}_#', 'pane', categories={
'V': 'aiu',
'P': 'ptk',
'N': 'mn',
}) == 'pani'
def test_apply_with_complex_group_and_categories_and_digraphs():
def test_with_complex_group_and_categories_and_digraphs():
assert apply('u>o/#V{ts,pf,t}_k{V,e,o}#', 'atsuka', categories={
'V': ['a', 'i', 'u']
}) == 'atsoka'
@ -34,3 +64,14 @@ def test_apply_with_complex_group_and_categories_and_digraphs():
assert apply('u>o/#V{ts,pf,t}_k{V,e,o}#', 'matsuka', categories={
'V': ['a', 'i', 'u']
}) == 'matsuka'
def test_multiple_changes():
string = 'pana'
for change in ['p>f', 'n>m/fa_']:
string = apply(change, string)
assert string == 'fama'
def test_change_from_category():
assert apply('V>o', 'tatiru', categories={
'V': 'aiu'
}) == 'totoro'

View File

@ -2,14 +2,18 @@ import pytest
import re
from soundchanger.change import apply
def test_parse_change_error_change():
def test_error_in_change():
with pytest.raises(ValueError, match=re.escape("Change is not a valid sound change. (Missing character '>')")):
apply('', '')
def test_apply_error_split():
def test_error_split():
with pytest.raises(ValueError, match=re.escape("Change a>b/c/d is not a valid sound change. (More than one '/' character)")):
apply('a>b/c/d', '')
def test_apply_error_environment():
def test_error_in_environment():
with pytest.raises(ValueError, match=re.escape("Environment c is not a valid environment. (Character '_' should exist exactly once)")):
apply('a>b/c', '')
def test_no_change_from():
with pytest.raises(ValueError, match=re.escape("Nothing to change from.")):
apply('>b', '')