pytest-grader 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,6 @@
1
+ pytest_grader.py,sha256=hrHcxBFegpmIbL7i3uGpXpYRc8YPXmCPLToBRCFwDvs,2449
2
+ pytest_grader-0.1.0.dist-info/METADATA,sha256=Yj90Tsv6rsVoinF5c2WqmUfp_alJb2oqAR1D67cy4J8,2015
3
+ pytest_grader-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
+ pytest_grader-0.1.0.dist-info/entry_points.txt,sha256=RH46nwyg-l-EAeH_ywIUfwn3mIOCeyTGiop_HlPFV-U,54
5
+ pytest_grader-0.1.0.dist-info/top_level.txt,sha256=uMeNBa9jT1Hc3T6RACXxfFfuN3meyY_mwPIcTjvxdxo,14
6
+ pytest_grader-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ build = build:create_executable_zip
@@ -0,0 +1 @@
1
+ pytest_grader
pytest_grader.py ADDED
@@ -0,0 +1,73 @@
1
+ import pytest
2
+
3
+
4
+ def points(n):
5
+ """Decorator to add a points attribute to a test function."""
6
+ def wrapper(f):
7
+ f.points = n
8
+ return f
9
+ return wrapper
10
+
11
+
12
+ def has_points(item: pytest.Item):
13
+ return isinstance(item, pytest.Function) and hasattr(item.function, 'points')
14
+
15
+
16
+ class GraderPlugin:
17
+ def __init__(self):
18
+ self.test_items = {}
19
+ self.test_results = []
20
+ self.total_points_in_all_tests = 0
21
+
22
+ def pytest_collection_modifyitems(self, session, config, items):
23
+ self.total_points_in_all_tests = sum(f.function.points for f in items if has_points(f))
24
+
25
+ def pytest_runtest_setup(self, item):
26
+ self.test_items[item.nodeid] = item
27
+
28
+ def pytest_runtest_logreport(self, report):
29
+ if report.when == "call":
30
+ self.test_results.append(report)
31
+
32
+ def pytest_terminal_summary(self, terminalreporter, exitstatus, config):
33
+ if config.getoption("--score"):
34
+ self.print_score_report()
35
+
36
+ def print_score_report(self):
37
+ total_earned = 0
38
+ total_points = 0
39
+
40
+ print('═' * 40)
41
+ for report in self.test_results:
42
+ if report.nodeid in self.test_items:
43
+ test_item = self.test_items[report.nodeid]
44
+ if has_points(test_item):
45
+ points = test_item.function.points
46
+ earned = points if report.outcome == 'passed' else 0
47
+ total_points += points
48
+ total_earned += earned
49
+ test_name = report.nodeid.split("::")[-1]
50
+ emoji = "✅" if report.outcome == 'passed' else "❌"
51
+ print(f" {emoji} {test_name:<25} {earned:>2}/{points} pts")
52
+
53
+ if total_points == self.total_points_in_all_tests:
54
+ percentage = 0.0 if total_points == 0 else round(100.0 * total_earned / total_points, 1)
55
+ decoration = ""
56
+ if total_earned == total_points:
57
+ percentage = "💯"
58
+ decoration = "✨"
59
+
60
+ print('─' * 40)
61
+ print(f" {decoration}Total Score: {total_earned}/{total_points} pts"
62
+ f" ({percentage}%){decoration}")
63
+
64
+
65
+ def pytest_addoption(parser):
66
+ parser.addoption(
67
+ "--score", action="store_true", default=False,
68
+ help="Show score report after running tests"
69
+ )
70
+
71
+
72
+ def pytest_configure(config):
73
+ config.pluginmanager.register(GraderPlugin(), "pytest-grader")