-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_evaluators.py
More file actions
146 lines (117 loc) · 5.9 KB
/
Copy pathtest_evaluators.py
File metadata and controls
146 lines (117 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"""Tests for evalwire.evaluators."""
import pytest
from evalwire.evaluators import make_membership_evaluator, make_top_k_evaluator
class TestMakeTopKEvaluator:
def test_returns_callable_named_top_k(self):
fn = make_top_k_evaluator(K=10)
assert callable(fn)
assert fn.__name__ == "top_k" # ty: ignore[unresolved-attribute]
def test_item_at_rank_1_scores_1(self):
top_k = make_top_k_evaluator(K=10)
score = top_k(["url-a"], {"expected_output": ["url-a"]})
assert score == pytest.approx(1.0)
def test_item_not_found_scores_0(self):
top_k = make_top_k_evaluator(K=10)
score = top_k(["url-x", "url-y"], {"expected_output": ["url-z"]})
assert score == pytest.approx(0.0)
def test_item_beyond_k_scores_0(self):
top_k = make_top_k_evaluator(K=2)
# url-c is at index 2, which is >= K=2 so outside the window
score = top_k(["url-a", "url-b", "url-c"], {"expected_output": ["url-c"]})
assert score == pytest.approx(0.0)
def test_position_weighting(self):
# K=10, item at position 5 → score = 1 - 5/10 = 0.5
top_k = make_top_k_evaluator(K=10)
output = ["a", "b", "c", "d", "e", "target"]
score = top_k(output, {"expected_output": ["target"]})
assert score == pytest.approx(0.5)
def test_multiple_expected_items_averaged(self):
# K=10: "a" at pos 0 → 1.0; "b" at pos 1 → 0.9; mean = 0.95
top_k = make_top_k_evaluator(K=10)
output = ["a", "b", "c"]
score = top_k(output, {"expected_output": ["a", "b"]})
assert score == pytest.approx(0.95)
def test_partial_hit_among_multiple(self):
# K=4: "a" at pos 0 → 1.0; "missing" not found → 0.0; mean = 0.5
top_k = make_top_k_evaluator(K=4)
output = ["a", "b", "c", "d"]
score = top_k(output, {"expected_output": ["a", "missing"]})
assert score == pytest.approx(0.5)
def test_empty_expected_returns_0(self):
top_k = make_top_k_evaluator(K=10)
score = top_k(["a", "b"], {"expected_output": []})
assert score == pytest.approx(0.0)
def test_expected_as_string_literal_eval(self):
top_k = make_top_k_evaluator(K=10)
score = top_k(["url-a"], {"expected_output": "['url-a']"})
assert score == pytest.approx(1.0)
def test_default_k_is_20(self):
top_k = make_top_k_evaluator()
# item at position 19 (last in top-20) → 1 - 19/20 = 0.05
output = [str(i) for i in range(20)]
score = top_k(output, {"expected_output": ["19"]})
assert score == pytest.approx(1 - 19 / 20)
def test_score_at_last_k_position(self):
# K=5, item at position 4 → 1 - 4/5 = 0.2
top_k = make_top_k_evaluator(K=5)
output = ["a", "b", "c", "d", "target"]
score = top_k(output, {"expected_output": ["target"]})
assert score == pytest.approx(0.2)
def test_empty_output_scores_0(self):
top_k = make_top_k_evaluator(K=10)
score = top_k([], {"expected_output": ["url-a"]})
assert score == pytest.approx(0.0)
def test_missing_expected_output_key_returns_0(self):
top_k = make_top_k_evaluator(K=10)
score = top_k(["a"], {})
assert score == pytest.approx(0.0)
def test_bare_string_expected_output_is_treated_as_single_item(self):
"""A plain identifier string (e.g. from a CSV column) must not crash
ast.literal_eval and should be treated as a single-item expected list."""
top_k = make_top_k_evaluator(K=10)
# "some_url" is a bare identifier — not a Python literal
score = top_k(["some_url"], {"expected_output": "some_url"})
assert score == pytest.approx(1.0)
def test_bare_string_expected_output_no_match(self):
top_k = make_top_k_evaluator(K=10)
score = top_k(["other_url"], {"expected_output": "some_url"})
assert score == pytest.approx(0.0)
class TestMakeMembershipEvaluator:
def test_returns_callable_named_is_in(self):
fn = make_membership_evaluator()
assert callable(fn)
assert fn.__name__ == "is_in" # ty: ignore[unresolved-attribute]
def test_match_returns_true(self):
is_in = make_membership_evaluator()
assert (
is_in("es_search", {"expected_output": ["es_search", "web_search"]}) is True
)
def test_no_match_returns_false(self):
is_in = make_membership_evaluator()
assert (
is_in("unknown", {"expected_output": ["es_search", "web_search"]}) is False
)
def test_expected_as_string_literal_eval(self):
is_in = make_membership_evaluator()
assert is_in("es_search", {"expected_output": "['es_search']"}) is True
def test_empty_expected_returns_false(self):
is_in = make_membership_evaluator()
assert is_in("es_search", {"expected_output": []}) is False
def test_missing_expected_output_key_returns_false(self):
is_in = make_membership_evaluator()
assert is_in("es_search", {}) is False
def test_single_item_list_match(self):
is_in = make_membership_evaluator()
assert is_in("only", {"expected_output": ["only"]}) is True
def test_case_sensitive(self):
is_in = make_membership_evaluator()
assert is_in("ES_SEARCH", {"expected_output": ["es_search"]}) is False
def test_bare_string_expected_output_is_treated_as_single_item(self):
"""A plain identifier string (e.g. from a CSV column) must not crash
ast.literal_eval and should be treated as a single-item expected list."""
is_in = make_membership_evaluator()
# "elasticsearch" is a bare identifier — not a Python literal
assert is_in("elasticsearch", {"expected_output": "elasticsearch"}) is True
def test_bare_string_expected_output_no_match(self):
is_in = make_membership_evaluator()
assert is_in("cms", {"expected_output": "elasticsearch"}) is False