This commit is contained in:
2024-02-23 01:48:36 +01:00
parent 20423b5655
commit 1bab9d352c
2 changed files with 140 additions and 7 deletions

View File

@ -1,6 +1,8 @@
from ex2_dictionary import calculate_price from ex2_dictionary import calculate_price
from util import eidp_test, has_annotations, imported_modules_of, has_no_annotations from util import *
import pytest import pytest
import sys
import argparse
from enum import Enum from enum import Enum
from copy import deepcopy from copy import deepcopy
@ -72,7 +74,7 @@ def test_typeannotation_by_amount():
@pytest.mark.dependency(depends=[Task.A]) @pytest.mark.dependency(depends=[Task.A])
@pytest.mark.timeout(10) @pytest.mark.timeout(10)
@eidp_test("es wird nicht geschaut ob ein ein Produkt in `articles` ist", -2) @eidp_test("nicht überprüft ob Produkte in `articles` enthalten", -2)
def test_article_not_in_articles(): def test_article_not_in_articles():
articles = {'Coke': 200} articles = {'Coke': 200}
basket = {'Vitamine R': 1} basket = {'Vitamine R': 1}
@ -98,11 +100,16 @@ def test_price_calc():
articles = {'Coke': 200, 'Eis': 350} articles = {'Coke': 200, 'Eis': 350}
basket = {'Coke': 2, 'Eis': 3} basket = {'Coke': 2, 'Eis': 3}
assert abs(calculate_price(articles, basket) - 14.5) < EPS assert abs(calculate_price(articles, basket) - 14.5) < EPS
articles_dict = {"apples": 100, "oranges": 100,
"lemons": 200, "avocado": 500}
cart_dict = {"apples": 2, "oranges": 2, "lemons": 1, "bananas": 5}
assert abs(calculate_price(articles_dict, cart_dict) - 6) < EPS
@pytest.mark.dependency(depends=[Task.A]) @pytest.mark.dependency(depends=[Task.A])
@pytest.mark.timeout(10) @pytest.mark.timeout(10)
@eidp_test("`articles`/`cart` wird veraendert", -2) @eidp_test("`articles`/`cart` wird verwendet", -2)
def test_sideeffectss(): def test_sideeffectss():
a = {'Coke': 200, 'Eis': 350} a = {'Coke': 200, 'Eis': 350}
b = {'Coke': 2, 'Eis': 3} b = {'Coke': 2, 'Eis': 3}
@ -110,5 +117,74 @@ def test_sideeffectss():
assert a == a2 and b2 == b assert a == a2 and b2 == b
@pytest.mark.dependency(depends=[Task.B])
@pytest.mark.timeout(10)
@eidp_test("nicht überprüft ob Produkte in `articles` enthalten", -2)
def test_article_not_in_articles_by_amount():
from ex2_dictionary import by_amount
articles_dict = {"apples_ex": 100, "oranges_ex": 100,
"lemons": 200, "avocado_ex": 500}
cart_dict = {"apples": 2, "oranges": 2, "lemons": 1, "bananas": 5}
assert by_amount(articles_dict, cart_dict) == {1: ['lemons']}
@pytest.mark.dependency(depends=[Task.B])
@pytest.mark.timeout(10)
@eidp_test("`by_amount` wird nicht korrekt berechnet", -2)
def test_by_amount():
from ex2_dictionary import by_amount
articles_dict = {"apples": 100, "oranges": 100,
"lemons": 200, "avocado": 500}
cart_dict = {"apples": 2, "oranges": 2, "lemons": 1, "bananas": 5}
assert by_amount(articles_dict, cart_dict) == {
2: ['apples', 'oranges'], 1: ['lemons']}
@pytest.mark.dependency(depends=[Task.B])
@pytest.mark.timeout(10)
@eidp_test("es wird kein neues Dictionary erstellt", -4)
def test_sideeffects_by_amount():
from ex2_dictionary import by_amount
a = {"apples": 100, "oranges": 100,
"lemons": 200, "avocado": 500}
b = {"apples": 2, "oranges": 2, "lemons": 1, "bananas": 5}
r = by_amount(a2 := deepcopy(a), b2 := deepcopy(b)) == {
2: ['apples', 'oranges'], 1: ['lemons']}
assert a2 == a and b2 == b and r is not a and r is not b
if __name__ == '__main__': if __name__ == '__main__':
pass verbose, testing, force = tuple(parse_args(sys.argv).values())
parser = argparse.ArgumentParser(
prog='ex2_dictionary.py test',
description='testing for eidp 2023 ex2 dictionaries',
)
parser.add_argument('-v', '--verbose',
help="don't print out test output", action="store_true")
parser.add_argument(
'-t', '--test_only', help='only test without writing readme', action="store_true")
args = parser.parse_args()
# print(options)
# print(f'verbose := {verbose}, backup := {backup}')
collector = ResultsCollector()
pytest.main(['test_dictionary.py', '-vv', '-s'], plugins=[collector])
readme_template = []
passed, failed, skipped = collector.get_results()
if args.verbose:
print(f"passed := {passed}")
print(f"failed := {failed}")
print(f"skipped := {skipped}")
if not args.test_only:
tests = dict([(name, f) for name, f in vars() if callable(
f) and hasattr(f, "is_test")])
passed_tests = list(map(lambda m: m[1], filter(
lambda m: m[0] in passed, tests)))
print(passed_tests)

View File

@ -1,6 +1,8 @@
from typing import Callable, Any, TypeAliasType, Iterator from typing import Callable, Any, TypeAliasType, Iterator
from types import ModuleType from types import ModuleType
import inspect import inspect
import pytest
import time
def has_annotations(f: Callable, param_types: list[object], return_type: object = None) -> bool: def has_annotations(f: Callable, param_types: list[object], return_type: object = None) -> bool:
@ -34,6 +36,61 @@ def eidp_test(message: str, minus_points: float) -> Callable[[Callable[..., Any]
return wrapper return wrapper
def get_tests(module: ModuleType) -> dict[str, Callable[..., Any]]: class ResultsCollector:
return dict([(name, f) for name, f in module.__dict__ def __init__(self):
if callable(f) and hasattr(f, "is_test")]) self.reports = []
self.collected = 0
self.exitcode = 0
self.passed = 0
self.failed = 0
self.xfailed = 0
self.skipped = 0
self.total_duration = 0
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(self, item, call):
outcome = yield
report = outcome.get_result()
if report.when == 'call':
self.reports.append(report)
def pytest_collection_modifyitems(self, items):
self.collected = len(items)
def pytest_terminal_summary(self, terminalreporter, exitstatus):
self.passed = len(terminalreporter.stats.get('passed', []))
self.failed = len(terminalreporter.stats.get('failed', []))
self.xfailed = len(terminalreporter.stats.get('xfailed', []))
self.skipped = len(terminalreporter.stats.get('skipped', []))
self.total_duration = time.time() - terminalreporter._sessionstarttime
def get_results(self) -> tuple[list[str], list[str], list[str]]:
passed = []
failed = []
skipped = []
for report in self.reports:
if report.outcome == 'passed':
passed.append(report.nodeid.split('::')[-1])
elif report.outcome == 'failed':
failed.append(report.nodeid.split('::')[-1])
elif report.outcome == 'skipped':
skipped.append(report.nodeid.split('::')[-1])
return passed, failed, skipped
def parse_args(args: list[str]) -> dict[str, bool]:
arguments = args[1:]
retval = {'verbose': False, 'test': False, 'force': False}
for argument in arguments:
_args = argument[1:] if argument[0] == '-' else argument
for arg in _args:
match arg:
case 'v':
retval['verbose'] = True
case 't':
retval['test'] = True
case 'f':
retval['force'] = True
return retval