async def test_run_check_by_name_filter() -> None: nc = NamedChecks(BaseConfiguration()) checks = await nc.run_all(matching=CheckFilter(name="Check connectivity")) check = checks[0] assert check assert check.name == "Check connectivity" assert check.success
async def test_run_check_by_invalid_value(attr) -> None: selector = {attr: "INVALID"} nc = NamedChecks(BaseConfiguration()) with pytest.raises(ValueError) as e: await nc.run_one(**selector) assert (str(e.value) == f"failed running check: no check found with {attr} = 'INVALID'")
async def test_allows_underscored_method_names() -> None: class MeasureChecks(BaseChecks): def _allowed_helper(self) -> Check: return Check(name="Test", success=True) config = BaseConfiguration() results = await MeasureChecks.run(config) assert results is not None
async def test_filtering(name, id, tags, expected_ids) -> None: checks = await FilterableChecks.run(BaseConfiguration(), matching=CheckFilter(name=name, id=id, tags=tags)) ids = list(map(lambda c: c.id, checks)) assert len(ids) == len(expected_ids) assert ids == expected_ids
async def test_handles_method_attrs() -> None: class Other: def test(self): ... class MethodAttrsCheck(BaseChecks): other: Callable[..., None] checker = MethodAttrsCheck(BaseConfiguration(), other=Other().test) await checker.run_all()
async def test_generate_checks() -> None: handler = lambda c: f"so_check_it_{c}" items = ["one", "two", "three"] ItemChecks = create_checks_from_iterable(handler, items) checker = ItemChecks(BaseConfiguration()) results = await checker.run_all() assert len(results) == 3 messages = list(map(lambda c: c.message, results)) assert messages == [ "so_check_it_one", "so_check_it_two", "so_check_it_three" ]
async def test_valid_checks() -> None: class MeasureChecks(BaseChecks): def check_something(self) -> Check: return Check(name="Test", success=True) config = BaseConfiguration() checks = await MeasureChecks.run(config) assert checks == [ Check(name="Test", success=True, created_at=datetime(2020, 8, 24, 0, 0)) ]
async def test_run_as_instance() -> None: class MeasureChecks(BaseChecks): def check_something(self) -> Check: return Check(name="Test", success=True) config = BaseConfiguration() checker = MeasureChecks(config) checks = await checker.run_all() assert checks == [ Check(name="Test", success=True, created_at=datetime(2020, 8, 24, 0, 0)) ]
async def test_raises_on_invalid_method_name() -> None: class MeasureChecks(BaseChecks): def invalid_check(self) -> Check: return Check(name="Test", success=True) with pytest.raises(ValueError) as e: config = BaseConfiguration() await MeasureChecks.run(config) assert e assert ( str(e.value) == 'invalid method name "invalid_check": method names of Checks subtypes must start with "_" or "check_"' )
async def test_raises_on_invalid_return_type() -> None: class MeasureChecks(BaseChecks): def check_invalid(self) -> Check: return 123 with pytest.raises(TypeError) as e: config = BaseConfiguration() await MeasureChecks.run(config) assert e assert ( str(e.value) == """invalid check "check_invalid": expected return type "Check" but handler returned "int\"""" )
async def test_raises_on_invalid_signature() -> None: class MeasureChecks(BaseChecks): def check_invalid(self) -> int: return 123 with pytest.raises(TypeError) as e: config = BaseConfiguration() await MeasureChecks.run(config) assert e assert ( str(e.value) == """invalid check "check_invalid": incompatible return type annotation "<class 'int'>" in callable signature "() -> int", expected "<class 'servo.checks.Check'>\"""" )
async def test_check_ordering() -> None: class MeasureChecks(BaseChecks): def check_one(self) -> Check: return Check(name="1", success=True) def check_two(self) -> Check: return Check(name="2", success=False) def check_three(self) -> Check: return Check(name="3", success=True) config = BaseConfiguration() checks = await MeasureChecks.run(config) values = list(map(lambda c: (c.name, c.success), checks)) assert values == [("1", True), ("2", False), ("3", True)]
async def test_invalid_multichecks() -> None: checker = InvalidMultichecks(BaseConfiguration()) results = await checker.run_all() attrs = list(map(lambda c: [c.name, c.id, c.message], results)) assert attrs == [ [ "Check number NOT A VALID IDENTIFIER", "check_invalid_identifiers_item_0", "Identifier NOT A VALID IDENTIFIER was checked", ], [ "Check number •••••", "check_invalid_identifiers_item_1", "Identifier ••••• was checked", ], ]
async def test_add_checks_to_existing_class() -> None: handler = lambda c: f"so_check_it_{c}" items = ["five", "six", "seven"] ExtendedChecks = create_checks_from_iterable(handler, items, base_class=MixedChecks) checker = ExtendedChecks(BaseConfiguration()) results = await checker.run_all() assert len(results) == 7 attrs = list(map(lambda c: [c.name, c.id, c.message], results)) assert attrs == [ [ "one", "check_one", None, ], [ "two", "0b1c4a4d", None, ], [ "three", "check_three", None, ], [ "four", "31d68b28", None, ], [ "Check five", "b3f49d29", "so_check_it_five", ], [ "Check six", "bdc0e261", "so_check_it_six", ], [ "Check seven", "b991c85a", "so_check_it_seven", ], ]
async def test_warnings() -> None: results = await WarningChecks.run(BaseConfiguration()) attrs = list(map(lambda c: [c.name, c.id, c.success, c.message], results)) assert attrs == [ [ "warning-1", "check_one", False, "caught exception (RuntimeError): Failure", ], [ "warning-2", "check_two", False, "Something may not be quite right", ], ]
async def test_check_aborts_on_failed_requirement() -> None: class MeasureChecks(BaseChecks): def check_one(self) -> Check: return Check(name="1", success=True) def check_two(self) -> Check: return Check(name="2", success=False, severity=ErrorSeverity.critical) def check_three(self) -> Check: return Check(name="3", success=True) config = BaseConfiguration() checks = await MeasureChecks.run(config) values = list(map(lambda c: (c.name, c.success), checks)) assert values == [("1", True), ("2", False)]
async def test_multichecks_filtering() -> None: checker = MultiChecks(BaseConfiguration()) results = await checker.run_all(matching=CheckFilter( id=["check_numbers_item_0", "check_numbers_async_item_1"])) attrs = list(map(lambda c: [c.name, c.id, c.message], results)) assert attrs == [ [ "Check number one", "check_numbers_item_0", "Number one was checked", ], [ "Asynchronously check number five", "check_numbers_async_item_1", "Number five was checked", ], ]
async def test_multichecks_async() -> None: checker = MultiChecks(BaseConfiguration()) results = await checker.run_all() attrs = list(map(lambda c: [c.name, c.id, c.message], results)) assert attrs == [ [ "Check number one", "check_numbers_item_0", "Number one was checked", ], [ "Check number two", "check_numbers_item_1", "Number two was checked", ], [ "Check number three", "check_numbers_item_2", "Number three was checked", ], [ "Asynchronously check number four", "check_numbers_async_item_0", "Number four was checked", ], [ "Asynchronously check number five", "check_numbers_async_item_1", "Number five was checked", ], [ "Asynchronously check number six", "check_numbers_async_item_2", "Number six was checked", ], ]
def test_decorator_sets_id_to_method_name() -> None: checks = NamedChecks(BaseConfiguration()) assert checks.check_connectivity.__check__.id == "check_connectivity"
async def test_mixed_checks(name, expected_results) -> None: checks = await MixedChecks.run(BaseConfiguration(), matching=CheckFilter(name=name)) actual_results = list(map(lambda c: c.name, checks)) assert actual_results == expected_results
async def test_run_check_by_id() -> None: nc = NamedChecks(BaseConfiguration()) check = await nc.run_one(id="check_connectivity") assert check assert check.name == "Check connectivity" assert check.success
async def test_running_requirements(name, halt_on, expected_results) -> None: checks = await RequirementChecks.run(BaseConfiguration(), matching=CheckFilter(name=name), halt_on=halt_on) actual_results = dict(map(lambda c: (c.name, c.success), checks)) assert actual_results == expected_results