def test_debug_mode_doesnt_swallow_exception(self): some_exception = RuntimeError("There was some sort of exception.") reader = ExceptionRaisingUserOptionReader(exception=some_exception) settings.configure( USER_OPTION_READERS=[reader], GRAPH_BUILDER=FakeGraphBuilder(), PRINTER=FakePrinter() ) with pytest.raises(some_exception.__class__, match=str(some_exception)): lint_imports(is_debug_mode=True)
def test_non_debug_mode_prints_exception(self): some_exception = RuntimeError("There was some sort of exception.") reader = ExceptionRaisingUserOptionReader(exception=some_exception) settings.configure( USER_OPTION_READERS=[reader], GRAPH_BUILDER=FakeGraphBuilder(), PRINTER=FakePrinter() ) lint_imports(is_debug_mode=False) settings.PRINTER.pop_and_assert( """There was some sort of exception. """ )
def test_invalid_contract(self): self._configure(contracts_options=[ { "type": "fields", "name": "Contract foo", "single_field": ["one", "two"], "multiple_field": "one", "import_field": "foobar", }, { "type": "always_passes", "name": "Contract bar" }, ]) result = lint_imports() assert result == FAILURE settings.PRINTER.pop_and_assert(""" Contract "Contract foo" is not configured correctly: single_field: Expected a single value, got multiple values. import_field: Must be in the form "package.importer -> package.imported". required_field: This is a required field. """)
def test_all_successful(self): self._configure(contracts_options=[ { "type": "always_passes", "name": "Contract foo" }, { "type": "always_passes", "name": "Contract bar" }, ]) result = lint_imports() assert result == SUCCESS settings.PRINTER.pop_and_assert(""" ============= Import Linter ============= --------- Contracts --------- Analyzed 26 files, 10 dependencies. ----------------------------------- Contract foo KEPT Contract bar KEPT Contracts: 2 kept, 0 broken. """)
def test_graph_can_be_mutated_without_affecting_other_contracts(self): # The MutationCheckContract checks that there are a certain number of modules and imports # in the graph, then adds one more module and one more import. We can check two such # contracts and the second one will fail, if the graph gets mutated by other contracts. session_options = { "root_package": "mypackage", "contract_types": ["mutation_check: tests.helpers.contracts.MutationCheckContract"], } reader = FakeUserOptionReader( UserOptions( session_options=session_options, contracts_options=[ { "type": "mutation_check", "name": "Contract one", "number_of_modules": "5", "number_of_imports": "2", }, { "type": "mutation_check", "name": "Contract two", "number_of_modules": "5", "number_of_imports": "2", }, ], ) ) settings.configure( USER_OPTION_READERS=[reader], GRAPH_BUILDER=FakeGraphBuilder(), PRINTER=FakePrinter() ) graph = ImportGraph() # Create a graph with five modules and two imports. for module in ("one", "two", "three", "four", "five"): graph.add_module(module) graph.add_import(importer="one", imported="two") graph.add_import(importer="one", imported="three") settings.GRAPH_BUILDER.inject_graph(graph) result = lint_imports(is_debug_mode=True) assert result == SUCCESS
def test_one_failure(self): self._configure(contracts_options=[ { "type": "always_fails", "name": "Contract foo" }, { "type": "always_passes", "name": "Contract bar" }, ]) result = lint_imports() assert result == FAILURE settings.PRINTER.pop_and_assert(""" ============= Import Linter ============= --------- Contracts --------- Analyzed 26 files, 10 dependencies. ----------------------------------- Contract foo BROKEN Contract bar KEPT Contracts: 1 kept, 1 broken. ---------------- Broken contracts ---------------- Contract foo ------------ This contract will always fail. """)
def test_forbidden_import(self): """ Tests the ForbiddenImportContract - a simple contract that looks at the graph. """ graph = self._build_default_graph() graph.add_import( importer="mypackage.foo", imported="mypackage.bar", line_number=8, line_contents="from mypackage import bar", ) graph.add_import( importer="mypackage.foo", imported="mypackage.bar", line_number=16, line_contents="from mypackage.bar import something", ) self._configure( contracts_options=[ { "type": "always_passes", "name": "Contract foo" }, { "type": "forbidden", "name": "Forbidden contract one", "importer": "mypackage.foo", "imported": "mypackage.bar", }, { "type": "forbidden", "name": "Forbidden contract two", "importer": "mypackage.foo", "imported": "mypackage.baz", }, ], graph=graph, ) result = lint_imports() assert result == FAILURE # Expecting 28 files (default graph has 26 modules, we add 2). # Expecting 11 dependencies (default graph has 10 imports, we add 2, # but it counts as 1 as it's between the same modules). settings.PRINTER.pop_and_assert(""" ============= Import Linter ============= --------- Contracts --------- Analyzed 28 files, 11 dependencies. ----------------------------------- Contract foo KEPT Forbidden contract one BROKEN Forbidden contract two KEPT Contracts: 2 kept, 1 broken. ---------------- Broken contracts ---------------- Forbidden contract one ---------------------- mypackage.foo is not allowed to import mypackage.bar: mypackage.foo:8: from mypackage import bar mypackage.foo:16: from mypackage.bar import something """)