Skip to content

Commit ce62276

Browse files
authored
Better output ordering (#10)
* Better output ordering * Format with black * Fix the tests * Remove clutter in output
1 parent bfcd15c commit ce62276

File tree

6 files changed

+87
-17
lines changed

6 files changed

+87
-17
lines changed

Diff for: homework_checker/checker.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class Checker:
2020
"""Check homework."""
2121

2222
TESTS_TAG = "tests"
23+
NUMBERING_TAG = "____"
2324

2425
def __init__(self: "Checker", job_file_path: Path):
2526
"""Initialize the checker from file."""
@@ -41,22 +42,22 @@ def check_homework(self: "Checker", homework_node: dict) -> HomeworkResultDict:
4142
deadline_datetime = datetime.strptime(deadline_str, tools.DATE_PATTERN)
4243
if datetime.now() > deadline_datetime:
4344
results[tools.EXPIRED_TAG] = {}
44-
for task_node in homework_node[Tags.TASKS_TAG]:
45+
for idx, task_node in enumerate(homework_node[Tags.TASKS_TAG]):
4546
task = Task.from_yaml_node(
4647
task_node=task_node,
4748
student_hw_folder=current_folder,
4849
job_file=self._job_file_path,
4950
)
5051
if not task:
5152
continue
52-
results[task.name] = task.check()
53+
results[tools.add_number_to_name(idx, task.name)] = task.check()
5354
return results
5455

5556
def check_all_homeworks(self: "Checker") -> Dict[str, HomeworkResultDict]:
5657
"""Run over all Tasks in all homeworks."""
5758
results: Dict[str, HomeworkResultDict] = {}
58-
for homework_node in self._base_node[Tags.HOMEWORKS_TAG]:
59-
hw_name = homework_node[Tags.NAME_TAG]
59+
for idx, homework_node in enumerate(self._base_node[Tags.HOMEWORKS_TAG]):
60+
hw_name = tools.add_number_to_name(idx, homework_node[Tags.NAME_TAG])
6061
current_homework_results = self.check_homework(homework_node)
6162
if current_homework_results:
6263
results[hw_name] = current_homework_results

Diff for: homework_checker/md_writer.py

+24-8
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,48 @@
44

55
from .tools import EXPIRED_TAG
66
from .tools import CmdResult
7+
from .tools import remove_number_from_name
78
from .checker import HomeworkResultDict
89

910
TABLE_TEMPLATE = "| {hw_name} | {task_name} | {test_name} | {result_sign} |\n"
1011
TABLE_SEPARATOR = "|---|---|---|:---:|\n"
1112

12-
ERROR_TEMPLATE = """### `[{hw_name}][{task_name}][{test_name}]:`
13+
ERROR_TEMPLATE = """
14+
<details><summary><b>{hw_name} | {task_name} | {test_name}</b></summary>
1315
14-
*stderr*:
16+
**`stderr`**
1517
```apiblueprint
1618
{stderr}
1719
```
18-
*stdout*:
20+
21+
**`stdout`**
1922
```
2023
{stdout}
2124
```
25+
2226
--------
27+
28+
</details>
29+
2330
"""
2431

2532
EXPIRED_TEMPLATE = """
2633
27-
### `[{hw_name}][Past Deadline][Errors Hidden]`
34+
<details><summary><b>{hw_name}</b></summary>
35+
36+
The deadline for this homework is exceeded. Errors hidden.
37+
38+
-------
39+
40+
</details>
2841
2942
"""
3043

3144
SEPARATOR = "--------\n"
32-
FINISHING_NOTE = "With 💙 from homework bot 🤖\n"
45+
FINISHING_NOTE = "With ❤️ from Homework Bot 🤖\n"
3346

34-
SUCCESS_TAG = ""
35-
FAILED_TAG = ""
47+
SUCCESS_TAG = ""
48+
FAILED_TAG = ""
3649

3750

3851
class MdWriter:
@@ -52,18 +65,21 @@ def __init__(self: "MdWriter"):
5265
def update(self: "MdWriter", hw_results: Dict[str, HomeworkResultDict]):
5366
"""Update the table of completion."""
5467
for hw_name, hw_dict in sorted(hw_results.items()):
68+
hw_name = remove_number_from_name(hw_name)
5569
need_hw_name = True
5670
expired = False
5771
if EXPIRED_TAG in hw_dict:
5872
expired = True
5973
for task_name, ex_dict in sorted(hw_dict.items()):
74+
task_name = remove_number_from_name(task_name)
6075
if task_name == EXPIRED_TAG:
6176
# Maybe there is a better way to handle this, but I don't
6277
# want to dig into this right now. We have added the
6378
# EXPIRED_TAG to this dict and need to ignore it here.
6479
continue
6580
need_task_name = True
6681
for test_name, test_result in sorted(ex_dict.items()):
82+
test_name = remove_number_from_name(test_name)
6783
result_sign = SUCCESS_TAG if test_result.succeeded() else FAILED_TAG
6884
extended_hw_name = (
6985
hw_name + " `[PAST DEADLINE]`" if expired else hw_name
@@ -83,7 +99,7 @@ def write_md_file(self: "MdWriter", md_file_path: Path):
8399
md_file_content = "# Test results\n"
84100
md_file_content += self._md_table
85101
if self._errors:
86-
md_file_content += "\n## Encountered errors\n"
102+
md_file_content += "\n# Encountered errors\n"
87103
md_file_content += self._errors
88104
md_file_content += SEPARATOR
89105
md_file_content += FINISHING_NOTE

Diff for: homework_checker/tasks.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
Your output '{actual}'
1919
Expected output: '{expected}'"""
2020

21-
BUILD_SUCCESS_TAG = "0. Build succeeded"
22-
STYLE_ERROR_TAG = "0. Style errors"
21+
BUILD_SUCCESS_TAG = "Build succeeded"
22+
STYLE_ERROR_TAG = "Style errors"
2323

2424
TOTAL_ERRORS_FOUND_TAG = "Total errors found"
2525

@@ -80,6 +80,12 @@ def __init__(
8080
self._test_nodes = task_node[Tags.TESTS_TAG]
8181
else:
8282
self._test_nodes = [] # Sometimes we don't have tests.
83+
self.__test_counter = 0
84+
85+
def __with_number_prefix(self: Task, test_name: str) -> str:
86+
"""Get the test name with number."""
87+
self.__test_counter += 1
88+
return tools.add_number_to_name(self.__test_counter, test_name)
8389

8490
def check(self: Task) -> Task.ResultDictType:
8591
"""Iterate over the tests and check them."""
@@ -94,7 +100,9 @@ def run_all_tests(
94100
if Tags.INJECT_FOLDER_TAG not in test_node:
95101
# There is no need to rebuild the code. We can just run our tests.
96102
test_result = self._run_test(test_node, executable_folder)
97-
results[test_node[Tags.NAME_TAG]] = test_result
103+
results[
104+
self.__with_number_prefix(test_node[Tags.NAME_TAG])
105+
] = test_result
98106
return results
99107
# There are folders to inject, so we will have to rebuild with the newly
100108
# injected folders. We do it in a new temp folder.
@@ -111,14 +119,16 @@ def run_all_tests(
111119
test_result = self._run_test(
112120
test_node=test_node, executable_folder=build_folder
113121
)
114-
results[test_node[Tags.NAME_TAG]] = test_result
122+
results[
123+
self.__with_number_prefix(test_node[Tags.NAME_TAG])
124+
] = test_result
115125
return results
116126

117127
with tools.TempDirCopy(self._student_task_folder) as code_folder:
118128
# Build the source if this is needed.
119129
build_result, build_folder = self._build_if_needed(code_folder)
120130
if build_result:
121-
results[BUILD_SUCCESS_TAG] = build_result
131+
results[self.__with_number_prefix(BUILD_SUCCESS_TAG)] = build_result
122132
if not build_result.succeeded():
123133
# The build has failed, so no further testing needed.
124134
return results

Diff for: homework_checker/tests/test_checker.py

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import unittest
66

77
from pathlib import Path
8+
from typing import Dict
9+
810
from homework_checker.checker import Checker
911
from homework_checker.md_writer import MdWriter
1012
from homework_checker import tools
@@ -13,6 +15,16 @@
1315
class TestChecker(unittest.TestCase):
1416
"""Test the checker."""
1517

18+
@staticmethod
19+
def __sanitize_results(results: Dict[str, Dict[str, tools.CmdResult]]):
20+
sanitized_results = {}
21+
for key, value in results.items():
22+
sanitized_value = {}
23+
for inner_key, inner_value in value.items():
24+
sanitized_value[tools.remove_number_from_name(inner_key)] = inner_value
25+
sanitized_results[tools.remove_number_from_name(key)] = sanitized_value
26+
return sanitized_results
27+
1628
def test_everything(self: TestChecker):
1729
"""Check all homeworks and Tasks."""
1830
path_to_job = (
@@ -25,6 +37,7 @@ def test_everything(self: TestChecker):
2537
)
2638
checker = Checker(path_to_job)
2739
results = checker.check_all_homeworks()
40+
results = TestChecker.__sanitize_results(results)
2841
self.assertEqual(len(results), 3)
2942
self.assertNotIn("Non existing homework", results)
3043

Diff for: homework_checker/tests/test_task.py

+17
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ def __get_homework_name_and_task(
5050
self.fail("Task cannot be None")
5151
return homework_node[Tags.NAME_TAG], task
5252

53+
@staticmethod
54+
def __sanitize_results(results: dict) -> dict:
55+
"""Sanitize the outputs of the tasks."""
56+
sanitized_results = {}
57+
for key, value in results.items():
58+
sanitized_results[tools.remove_number_from_name(key)] = value
59+
return sanitized_results
60+
5361
def test_check_simple_cpp_io_task(self: "TestTask"):
5462
"""Check that we can build and run cpp code and get some output."""
5563

@@ -59,6 +67,7 @@ def test_check_simple_cpp_io_task(self: "TestTask"):
5967
self.assertEqual(homework_name, "Sample homework")
6068
self.assertEqual(task.name, "Simple cpp tasks")
6169
results = task.check()
70+
results = TestTask.__sanitize_results(results)
6271
expected_number_of_build_outputs = 1
6372
expected_number_of_test_outputs = 3
6473
self.assertEqual(
@@ -81,6 +90,7 @@ def test_check_build_failure_task(self: "TestTask"):
8190
self.assertEqual(homework_name, "Sample homework")
8291
self.assertEqual(task.name, "Build failure task")
8392
results = task.check()
93+
results = TestTask.__sanitize_results(results)
8494
expected_number_of_build_outputs = 1
8595
expected_number_of_test_outputs = 0
8696
self.assertEqual(
@@ -99,6 +109,7 @@ def test_check_cmake_arithmetics_task(self: "TestTask"):
99109
self.assertEqual(homework_name, "Sample homework")
100110
self.assertEqual(task.name, "CMake build arithmetics task")
101111
results = task.check()
112+
results = TestTask.__sanitize_results(results)
102113
expected_number_of_build_outputs = 1
103114
expected_number_of_test_outputs = 2
104115
expected_number_of_code_style_outputs = 0
@@ -122,6 +133,7 @@ def test_check_bash_task(self: "TestTask"):
122133
self.assertEqual(homework_name, "Sample homework")
123134
self.assertEqual(task.name, "Bash task")
124135
results = task.check()
136+
results = TestTask.__sanitize_results(results)
125137
expected_number_of_build_outputs = 0
126138
expected_number_of_test_outputs = 2
127139
expected_number_of_code_style_outputs = 0
@@ -132,6 +144,7 @@ def test_check_bash_task(self: "TestTask"):
132144
+ expected_number_of_code_style_outputs,
133145
"Wrong results: {}".format(results),
134146
)
147+
print(results)
135148
self.assertTrue(results["Test output"].succeeded())
136149
self.assertFalse(results["Test wrong output"].succeeded())
137150

@@ -144,6 +157,7 @@ def test_check_wrong_output_type(self: "TestTask"):
144157
self.assertEqual(homework_name, "Homework where things go wrong")
145158
self.assertEqual(task.name, "Return number task")
146159
results = task.check()
160+
results = TestTask.__sanitize_results(results)
147161
expected_number_of_build_outputs = 1
148162
expected_number_of_test_outputs = 1
149163
expected_number_of_code_style_outputs = 0
@@ -170,6 +184,7 @@ def test_timing_out_task(self: "TestTask"):
170184
self.assertEqual(homework_name, "Homework where things go wrong")
171185
self.assertEqual(task.name, "While loop task")
172186
results = task.check()
187+
results = TestTask.__sanitize_results(results)
173188
expected_number_of_build_outputs = 1
174189
expected_number_of_test_outputs = 1
175190
expected_number_of_code_style_outputs = 0
@@ -198,6 +213,7 @@ def test_google_tests_task(self: "TestTask"):
198213
self.assertEqual(homework_name, "Homework with injections")
199214
self.assertEqual(task.name, "Google Tests")
200215
results = task.check()
216+
results = TestTask.__sanitize_results(results)
201217
expected_number_of_build_outputs = 1
202218
expected_number_of_test_outputs = 3
203219
expected_number_of_code_style_outputs = 0
@@ -222,6 +238,7 @@ def test_bash_task_with_injections(self: "TestTask"):
222238
self.assertEqual(homework_name, "Homework with injections")
223239
self.assertEqual(task.name, "Bash with many folders")
224240
results = task.check()
241+
results = TestTask.__sanitize_results(results)
225242
expected_number_of_build_outputs = 0
226243
expected_number_of_test_outputs = 1
227244
expected_number_of_code_style_outputs = 0

Diff for: homework_checker/tools.py

+13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
MAX_DATE_STR = datetime.datetime.max.strftime(DATE_PATTERN)
2323

2424
EXPIRED_TAG = "expired"
25+
NUMBER_SPLIT_TAG = "____"
2526

2627
log = logging.getLogger("GHC")
2728

@@ -31,6 +32,18 @@ def get_unique_str(seed: str) -> str:
3132
return hashlib.md5(seed.encode("utf-8")).hexdigest()
3233

3334

35+
def add_number_to_name(number: int, name: str) -> str:
36+
"""Add a number before a string."""
37+
return str(number) + NUMBER_SPLIT_TAG + name
38+
39+
40+
def remove_number_from_name(name: str) -> str:
41+
"""Add a number before a string."""
42+
if NUMBER_SPLIT_TAG not in name:
43+
return name
44+
return name.split(NUMBER_SPLIT_TAG)[1]
45+
46+
3447
class TempDirCopy:
3548
"""docstring for TempDirCopy"""
3649

0 commit comments

Comments
 (0)