Skip to content

Commit 60fe20c

Browse files
author
Nils Bars
committed
Streamline the usage of the word group and task
See remote-exercise-framework/ref/issues/16
1 parent 827bb60 commit 60fe20c

1 file changed

Lines changed: 50 additions & 45 deletions

File tree

ref_utils/decorator.py

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
import json
1212

1313
TEST_RESULT_PATH = Path("/var/test_result")
14-
DEFAULT_GROUP_NAME = 'default'
15-
__registered_test_groups: ty.Dict[str, '_TestGroup'] = {}
14+
DEFAULT_TASK_NAME = 'default'
15+
__registered_tasks: ty.Dict[str, '_Task'] = {}
1616

1717
@dataclass
1818
class TestResult():
@@ -32,13 +32,18 @@ class _TestResult():
3232
"""
3333
Class used to serialize data before sending it to the webserver.
3434
"""
35-
name: str
35+
task_name: str
3636
success: bool
3737
score: ty.Optional[float]
3838

39-
class _TestGroup():
39+
class _Task():
4040
"""
41-
Tests can be grouped and a group is only successfull when all tests in it pass.
41+
A submission test can contain multiple tasks that are each checked individually and
42+
do not require other tasks to success.
43+
A Task consists of (see decorators below):
44+
- none or multiple environment tests
45+
- none or one submission_test
46+
- none or one extended_submission_test
4247
"""
4348

4449
def __init__(self, name: str) -> None:
@@ -47,58 +52,58 @@ def __init__(self, name: str) -> None:
4752
self.submission_test: ty.Optional[Callable[..., Any]]= None
4853
self.extended_submission_test: ty.Optional[Callable[..., Any]] = None
4954

50-
def add_environment_test(group: str = DEFAULT_GROUP_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
55+
def add_environment_test(task_name: str = DEFAULT_TASK_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
5156
warnings.warn("Please use @environment_test instead of @add_environment_test")
52-
return environment_test(group)
57+
return environment_test(task_name)
5358

54-
def environment_test(group: str = DEFAULT_GROUP_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
59+
def environment_test(task_name: str = DEFAULT_TASK_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
5560

5661
def _environment_test(func: Callable[..., Any]) -> Callable[..., Any]:
5762
@wraps(func)
5863
def wrapper(*args: str, **kwargs: Any) -> Any:
5964
return func(*args, **kwargs)
6065

61-
if group not in __registered_test_groups:
62-
__registered_test_groups[group] = _TestGroup(group)
63-
__registered_test_groups[group].env_tests.append(wrapper)
66+
if task_name not in __registered_tasks:
67+
__registered_tasks[task_name] = _Task(task_name)
68+
__registered_tasks[task_name].env_tests.append(wrapper)
6469

6570
return wrapper
6671
return _environment_test
6772

68-
def add_submission_test(group: str = DEFAULT_GROUP_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
73+
def add_submission_test(task_name: str = DEFAULT_TASK_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
6974
warnings.warn("Please use @submission_test instead of @add_submission_test")
70-
return submission_test(group)
75+
return submission_test(task_name)
7176

72-
def submission_test(group: str = DEFAULT_GROUP_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
77+
def submission_test(task_name: str = DEFAULT_TASK_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
7378

7479
def _submission_test(func: Callable[..., Any]) -> Callable[..., Any]:
7580
@wraps(func)
7681
def wrapper(*args: str, **kwargs: Any) -> Any:
7782
return func(*args, **kwargs)
7883

79-
if group not in __registered_test_groups:
80-
__registered_test_groups[group] = _TestGroup(group)
81-
g = __registered_test_groups[group]
84+
if task_name not in __registered_tasks:
85+
__registered_tasks[task_name] = _Task(task_name)
86+
g = __registered_tasks[task_name]
8287
if g.submission_test is not None:
83-
raise RefUtilsError("The @submission_test decorator can only be used once. Set the group kwarg to different values, if you have multiple tasks.")
88+
raise RefUtilsError("The @submission_test decorator can only be used once. Set the task_name kwarg to different values, if you have multiple tasks.")
8489
g.submission_test = wrapper
8590

8691
return wrapper
8792
return _submission_test
8893

89-
def extended_submission_test(group: str = DEFAULT_GROUP_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
94+
def extended_submission_test(task_name: str = DEFAULT_TASK_NAME) -> Callable[[Callable[[Callable[..., Any]], Any]], Any]:
9095

9196
def _extended_submission_test(func: Callable[..., Any]) -> Callable[..., Any]:
9297
@wraps(func)
9398
def wrapper(*args: str, **kwargs: Any) -> Any:
9499
return func(*args, **kwargs)
95100

96-
if group not in __registered_test_groups:
97-
__registered_test_groups[group] = _TestGroup(group)
98-
g = __registered_test_groups[group]
101+
if task_name not in __registered_tasks:
102+
__registered_tasks[task_name] = _Task(task_name)
103+
g = __registered_tasks[task_name]
99104
if g.extended_submission_test is not None:
100-
raise RefUtilsError("The @extended_submission_test decorator can only be used once. Set the group kwarg to different values, if you have multiple tasks.")
101-
__registered_test_groups[group].extended_submission_test = wrapper
105+
raise RefUtilsError("The @extended_submission_test decorator can only be used once. Set the task_name kwarg to different values, if you have multiple tasks.")
106+
__registered_tasks[task_name].extended_submission_test = wrapper
102107

103108
return wrapper
104109
return _extended_submission_test
@@ -110,17 +115,17 @@ def run_tests() -> None:
110115
"""
111116
print_ok('[+] Running tests..')
112117
all_tests_passed = True
113-
has_multiple_groups = len(__registered_test_groups) > 1
114-
group_test_results: ty.List[_TestResult] = []
118+
has_multiple_tasks = len(__registered_tasks) > 1
119+
task_test_results: ty.List[_TestResult] = []
115120

116121
# Run all sub-tasks one after another.
117-
for group_name, tests in __registered_test_groups.items():
118-
group_passed = True
122+
for task_name, tests in __registered_tasks.items():
123+
task_passed = True
119124

120125
TEST_RESULT_PATH.unlink(missing_ok=True)
121126

122-
if has_multiple_groups:
123-
print_ok(f'[+] *** Running tests for group \"{group_name}\" ***')
127+
if has_multiple_tasks:
128+
print_ok(f'[+] *** Running tests for task \"{task_name}\" ***')
124129

125130
if tests.env_tests and not tests.submission_test and not tests.extended_submission_test:
126131
raise RefUtilsError("Using @environment_test without @submission_test or @extended_submission_test is not allowed")
@@ -130,47 +135,47 @@ def run_tests() -> None:
130135
ret = test()
131136
if not isinstance(ret, bool):
132137
raise RefUtilsError("Function with the @environment_test decorator must return a bool")
133-
group_passed &= ret
138+
task_passed &= ret
134139
all_tests_passed = False
135140

136141
#Do not run submission tests if the environ is invalid
137-
if not group_passed:
138-
group_test_results.append(_TestResult(group_name, False, None))
139-
if has_multiple_groups:
140-
# Only print this if we have multiple groups. If we only have one,
142+
if not task_passed:
143+
task_test_results.append(_TestResult(task_name, False, None))
144+
if has_multiple_tasks:
145+
# Only print this if we have multiple tasks. If we only have one,
141146
# the would just duplicate the error printed at the end.
142-
print_err('[!] Group failed!')
147+
print_err('[!] Task failed!')
143148
continue
144149
print_ok('[+] Environment tests passed')
145150

146151
print_ok('[+] Testing submission...')
147152
if tests.submission_test:
148153
ret = tests.submission_test()
149154
if isinstance(ret, bool):
150-
ret = _TestResult(group_name, ret, None)
155+
ret = _TestResult(task_name, ret, None)
151156
elif isinstance(ret, TestResult):
152-
ret = _TestResult(group_name, ret.success, ret.score)
157+
ret = _TestResult(task_name, ret.success, ret.score)
153158
else:
154159
raise RefUtilsError(f"Submission test returned unexpected type: {type(ret)}")
155160

156-
group_test_results.append(ret)
157-
group_passed &= ret.success
161+
task_test_results.append(ret)
162+
task_passed &= ret.success
158163
all_tests_passed = False
159164
else:
160165
# If there is no test, we consider this to be an success.
161-
group_test_results.append(_TestResult(group_name, True, None))
166+
task_test_results.append(_TestResult(task_name, True, None))
162167
print_ok("[+] No test found")
163168

164-
if not group_passed and has_multiple_groups:
169+
if not task_passed and has_multiple_tasks:
165170
# Avoid printing errors twice.
166-
print_err('[!] Group failed!')
167-
elif group_passed:
171+
print_err('[!] Task failed!')
172+
elif task_passed:
168173
print_ok('[+] Test passed')
169174

170175
if not all_tests_passed:
171176
print_err('[!] Some tests failed! Please review your submission to avoid penalties during grading.')
172177
else:
173178
print_ok('[+] All tests passed! Good job. Ready to submit!')
174179

175-
results = json.dumps([asdict(e) for e in group_test_results])
180+
results = json.dumps([asdict(e) for e in task_test_results])
176181
TEST_RESULT_PATH.write_text(results)

0 commit comments

Comments
 (0)