import hypothesis
import hypothesis.strategies as st
from skimtoken import (
estimate_tokens,
estimate_tokens_basic,
estimate_tokens_multilingual,
estimate_tokens_multilingual_simple,
estimate_tokens_simple,
)
ESTIMATION_METHODS = [
("default", estimate_tokens),
("basic", estimate_tokens_basic),
("simple", estimate_tokens_simple),
("multilingual", estimate_tokens_multilingual),
("multilingual_simple", estimate_tokens_multilingual_simple),
]
class TestSkimtokenHypothesis:
@hypothesis.given(text=st.text())
@hypothesis.settings(max_examples=100)
def test_non_negative_property(self, text: str):
for name, method in ESTIMATION_METHODS:
result = method(text)
assert result >= 0, f"{name}: negative result {result} for text"
@hypothesis.given(text=st.text(min_size=1))
@hypothesis.settings(max_examples=50)
def test_deterministic_property(self, text: str):
for name, method in ESTIMATION_METHODS:
results = [method(text) for _ in range(3)]
assert len(set(results)) == 1, f"{name}: inconsistent results {results}"
@hypothesis.given(text=st.text(alphabet=st.characters(min_codepoint=32, max_codepoint=126)))
@hypothesis.settings(max_examples=100)
def test_ascii_text_property(self, text: str):
for name, method in ESTIMATION_METHODS:
result = method(text)
assert result >= 0, f"{name}: negative result for ASCII text"
@hypothesis.given(char=st.characters())
@hypothesis.settings(max_examples=200)
def test_single_character_property(self, char: str):
for name, method in ESTIMATION_METHODS:
result = method(char)
assert result >= 0, f"{name}: character '{repr(char)}' returned {result}"
@hypothesis.given(
base=st.text(
min_size=10, max_size=100, alphabet=st.characters(min_codepoint=32, max_codepoint=126)
),
multiplier=st.integers(min_value=3, max_value=5),
)
@hypothesis.settings(max_examples=30)
def test_monotonic_property(self, base: str, multiplier: int):
for name, method in ESTIMATION_METHODS:
single = method(base)
multiple = method(base * multiplier)
assert multiple >= single, (
f"{name}: tokens decreased with more text - {single} -> {multiple}"
)
@hypothesis.given(text1=st.text(min_size=1), text2=st.text(min_size=1))
@hypothesis.settings(max_examples=50)
def test_concatenation_property(self, text1: str, text2: str):
for name, method in ESTIMATION_METHODS:
tokens1 = method(text1)
tokens2 = method(text2)
tokens_concat = method(text1 + text2)
if tokens1 < 0.5 or tokens2 < 0.5:
continue
expected = tokens1 + tokens2
assert expected * 0.3 <= tokens_concat <= expected * 2.5, (
f"{name}: concatenation not additive"
)
@hypothesis.given(size=st.integers(min_value=0, max_value=100000))
@hypothesis.settings(deadline=None) def test_scalability_property(self, size: int):
text = "a" * size
for name, method in ESTIMATION_METHODS:
result = method(text)
assert result >= 0, f"{name}: negative result for size {size}"
@hypothesis.given(whitespace=st.sampled_from([" ", "\t", "\n", "\r", "\f", "\v"]))
def test_whitespace_property(self, whitespace: str):
text = whitespace * 10
for name, method in ESTIMATION_METHODS:
result = method(text)
assert result >= 0, f"{name}: negative result for whitespace"