Repository: zyskarch/pytestarch (language: python)

Issue:
Overhaul module structure
The current module structure is not ideal with regard to cohesion/coupling and also not tested. In addition, some classes have gotten too big for comfort and should be refactored as well.


Discussion / hints:

Fix patch:
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index fd5d315..b22a112 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -7,17 +7,17 @@ and on which requirements need to be fulfilled for a PR to be ready for approval
 [Poetry](https://python-poetry.org/) is used for dependency and packaging management. Install poetry if you haven't already.
 Run `poetry install` to create a virtual environment with the required dependencies.
 
-There are also git hooks for black and flake8 available via `pre-commit install`.
+There are also git hooks for black, flake8, isort, and bandit available via `pre-commit install`.
 
 ## Running the test suite
-To make sure that everything works as expected, run `poetry run pytest`.
+To make sure that everything works as expected, run `nox`.
 
 
 ## Requirements for PRs
 When opening a PR, make sure the following requirements are fulfilled:
 1. All existing tests should pass: Run `nox` to ensure this.
-2. Ensure your code is properly formatted. Running `nox` also takes care of this.
-3. For new features of bugfixes, your added code should be covered by new tests.
+2. Ensure your code is properly formatted. Make sure you are using the pre-commit hooks to ensure this.
+3. For new features or bugfixes, your added code should be covered by new tests.
 4. Add your changes to the [changelog](docs/changelog.md).
 5. Update existing doc strings and documentation.
 6. Add doc strings for newly added public functions and methods.
diff --git a/docs/changelog.md b/docs/changelog.md
index 15b23af..1aab66c 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -4,6 +4,8 @@ This project uses semantic versioning and follows [keep a changelog](https://kee
 
 
 ## [Unreleased]
+### Changed
+- Internal module structure to improve coupling, cohesion.
 
 ## [1.3.0] -- 2022-11-28
 ### Added
diff --git a/docs/details.md b/docs/details.md
index f6100e4..e4e0b2b 100644
--- a/docs/details.md
+++ b/docs/details.md
@@ -134,7 +134,7 @@ Currently, the following markers are supported by PyTestArch:
 #### RULE_SUBJECT
 * are_named("X"): applies to module named "X" (and also to its submodules)
 * are_submodules_of("Y"): applies to submodules of module named "Y", but not "Y" itself
-* have_name_containing("*Z*"): applies to modules with names containing Z. The syntax is the same as for the file exclusion mechanism
+* have_name_containing("*Z*"): applies to modules with names containing Z. The syntax is the same as for the file exclusion mechanism.
 
 #### RULE_OBJECT
 same as RULE_SUBJECT, with an additional
@@ -248,7 +248,7 @@ resulting labels for a given aliases are:
 
 ## Testing your architecture based on PlantUML component diagrams
 ### General
-Instead of hand-crafting a number of rules, you can supply the path to a PlantUML component diagram. PyTestArch will
+Instead of hand-crafting a number of rules, you can supply the path to a PlantUML component diagram via a `DiagramRule`. PyTestArch will
 then parse this file and generate rules based on the connections of nodes in this diagram. Connections between two nodes
 will be converted into 'should only' or 'should' import rules; the absence of a connection will be converted into
 'should not' import rules. All rules are then evaluated against an Evaluable.
diff --git a/docs/parsing.md b/docs/parsing.md
deleted file mode 100644
index d73b912..0000000
--- a/docs/parsing.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Parsing
-
-## ::: src.pytestarch.importer.converter
-
-## ::: src.pytestarch.importer.file_filter
-
-## ::: src.pytestarch.importer.import_filter
-
-## ::: src.pytestarch.importer.import_types
-
-## ::: src.pytestarch.importer.importee_module_calculator
-
-## ::: src.pytestarch.importer.parser
diff --git a/docs/query_language.md b/docs/query_language.md
deleted file mode 100644
index e7b00d1..0000000
--- a/docs/query_language.md
+++ /dev/null
@@ -1,13 +0,0 @@
-#  Query Language
-
-## ::: src.pytestarch.query_language.base_language
-
-## ::: src.pytestarch.query_language.rule_matcher
-
-## ::: src.pytestarch.query_language.message_generator
-
-## ::: src.pytestarch.query_language.multiple_rule_applier
-
-## ::: src.pytestarch.query_language.diagrams.dependency_to_rule_converter
-
-## ::: src.pytestarch.query_language.diagrams.diagram_rule
\ No newline at end of file
diff --git a/docs/references/diagram_extension.md b/docs/references/diagram_extension.md
new file mode 100644
index 0000000..af42679
--- /dev/null
+++ b/docs/references/diagram_extension.md
@@ -0,0 +1,11 @@
+# Diagram Extension
+
+## ::: src.pytestarch.diagram_extension
+
+## ::: src.pytestarch.diagram_extension.diagram_rule
+
+## ::: src.pytestarch.diagram_extension.dependency_to_rule_converter
+
+## ::: src.pytestarch.diagram_extension.diagram_parser
+
+## ::: src.pytestarch.diagram_extension.parsed_dependencies
\ No newline at end of file
diff --git a/docs/eval_structure.md b/docs/references/eval_structure.md
similarity index 64%
rename from docs/eval_structure.md
rename to docs/references/eval_structure.md
index 6b71b4d..4b54fd5 100644
--- a/docs/eval_structure.md
+++ b/docs/references/eval_structure.md
@@ -1,4 +1,4 @@
-# Evaluation
+# Evaluation Structures
 
 ## ::: src.pytestarch.eval_structure
 
@@ -8,4 +8,6 @@
 
 ## ::: src.pytestarch.eval_structure.evaluable_graph
 
-## ::: src.pytestarch.eval_structure_impl.networkxgraph
\ No newline at end of file
+## ::: src.pytestarch.eval_structure.networkxgraph
+
+## ::: src.pytestarch.eval_structure.types
\ No newline at end of file
diff --git a/docs/references/eval_structure_generation.md b/docs/references/eval_structure_generation.md
new file mode 100644
index 0000000..44c9a64
--- /dev/null
+++ b/docs/references/eval_structure_generation.md
@@ -0,0 +1,20 @@
+# Evaluation Structure Generation
+
+## ::: src.pytestarch.eval_structure_generation
+
+## ::: src.pytestarch.eval_structure_generation.file_import
+
+## ::: src.pytestarch.eval_structure_generation.file_import.file_filter
+
+## ::: src.pytestarch.eval_structure_generation.file_import.import_filter
+
+## ::: src.pytestarch.eval_structure_generation.file_import.import_types
+
+## ::: src.pytestarch.eval_structure_generation.file_import.importee_module_calculator
+
+## ::: src.pytestarch.eval_structure_generation.file_import.parser
+
+## ::: src.pytestarch.eval_structure_generation.graph_generation
+
+## ::: src.pytestarch.eval_structure_generation.graph_generation.graph_generator
+
diff --git a/docs/general.md b/docs/references/general.md
similarity index 100%
rename from docs/general.md
rename to docs/references/general.md
diff --git a/docs/references/query_language.md b/docs/references/query_language.md
new file mode 100644
index 0000000..5ef8d1b
--- /dev/null
+++ b/docs/references/query_language.md
@@ -0,0 +1,9 @@
+#  Query Language
+
+## ::: src.pytestarch.query_language
+
+## ::: src.pytestarch.query_language.base_language
+
+## ::: src.pytestarch.query_language.rule
+
+## ::: src.pytestarch.query_language.multiple_rule_applier
diff --git a/docs/references/rule_assessment.md b/docs/references/rule_assessment.md
new file mode 100644
index 0000000..78854db
--- /dev/null
+++ b/docs/references/rule_assessment.md
@@ -0,0 +1,17 @@
+# Rule Assessment
+
+## ::: src.pytestarch.rule_assessment
+
+## ::: src.pytestarch.rule_assessment.error_message
+
+## ::: src.pytestarch.rule_assessment.error_message.message_generator
+
+## ::: src.pytestarch.rule_assessment.rule_check
+
+## ::: src.pytestarch.rule_assessment.rule_check.rule_matcher
+
+## ::: src.pytestarch.rule_assessment.rule_check.rule_violations
+
+## ::: src.pytestarch.rule_assessment.rule_check.behavior_requirement
+
+## ::: src.pytestarch.rule_assessment.rule_check.module_requirement
diff --git a/mkdocs.yml b/mkdocs.yml
index 0c4bba6..bc44c9a 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -21,10 +21,13 @@ nav:
   - details.md
   - changelog.md
   - Reference:
-      - general.md
-      - eval_structure.md
-      - parsing.md
-      - query_language.md
+      - references/general.md
+      - references/query_language.md
+      - references/eval_structure.md
+      - references/eval_structure_generation.md
+      - references/diagram_extension.md
+      - references/rule_assessment.md
+
 
 
 repo_url: https://github.com/zyskarch/pytestarch
\ No newline at end of file


Test patch:
diff --git a/src/pytestarch/__init__.py b/src/pytestarch/__init__.py
index 163a6f9..18ca9ce 100644
--- a/src/pytestarch/__init__.py
+++ b/src/pytestarch/__init__.py
@@ -1,7 +1,9 @@
-from .eval_structure.evaluable_architecture import EvaluableArchitecture  # noqa: F401
+from pytestarch.eval_structure.evaluable_architecture import (  # noqa: F401
+    EvaluableArchitecture,
+)
 from .pytestarch import get_evaluable_architecture  # noqa: F401 E401
 from .pytestarch import (  # noqa: F401 E401; noqa: F401 E401
     get_evaluable_architecture_for_module_objects,
 )
-from .query_language.rule import Rule  # noqa: F401
-from .query_language.diagrams.diagram_rule import DiagramRule  # noqa: F401
+from pytestarch.query_language.rule import Rule  # noqa: F401
+from pytestarch.diagram_extension.diagram_rule import DiagramRule  # noqa: F401
diff --git a/src/pytestarch/config/__init__.py b/src/pytestarch/diagram_extension/__init__.py
similarity index 100%
rename from src/pytestarch/config/__init__.py
rename to src/pytestarch/diagram_extension/__init__.py
diff --git a/src/pytestarch/query_language/diagrams/dependency_to_rule_converter.py b/src/pytestarch/diagram_extension/dependency_to_rule_converter.py
similarity index 97%
rename from src/pytestarch/query_language/diagrams/dependency_to_rule_converter.py
rename to src/pytestarch/diagram_extension/dependency_to_rule_converter.py
index 1a82cfc..9a025df 100644
--- a/src/pytestarch/query_language/diagrams/dependency_to_rule_converter.py
+++ b/src/pytestarch/diagram_extension/dependency_to_rule_converter.py
@@ -1,7 +1,7 @@
 from typing import List, Set
 
 from pytestarch import Rule
-from pytestarch.diagram_import.parsed_dependencies import ParsedDependencies
+from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
 from pytestarch.query_language.base_language import RuleApplier
 
 
diff --git a/src/pytestarch/diagram_import/diagram_parser.py b/src/pytestarch/diagram_extension/diagram_parser.py
similarity index 97%
rename from src/pytestarch/diagram_import/diagram_parser.py
rename to src/pytestarch/diagram_extension/diagram_parser.py
index ff24a47..c30c09d 100644
--- a/src/pytestarch/diagram_import/diagram_parser.py
+++ b/src/pytestarch/diagram_extension/diagram_parser.py
@@ -5,8 +5,8 @@
 from pathlib import Path
 from typing import Dict, Optional, Set, Tuple
 
-from pytestarch.diagram_import.parsed_dependencies import ParsedDependencies
-from pytestarch.exceptions import PumlParsingError
+from pytestarch.diagram_extension.exceptions import PumlParsingError
+from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
 
 
 class DiagramParser(ABC):
@@ -18,7 +18,7 @@ def parse(self, file_path: Path) -> ParsedDependencies:
 @dataclass(frozen=True)
 class Module:
     name: str
-    alias: Optional[str]
+    alias: Optional[str] = None
 
 
 PUML_START_MARKER = "@startuml"
diff --git a/src/pytestarch/query_language/diagrams/diagram_rule.py b/src/pytestarch/diagram_extension/diagram_rule.py
similarity index 92%
rename from src/pytestarch/query_language/diagrams/diagram_rule.py
rename to src/pytestarch/diagram_extension/diagram_rule.py
index b58a1c2..8ac92b9 100644
--- a/src/pytestarch/query_language/diagrams/diagram_rule.py
+++ b/src/pytestarch/diagram_extension/diagram_rule.py
@@ -2,17 +2,17 @@
 from typing import List, Optional
 
 from pytestarch import EvaluableArchitecture
-from pytestarch.diagram_import.diagram_parser import PumlParser
-from pytestarch.diagram_import.parsed_dependencies import ParsedDependencies
-from pytestarch.exceptions import ImproperlyConfigured
+from pytestarch.diagram_extension.dependency_to_rule_converter import (
+    DependencyToRuleConverter,
+)
+from pytestarch.diagram_extension.diagram_parser import PumlParser
+from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
 from pytestarch.query_language.base_language import (
     BaseModuleSpecifier,
     FileRule,
     RuleApplier,
 )
-from pytestarch.query_language.diagrams.dependency_to_rule_converter import (
-    DependencyToRuleConverter,
-)
+from pytestarch.query_language.exceptions import ImproperlyConfigured
 from pytestarch.query_language.multiple_rule_applier import MultipleRuleApplier
 
 
diff --git a/src/pytestarch/diagram_extension/exceptions.py b/src/pytestarch/diagram_extension/exceptions.py
new file mode 100644
index 0000000..10a06ff
--- /dev/null
+++ b/src/pytestarch/diagram_extension/exceptions.py
@@ -0,0 +1,6 @@
+class ParsingError(Exception):
+    pass
+
+
+class PumlParsingError(ParsingError):
+    pass
diff --git a/src/pytestarch/diagram_import/parsed_dependencies.py b/src/pytestarch/diagram_extension/parsed_dependencies.py
similarity index 100%
rename from src/pytestarch/diagram_import/parsed_dependencies.py
rename to src/pytestarch/diagram_extension/parsed_dependencies.py
diff --git a/src/pytestarch/eval_structure/__init__.py b/src/pytestarch/eval_structure/__init__.py
index 5e91d7d..e69de29 100644
--- a/src/pytestarch/eval_structure/__init__.py
+++ b/src/pytestarch/eval_structure/__init__.py
@@ -1,3 +0,0 @@
-"""This model contains abstract types as well as their implementations to represent the imported dependencies in a
-queryable structure, such as graphs.
-"""
diff --git a/src/pytestarch/eval_structure/breadth_first_searches.py b/src/pytestarch/eval_structure/breadth_first_searches.py
new file mode 100644
index 0000000..3b72866
--- /dev/null
+++ b/src/pytestarch/eval_structure/breadth_first_searches.py
@@ -0,0 +1,211 @@
+from typing import List, Set
+
+from pytestarch.eval_structure.evaluable_architecture import Module, StrictDependency
+from pytestarch.eval_structure.evaluable_structures import AbstractGraph, AbstractNode
+from pytestarch.eval_structure.utils import get_excluded_nodes, get_node, to_modules
+
+
+def get_dependency_between_modules(
+    graph: AbstractGraph, dependent: Module, dependent_upon: Module
+) -> List[StrictDependency]:
+    dependent_node = get_node(dependent)
+    dependent_upon_nodes = _get_all_submodules_of(graph, dependent_upon)
+
+    nodes_to_exclude = get_excluded_nodes([dependent, dependent_upon])
+
+    nodes_to_check = [dependent_node]
+    checked_nodes = set()
+
+    dependencies = []
+
+    while nodes_to_check:
+        node = nodes_to_check.pop()
+
+        if node in checked_nodes:
+            continue
+
+        checked_nodes.add(node)
+
+        children = graph.direct_successor_nodes(node)
+
+        for child in children:
+            if graph.parent_child_relationship(node, child):
+                nodes_to_check.append(child)
+
+            elif (
+                child in dependent_upon_nodes
+                and node not in nodes_to_exclude
+                and child not in nodes_to_exclude
+            ):
+                dependencies.append(tuple(to_modules([node, child])))
+    return dependencies  # type: ignore
+
+
+def any_dependency_to_module_other_than(  # noqa: C901
+    graph: AbstractGraph, dependent: Module, dependent_upons: List[Module]
+) -> List[StrictDependency]:
+    # nodes to exclude are nodes that once reached will not have their submodules analysed next
+    nodes_to_exclude = set()
+    for dependent_upon in dependent_upons:
+        if dependent_upon == dependent:
+            continue
+        nodes_to_exclude.update(_get_all_submodules_of(graph, dependent_upon))
+
+    nodes_fulfilling_criteria = []
+
+    # nodes that count as not fulfilling the criterion are nodes that would technically fulfill the criterion,
+    # but have to be excluded for consistency reasons. For example, if the dependent is called A and has two
+    # submodules A.X and A.Y. If A.X and A.Y import each other, this would be registered as fulfilling the
+    # requirement of a module other than the dependent upons (assuming that A.X and A.Y are not in this list).
+    # however, this is not really an import of a module outside A, which is what we are actually looking for
+
+    # should submodules of the dependent module import each other, this does not count as a dependency
+    nodes_that_do_not_fulfill_criterion = _get_all_submodules_of(graph, dependent)
+
+    if dependent.parent_module is not None:
+        # if the parent module is set and has a dependency other than dependent upon, it should not count as only
+        # the dependent and its submodules should be considered
+        # Example: if we are looking for imports by A.X, we do not care if A itself imports something
+        # (but we do care if A.X.M (submodule of A.X) imports something, as this is part of A.X)
+        nodes_to_exclude.add(dependent.parent_module)
+
+    for dependent_upon in dependent_upons:
+        if dependent_upon.parent_module is not None:
+            # if there is a dependency to the parent module of dependent upon, this counts, as only dependencies to
+            # the true submodules are excluded
+            # reason: if something imports B, then it imports something that is not B.X (and B.X is a dependent_upon module)
+            # (but we do not care if it imports B.X.M, as this is part of B.X)
+            nodes_to_exclude.remove(dependent_upon.parent_module)
+
+    nodes_to_check = list(nodes_that_do_not_fulfill_criterion)
+    checked_nodes = set()
+
+    while nodes_to_check:
+        node = nodes_to_check.pop()
+
+        if node in checked_nodes:
+            continue
+
+        if node in nodes_to_exclude:
+            continue
+
+        checked_nodes.add(node)
+
+        children = graph.direct_successor_nodes(node)
+
+        for child in children:
+
+            if not graph.parent_child_relationship(node, child):
+                if (
+                    child not in nodes_to_exclude
+                    and child not in nodes_that_do_not_fulfill_criterion
+                ):
+                    nodes_fulfilling_criteria.append(tuple(to_modules([node, child])))
+                else:
+                    nodes_to_check.append(child)
+
+    return nodes_fulfilling_criteria  # type: ignore
+
+
+def any_other_dependency_to_module_than(  # noqa: C901
+    graph: AbstractGraph, dependents: List[Module], dependent_upon: Module
+) -> List[StrictDependency]:
+    # submodules of the dependent upon module do not count as an import that is not the dependent upon module
+    # submodules of and including the dependent do not count as allowed imports
+
+    # nodes to exclude are nodes that once reached will not have their submodules analysed next
+    nodes_to_exclude = set()
+    for dependent in dependents:
+        if dependent == dependent_upon:
+            continue
+        nodes_to_exclude.update(_get_all_submodules_of(graph, dependent))
+
+    nodes_fulfilling_criteria = []
+
+    # nodes that count as not fulfilling the criterion are nodes that would technically fulfill the criterion,
+    # but have to be excluded for consistency reasons. For example, if the dependent upon is called A and has two
+    # submodules A.X and A.Y. If A.X and A.Y import each other, this would be registered as fulfilling the
+    # requirement of a module other than the dependents (assuming that A.X and A.Y are not in this list).
+    # however, this is not really an import by a module outside A, which is what we are actually looking for
+
+    # submodules of the dependent upon do not count as allowed imports e.g. if they import each other
+    nodes_that_count_as_not_fulfilling_criterion = _get_all_submodules_of(
+        graph, dependent_upon
+    )
+
+    if dependent_upon.parent_module is not None:
+        # if the dependent upon module is defined via a parent module, this parent module is not included in the
+        # list of modules that do not fulfill the criteria - only its true submodules are
+        # reason: there is a dependency from the parent module to the child module, but this is not an import
+        nodes_that_count_as_not_fulfilling_criterion.remove(
+            dependent_upon.parent_module
+        )
+
+    nodes_to_check = list(nodes_that_count_as_not_fulfilling_criterion)
+
+    for dependent in dependents:
+        if dependent.parent_module is not None:
+            # if the dependent module is defined via a parent module, this parent module counts as an allowed import
+            # reason: we are looking for dependencies other than module A.X. Parent module A is not (only) A.X, so it counts
+            # (submodule A.X.M does not count, as it is not anything else but A.X)
+            nodes_to_exclude.remove(dependent.parent_module)
+
+    checked_nodes = set()
+
+    while nodes_to_check:
+        node = nodes_to_check.pop()
+
+        if node in checked_nodes:
+            continue
+
+        checked_nodes.add(node)
+
+        parents = graph.direct_predecessor_nodes(node)
+
+        for parent in parents:
+
+            if not graph.parent_child_relationship(parent, node):
+                if (
+                    parent not in nodes_to_exclude
+                    and parent not in nodes_that_count_as_not_fulfilling_criterion
+                ):
+                    nodes_fulfilling_criteria.append(tuple(to_modules([parent, node])))
+
+                if parent not in nodes_to_exclude:
+                    nodes_to_check.append(parent)
+
+    return nodes_fulfilling_criteria  # type: ignore
+
+
+def _get_all_submodules_of(graph: AbstractGraph, module: Module) -> Set[AbstractNode]:
+    """Returns all submodules of a given module.
+
+    Args:
+        module: module to retrieve submodules of
+
+    Returns:
+        all submodules, including the module itself
+    """
+    start_node = get_node(module)
+
+    nodes_to_check = [start_node]
+    checked_nodes = set()
+
+    submodules = set()
+
+    while nodes_to_check:
+        node = nodes_to_check.pop()
+
+        if node in checked_nodes:
+            continue
+
+        checked_nodes.add(node)
+        submodules.add(node)
+
+        children = graph.direct_successor_nodes(node)
+
+        for child in children:
+            if graph.parent_child_relationship(node, child):
+                nodes_to_check.append(child)
+
+    return submodules
diff --git a/src/pytestarch/eval_structure/evaluable_architecture.py b/src/pytestarch/eval_structure/evaluable_architecture.py
index 1b8ab49..e63b97a 100644
--- a/src/pytestarch/eval_structure/evaluable_architecture.py
+++ b/src/pytestarch/eval_structure/evaluable_architecture.py
@@ -21,11 +21,12 @@ class Module:
 
 
 StrictDependency = Tuple[Module, Module]
-# if value is not None, it contains the actual (sub) modules of the key-modules that are connected
-StrictDependenciesByBaseModules = Dict[StrictDependency, List[StrictDependency]]
-# key: module that either has dependencies or that other are dependent on that were not expected
+# key: module that has dependencies
+# values: modules the key depends on
+DependenciesByBaseModules = Dict[StrictDependency, List[StrictDependency]]
+# key: module that either has dependencies or that others are dependent on that were not expected
 # value: importer and importee that were not expected
-LaxDependenciesByBaseModule = Dict[Module, List[StrictDependency]]
+UnexpectedDependenciesByBaseModule = Dict[Module, List[StrictDependency]]
 
 
 class EvaluableArchitecture(Protocol):
@@ -33,16 +34,20 @@ def get_dependencies(
         self,
         dependents: Union[Module, List[Module]],
         dependent_upons: Union[Module, List[Module]],
-    ) -> StrictDependenciesByBaseModules:
+    ) -> DependenciesByBaseModules:
         """Returns tuple of importer and importee per dependent and depending module if the dependent module is indeed
-        depending on the dependent_upon module.
-        Submodules of dependent towards are taken into account, but submodules of dependent_upon are not.
+        depending on the dependent_upon module. In short: find all dependencies between dependent and dependent_upons.
+
+        Submodules of dependent and dependent upon are taken into account.
+        If X.A depends on Y, then X also depends on Y, as X.A is part of X.
+        If X depends on Y.Z, then it also depends on Y.
+
         If one or both of the modules are defined by their parent module, this parent module is excluded from possible
         matches.
 
         Args:
-            dependent: Module
-            dependent_upon: Module
+            dependent: Module(s)
+            dependent_upon: Module(s)
 
         Returns:
             Importer and importee per pair of dependent and dependent_upon module if there are any
@@ -50,16 +55,19 @@ def get_dependencies(
         """
         raise NotImplementedError()
 
-    def any_dependencies_to_modules_other_than(
+    def any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
         self,
         dependents: Union[Module, List[Module]],
         dependent_upons: Union[Module, List[Module]],
-    ) -> LaxDependenciesByBaseModule:
+    ) -> UnexpectedDependenciesByBaseModule:
         """Returns list of depending modules per dependent module if the dependent module has any
         dependency to a module other than the dependent_upon modules
         or any of their submodules.
+
         If a dependent module is defined via a parent module, this parent module is not taken into account.
         If a dependent upon module is defined via a parent module, this parent module counts as an 'other' dependency.
+            Reason behind this: If we want to know whether there are any dependencies from X to any non-Y modules,
+            Y's parent is such a module, as this parent module can and usually will also contain other modules than Y.
 
         Args:
             dependent: Module
@@ -70,11 +78,11 @@ def any_dependencies_to_modules_other_than(
         """
         raise NotImplementedError()
 
-    def any_other_dependencies_to_modules_than(
+    def any_other_dependencies_on_dependent_upons_than_from_dependents(
         self,
         dependents: Union[Module, List[Module]],
         dependent_upons: Union[Module, List[Module]],
-    ) -> LaxDependenciesByBaseModule:
+    ) -> UnexpectedDependenciesByBaseModule:
         """Returns list of depending modules per dependent_upon module if any module other than the dependent
         module and its submodules has any dependency to the
         dependent_upon module.
diff --git a/src/pytestarch/eval_structure/evaluable_graph.py b/src/pytestarch/eval_structure/evaluable_graph.py
index 509483a..f11a01d 100644
--- a/src/pytestarch/eval_structure/evaluable_graph.py
+++ b/src/pytestarch/eval_structure/evaluable_graph.py
@@ -5,15 +5,20 @@
 from itertools import product
 from typing import Any, Dict, Iterable, List, Set, Tuple, Union
 
+from pytestarch.eval_structure.breadth_first_searches import (
+    any_dependency_to_module_other_than,
+    any_other_dependency_to_module_than,
+    get_dependency_between_modules,
+)
 from pytestarch.eval_structure.evaluable_architecture import (
+    DependenciesByBaseModules,
     EvaluableArchitecture,
-    LaxDependenciesByBaseModule,
     Module,
-    StrictDependenciesByBaseModules,
-    StrictDependency,
+    UnexpectedDependenciesByBaseModule,
 )
 from pytestarch.eval_structure.evaluable_structures import AbstractGraph, AbstractNode
-from pytestarch.exceptions import ImpossibleMatch
+from pytestarch.eval_structure.exceptions import ImpossibleMatch
+from pytestarch.eval_structure.utils import get_node
 
 ALL_MARKER = "*"
 
@@ -28,7 +33,7 @@ def get_dependencies(
         self,
         dependents: Union[Module, List[Module]],
         dependent_upons: Union[Module, List[Module]],
-    ) -> StrictDependenciesByBaseModules:
+    ) -> DependenciesByBaseModules:
         result = {}
 
         dependents = self._listify(dependents)
@@ -39,54 +44,18 @@ def get_dependencies(
         )
 
         for dependent, dependent_upon in product(dependents, dependent_upons):
-            dependency = self._get_dependency_between_modules(dependent, dependent_upon)
+            dependency = get_dependency_between_modules(
+                self._graph, dependent, dependent_upon
+            )
             result[(dependent, dependent_upon)] = dependency
 
         return result
 
-    def _get_dependency_between_modules(
-        self, dependent: Module, dependent_upon: Module
-    ) -> List[StrictDependency]:
-        dependent_node = self._get_node(dependent)
-        dependent_upon_nodes = self._get_all_submodules_of(dependent_upon)
-
-        nodes_to_exclude = self._get_excluded_nodes([dependent, dependent_upon])
-
-        nodes_to_check = [dependent_node]
-        checked_nodes = set()
-
-        dependencies = []
-
-        while nodes_to_check:
-            node = nodes_to_check.pop()
-
-            if node in checked_nodes:
-                continue
-
-            checked_nodes.add(node)
-
-            children = self._graph.direct_successor_nodes(node)
-
-            for child in children:
-                if self._graph.parent_child_relationship(node, child):
-                    nodes_to_check.append(child)
-
-                elif (
-                    child in dependent_upon_nodes
-                    and node not in nodes_to_exclude
-                    and child not in nodes_to_exclude
-                ):
-                    dependencies.append(tuple(self._to_modules([node, child])))
-        return dependencies  # type: ignore
-
-    def _get_node(self, dependent: Module) -> AbstractNode:
-        return dependent.name or dependent.parent_module
-
-    def any_dependencies_to_modules_other_than(
+    def any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
         self,
         dependents: Union[Module, List[Module]],
         dependent_upons: Union[Module, List[Module]],
-    ) -> LaxDependenciesByBaseModule:
+    ) -> UnexpectedDependenciesByBaseModule:
         result = {}
 
         dependents = self._listify(dependents)
@@ -97,8 +66,8 @@ def any_dependencies_to_modules_other_than(
         )
 
         for dependent in dependents:
-            dependencies = self._any_dependency_to_module_other_than(
-                dependent, dependent_upons
+            dependencies = any_dependency_to_module_other_than(
+                self._graph, dependent, dependent_upons
             )
             result[dependent] = dependencies
 
@@ -107,78 +76,11 @@ def any_dependencies_to_modules_other_than(
     def _listify(self, module: Union[Module, List[Module]]) -> List[Module]:
         return [module] if not isinstance(module, list) else module
 
-    def _any_dependency_to_module_other_than(  # noqa: C901
-        self, dependent: Module, dependent_upons: List[Module]
-    ) -> List[StrictDependency]:
-        # nodes to exclude are nodes that once reached will not have their submodules analysed next
-        nodes_to_exclude = set()
-        for dependent_upon in dependent_upons:
-            if dependent_upon == dependent:
-                continue
-            nodes_to_exclude.update(self._get_all_submodules_of(dependent_upon))
-
-        nodes_fulfilling_criteria = []
-
-        # nodes that count as not fulfilling the criterion are nodes that would technically fulfill the criterion,
-        # but have to be excluded for consistency reasons. For example, if the dependent is called A and has two
-        # submodules A.X and A.Y. If A.X and A.Y import each other, this would be registered as fulfilling the
-        # requirement of a module other than the dependent upons (assuming that A.X and A.Y are not in this list).
-        # however, this is not really an import of a module outside A, which is what we are actually looking for
-
-        # should submodules of the dependent module import each other, this does not count as a dependency
-        nodes_that_do_not_fulfill_criterion = self._get_all_submodules_of(dependent)
-
-        if dependent.parent_module is not None:
-            # if the parent module is set and has a dependency other than dependent upon, it should not count as only
-            # the dependent and its submodules should be considered
-            # Example: if we are looking for imports by A.X, we do not care if A itself imports something
-            # (but we do care if A.X.M (submodule of A.X) imports something, as this is part of A.X)
-            nodes_to_exclude.add(dependent.parent_module)
-
-        for dependent_upon in dependent_upons:
-            if dependent_upon.parent_module is not None:
-                # if there is a dependency to the parent module of dependent upon, this counts, as only dependencies to
-                # the true submodules are excluded
-                # reason: if something imports B, then it imports something that is not B.X (and B.X is a dependent_upon module)
-                # (but we do not care if it imports B.X.M, as this is part of B.X)
-                nodes_to_exclude.remove(dependent_upon.parent_module)
-
-        nodes_to_check = list(nodes_that_do_not_fulfill_criterion)
-        checked_nodes = set()
-
-        while nodes_to_check:
-            node = nodes_to_check.pop()
-
-            if node in checked_nodes:
-                continue
-
-            if node in nodes_to_exclude:
-                continue
-
-            checked_nodes.add(node)
-
-            children = self._graph.direct_successor_nodes(node)
-
-            for child in children:
-
-                if not self._graph.parent_child_relationship(node, child):
-                    if (
-                        child not in nodes_to_exclude
-                        and child not in nodes_that_do_not_fulfill_criterion
-                    ):
-                        nodes_fulfilling_criteria.append(
-                            tuple(self._to_modules([node, child]))
-                        )
-                    else:
-                        nodes_to_check.append(child)
-
-        return nodes_fulfilling_criteria  # type: ignore
-
-    def any_other_dependencies_to_modules_than(
+    def any_other_dependencies_on_dependent_upons_than_from_dependents(
         self,
         dependents: Union[Module, List[Module]],
         dependent_upons: Union[Module, List[Module]],
-    ) -> LaxDependenciesByBaseModule:
+    ) -> UnexpectedDependenciesByBaseModule:
         result = {}
 
         dependents = self._listify(dependents)
@@ -189,129 +91,16 @@ def any_other_dependencies_to_modules_than(
         )
 
         for dependent_upon in dependent_upons:
-            dependencies = self._any_other_dependency_to_module_than(
-                dependents, dependent_upon
+            dependencies = any_other_dependency_to_module_than(
+                self._graph, dependents, dependent_upon
             )
             result[dependent_upon] = dependencies
 
         return result
 
-    def _any_other_dependency_to_module_than(  # noqa: C901
-        self, dependents: List[Module], dependent_upon: Module
-    ) -> List[StrictDependency]:
-        # submodules of the dependent upon module do not count as an import that is not the dependent upon module
-        # submodules of and including the dependent do not count as allowed imports
-
-        # nodes to exclude are nodes that once reached will not have their submodules analysed next
-        nodes_to_exclude = set()
-        for dependent in dependents:
-            if dependent == dependent_upon:
-                continue
-            nodes_to_exclude.update(self._get_all_submodules_of(dependent))
-
-        nodes_fulfilling_criteria = []
-
-        # nodes that count as not fulfilling the criterion are nodes that would technically fulfill the criterion,
-        # but have to be excluded for consistency reasons. For example, if the dependent upon is called A and has two
-        # submodules A.X and A.Y. If A.X and A.Y import each other, this would be registered as fulfilling the
-        # requirement of a module other than the dependents (assuming that A.X and A.Y are not in this list).
-        # however, this is not really an import by a module outside A, which is what we are actually looking for
-
-        # submodules of the dependent upon do not count as allowed imports e.g. if they import each other
-        nodes_that_count_as_not_fulfilling_criterion = self._get_all_submodules_of(
-            dependent_upon
-        )
-
-        if dependent_upon.parent_module is not None:
-            # if the dependent upon module is defined via a parent module, this parent module is not included in the
-            # list of modules that do not fulfill the criteria - only its true submodules are
-            # reason: there is a dependency from the parent module to the child module, but this is not an import
-            nodes_that_count_as_not_fulfilling_criterion.remove(
-                dependent_upon.parent_module
-            )
-
-        nodes_to_check = list(nodes_that_count_as_not_fulfilling_criterion)
-
-        for dependent in dependents:
-            if dependent.parent_module is not None:
-                # if the dependent module is defined via a parent module, this parent module counts as an allowed import
-                # reason: we are looking for dependencies other than module A.X. Parent module A is not (only) A.X, so it counts
-                # (submodule A.X.M does not count, as it is not anything else but A.X)
-                nodes_to_exclude.remove(dependent.parent_module)
-
-        checked_nodes = set()
-
-        while nodes_to_check:
-            node = nodes_to_check.pop()
-
-            if node in checked_nodes:
-                continue
-
-            checked_nodes.add(node)
-
-            parents = self._graph.direct_predecessor_nodes(node)
-
-            for parent in parents:
-
-                if not self._graph.parent_child_relationship(parent, node):
-                    if (
-                        parent not in nodes_to_exclude
-                        and parent not in nodes_that_count_as_not_fulfilling_criterion
-                    ):
-                        nodes_fulfilling_criteria.append(
-                            tuple(self._to_modules([parent, node]))
-                        )
-
-                    if parent not in nodes_to_exclude:
-                        nodes_to_check.append(parent)
-
-        return nodes_fulfilling_criteria  # type: ignore
-
-    @classmethod
-    def _to_modules(cls, nodes: List[AbstractNode]) -> List[Module]:
-        return list(map(lambda node: Module(name=node), nodes))
-
-    def _get_all_submodules_of(self, module: Module) -> Set[AbstractNode]:
-        """Returns all submodules of a given module.
-
-        Args:
-            module: module to retrieve submodules of
-
-        Returns:
-            all submodules, including the module itself
-        """
-        start_node = self._get_node(module)
-
-        nodes_to_check = [start_node]
-        checked_nodes = set()
-
-        submodules = set()
-
-        while nodes_to_check:
-            node = nodes_to_check.pop()
-
-            if node in checked_nodes:
-                continue
-
-            checked_nodes.add(node)
-            submodules.add(node)
-
-            children = self._graph.direct_successor_nodes(node)
-
-            for child in children:
-                if self._graph.parent_child_relationship(node, child):
-                    nodes_to_check.append(child)
-
-        return submodules
-
     def visualize(self, **kwargs: Any) -> None:
         self._graph.draw(**kwargs)
 
-    @classmethod
-    def _get_excluded_nodes(cls, modules: List[Module]) -> List[AbstractNode]:
-        result = [module.parent_module for module in modules]
-        return [node for node in result if node is not None]
-
     def _convert_to_full_name_matches(
         self, module_groups: List[List[Module]]
     ) -> List[List[Module]]:
@@ -381,7 +170,7 @@ def _split_into_complete_modules_and_partial_matches(
 
             for node in modules:
                 partial_match_module_names.append(
-                    self._get_node(node)
+                    get_node(node)
                 ) if node.partial_match else result.append(node)
 
             result_by_group[group] = result
diff --git a/src/pytestarch/eval_structure/exceptions.py b/src/pytestarch/eval_structure/exceptions.py
new file mode 100644
index 0000000..0075d6b
--- /dev/null
+++ b/src/pytestarch/eval_structure/exceptions.py
@@ -0,0 +1,2 @@
+class ImpossibleMatch(Exception):
+    pass
diff --git a/src/pytestarch/eval_structure_impl/networkxgraph.py b/src/pytestarch/eval_structure/networkxgraph.py
similarity index 99%
rename from src/pytestarch/eval_structure_impl/networkxgraph.py
rename to src/pytestarch/eval_structure/networkxgraph.py
index 37dbbda..625758e 100644
--- a/src/pytestarch/eval_structure_impl/networkxgraph.py
+++ b/src/pytestarch/eval_structure/networkxgraph.py
@@ -6,7 +6,7 @@
 from networkx import draw_networkx, has_path, spring_layout
 
 from pytestarch.eval_structure.evaluable_structures import AbstractGraph, AbstractNode
-from pytestarch.importer.import_types import Import
+from pytestarch.eval_structure.types import Import
 
 EXPECTED_EDGE_AND_NODE_TYPES = "Only str and tuple of two str supported."
 
diff --git a/src/pytestarch/importer/import_types.py b/src/pytestarch/eval_structure/types.py
similarity index 51%
rename from src/pytestarch/importer/import_types.py
rename to src/pytestarch/eval_structure/types.py
index 5699d23..78ae39f 100644
--- a/src/pytestarch/importer/import_types.py
+++ b/src/pytestarch/eval_structure/types.py
@@ -1,22 +1,5 @@
-import ast
 from abc import ABC, abstractmethod
-from dataclasses import dataclass
-from typing import List, Optional
-
-from pytestarch.exceptions import ImproperlyConfigured
-
-
-@dataclass
-class NamedModule:
-    """Contains an ast module with its name.
-
-    Attributes:
-        module: ast module object
-        name: module name
-    """
-
-    module: ast.Module
-    name: str
+from typing import List
 
 
 class Import(ABC):
@@ -89,51 +72,3 @@ def _get_parent_modules(self, module: str) -> List[str]:
 
     def _append_prefix(self, value: str, prefix: str) -> str:
         return f"{prefix}.{value}"
-
-
-class AbsoluteImport(Import):
-    """Represents an absolute import."""
-
-    def __init__(self, importer: str, module_name: str) -> None:
-        super().__init__(importer)
-        self._module_name = module_name
-        self._importee_module_hierarchy = self._get_parent_modules(self._module_name)
-
-    def importee(self) -> str:
-        return self._module_name
-
-    def importee_parent_modules(self) -> List[str]:
-        return self._importee_module_hierarchy
-
-
-class RelativeImport(Import):
-    """Represents a relative import."""
-
-    def __init__(
-        self,
-        importer: str,
-        module_name: Optional[str],
-        import_name: Optional[str],
-        level: int,
-    ) -> None:
-        super().__init__(importer)
-        self._module_name = module_name or import_name
-        self._level = level
-
-        if module_name is None and import_name is None:
-            raise ImproperlyConfigured(
-                "Either name of module of of import needs to be specified."
-            )
-
-        self._importee = self._calculate_importee()
-
-        self._importee_module_hierarchy = self._get_parent_modules(self._module_name)
-
-    def importee(self) -> str:
-        return self._importee
-
-    def importee_parent_modules(self) -> List[str]:
-        return self._importee_module_hierarchy
-
-    def _calculate_importee(self) -> str:
-        return self._importer_module_hierarchy[-self._level] + "." + self._module_name
diff --git a/src/pytestarch/eval_structure/utils.py b/src/pytestarch/eval_structure/utils.py
new file mode 100644
index 0000000..3542523
--- /dev/null
+++ b/src/pytestarch/eval_structure/utils.py
@@ -0,0 +1,17 @@
+from typing import List
+
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_structures import AbstractNode
+
+
+def to_modules(nodes: List[AbstractNode]) -> List[Module]:
+    return list(map(lambda node: Module(name=node), nodes))
+
+
+def get_node(dependent: Module) -> AbstractNode:
+    return dependent.name or dependent.parent_module
+
+
+def get_excluded_nodes(modules: List[Module]) -> List[AbstractNode]:
+    result = [module.parent_module for module in modules]
+    return [node for node in result if node is not None]
diff --git a/src/pytestarch/importer/__init__.py b/src/pytestarch/eval_structure_generation/__init__.py
similarity index 100%
rename from src/pytestarch/importer/__init__.py
rename to src/pytestarch/eval_structure_generation/__init__.py
diff --git a/src/pytestarch/diagram_import/__init__.py b/src/pytestarch/eval_structure_generation/file_import/__init__.py
similarity index 100%
rename from src/pytestarch/diagram_import/__init__.py
rename to src/pytestarch/eval_structure_generation/file_import/__init__.py
diff --git a/src/pytestarch/config/config.py b/src/pytestarch/eval_structure_generation/file_import/config.py
similarity index 100%
rename from src/pytestarch/config/config.py
rename to src/pytestarch/eval_structure_generation/file_import/config.py
diff --git a/src/pytestarch/importer/converter.py b/src/pytestarch/eval_structure_generation/file_import/converter.py
similarity index 93%
rename from src/pytestarch/importer/converter.py
rename to src/pytestarch/eval_structure_generation/file_import/converter.py
index 629c33f..c76ed9b 100644
--- a/src/pytestarch/importer/converter.py
+++ b/src/pytestarch/eval_structure_generation/file_import/converter.py
@@ -2,7 +2,11 @@
 from _ast import Import
 from typing import List, Optional
 
-from pytestarch.importer.import_types import AbsoluteImport, NamedModule, RelativeImport
+from pytestarch.eval_structure_generation.file_import.import_types import (
+    AbsoluteImport,
+    NamedModule,
+    RelativeImport,
+)
 
 
 class ImportConverter:
diff --git a/src/pytestarch/eval_structure_generation/file_import/exceptions.py b/src/pytestarch/eval_structure_generation/file_import/exceptions.py
new file mode 100644
index 0000000..9ba8edc
--- /dev/null
+++ b/src/pytestarch/eval_structure_generation/file_import/exceptions.py
@@ -0,0 +1,2 @@
+class ImportException(Exception):
+    pass
diff --git a/src/pytestarch/importer/file_filter.py b/src/pytestarch/eval_structure_generation/file_import/file_filter.py
similarity index 96%
rename from src/pytestarch/importer/file_filter.py
rename to src/pytestarch/eval_structure_generation/file_import/file_filter.py
index ca4ba13..40f4fdb 100644
--- a/src/pytestarch/importer/file_filter.py
+++ b/src/pytestarch/eval_structure_generation/file_import/file_filter.py
@@ -1,6 +1,6 @@
 from pathlib import Path
 
-from pytestarch.config.config import Config
+from pytestarch.eval_structure_generation.file_import.config import Config
 
 ALL_MARKER = "*"
 
diff --git a/src/pytestarch/importer/import_filter.py b/src/pytestarch/eval_structure_generation/file_import/import_filter.py
similarity index 96%
rename from src/pytestarch/importer/import_filter.py
rename to src/pytestarch/eval_structure_generation/file_import/import_filter.py
index a8a9353..99dc199 100644
--- a/src/pytestarch/importer/import_filter.py
+++ b/src/pytestarch/eval_structure_generation/file_import/import_filter.py
@@ -1,6 +1,6 @@
 from typing import List
 
-from pytestarch.importer.import_types import Import
+from pytestarch.eval_structure.types import Import
 
 
 class ImportFilter:
diff --git a/src/pytestarch/eval_structure_generation/file_import/import_types.py b/src/pytestarch/eval_structure_generation/file_import/import_types.py
new file mode 100644
index 0000000..3aa17b5
--- /dev/null
+++ b/src/pytestarch/eval_structure_generation/file_import/import_types.py
@@ -0,0 +1,67 @@
+import ast
+from dataclasses import dataclass
+from typing import List, Optional
+
+from pytestarch.eval_structure.types import Import
+from pytestarch.eval_structure_generation.file_import.exceptions import ImportException
+
+
+@dataclass
+class NamedModule:
+    """Contains an ast module with its name.
+
+    Attributes:
+        module: ast module object
+        name: module name
+    """
+
+    module: ast.Module
+    name: str
+
+
+class AbsoluteImport(Import):
+    """Represents an absolute import."""
+
+    def __init__(self, importer: str, module_name: str) -> None:
+        super().__init__(importer)
+        self._module_name = module_name
+        self._importee_module_hierarchy = self._get_parent_modules(self._module_name)
+
+    def importee(self) -> str:
+        return self._module_name
+
+    def importee_parent_modules(self) -> List[str]:
+        return self._importee_module_hierarchy
+
+
+class RelativeImport(Import):
+    """Represents a relative import."""
+
+    def __init__(
+        self,
+        importer: str,
+        module_name: Optional[str],
+        import_name: Optional[str],
+        level: int,
+    ) -> None:
+        super().__init__(importer)
+        self._module_name = module_name or import_name
+        self._level = level
+
+        if module_name is None and import_name is None:
+            raise ImportException(
+                "Either name of module of of import needs to be specified."
+            )
+
+        self._importee = self._calculate_importee()
+
+        self._importee_module_hierarchy = self._get_parent_modules(self._module_name)
+
+    def importee(self) -> str:
+        return self._importee
+
+    def importee_parent_modules(self) -> List[str]:
+        return self._importee_module_hierarchy
+
+    def _calculate_importee(self) -> str:
+        return self._importer_module_hierarchy[-self._level] + "." + self._module_name
diff --git a/src/pytestarch/importer/importee_module_calculator.py b/src/pytestarch/eval_structure_generation/file_import/importee_module_calculator.py
similarity index 95%
rename from src/pytestarch/importer/importee_module_calculator.py
rename to src/pytestarch/eval_structure_generation/file_import/importee_module_calculator.py
index 33ca271..9c04a96 100644
--- a/src/pytestarch/importer/importee_module_calculator.py
+++ b/src/pytestarch/eval_structure_generation/file_import/importee_module_calculator.py
@@ -1,7 +1,7 @@
 from pathlib import Path
 from typing import List, Set
 
-from pytestarch.importer.import_types import Import
+from pytestarch.eval_structure.types import Import
 
 
 class ImporteeModuleCalculator:
diff --git a/src/pytestarch/importer/parser.py b/src/pytestarch/eval_structure_generation/file_import/parser.py
similarity index 93%
rename from src/pytestarch/importer/parser.py
rename to src/pytestarch/eval_structure_generation/file_import/parser.py
index 11e809d..d77b918 100644
--- a/src/pytestarch/importer/parser.py
+++ b/src/pytestarch/eval_structure_generation/file_import/parser.py
@@ -3,8 +3,8 @@
 from pathlib import Path
 from typing import List, Optional, Tuple
 
-from pytestarch.importer.file_filter import FileFilter
-from pytestarch.importer.import_types import NamedModule
+from pytestarch.eval_structure_generation.file_import.file_filter import FileFilter
+from pytestarch.eval_structure_generation.file_import.import_types import NamedModule
 
 PYTHON_FILE_SUFFIX = ".py"
 
diff --git a/src/pytestarch/eval_structure_impl/__init__.py b/src/pytestarch/eval_structure_generation/graph_generation/__init__.py
similarity index 100%
rename from src/pytestarch/eval_structure_impl/__init__.py
rename to src/pytestarch/eval_structure_generation/graph_generation/__init__.py
diff --git a/src/pytestarch/eval_structure_generation/graph_generation/graph_generator.py b/src/pytestarch/eval_structure_generation/graph_generation/graph_generator.py
new file mode 100644
index 0000000..9e90a8b
--- /dev/null
+++ b/src/pytestarch/eval_structure_generation/graph_generation/graph_generator.py
@@ -0,0 +1,115 @@
+from pathlib import Path
+from typing import List, Optional, Tuple
+
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph, Node
+from pytestarch.eval_structure.types import Import
+from pytestarch.eval_structure_generation.file_import.config import Config
+from pytestarch.eval_structure_generation.file_import.converter import ImportConverter
+from pytestarch.eval_structure_generation.file_import.file_filter import FileFilter
+from pytestarch.eval_structure_generation.file_import.import_filter import ImportFilter
+from pytestarch.eval_structure_generation.file_import.import_types import NamedModule
+from pytestarch.eval_structure_generation.file_import.importee_module_calculator import (
+    ImporteeModuleCalculator,
+)
+from pytestarch.eval_structure_generation.file_import.parser import Parser
+
+
+def generate_graph(
+    root_path: Path,
+    module_path: Path,
+    path_diff_between_root_and_module: str,
+    exclusions: Tuple[str, ...],
+    exclude_external_libraries: bool,
+    level_limit: Optional[int],
+) -> EvaluableArchitectureGraph:
+    level_limit = _add_extra_levels_to_limit_if_root_and_module_path_differ(
+        level_limit,
+        path_diff_between_root_and_module,
+    )
+
+    all_modules, ast = _get_all_ast_modules(module_path, root_path, exclusions)
+    imports = _get_imports_from_ast(ast)
+
+    internal_module_prefix = _get_internal_module_prefix(
+        path_diff_between_root_and_module, root_path
+    )
+
+    imports = _remove_excluded_imports(
+        exclude_external_libraries, imports, internal_module_prefix
+    )
+
+    all_modules = _append_external_modules_to_module_list(
+        all_modules, exclude_external_libraries, imports, root_path
+    )
+    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports, level_limit))
+
+
+def _append_external_modules_to_module_list(
+    all_modules: List[Node],
+    exclude_external_libraries: bool,
+    imports: List[Import],
+    root_path: Path,
+) -> List[Node]:
+    """External modules are not detected as modules when importing the source folder - but they will of course show up
+    in the imports. To ensure that all edges in the graph have nodes attached, the external modules need to be added to
+    the list of modules/nodes."""
+    if not exclude_external_libraries:
+        all_modules = ImporteeModuleCalculator(root_path).calculate_importee_modules(
+            imports,
+            all_modules,
+        )
+    return all_modules
+
+
+def _remove_excluded_imports(
+    exclude_external_libraries: bool, imports: List[Import], internal_module_prefix: str
+) -> List[Import]:
+    import_filter = ImportFilter(exclude_external_libraries, internal_module_prefix)
+    return import_filter.filter(imports)
+
+
+def _get_internal_module_prefix(
+    path_diff_between_root_and_module: str, root_path: Path
+) -> str:
+    """In general, all internal modules should start with the root module name to be able to differentiate between
+    internal and external modules. If the root and base module differ, the modules between them also need to be taken
+    into account, as not root.a.b modules are external, but root.a.b.base are internal."""
+    internal_module_prefix = root_path.name + "."
+
+    if path_diff_between_root_and_module != ".":
+        internal_module_prefix += path_diff_between_root_and_module
+
+    return internal_module_prefix
+
+
+def _add_extra_levels_to_limit_if_root_and_module_path_differ(
+    level_limit: Optional[int], path_diff_between_root_and_module: str
+) -> Optional[int]:
+    """If the root and base module are not the same, the level limit needs to be increased by the number of levels
+    between these two modules. Otherwise, the actual base module might not even be in the graph, let alone all required
+    levels below it."""
+    if level_limit is None:
+        return None
+
+    if path_diff_between_root_and_module != ".":
+        levels = len(path_diff_between_root_and_module.split("."))
+        level_limit += levels
+
+    return level_limit
+
+
+def _get_imports_from_ast(ast: List[NamedModule]) -> List[Import]:
+    converter = ImportConverter()
+    return converter.convert(ast)
+
+
+def _get_all_ast_modules(
+    module_path: Path, root_path: Path, exclusions: Tuple[str, ...]
+) -> Tuple[List[str], List[NamedModule]]:
+    config = Config(exclusions)
+    file_filter = FileFilter(config)
+
+    parser = Parser(file_filter, root_path)
+    all_modules, ast = parser.parse(module_path)
+    return all_modules, ast
diff --git a/src/pytestarch/exceptions.py b/src/pytestarch/exceptions.py
deleted file mode 100644
index 18de964..0000000
--- a/src/pytestarch/exceptions.py
+++ /dev/null
@@ -1,14 +0,0 @@
-class ImproperlyConfigured(Exception):
-    pass
-
-
-class ParsingError(Exception):
-    pass
-
-
-class PumlParsingError(ParsingError):
-    pass
-
-
-class ImpossibleMatch(Exception):
-    pass
diff --git a/src/pytestarch/pytestarch.py b/src/pytestarch/pytestarch.py
index 4f1ab9b..bbba5f8 100755
--- a/src/pytestarch/pytestarch.py
+++ b/src/pytestarch/pytestarch.py
@@ -7,15 +7,10 @@
 from types import ModuleType
 from typing import Optional, Tuple
 
-from pytestarch.config.config import Config
-from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
-from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.importer.converter import ImportConverter
-from pytestarch.importer.file_filter import FileFilter
-from pytestarch.importer.import_filter import ImportFilter
-from pytestarch.importer.importee_module_calculator import ImporteeModuleCalculator
-from pytestarch.importer.parser import Parser
+from pytestarch import EvaluableArchitecture
+from pytestarch.eval_structure_generation.graph_generation.graph_generator import (
+    generate_graph,
+)
 
 DEFAULT_EXCLUSIONS = ("*__pycache__",)
 
@@ -47,34 +42,14 @@ def get_evaluable_architecture(
         os.sep, "."
     )
 
-    if level_limit is not None:
-        if path_diff_between_root_and_module != ".":
-            levels = len(path_diff_between_root_and_module.split("."))
-            level_limit += levels
-
-    config = Config(exclusions)
-    file_filter = FileFilter(config)
-
-    parser = Parser(file_filter, root_path)
-    converter = ImportConverter()
-
-    all_modules, ast = parser.parse(module_path)
-
-    imports = converter.convert(ast)
-
-    internal_module_prefix = root_path.name + "."
-    if path_diff_between_root_and_module != ".":
-        internal_module_prefix += path_diff_between_root_and_module
-
-    import_filter = ImportFilter(exclude_external_libraries, internal_module_prefix)
-    imports = import_filter.filter(imports)
-
-    if not exclude_external_libraries:
-        all_modules = ImporteeModuleCalculator(root_path).calculate_importee_modules(
-            imports,
-            all_modules,
-        )
-    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports, level_limit))
+    return generate_graph(
+        root_path,
+        module_path,
+        path_diff_between_root_and_module,
+        exclusions,
+        exclude_external_libraries,
+        level_limit,
+    )
 
 
 def get_evaluable_architecture_for_module_objects(
diff --git a/src/pytestarch/query_language/base_language.py b/src/pytestarch/query_language/base_language.py
index cb4b80b..d060dfc 100644
--- a/src/pytestarch/query_language/base_language.py
+++ b/src/pytestarch/query_language/base_language.py
@@ -4,8 +4,10 @@
 from pathlib import Path
 from typing import Generic, List, TypeVar, Union
 
-from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
-from pytestarch.query_language.rule_matcher import BehaviorRequirement
+from pytestarch import EvaluableArchitecture
+from pytestarch.rule_assessment.rule_check.behavior_requirement import (
+    BehaviorRequirement,
+)
 
 
 class FileRule(ABC):
diff --git a/src/pytestarch/query_language/exceptions.py b/src/pytestarch/query_language/exceptions.py
new file mode 100644
index 0000000..c47bebb
--- /dev/null
+++ b/src/pytestarch/query_language/exceptions.py
@@ -0,0 +1,2 @@
+class ImproperlyConfigured(Exception):
+    pass
diff --git a/src/pytestarch/query_language/rule.py b/src/pytestarch/query_language/rule.py
index 3fd762a..0e8225c 100644
--- a/src/pytestarch/query_language/rule.py
+++ b/src/pytestarch/query_language/rule.py
@@ -5,7 +5,6 @@
 
 from pytestarch import EvaluableArchitecture
 from pytestarch.eval_structure.evaluable_architecture import Module
-from pytestarch.exceptions import ImproperlyConfigured
 from pytestarch.query_language.base_language import (
     BehaviorSpecification,
     DependencySpecification,
@@ -14,13 +13,14 @@
     RuleObject,
     RuleSubject,
 )
-from pytestarch.query_language.message_generator import RuleViolationMessageGenerator
-from pytestarch.query_language.rule_matcher import (
+from pytestarch.query_language.exceptions import ImproperlyConfigured
+from pytestarch.rule_assessment.rule_check.behavior_requirement import (
     BehaviorRequirement,
+)
+from pytestarch.rule_assessment.rule_check.module_requirement import ModuleRequirement
+from pytestarch.rule_assessment.rule_check.rule_matcher import (
     DefaultRuleMatcher,
-    ModuleRequirement,
     RuleMatcher,
-    RuleViolations,
 )
 
 
@@ -155,10 +155,7 @@ def assert_applies(self, evaluable: EvaluableArchitecture) -> None:
         self._assert_required_configuration_present()
 
         matcher = self._prepare_rule_matcher()
-        rule_violations = matcher.match(evaluable)
-
-        if rule_violations:
-            raise AssertionError(self._create_rule_violation_message(rule_violations))
+        matcher.match(evaluable)
 
     def _prepare_rule_matcher(self) -> RuleMatcher:
         module_requirement = ModuleRequirement(
@@ -249,17 +246,6 @@ def _assert_required_configuration_present(self) -> None:
     def _name_or_empty(cls, empty: bool, clz: type) -> str:
         return f"a {clz.__name__}" if empty else ""
 
-    def _create_rule_violation_message(self, rule_violations: RuleViolations) -> str:
-        message_generator = RuleViolationMessageGenerator(
-            self._configuration.module_to_check,
-            self._configuration.modules_to_check_against,
-            self._configuration.import_,
-        )
-        single_violation_messages = message_generator.create_rule_violation_messages(
-            rule_violations
-        )
-        return "\n".join(single_violation_messages)
-
     @classmethod
     def _convert_aliases(cls, configuration: RuleConfiguration) -> RuleConfiguration:
         if not configuration.rule_object_anything:
diff --git a/src/pytestarch/query_language/rule_matcher.py b/src/pytestarch/query_language/rule_matcher.py
deleted file mode 100644
index 995a04c..0000000
--- a/src/pytestarch/query_language/rule_matcher.py
+++ /dev/null
@@ -1,247 +0,0 @@
-from abc import ABC, abstractmethod
-from dataclasses import dataclass, fields
-from typing import List, Optional, Union
-
-from pytestarch.eval_structure.evaluable_architecture import (
-    EvaluableArchitecture,
-    LaxDependenciesByBaseModule,
-    Module,
-    StrictDependenciesByBaseModules,
-)
-from pytestarch.exceptions import ImproperlyConfigured
-
-
-class ModuleRequirement:
-    """Stores information about which module is supposed to be checked against which module."""
-
-    def __init__(
-        self,
-        left_hand_module: Module,
-        right_hand_modules: List[Module],
-        import_relation: bool,
-    ) -> None:
-        self._left_hand_modules = left_hand_module
-        self._right_hand_modules = right_hand_modules
-
-        self._right_hand_module_has_specifier = import_relation
-
-        if self.left_hand_module_has_specifier:
-            self._left_hand_modules, self._right_hand_modules = (
-                self._right_hand_modules,
-                self._left_hand_modules,
-            )
-
-    @property
-    def left_hand_modules(self) -> Union[Module, List[Module]]:
-        return self._left_hand_modules
-
-    @property
-    def right_hand_modules(self) -> Union[Module, List[Module]]:
-        return self._right_hand_modules
-
-    @property
-    def left_hand_module_has_specifier(self) -> bool:
-        # True if rule is of format "is imported by"
-        return not self._right_hand_module_has_specifier
-
-
-@dataclass
-class RuleViolations:
-    lax_dependencies: Optional[LaxDependenciesByBaseModule]
-    strict_dependencies: Optional[StrictDependenciesByBaseModules]
-
-    should_violated: bool = False
-    should_only_violated_by_forbidden_import: bool = False
-    should_only_violated_by_no_import: bool = False
-    should_not_violated: bool = False
-    should_except_violated: bool = False
-    should_only_except_violated_by_forbidden_import: bool = False
-    should_only_except_violated_by_no_import: bool = False
-    should_not_except_violated: bool = False
-
-    def __bool__(self) -> bool:
-        return any(self.__dict__[a] for a in self._bool_field_names())
-
-    @classmethod
-    def _bool_field_names(cls) -> List[str]:
-        return [field.name for field in fields(cls) if field.type == bool]
-
-
-class BehaviorRequirement:
-    """Stores information about which import behavior the checked module is supposed to exhibit."""
-
-    def __init__(
-        self,
-        positive_behavior_lax: bool,
-        positive_behavior_strict: bool,
-        negative_behavior: bool,
-        behavior_exception: bool,
-    ) -> None:
-        self._should = positive_behavior_lax
-        self._should_only = positive_behavior_strict
-        self._should_not = negative_behavior
-
-        self._behavior_exception = behavior_exception
-
-        self._validate()
-
-    @property
-    def strict_dependency_required(self) -> bool:
-        """Returns True if a dependency between two specific modules is required."""
-        return (self._should or self._should_only) and not self._behavior_exception
-
-    @property
-    def lax_dependency_required(self) -> bool:
-        """Returns True if a dependency between a specific module and
-        any other modules is required. Which other modules are required
-        is specified by the module requirement."""
-        return self._behavior_exception and (self._should or self._should_only)
-
-    @property
-    def strict_dependency_not_allowed(self) -> bool:
-        """Returns True if a dependency between two specific modules is not allowed."""
-        return (self._should_not and not self._behavior_exception) or (
-            self._should_only and self._behavior_exception
-        )
-
-    @property
-    def lax_dependency_not_allowed(self) -> bool:
-        """Returns True if no dependency between a specific module
-        and a set of other modules is not allowed. Which other modules
-        are not allowed is specified by the module requirement."""
-        return (self._should_not and self._behavior_exception) or (
-            self._should_only and not self._behavior_exception
-        )
-
-    def _validate(self) -> None:
-        if self.strict_dependency_required and self.strict_dependency_not_allowed:
-            raise ImproperlyConfigured(
-                "Strict dependency both required and not allowed."
-            )
-
-        if self.lax_dependency_required and self.lax_dependency_not_allowed:
-            raise ImproperlyConfigured("Lax dependency both required and not allowed.")
-
-    def generate_rule_violation(
-        self,
-        strict_dependencies: Optional[StrictDependenciesByBaseModules],
-        lax_dependencies: Optional[LaxDependenciesByBaseModule],
-    ) -> RuleViolations:
-        """Translate from the detected types of dependencies back to which behavior and dependency requirements are violated by them.
-        Args:
-            strict_dependencies: dependency between the two specified modules found, grouped by requested modules
-            lax_dependencies: other dependencies found beside the two specified modules
-        Returns:
-            overview of all rule violations
-        """
-        should_not_except_expected = self._should_not and self._behavior_exception
-        should_only_except_violated_by_forbidden_expected = (
-            self._should_only and self._behavior_exception
-        )
-        should_not_expected = self._should_not and not self._behavior_exception
-        should_only_expected = self._should_only and not self._behavior_exception
-        should_only_except_violated_by_no_expected = (
-            self._should_only and self._behavior_exception
-        )
-        should_except_expected = self._should and self._behavior_exception
-        should_expected = self._should and not self._behavior_exception
-
-        lax_dependencies_present = lax_dependencies is not None and any(
-            lax_dependency for lax_dependency in lax_dependencies.values()
-        )
-        strict_dependency_present = strict_dependencies is not None and any(
-            strict_dependency for strict_dependency in strict_dependencies.values()
-        )
-
-        return RuleViolations(
-            should_not_except_violated=should_not_except_expected
-            and lax_dependencies_present,
-            should_only_except_violated_by_forbidden_import=should_only_except_violated_by_forbidden_expected
-            and strict_dependency_present,
-            should_not_violated=should_not_expected and strict_dependency_present,
-            should_only_violated_by_no_import=should_only_expected
-            and any(dependency == [] for dependency in strict_dependencies.values()),
-            should_only_violated_by_forbidden_import=should_only_expected
-            and lax_dependencies_present,
-            should_only_except_violated_by_no_import=should_only_except_violated_by_no_expected
-            and not lax_dependencies_present,
-            should_except_violated=should_except_expected
-            and not lax_dependencies_present,
-            should_violated=should_expected and not strict_dependency_present,
-            lax_dependencies=lax_dependencies,
-            strict_dependencies=strict_dependencies,
-        )
-
-
-class RuleMatcher(ABC):
-    """Checks whether given modules fulfill the module and behavior requirements that have been specified for them."""
-
-    def __init__(
-        self,
-        module_requirement: ModuleRequirement,
-        behavior_requirement: BehaviorRequirement,
-    ) -> None:
-        self._module_requirement = module_requirement
-        self._behavior_requirement = behavior_requirement
-
-    @abstractmethod
-    def match(self, evaluable: EvaluableArchitecture) -> RuleViolations:
-        """
-        Checks whether an expected behavior is exhibited by the EvaluableArchitecture.
-
-        Args:
-            evaluable: object to check
-        Returns:
-            overview of rule violations
-        """
-        raise NotImplementedError()
-
-
-class DefaultRuleMatcher(RuleMatcher):
-    def match(self, evaluable: EvaluableArchitecture) -> RuleViolations:
-        strict_dependencies = self._get_strict_dependencies(evaluable)
-
-        lax_dependencies = self._get_lax_dependencies(evaluable)
-
-        return self._behavior_requirement.generate_rule_violation(
-            strict_dependencies,
-            lax_dependencies,
-        )
-
-    def _get_lax_dependencies(
-        self, evaluable: EvaluableArchitecture
-    ) -> Optional[LaxDependenciesByBaseModule]:
-        if (
-            self._behavior_requirement.lax_dependency_required
-            or self._behavior_requirement.lax_dependency_not_allowed
-        ):
-            if not self._module_requirement.left_hand_module_has_specifier:
-                lax_dependency_check_method = (
-                    evaluable.any_dependencies_to_modules_other_than
-                )
-            else:
-                lax_dependency_check_method = (
-                    evaluable.any_other_dependencies_to_modules_than
-                )
-
-            return lax_dependency_check_method(
-                self._module_requirement.left_hand_modules,
-                self._module_requirement.right_hand_modules,
-            )
-
-        return None
-
-    def _get_strict_dependencies(
-        self,
-        evaluable: EvaluableArchitecture,
-    ) -> Optional[StrictDependenciesByBaseModules]:
-        if (
-            self._behavior_requirement.strict_dependency_required
-            or self._behavior_requirement.strict_dependency_not_allowed
-        ):
-            return evaluable.get_dependencies(
-                self._module_requirement.left_hand_modules,
-                self._module_requirement.right_hand_modules,
-            )
-
-        return None
diff --git a/src/pytestarch/query_language/diagrams/__init__.py b/src/pytestarch/rule_assessment/__init__.py
similarity index 100%
rename from src/pytestarch/query_language/diagrams/__init__.py
rename to src/pytestarch/rule_assessment/__init__.py
diff --git a/tests/diagram_import/__init__.py b/src/pytestarch/rule_assessment/error_message/__init__.py
similarity index 100%
rename from tests/diagram_import/__init__.py
rename to src/pytestarch/rule_assessment/error_message/__init__.py
diff --git a/src/pytestarch/query_language/message_generator.py b/src/pytestarch/rule_assessment/error_message/message_generator.py
similarity index 90%
rename from src/pytestarch/query_language/message_generator.py
rename to src/pytestarch/rule_assessment/error_message/message_generator.py
index 1094de5..e29044f 100644
--- a/src/pytestarch/query_language/message_generator.py
+++ b/src/pytestarch/rule_assessment/error_message/message_generator.py
@@ -5,7 +5,7 @@
 from typing import Iterable, List, Optional, Tuple
 
 from pytestarch.eval_structure.evaluable_architecture import Module, StrictDependency
-from pytestarch.query_language.rule_matcher import RuleViolations
+from pytestarch.rule_assessment.rule_check.rule_violations import RuleViolations
 
 IMPORT = "import"
 IMPORTED_BY = "imported by"
@@ -68,6 +68,17 @@ def __init__(
 
         self._base_verb = IMPORT if self._import_rule else IMPORTED_BY
 
+    def create_rule_violation_message(self, rule_violations: RuleViolations) -> str:
+        """Create a message about all rule violations.
+
+        Args:
+            rule_violations: to convert to human-readable format
+
+        Returns:
+            message containing all individual rule violation messages
+        """
+        return "\n".join(self.create_rule_violation_messages(rule_violations))
+
     def create_rule_violation_messages(
         self, rule_violations: RuleViolations
     ) -> List[str]:
@@ -184,7 +195,7 @@ def _create_should_only_import_forbidden_import_violated_messages(
         if not rule_violations.should_only_violated_by_forbidden_import:
             return []
 
-        violating_dependencies = rule_violations.lax_dependencies.values()
+        violating_dependencies = rule_violations.unexpected_dependencies.values()
         return self._create_other_violating_dependencies_message(violating_dependencies)
 
     def _create_other_violating_dependencies_message(
@@ -200,14 +211,12 @@ def _create_other_violating_dependencies_message(
             prefix=verb_prefix, verb=self._base_verb, suffix=suffix
         )
 
-        for strict_dependencies in violating_dependencies:
-            for strict_dependency in strict_dependencies:
+        for dependencies in violating_dependencies:
+            for dependency in dependencies:
                 (
                     rule_subject,
                     rule_object,
-                ) = self._get_rule_subject_and_object_of_strict_dependency(
-                    strict_dependency
-                )
+                ) = self._get_rule_subject_and_object_of_dependency(dependency)
                 messages.append(
                     RuleViolatedMessage(rule_subject, rule_verb, rule_object)
                 )
@@ -228,7 +237,7 @@ def _create_should_not_import_violated_messages(
         if not rule_violations.should_not_violated:
             return []
 
-        violating_dependencies = rule_violations.strict_dependencies.values()
+        violating_dependencies = rule_violations.dependencies.values()
         return self._create_other_violating_dependencies_message(violating_dependencies)
 
     def _create_should_import_except_violated_messages(
@@ -295,7 +304,7 @@ def _create_should_only_import_except_forbidden_import_violated_messages(
         if not rule_violations.should_only_except_violated_by_forbidden_import:
             return []
 
-        violating_dependencies = rule_violations.strict_dependencies.values()
+        violating_dependencies = rule_violations.dependencies.values()
         return self._create_other_violating_dependencies_message(violating_dependencies)
 
     def _create_should_only_import_except_no_import_violated_messages(
@@ -314,7 +323,7 @@ def _create_should_not_import_except_violated_messages(
         if not rule_violations.should_not_except_violated:
             return []
 
-        violating_dependencies = rule_violations.lax_dependencies.values()
+        violating_dependencies = rule_violations.unexpected_dependencies.values()
         return self._create_other_violating_dependencies_message(violating_dependencies)
 
     def _generate_rule_subject_name(self, module: Module) -> str:
@@ -355,15 +364,15 @@ def _get_rule_object(self, rule_object: str, is_singular: bool) -> str:
     def _quoted_name(self, name: str) -> str:
         return f'"{name}"'
 
-    def _get_rule_subject_and_object_of_strict_dependency(
-        self, strict_dependency: StrictDependency
+    def _get_rule_subject_and_object_of_dependency(
+        self, dependency: StrictDependency
     ) -> Tuple[str, str]:
-        # strict dependency is always reported in format (importer, importee)
+        # dependency is always reported in format (importer, importee)
         # if rule is of format A ... imports B, the dependency will be (A, B)
         if self._import_rule:
-            rule_subject, rule_object = strict_dependency
+            rule_subject, rule_object = dependency
         else:
-            rule_object, rule_subject = strict_dependency
+            rule_object, rule_subject = dependency
 
         rule_subject_name = self._get_module_name(rule_subject)
         rule_object_name = self._get_module_name(rule_object)
diff --git a/src/pytestarch/rule_assessment/exceptions.py b/src/pytestarch/rule_assessment/exceptions.py
new file mode 100644
index 0000000..eaca15b
--- /dev/null
+++ b/src/pytestarch/rule_assessment/exceptions.py
@@ -0,0 +1,2 @@
+class RuleInconsistency(Exception):
+    pass
diff --git a/tests/graph/__init__.py b/src/pytestarch/rule_assessment/rule_check/__init__.py
similarity index 100%
rename from tests/graph/__init__.py
rename to src/pytestarch/rule_assessment/rule_check/__init__.py
diff --git a/src/pytestarch/rule_assessment/rule_check/behavior_requirement.py b/src/pytestarch/rule_assessment/rule_check/behavior_requirement.py
new file mode 100644
index 0000000..c2f9b0a
--- /dev/null
+++ b/src/pytestarch/rule_assessment/rule_check/behavior_requirement.py
@@ -0,0 +1,112 @@
+from typing import Optional
+
+from pytestarch.eval_structure.evaluable_architecture import (
+    DependenciesByBaseModules,
+    UnexpectedDependenciesByBaseModule,
+)
+from pytestarch.rule_assessment.exceptions import RuleInconsistency
+from pytestarch.rule_assessment.rule_check.rule_violations import RuleViolations
+
+
+class BehaviorRequirement:
+    """Stores information about which import behavior the checked module is supposed to exhibit."""
+
+    def __init__(
+        self,
+        positive_behavior_lax: bool,
+        positive_behavior_strict: bool,
+        negative_behavior: bool,
+        behavior_exception: bool,
+    ) -> None:
+        self._should = positive_behavior_lax
+        self._should_only = positive_behavior_strict
+        self._should_not = negative_behavior
+
+        self._behavior_exception = behavior_exception
+
+        self._validate()
+
+    @property
+    def strict_dependency_required(self) -> bool:
+        """Returns True if a dependency between two specific modules is required."""
+        return (self._should or self._should_only) and not self._behavior_exception
+
+    @property
+    def lax_dependency_required(self) -> bool:
+        """Returns True if a dependency between a specific module and
+        any other modules is required. Which other modules are required
+        is specified by the module requirement."""
+        return self._behavior_exception and (self._should or self._should_only)
+
+    @property
+    def strict_dependency_not_allowed(self) -> bool:
+        """Returns True if a dependency between two specific modules is not allowed."""
+        return (self._should_not and not self._behavior_exception) or (
+            self._should_only and self._behavior_exception
+        )
+
+    @property
+    def lax_dependency_not_allowed(self) -> bool:
+        """Returns True if no dependency between a specific module
+        and a set of other modules is not allowed. Which other modules
+        are not allowed is specified by the module requirement."""
+        return (self._should_not and self._behavior_exception) or (
+            self._should_only and not self._behavior_exception
+        )
+
+    def _validate(self) -> None:
+        if self.strict_dependency_required and self.strict_dependency_not_allowed:
+            raise RuleInconsistency("Strict dependency both required and not allowed.")
+
+        if self.lax_dependency_required and self.lax_dependency_not_allowed:
+            raise RuleInconsistency("Lax dependency both required and not allowed.")
+
+    def generate_rule_violation(
+        self,
+        strict_dependencies: Optional[DependenciesByBaseModules],
+        lax_dependencies: Optional[UnexpectedDependenciesByBaseModule],
+    ) -> RuleViolations:
+        """Translate from the detected types of dependencies back to which behavior and dependency requirements are violated by them.
+        Args:
+            strict_dependencies: dependency between the two specified modules found, grouped by requested modules
+            lax_dependencies: other dependencies found beside the two specified modules
+        Returns:
+            overview of all rule violations
+        """
+        should_not_except_expected = self._should_not and self._behavior_exception
+        should_only_except_violated_by_forbidden_expected = (
+            self._should_only and self._behavior_exception
+        )
+        should_not_expected = self._should_not and not self._behavior_exception
+        should_only_expected = self._should_only and not self._behavior_exception
+        should_only_except_violated_by_no_expected = (
+            self._should_only and self._behavior_exception
+        )
+        should_except_expected = self._should and self._behavior_exception
+        should_expected = self._should and not self._behavior_exception
+
+        lax_dependencies_present = lax_dependencies is not None and any(
+            lax_dependency for lax_dependency in lax_dependencies.values()
+        )
+        strict_dependency_present = strict_dependencies is not None and any(
+            strict_dependency for strict_dependency in strict_dependencies.values()
+        )
+
+        return RuleViolations(
+            should_not_except_violated=should_not_except_expected
+            and lax_dependencies_present,
+            should_only_except_violated_by_forbidden_import=should_only_except_violated_by_forbidden_expected
+            and strict_dependency_present,
+            should_not_violated=should_not_expected and strict_dependency_present,
+            should_only_violated_by_no_import=should_only_expected
+            and any(dependency == [] for dependency in strict_dependencies.values()),
+            should_only_violated_by_forbidden_import=should_only_expected
+            and lax_dependencies_present,
+            should_only_except_violated_by_no_import=should_only_except_violated_by_no_expected
+            and not lax_dependencies_present,
+            should_except_violated=should_except_expected
+            and not lax_dependencies_present,
+            should_violated=should_expected and not strict_dependency_present,
+            unexpected_dependencies=lax_dependencies,
+            dependencies=strict_dependencies,
+        )
diff --git a/src/pytestarch/rule_assessment/rule_check/module_requirement.py b/src/pytestarch/rule_assessment/rule_check/module_requirement.py
new file mode 100644
index 0000000..50ebf89
--- /dev/null
+++ b/src/pytestarch/rule_assessment/rule_check/module_requirement.py
@@ -0,0 +1,53 @@
+from typing import List, Union
+
+from pytestarch.eval_structure.evaluable_architecture import Module
+
+
+class ModuleRequirement:
+    """Stores information about which module is supposed to be checked against which module."""
+
+    def __init__(
+        self,
+        importer: Module,
+        importees: List[Module],
+        flip_importer_and_importees: bool,
+    ) -> None:
+        self._importer_as_specified_by_user = importer
+        self._importees_as_specified_by_user = importees
+
+        self._importers = importer
+        self._importees = importees
+
+        self._flip_importer_and_importees = flip_importer_and_importees
+
+        if self.rule_specified_with_importer_as_rule_object:
+            self._importers, self._importees = (
+                self._importees,
+                self._importers,
+            )
+
+    @property
+    def importers(self) -> Union[Module, List[Module]]:
+        return self._importers
+
+    @property
+    def importees(self) -> Union[Module, List[Module]]:
+        return self._importees
+
+    @property
+    def importers_as_specified_by_user(self) -> Module:
+        return self._importer_as_specified_by_user
+
+    @property
+    def importees_as_specified_by_user(self) -> Union[Module, List[Module]]:
+        return self._importees_as_specified_by_user
+
+    @property
+    def rule_specified_with_importer_as_rule_object(self) -> bool:
+        # True if rule is of format "is imported by"
+        return not self._flip_importer_and_importees
+
+    @property
+    def rule_specified_with_importer_as_rule_subject(self) -> bool:
+        # True if rule is of format "is imported by"
+        return self._flip_importer_and_importees
diff --git a/src/pytestarch/rule_assessment/rule_check/rule_matcher.py b/src/pytestarch/rule_assessment/rule_check/rule_matcher.py
new file mode 100644
index 0000000..f480d52
--- /dev/null
+++ b/src/pytestarch/rule_assessment/rule_check/rule_matcher.py
@@ -0,0 +1,104 @@
+from abc import ABC, abstractmethod
+from typing import Optional
+
+from pytestarch.eval_structure.evaluable_architecture import (
+    DependenciesByBaseModules,
+    EvaluableArchitecture,
+    UnexpectedDependenciesByBaseModule,
+)
+from pytestarch.rule_assessment.error_message.message_generator import (
+    RuleViolationMessageGenerator,
+)
+from pytestarch.rule_assessment.rule_check.behavior_requirement import (
+    BehaviorRequirement,
+)
+from pytestarch.rule_assessment.rule_check.module_requirement import ModuleRequirement
+from pytestarch.rule_assessment.rule_check.rule_violations import RuleViolations
+
+
+class RuleMatcher(ABC):
+    """Checks whether given modules fulfill the module and behavior requirements that have been specified for them."""
+
+    def __init__(
+        self,
+        module_requirement: ModuleRequirement,
+        behavior_requirement: BehaviorRequirement,
+    ) -> None:
+        self._module_requirement = module_requirement
+        self._behavior_requirement = behavior_requirement
+
+    @abstractmethod
+    def match(self, evaluable: EvaluableArchitecture) -> None:
+        """
+        Checks whether an expected behavior is exhibited by the EvaluableArchitecture.
+        If there are any rule violations, will raise an error detailing the violations.
+
+        Args:
+            evaluable: object to check
+        Raises:
+            AssertionError
+        """
+        raise NotImplementedError()
+
+
+class DefaultRuleMatcher(RuleMatcher):
+    def match(self, evaluable: EvaluableArchitecture) -> None:
+        rule_violations = self._find_rule_violations(evaluable)
+
+        if rule_violations:
+            raise AssertionError(self._create_rule_violation_message(rule_violations))
+
+    def _find_rule_violations(self, evaluable: EvaluableArchitecture) -> RuleViolations:
+        strict_dependencies = self._get_strict_dependencies(evaluable)
+        lax_dependencies = self._get_lax_dependencies(evaluable)
+
+        return self._behavior_requirement.generate_rule_violation(
+            strict_dependencies,
+            lax_dependencies,
+        )
+
+    def _create_rule_violation_message(self, rule_violations: RuleViolations) -> str:
+        message_generator = RuleViolationMessageGenerator(
+            self._module_requirement.importers_as_specified_by_user,
+            self._module_requirement.importees_as_specified_by_user,
+            self._module_requirement.rule_specified_with_importer_as_rule_subject,
+        )
+        return message_generator.create_rule_violation_message(rule_violations)
+
+    def _get_lax_dependencies(
+        self, evaluable: EvaluableArchitecture
+    ) -> Optional[UnexpectedDependenciesByBaseModule]:
+        if (
+            self._behavior_requirement.lax_dependency_required
+            or self._behavior_requirement.lax_dependency_not_allowed
+        ):
+            if not self._module_requirement.rule_specified_with_importer_as_rule_object:
+                lax_dependency_check_method = (
+                    evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons
+                )
+            else:
+                lax_dependency_check_method = (
+                    evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents
+                )
+
+            return lax_dependency_check_method(
+                self._module_requirement.importers,
+                self._module_requirement.importees,
+            )
+
+        return None
+
+    def _get_strict_dependencies(
+        self,
+        evaluable: EvaluableArchitecture,
+    ) -> Optional[DependenciesByBaseModules]:
+        if (
+            self._behavior_requirement.strict_dependency_required
+            or self._behavior_requirement.strict_dependency_not_allowed
+        ):
+            return evaluable.get_dependencies(
+                self._module_requirement.importers,
+                self._module_requirement.importees,
+            )
+
+        return None
diff --git a/src/pytestarch/rule_assessment/rule_check/rule_violations.py b/src/pytestarch/rule_assessment/rule_check/rule_violations.py
new file mode 100644
index 0000000..4a22fca
--- /dev/null
+++ b/src/pytestarch/rule_assessment/rule_check/rule_violations.py
@@ -0,0 +1,29 @@
+from dataclasses import dataclass, fields
+from typing import List, Optional
+
+from pytestarch.eval_structure.evaluable_architecture import (
+    DependenciesByBaseModules,
+    UnexpectedDependenciesByBaseModule,
+)
+
+
+@dataclass
+class RuleViolations:
+    unexpected_dependencies: Optional[UnexpectedDependenciesByBaseModule]
+    dependencies: Optional[DependenciesByBaseModules]
+
+    should_violated: bool = False
+    should_only_violated_by_forbidden_import: bool = False
+    should_only_violated_by_no_import: bool = False
+    should_not_violated: bool = False
+    should_except_violated: bool = False
+    should_only_except_violated_by_forbidden_import: bool = False
+    should_only_except_violated_by_no_import: bool = False
+    should_not_except_violated: bool = False
+
+    def __bool__(self) -> bool:
+        return any(self.__dict__[a] for a in self._bool_field_names())
+
+    @classmethod
+    def _bool_field_names(cls) -> List[str]:
+        return [field.name for field in fields(cls) if field.type == bool]
diff --git a/tests/conftest.py b/tests/conftest.py
index 280fb72..f06eeef 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -4,7 +4,7 @@
 import pytest
 from resources.test_project import src
 
-from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
+from pytestarch import EvaluableArchitecture
 from pytestarch.pytestarch import (
     get_evaluable_architecture,
     get_evaluable_architecture_for_module_objects,
diff --git a/tests/importer/__init__.py b/tests/diagram_extension/__init__.py
similarity index 100%
rename from tests/importer/__init__.py
rename to tests/diagram_extension/__init__.py
diff --git a/tests/query_language/diagrams/test_dependency_to_rule_converter.py b/tests/diagram_extension/test_dependency_to_rule_converter.py
similarity index 95%
rename from tests/query_language/diagrams/test_dependency_to_rule_converter.py
rename to tests/diagram_extension/test_dependency_to_rule_converter.py
index 2ece904..854be36 100644
--- a/tests/query_language/diagrams/test_dependency_to_rule_converter.py
+++ b/tests/diagram_extension/test_dependency_to_rule_converter.py
@@ -1,7 +1,7 @@
-from pytestarch.diagram_import.parsed_dependencies import ParsedDependencies
-from pytestarch.query_language.diagrams.dependency_to_rule_converter import (
+from pytestarch.diagram_extension.dependency_to_rule_converter import (
     DependencyToRuleConverter,
 )
+from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
 
 M1 = "M1"
 M2 = "M2"
diff --git a/tests/diagram_import/test_diagram_parser.py b/tests/diagram_extension/test_diagram_parser.py
similarity index 95%
rename from tests/diagram_import/test_diagram_parser.py
rename to tests/diagram_extension/test_diagram_parser.py
index 6fa1bda..2062481 100644
--- a/tests/diagram_import/test_diagram_parser.py
+++ b/tests/diagram_extension/test_diagram_parser.py
@@ -1,8 +1,8 @@
 import pytest
 from conftest import ROOT_DIR
 
-from pytestarch.diagram_import.diagram_parser import PumlParser
-from pytestarch.exceptions import PumlParsingError
+from pytestarch.diagram_extension.diagram_parser import PumlParser
+from pytestarch.diagram_extension.exceptions import PumlParsingError
 
 
 def test_error_raised_when_no_puml_start_tag_found() -> None:
diff --git a/tests/query_language/diagrams/test_diagram_rule.py b/tests/diagram_extension/test_diagram_rule.py
similarity index 93%
rename from tests/query_language/diagrams/test_diagram_rule.py
rename to tests/diagram_extension/test_diagram_rule.py
index d8e6f19..d208557 100644
--- a/tests/query_language/diagrams/test_diagram_rule.py
+++ b/tests/diagram_extension/test_diagram_rule.py
@@ -5,11 +5,11 @@
 from resources import flat_test_project_1, flat_test_project_2
 
 from pytestarch import DiagramRule, EvaluableArchitecture, get_evaluable_architecture
-from pytestarch.diagram_import.parsed_dependencies import ParsedDependencies
+from pytestarch.diagram_extension.diagram_rule import ModulePrefixer
+from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
 from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.importer.import_types import AbsoluteImport
-from pytestarch.query_language.diagrams.diagram_rule import ModulePrefixer
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
 
 MULTIPLE_COMPONENTS_FILE_PATH = (
     ROOT_DIR / "tests/resources/pumls/multiple_component_example_with_brackets.puml"
diff --git a/tests/query_language/diagrams/__init__.py b/tests/eval_structure/evaluable_graph/__init__.py
similarity index 100%
rename from tests/query_language/diagrams/__init__.py
rename to tests/eval_structure/evaluable_graph/__init__.py
diff --git a/tests/eval_structure/evaluable_graph/conftest.py b/tests/eval_structure/evaluable_graph/conftest.py
new file mode 100644
index 0000000..1dd3753
--- /dev/null
+++ b/tests/eval_structure/evaluable_graph/conftest.py
@@ -0,0 +1,53 @@
+import pytest
+
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
+
+MODULE_1 = "Module1"
+MODULE_OBJECT_1 = Module(name=MODULE_1)
+MODULE_2 = "Module2"
+MODULE_OBJECT_2 = Module(name=MODULE_2)
+MODULE_3 = "Module3"
+MODULE_OBJECT_3 = Module(name=MODULE_3)
+MODULE_4 = "Module4"
+MODULE_OBJECT_4 = Module(name=MODULE_4)
+MODULE_6 = "Module6"
+MODULE_OBJECT_6 = Module(name=MODULE_6)
+SUB_MODULE_OF_2 = "Module2.SubModule1"
+SUB_MODULE_OBJECT_2 = Module(name=SUB_MODULE_OF_2)
+SUB_MODULE_OF_1 = "Module1.SubModule1"
+MODULE_A = "E.A"  # submodule of E
+MODULE_B = "E.A.B"  # submodule of A
+MODULE_C = "C"
+MODULE_D = "E.A.B.D"  # submodule of B
+MODULE_E = "E"
+MODULE_F = "E.F"  # submodule of E
+
+
+@pytest.fixture(scope="session")
+def evaluable() -> EvaluableArchitectureGraph:
+    all_modules = [MODULE_1, MODULE_2, MODULE_3, MODULE_4, SUB_MODULE_OF_2, MODULE_6]
+    imports = [
+        AbsoluteImport(MODULE_1, MODULE_2),
+        AbsoluteImport(MODULE_1, MODULE_3),
+        AbsoluteImport(MODULE_1, MODULE_4),
+        AbsoluteImport(MODULE_3, MODULE_2),
+        AbsoluteImport(MODULE_4, SUB_MODULE_OF_2),
+        AbsoluteImport(MODULE_3, MODULE_6),
+    ]
+
+    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+
+@pytest.fixture(scope="session")
+def submodule_evaluable() -> EvaluableArchitectureGraph:
+    all_modules = [MODULE_A, MODULE_B, MODULE_C, MODULE_D, MODULE_E, MODULE_F]
+    imports = [
+        AbsoluteImport(MODULE_F, MODULE_C),
+        AbsoluteImport(MODULE_C, MODULE_A),
+        AbsoluteImport(MODULE_C, MODULE_B),
+    ]
+
+    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
diff --git a/tests/eval_structure/evaluable_graph/test_aliases.py b/tests/eval_structure/evaluable_graph/test_aliases.py
new file mode 100644
index 0000000..5c34a2b
--- /dev/null
+++ b/tests/eval_structure/evaluable_graph/test_aliases.py
@@ -0,0 +1,84 @@
+import pytest
+from eval_structure.evaluable_graph.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_A,
+    MODULE_E,
+    SUB_MODULE_OF_2,
+)
+from matplotlib.pyplot import subplots
+
+from pytestarch import EvaluableArchitecture
+
+
+def test_all_modules_labeled_when_aliases_used(
+    evaluable: EvaluableArchitecture,
+) -> None:
+    module_1_alias = "1"
+    aliases = {MODULE_1: module_1_alias}
+    fig, ax = subplots()
+
+    evaluable.visualize(aliases=aliases, ax=ax)
+
+    labels_in_plot = [t.get_text() for t in ax.texts]
+    assert len(labels_in_plot) == 6
+
+
+def test_alias_replaces_module_name_in_plot(evaluable: EvaluableArchitecture) -> None:
+    module_2_alias = "2"
+    aliases = {MODULE_2: module_2_alias}
+    fig, ax = subplots()
+
+    evaluable.visualize(aliases=aliases, ax=ax)
+
+    labels_in_plot = [t.get_text() for t in ax.texts]
+    assert module_2_alias in labels_in_plot
+    assert MODULE_2 not in labels_in_plot
+    assert SUB_MODULE_OF_2 not in labels_in_plot
+    assert f"{module_2_alias}.SubModule1" in labels_in_plot
+
+
+def test_alias_replaces_module_name_in_submodules_plot(
+    evaluable: EvaluableArchitecture,
+) -> None:
+    module_2_alias = "2"
+    aliases = {MODULE_2: module_2_alias}
+    submodule_label_with_alias = f"{module_2_alias}.SubModule1"
+    fig, ax = subplots()
+
+    evaluable.visualize(aliases=aliases, ax=ax)
+
+    labels_in_plot = [t.get_text() for t in ax.texts]
+    assert module_2_alias in labels_in_plot
+    assert MODULE_2 not in labels_in_plot
+    assert SUB_MODULE_OF_2 not in labels_in_plot
+    assert submodule_label_with_alias in labels_in_plot
+
+
+def test_when_module_and_a_submodule_have_aliases_the_submodule_alias_takes_priority(
+    submodule_evaluable: EvaluableArchitecture,
+) -> None:
+    module_e_alias = "e"
+    submodule_of_e_alias = "ea"
+    submodule_label_with_parent_alias = f"{module_e_alias}.A"
+    aliases = {MODULE_E: module_e_alias, MODULE_A: submodule_of_e_alias}
+    fig, ax = subplots()
+
+    submodule_evaluable.visualize(aliases=aliases, ax=ax)
+
+    labels_in_plot = [t.get_text() for t in ax.texts]
+    assert module_e_alias in labels_in_plot
+    assert submodule_of_e_alias in labels_in_plot
+    assert SUB_MODULE_OF_2 not in labels_in_plot
+    assert submodule_label_with_parent_alias not in labels_in_plot
+    assert f"{module_e_alias}.F" in labels_in_plot
+
+
+def test_when_module_name_in_alias_spec_is_not_found_an_error_is_raised(
+    evaluable: EvaluableArchitecture,
+) -> None:
+    non_existent_module = "non_existent_module"
+    aliases = {non_existent_module: "a"}
+
+    with pytest.raises(KeyError, match=non_existent_module):
+        evaluable.visualize(aliases=aliases)
diff --git a/tests/eval_structure/evaluable_graph/test_any_dependencies_to_other_modules.py b/tests/eval_structure/evaluable_graph/test_any_dependencies_to_other_modules.py
new file mode 100644
index 0000000..d14c3cc
--- /dev/null
+++ b/tests/eval_structure/evaluable_graph/test_any_dependencies_to_other_modules.py
@@ -0,0 +1,189 @@
+from typing import List
+
+import pytest
+from eval_structure.evaluable_graph.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_3,
+    SUB_MODULE_OF_1,
+    SUB_MODULE_OF_2,
+)
+
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_3)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
+    ],
+)
+def test_any_to_other_between_named_modules(imports: List[AbsoluteImport]) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_3)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+    ],
+)
+def test_any_to_other_between_named_and_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
+    ],
+)
+def test_any_to_other_between_submodule_and_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+    ],
+)
+def test_any_to_other_between_submodule_modules(imports: List[AbsoluteImport]) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_not_any_to_other_between_named_modules(imports: List[AbsoluteImport]) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert not architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_not_any_to_other_between_named_and_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert not architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_3)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_not_any_to_other_between_submodule_and_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert not architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_3)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_not_any_to_other_between_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert not architecture.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        module_1, module_2
+    )[
+        module_1
+    ]
diff --git a/tests/eval_structure/evaluable_graph/test_dependencies_between_modules.py b/tests/eval_structure/evaluable_graph/test_dependencies_between_modules.py
new file mode 100644
index 0000000..281537b
--- /dev/null
+++ b/tests/eval_structure/evaluable_graph/test_dependencies_between_modules.py
@@ -0,0 +1,515 @@
+from typing import List
+
+import pytest
+from eval_structure.evaluable_graph.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_OBJECT_1,
+    MODULE_OBJECT_2,
+    MODULE_OBJECT_3,
+    MODULE_OBJECT_4,
+    MODULE_OBJECT_6,
+    SUB_MODULE_OBJECT_2,
+    SUB_MODULE_OF_1,
+    SUB_MODULE_OF_2,
+)
+
+from pytestarch import EvaluableArchitecture
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
+
+
+def test_a_depends_on_non_b(evaluable: EvaluableArchitecture) -> None:
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_1, MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_1
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_1, MODULE_OBJECT_3
+    )[
+        MODULE_OBJECT_1
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_1, MODULE_OBJECT_4
+    )[
+        MODULE_OBJECT_1
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_1, SUB_MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_1
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_1, MODULE_OBJECT_6
+    )[
+        MODULE_OBJECT_1
+    ]
+
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_2, MODULE_OBJECT_1
+    )[
+        MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_2, MODULE_OBJECT_3
+    )[
+        MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_2, MODULE_OBJECT_4
+    )[
+        MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_2, SUB_MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_2, MODULE_OBJECT_6
+    )[
+        MODULE_OBJECT_2
+    ]
+
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_3, MODULE_OBJECT_1
+    )[
+        MODULE_OBJECT_3
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_3, MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_3
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_3, MODULE_OBJECT_4
+    )[
+        MODULE_OBJECT_3
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_3, SUB_MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_3
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_3, MODULE_OBJECT_6
+    )[
+        MODULE_OBJECT_3
+    ]
+
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_4, MODULE_OBJECT_1
+    )[
+        MODULE_OBJECT_4
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_4, MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_4
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_4, MODULE_OBJECT_3
+    )[
+        MODULE_OBJECT_4
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_4, SUB_MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_4
+    ]
+    assert evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_4, MODULE_OBJECT_6
+    )[
+        MODULE_OBJECT_4
+    ]
+
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_1
+    )[
+        SUB_MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_2
+    )[
+        SUB_MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_3
+    )[
+        SUB_MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_4
+    )[
+        SUB_MODULE_OBJECT_2
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_6
+    )[
+        SUB_MODULE_OBJECT_2
+    ]
+
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_6, MODULE_OBJECT_1
+    )[
+        MODULE_OBJECT_6
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_6, MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_6
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_6, MODULE_OBJECT_3
+    )[
+        MODULE_OBJECT_6
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_6, MODULE_OBJECT_4
+    )[
+        MODULE_OBJECT_6
+    ]
+    assert not evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons(
+        MODULE_OBJECT_6, SUB_MODULE_OBJECT_2
+    )[
+        MODULE_OBJECT_6
+    ]
+
+
+def test_non_a_depends_on_b(evaluable: EvaluableArchitecture) -> None:
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_1, MODULE_OBJECT_2
+    )[MODULE_OBJECT_2]
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_1, MODULE_OBJECT_3
+    )[MODULE_OBJECT_3]
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_1, MODULE_OBJECT_4
+    )[MODULE_OBJECT_4]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_1, SUB_MODULE_OBJECT_2
+    )[SUB_MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_1, MODULE_OBJECT_6
+    )[MODULE_OBJECT_6]
+
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_2, MODULE_OBJECT_1
+    )[MODULE_OBJECT_1]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_2, MODULE_OBJECT_3
+    )[MODULE_OBJECT_3]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_2, MODULE_OBJECT_4
+    )[MODULE_OBJECT_4]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_2, SUB_MODULE_OBJECT_2
+    )[SUB_MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_2, MODULE_OBJECT_6
+    )[MODULE_OBJECT_6]
+
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_3, MODULE_OBJECT_1
+    )[MODULE_OBJECT_1]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_3, MODULE_OBJECT_2
+    )[MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_3, MODULE_OBJECT_4
+    )[MODULE_OBJECT_4]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_3, SUB_MODULE_OBJECT_2
+    )[SUB_MODULE_OBJECT_2]
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_3, MODULE_OBJECT_6
+    )[MODULE_OBJECT_6]
+
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_4, MODULE_OBJECT_1
+    )[MODULE_OBJECT_1]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_4, MODULE_OBJECT_2
+    )[MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_4, MODULE_OBJECT_3
+    )[MODULE_OBJECT_3]
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_4, SUB_MODULE_OBJECT_2
+    )[SUB_MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_4, MODULE_OBJECT_6
+    )[MODULE_OBJECT_6]
+
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_1
+    )[MODULE_OBJECT_1]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_2
+    )[MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_3
+    )[MODULE_OBJECT_3]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_4
+    )[MODULE_OBJECT_4]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        SUB_MODULE_OBJECT_2, MODULE_OBJECT_6
+    )[MODULE_OBJECT_6]
+
+    assert not evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_6, MODULE_OBJECT_1
+    )[MODULE_OBJECT_1]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_6, MODULE_OBJECT_2
+    )[MODULE_OBJECT_2]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_6, MODULE_OBJECT_3
+    )[MODULE_OBJECT_3]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_6, MODULE_OBJECT_4
+    )[MODULE_OBJECT_4]
+    assert evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        MODULE_OBJECT_6, SUB_MODULE_OBJECT_2
+    )[SUB_MODULE_OBJECT_2]
+
+
+def test_depends_on(evaluable: EvaluableArchitecture) -> None:
+    assert evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_2)[
+        (MODULE_OBJECT_1, MODULE_OBJECT_2)
+    ]
+    assert evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_3)[
+        (MODULE_OBJECT_1, MODULE_OBJECT_3)
+    ]
+    assert evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_4)[
+        (MODULE_OBJECT_1, MODULE_OBJECT_4)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_1, SUB_MODULE_OBJECT_2)[
+        (MODULE_OBJECT_1, SUB_MODULE_OBJECT_2)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_6)[
+        (MODULE_OBJECT_1, MODULE_OBJECT_6)
+    ]
+
+    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_1)[
+        (MODULE_OBJECT_2, MODULE_OBJECT_1)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_3)[
+        MODULE_OBJECT_2, MODULE_OBJECT_3
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_4)[
+        MODULE_OBJECT_2, MODULE_OBJECT_4
+    ]
+    assert not evaluable.get_dependencies(
+        MODULE_OBJECT_2, Module(name=SUB_MODULE_OF_2)
+    )[MODULE_OBJECT_2, SUB_MODULE_OBJECT_2]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_6)[
+        (MODULE_OBJECT_2, MODULE_OBJECT_6)
+    ]
+
+    assert not evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_1)[
+        (MODULE_OBJECT_3, MODULE_OBJECT_1)
+    ]
+    assert evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_2)[
+        (MODULE_OBJECT_3, MODULE_OBJECT_2)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_4)[
+        MODULE_OBJECT_3, MODULE_OBJECT_4
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_3, SUB_MODULE_OBJECT_2)[
+        (MODULE_OBJECT_3, SUB_MODULE_OBJECT_2)
+    ]
+    assert evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_6)[
+        (MODULE_OBJECT_3, MODULE_OBJECT_6)
+    ]
+
+    assert not evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_1)[
+        (MODULE_OBJECT_4, MODULE_OBJECT_1)
+    ]
+    assert evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_2)[
+        MODULE_OBJECT_4, MODULE_OBJECT_2
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_3)[
+        MODULE_OBJECT_4, MODULE_OBJECT_3
+    ]
+    assert evaluable.get_dependencies(MODULE_OBJECT_4, SUB_MODULE_OBJECT_2)[
+        (MODULE_OBJECT_4, SUB_MODULE_OBJECT_2)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_6)[
+        (MODULE_OBJECT_4, MODULE_OBJECT_6)
+    ]
+
+    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_1)[
+        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_1)
+    ]
+    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_2)[
+        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_2)
+    ]
+    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_3)[
+        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_3)
+    ]
+    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_4)[
+        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_4)
+    ]
+    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_6)[
+        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_6)
+    ]
+
+    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_1)[
+        (MODULE_OBJECT_6, MODULE_OBJECT_1)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_2)[
+        (MODULE_OBJECT_6, MODULE_OBJECT_2)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_3)[
+        (MODULE_OBJECT_6, MODULE_OBJECT_3)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_4)[
+        (MODULE_OBJECT_6, MODULE_OBJECT_4)
+    ]
+    assert not evaluable.get_dependencies(MODULE_OBJECT_6, SUB_MODULE_OBJECT_2)[
+        (MODULE_OBJECT_6, SUB_MODULE_OBJECT_2)
+    ]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+    ],
+)
+def test_is_dependent_between_named_modules(imports: List[AbsoluteImport]) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_is_dependent_between_named_and_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_is_dependent_between_submodule_and_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_is_dependent_between_submodule_modules(imports: List[AbsoluteImport]) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_1)],
+        [AbsoluteImport(SUB_MODULE_OF_2, SUB_MODULE_OF_2)],
+    ],
+)
+def test_is_not_dependent_between_named_modules(imports: List[AbsoluteImport]) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+    ],
+)
+def test_is_not_dependent_between_named_and_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_is_not_dependent_between_submodule_and_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+    ],
+)
+def test_is_not_dependent_between_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
diff --git a/tests/eval_structure/evaluable_graph/test_other_dependencies_towards_modules.py b/tests/eval_structure/evaluable_graph/test_other_dependencies_towards_modules.py
new file mode 100644
index 0000000..9249ded
--- /dev/null
+++ b/tests/eval_structure/evaluable_graph/test_other_dependencies_towards_modules.py
@@ -0,0 +1,189 @@
+from typing import List
+
+import pytest
+from eval_structure.evaluable_graph.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_3,
+    SUB_MODULE_OF_1,
+    SUB_MODULE_OF_2,
+)
+
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_3, MODULE_2)],
+        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
+    ],
+)
+def test_other_to_module_than_between_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        module_1, module_2
+    )[module_2]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
+    ],
+)
+def test_other_to_module_than_between_named_and_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        module_1, module_2
+    )[module_2]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(MODULE_3, MODULE_2)],
+        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
+    ],
+)
+def test_other_to_module_than_between_submodule_and_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        module_1, module_2
+    )[module_2]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
+    ],
+)
+def test_other_to_module_than_between_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+        module_1, module_2
+    )[module_2]
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_not_other_to_module_than_between_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert (
+        not architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+            module_1, module_2
+        )[module_2]
+    )
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(MODULE_3, MODULE_2)],
+    ],
+)
+def test_not_other_to_module_than_between_named_and_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(name=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert (
+        not architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+            module_1, module_2
+        )[module_2]
+    )
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+    ],
+)
+def test_not_other_to_module_than_between_submodule_and_named_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(name=MODULE_2)
+    assert (
+        not architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+            module_1, module_2
+        )[module_2]
+    )
+
+
+@pytest.mark.parametrize(
+    "imports",
+    [
+        [AbsoluteImport(MODULE_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
+        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
+        [AbsoluteImport(MODULE_3, MODULE_2)],
+    ],
+)
+def test_not_other_to_module_than_between_submodule_modules(
+    imports: List[AbsoluteImport],
+) -> None:
+    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
+    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+    module_1 = Module(parent_module=MODULE_1)
+    module_2 = Module(parent_module=MODULE_2)
+    assert (
+        not architecture.any_other_dependencies_on_dependent_upons_than_from_dependents(
+            module_1, module_2
+        )[module_2]
+    )
diff --git a/tests/eval_structure/evaluable_graph/test_partial_module_matches.py b/tests/eval_structure/evaluable_graph/test_partial_module_matches.py
new file mode 100644
index 0000000..b8f7513
--- /dev/null
+++ b/tests/eval_structure/evaluable_graph/test_partial_module_matches.py
@@ -0,0 +1,97 @@
+import pytest
+from eval_structure.evaluable_graph.conftest import MODULE_A, MODULE_B, MODULE_D
+
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.exceptions import ImpossibleMatch
+
+MODULE = "test.module.submodule.class"
+
+
+partial_match_test_cases = [
+    pytest.param("test.module.submodule.class", True, id="complete match - match"),
+    pytest.param("test.module.submodule.clasz", False, id="complete match - no match"),
+    pytest.param("*.class", True, id="end match - match"),
+    pytest.param("*.clasz", False, id="end match - no match"),
+    pytest.param("test.*", True, id="start match - match"),
+    pytest.param("test,*", False, id="start match - no match"),
+    pytest.param("*le.submo*", True, id="inner match - match"),
+    pytest.param("les.submo*", False, id="inner match - no match"),
+]
+
+
+@pytest.mark.parametrize("match, expected_result", partial_match_test_cases)
+def test_partial_match(match: str, expected_result: bool) -> None:
+    assert (
+        EvaluableArchitectureGraph._partial_name_match(match, MODULE) == expected_result
+    )
+
+
+def test_module_matches(submodule_evaluable: EvaluableArchitectureGraph) -> None:
+    module_matches = [
+        Module(name="*D", partial_match=True),
+        Module(name="*A*", partial_match=True),
+    ]
+
+    calculated_matches = submodule_evaluable._convert_to_full_name_matches(
+        [module_matches]
+    )
+
+    assert len(calculated_matches) == 1
+    assert len(calculated_matches[0]) == 3
+
+    assert Module(name=MODULE_A) in calculated_matches[0]
+    assert Module(name=MODULE_B) in calculated_matches[0]
+    assert Module(name=MODULE_D) in calculated_matches[0]
+
+
+def test_non_partial_module_does_not_match_anything_but_itself(
+    submodule_evaluable: EvaluableArchitectureGraph,
+) -> None:
+    module_matches = [Module(name="*.*")]
+
+    calculated_matches = submodule_evaluable._convert_to_full_name_matches(
+        [module_matches]
+    )
+
+    assert len(calculated_matches) == 1
+    assert len(calculated_matches[0]) == 1
+
+    assert Module(name="*.*") in calculated_matches[0]
+
+
+def test_never_matched_match_raises_error(
+    evaluable: EvaluableArchitectureGraph,
+) -> None:
+    module_matches = [Module(name="I will not match", partial_match=True)]
+
+    with pytest.raises(
+        ImpossibleMatch, match="No modules found that match: I will not match"
+    ):
+        evaluable._convert_to_full_name_matches([module_matches])
+
+
+def test_module_matches_reported_separately_by_group(
+    submodule_evaluable: EvaluableArchitectureGraph,
+) -> None:
+    module_matches_1 = [
+        Module(name="*D", partial_match=True),
+    ]
+
+    module_matches_2 = [
+        Module(name="*A*", partial_match=True),
+    ]
+
+    calculated_matches = submodule_evaluable._convert_to_full_name_matches(
+        [module_matches_1, module_matches_2]
+    )
+
+    assert len(calculated_matches) == 2
+
+    assert len(calculated_matches[0]) == 1
+    assert len(calculated_matches[1]) == 3
+
+    assert Module(name=MODULE_D) in calculated_matches[0]
+    assert Module(name=MODULE_A) in calculated_matches[1]
+    assert Module(name=MODULE_B) in calculated_matches[1]
+    assert Module(name=MODULE_D) in calculated_matches[1]
diff --git a/tests/eval_structure/test_breadth_first_searches.py b/tests/eval_structure/test_breadth_first_searches.py
new file mode 100644
index 0000000..6866977
--- /dev/null
+++ b/tests/eval_structure/test_breadth_first_searches.py
@@ -0,0 +1,58 @@
+import pytest
+from eval_structure.evaluable_graph.conftest import (
+    MODULE_A,
+    MODULE_B,
+    MODULE_C,
+    MODULE_D,
+    MODULE_E,
+    MODULE_F,
+)
+
+from pytestarch.eval_structure.breadth_first_searches import _get_all_submodules_of
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
+
+
+@pytest.fixture(scope="module")
+def submodule_evaluable() -> EvaluableArchitectureGraph:
+    all_modules = [MODULE_A, MODULE_B, MODULE_C, MODULE_D, MODULE_E, MODULE_F]
+    imports = [
+        AbsoluteImport(MODULE_F, MODULE_C),
+        AbsoluteImport(MODULE_C, MODULE_A),
+        AbsoluteImport(MODULE_C, MODULE_B),
+    ]
+
+    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
+
+
+def test_submodule_calculation(submodule_evaluable: EvaluableArchitectureGraph) -> None:
+    assert _get_all_submodules_of(
+        submodule_evaluable._graph, Module(name=MODULE_A)
+    ) == {
+        MODULE_A,
+        MODULE_B,
+    }  # D does not show up as it is not connected to any import
+    assert _get_all_submodules_of(
+        submodule_evaluable._graph, Module(name=MODULE_B)
+    ) == {
+        MODULE_B
+    }  # D does not show up as it is not connected to any import
+    assert _get_all_submodules_of(
+        submodule_evaluable._graph, Module(name=MODULE_C)
+    ) == {MODULE_C}
+    assert _get_all_submodules_of(
+        submodule_evaluable._graph, Module(name=MODULE_D)
+    ) == {MODULE_D}
+    assert _get_all_submodules_of(
+        submodule_evaluable._graph, Module(name=MODULE_E)
+    ) == {
+        MODULE_E,
+        MODULE_A,
+        MODULE_B,
+        MODULE_F,
+    }  # D does not show up as it is not connected to any import
+    assert _get_all_submodules_of(
+        submodule_evaluable._graph, Module(name=MODULE_F)
+    ) == {MODULE_F}
diff --git a/tests/eval_structure/test_evaluable_graph.py b/tests/eval_structure/test_evaluable_graph.py
deleted file mode 100644
index e6386b2..0000000
--- a/tests/eval_structure/test_evaluable_graph.py
+++ /dev/null
@@ -1,1009 +0,0 @@
-from typing import List
-
-import pytest
-from matplotlib.pyplot import subplots
-
-from pytestarch.eval_structure.evaluable_architecture import (
-    EvaluableArchitecture,
-    Module,
-)
-from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.exceptions import ImpossibleMatch
-from pytestarch.importer.import_types import AbsoluteImport
-
-MODULE_1 = "Module1"
-MODULE_OBJECT_1 = Module(name=MODULE_1)
-MODULE_2 = "Module2"
-MODULE_OBJECT_2 = Module(name=MODULE_2)
-MODULE_3 = "Module3"
-MODULE_OBJECT_3 = Module(name=MODULE_3)
-MODULE_4 = "Module4"
-MODULE_OBJECT_4 = Module(name=MODULE_4)
-MODULE_6 = "Module6"
-MODULE_OBJECT_6 = Module(name=MODULE_6)
-SUB_MODULE_OF_2 = "Module2.SubModule1"
-SUB_MODULE_OBJECT_2 = Module(name=SUB_MODULE_OF_2)
-SUB_MODULE_OF_1 = "Module1.SubModule1"
-
-MODULE_A = "E.A"  # submodule of E
-MODULE_B = "E.A.B"  # submodule of A
-MODULE_C = "C"
-MODULE_D = "E.A.B.D"  # submodule of B
-MODULE_E = "E"
-MODULE_F = "E.F"  # submodule of E
-
-
-@pytest.fixture(scope="module")
-def evaluable() -> EvaluableArchitectureGraph:
-    all_modules = [MODULE_1, MODULE_2, MODULE_3, MODULE_4, SUB_MODULE_OF_2, MODULE_6]
-    imports = [
-        AbsoluteImport(MODULE_1, MODULE_2),
-        AbsoluteImport(MODULE_1, MODULE_3),
-        AbsoluteImport(MODULE_1, MODULE_4),
-        AbsoluteImport(MODULE_3, MODULE_2),
-        AbsoluteImport(MODULE_4, SUB_MODULE_OF_2),
-        AbsoluteImport(MODULE_3, MODULE_6),
-    ]
-
-    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-
-@pytest.fixture(scope="module")
-def submodule_evaluable() -> EvaluableArchitectureGraph:
-    all_modules = [MODULE_A, MODULE_B, MODULE_C, MODULE_D, MODULE_E, MODULE_F]
-    imports = [
-        AbsoluteImport(MODULE_F, MODULE_C),
-        AbsoluteImport(MODULE_C, MODULE_A),
-        AbsoluteImport(MODULE_C, MODULE_B),
-    ]
-
-    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-
-def test_a_depends_on_non_b(evaluable: EvaluableArchitecture) -> None:
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_2
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_3
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_4
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_1, SUB_MODULE_OBJECT_2
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_6
-    )[MODULE_OBJECT_1]
-
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_1
-    )[MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_3
-    )[MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_4
-    )[MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_2, SUB_MODULE_OBJECT_2
-    )[MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_6
-    )[MODULE_OBJECT_2]
-
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_1
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_2
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_4
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_3, SUB_MODULE_OBJECT_2
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_6
-    )[MODULE_OBJECT_3]
-
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_1
-    )[MODULE_OBJECT_4]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_2
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_3
-    )[MODULE_OBJECT_4]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_4, SUB_MODULE_OBJECT_2
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_6
-    )[MODULE_OBJECT_4]
-
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_1
-    )[SUB_MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_2
-    )[SUB_MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_3
-    )[SUB_MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_4
-    )[SUB_MODULE_OBJECT_2]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_6
-    )[SUB_MODULE_OBJECT_2]
-
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_1
-    )[MODULE_OBJECT_6]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_2
-    )[MODULE_OBJECT_6]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_3
-    )[MODULE_OBJECT_6]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_4
-    )[MODULE_OBJECT_6]
-    assert not evaluable.any_dependencies_to_modules_other_than(
-        MODULE_OBJECT_6, SUB_MODULE_OBJECT_2
-    )[MODULE_OBJECT_6]
-
-
-def test_non_a_depends_on_b(evaluable: EvaluableArchitecture) -> None:
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_2
-    )[MODULE_OBJECT_2]
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_3
-    )[MODULE_OBJECT_3]
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_4
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_1, SUB_MODULE_OBJECT_2
-    )[SUB_MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_1, MODULE_OBJECT_6
-    )[MODULE_OBJECT_6]
-
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_1
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_3
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_4
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_2, SUB_MODULE_OBJECT_2
-    )[SUB_MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_2, MODULE_OBJECT_6
-    )[MODULE_OBJECT_6]
-
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_1
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_2
-    )[MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_4
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_3, SUB_MODULE_OBJECT_2
-    )[SUB_MODULE_OBJECT_2]
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_3, MODULE_OBJECT_6
-    )[MODULE_OBJECT_6]
-
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_1
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_2
-    )[MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_3
-    )[MODULE_OBJECT_3]
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_4, SUB_MODULE_OBJECT_2
-    )[SUB_MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_4, MODULE_OBJECT_6
-    )[MODULE_OBJECT_6]
-
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_1
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_2
-    )[MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_3
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_4
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        SUB_MODULE_OBJECT_2, MODULE_OBJECT_6
-    )[MODULE_OBJECT_6]
-
-    assert not evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_1
-    )[MODULE_OBJECT_1]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_2
-    )[MODULE_OBJECT_2]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_3
-    )[MODULE_OBJECT_3]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_6, MODULE_OBJECT_4
-    )[MODULE_OBJECT_4]
-    assert evaluable.any_other_dependencies_to_modules_than(
-        MODULE_OBJECT_6, SUB_MODULE_OBJECT_2
-    )[SUB_MODULE_OBJECT_2]
-
-
-def test_depends_on(evaluable: EvaluableArchitecture) -> None:
-    assert evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_2)[
-        (MODULE_OBJECT_1, MODULE_OBJECT_2)
-    ]
-    assert evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_3)[
-        (MODULE_OBJECT_1, MODULE_OBJECT_3)
-    ]
-    assert evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_4)[
-        (MODULE_OBJECT_1, MODULE_OBJECT_4)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_1, SUB_MODULE_OBJECT_2)[
-        (MODULE_OBJECT_1, SUB_MODULE_OBJECT_2)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_1, MODULE_OBJECT_6)[
-        (MODULE_OBJECT_1, MODULE_OBJECT_6)
-    ]
-
-    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_1)[
-        (MODULE_OBJECT_2, MODULE_OBJECT_1)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_3)[
-        MODULE_OBJECT_2, MODULE_OBJECT_3
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_4)[
-        MODULE_OBJECT_2, MODULE_OBJECT_4
-    ]
-    assert not evaluable.get_dependencies(
-        MODULE_OBJECT_2, Module(name=SUB_MODULE_OF_2)
-    )[MODULE_OBJECT_2, SUB_MODULE_OBJECT_2]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_2, MODULE_OBJECT_6)[
-        (MODULE_OBJECT_2, MODULE_OBJECT_6)
-    ]
-
-    assert not evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_1)[
-        (MODULE_OBJECT_3, MODULE_OBJECT_1)
-    ]
-    assert evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_2)[
-        (MODULE_OBJECT_3, MODULE_OBJECT_2)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_4)[
-        MODULE_OBJECT_3, MODULE_OBJECT_4
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_3, SUB_MODULE_OBJECT_2)[
-        (MODULE_OBJECT_3, SUB_MODULE_OBJECT_2)
-    ]
-    assert evaluable.get_dependencies(MODULE_OBJECT_3, MODULE_OBJECT_6)[
-        (MODULE_OBJECT_3, MODULE_OBJECT_6)
-    ]
-
-    assert not evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_1)[
-        (MODULE_OBJECT_4, MODULE_OBJECT_1)
-    ]
-    assert evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_2)[
-        MODULE_OBJECT_4, MODULE_OBJECT_2
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_3)[
-        MODULE_OBJECT_4, MODULE_OBJECT_3
-    ]
-    assert evaluable.get_dependencies(MODULE_OBJECT_4, SUB_MODULE_OBJECT_2)[
-        (MODULE_OBJECT_4, SUB_MODULE_OBJECT_2)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_4, MODULE_OBJECT_6)[
-        (MODULE_OBJECT_4, MODULE_OBJECT_6)
-    ]
-
-    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_1)[
-        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_1)
-    ]
-    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_2)[
-        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_2)
-    ]
-    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_3)[
-        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_3)
-    ]
-    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_4)[
-        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_4)
-    ]
-    assert not evaluable.get_dependencies(SUB_MODULE_OBJECT_2, MODULE_OBJECT_6)[
-        (SUB_MODULE_OBJECT_2, MODULE_OBJECT_6)
-    ]
-
-    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_1)[
-        (MODULE_OBJECT_6, MODULE_OBJECT_1)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_2)[
-        (MODULE_OBJECT_6, MODULE_OBJECT_2)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_3)[
-        (MODULE_OBJECT_6, MODULE_OBJECT_3)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_6, MODULE_OBJECT_4)[
-        (MODULE_OBJECT_6, MODULE_OBJECT_4)
-    ]
-    assert not evaluable.get_dependencies(MODULE_OBJECT_6, SUB_MODULE_OBJECT_2)[
-        (MODULE_OBJECT_6, SUB_MODULE_OBJECT_2)
-    ]
-
-
-def test_submodule_calculation(submodule_evaluable: EvaluableArchitectureGraph) -> None:
-    assert submodule_evaluable._get_all_submodules_of(Module(name=MODULE_A)) == {
-        MODULE_A,
-        MODULE_B,
-    }  # D does not show up as it is not connected to any import
-    assert submodule_evaluable._get_all_submodules_of(Module(name=MODULE_B)) == {
-        MODULE_B
-    }  # D does not show up as it is not connected to any import
-    assert submodule_evaluable._get_all_submodules_of(Module(name=MODULE_C)) == {
-        MODULE_C
-    }
-    assert submodule_evaluable._get_all_submodules_of(Module(name=MODULE_D)) == {
-        MODULE_D
-    }
-    assert submodule_evaluable._get_all_submodules_of(Module(name=MODULE_E)) == {
-        MODULE_E,
-        MODULE_A,
-        MODULE_B,
-        MODULE_F,
-    }  # D does not show up as it is not connected to any import
-    assert submodule_evaluable._get_all_submodules_of(Module(name=MODULE_F)) == {
-        MODULE_F
-    }
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-    ],
-)
-def test_is_dependent_between_named_modules(imports: List[AbsoluteImport]) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_is_dependent_between_named_and_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_is_dependent_between_submodule_and_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_is_dependent_between_submodule_modules(imports: List[AbsoluteImport]) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_1)],
-        [AbsoluteImport(SUB_MODULE_OF_2, SUB_MODULE_OF_2)],
-    ],
-)
-def test_is_not_dependent_between_named_modules(imports: List[AbsoluteImport]) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-    ],
-)
-def test_is_not_dependent_between_named_and_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_is_not_dependent_between_submodule_and_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-    ],
-)
-def test_is_not_dependent_between_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert not architecture.get_dependencies(module_1, module_2)[(module_1, module_2)]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_3)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
-    ],
-)
-def test_any_to_other_between_named_modules(imports: List[AbsoluteImport]) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_3)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-    ],
-)
-def test_any_to_other_between_named_and_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
-    ],
-)
-def test_any_to_other_between_submodule_and_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_3)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-    ],
-)
-def test_any_to_other_between_submodule_modules(imports: List[AbsoluteImport]) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_not_any_to_other_between_named_modules(imports: List[AbsoluteImport]) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert not architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_not_any_to_other_between_named_and_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert not architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_3)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_not_any_to_other_between_submodule_and_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert not architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_3)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_not_any_to_other_between_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert not architecture.any_dependencies_to_modules_other_than(module_1, module_2)[
-        module_1
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_3, MODULE_2)],
-        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
-    ],
-)
-def test_other_to_module_than_between_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
-    ],
-)
-def test_other_to_module_than_between_named_and_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(MODULE_3, MODULE_2)],
-        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
-    ],
-)
-def test_other_to_module_than_between_submodule_and_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(MODULE_3, SUB_MODULE_OF_2)],
-    ],
-)
-def test_other_to_module_than_between_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_not_other_to_module_than_between_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert not architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(MODULE_3, MODULE_2)],
-    ],
-)
-def test_not_other_to_module_than_between_named_and_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(name=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert not architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-    ],
-)
-def test_not_other_to_module_than_between_submodule_and_named_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(name=MODULE_2)
-    assert not architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-@pytest.mark.parametrize(
-    "imports",
-    [
-        [AbsoluteImport(MODULE_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, MODULE_2)],
-        [AbsoluteImport(SUB_MODULE_OF_1, SUB_MODULE_OF_2)],
-        [AbsoluteImport(MODULE_3, MODULE_2)],
-    ],
-)
-def test_not_other_to_module_than_between_submodule_modules(
-    imports: List[AbsoluteImport],
-) -> None:
-    all_modules = [MODULE_1, MODULE_2, SUB_MODULE_OF_1, SUB_MODULE_OF_2, MODULE_3]
-    architecture = EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-    module_1 = Module(parent_module=MODULE_1)
-    module_2 = Module(parent_module=MODULE_2)
-    assert not architecture.any_other_dependencies_to_modules_than(module_1, module_2)[
-        module_2
-    ]
-
-
-def test_all_modules_labeled_when_aliases_used(
-    evaluable: EvaluableArchitecture,
-) -> None:
-    module_1_alias = "1"
-    aliases = {MODULE_1: module_1_alias}
-    fig, ax = subplots()
-
-    evaluable.visualize(aliases=aliases, ax=ax)
-
-    labels_in_plot = [t.get_text() for t in ax.texts]
-    assert len(labels_in_plot) == 6
-
-
-def test_alias_replaces_module_name_in_plot(evaluable: EvaluableArchitecture) -> None:
-    module_2_alias = "2"
-    aliases = {MODULE_2: module_2_alias}
-    fig, ax = subplots()
-
-    evaluable.visualize(aliases=aliases, ax=ax)
-
-    labels_in_plot = [t.get_text() for t in ax.texts]
-    assert module_2_alias in labels_in_plot
-    assert MODULE_2 not in labels_in_plot
-    assert SUB_MODULE_OF_2 not in labels_in_plot
-    assert f"{module_2_alias}.SubModule1" in labels_in_plot
-
-
-def test_alias_replaces_module_name_in_submodules_plot(
-    evaluable: EvaluableArchitecture,
-) -> None:
-    module_2_alias = "2"
-    aliases = {MODULE_2: module_2_alias}
-    submodule_label_with_alias = f"{module_2_alias}.SubModule1"
-    fig, ax = subplots()
-
-    evaluable.visualize(aliases=aliases, ax=ax)
-
-    labels_in_plot = [t.get_text() for t in ax.texts]
-    assert module_2_alias in labels_in_plot
-    assert MODULE_2 not in labels_in_plot
-    assert SUB_MODULE_OF_2 not in labels_in_plot
-    assert submodule_label_with_alias in labels_in_plot
-
-
-def test_when_module_and_a_submodule_have_aliases_the_submodule_alias_takes_priority(
-    submodule_evaluable: EvaluableArchitecture,
-) -> None:
-    module_e_alias = "e"
-    submodule_of_e_alias = "ea"
-    submodule_label_with_parent_alias = f"{module_e_alias}.A"
-    aliases = {MODULE_E: module_e_alias, MODULE_A: submodule_of_e_alias}
-    fig, ax = subplots()
-
-    submodule_evaluable.visualize(aliases=aliases, ax=ax)
-
-    labels_in_plot = [t.get_text() for t in ax.texts]
-    assert module_e_alias in labels_in_plot
-    assert submodule_of_e_alias in labels_in_plot
-    assert SUB_MODULE_OF_2 not in labels_in_plot
-    assert submodule_label_with_parent_alias not in labels_in_plot
-    assert f"{module_e_alias}.F" in labels_in_plot
-
-
-def test_when_module_name_in_alias_spec_is_not_found_an_error_is_raised(
-    evaluable: EvaluableArchitecture,
-) -> None:
-    non_existent_module = "non_existent_module"
-    aliases = {non_existent_module: "a"}
-
-    with pytest.raises(KeyError, match=non_existent_module):
-        evaluable.visualize(aliases=aliases)
-
-
-MODULE = "test.module.submodule.class"
-
-
-partial_match_test_cases = [
-    pytest.param("test.module.submodule.class", True, id="complete match - match"),
-    pytest.param("test.module.submodule.clasz", False, id="complete match - no match"),
-    pytest.param("*.class", True, id="end match - match"),
-    pytest.param("*.clasz", False, id="end match - no match"),
-    pytest.param("test.*", True, id="start match - match"),
-    pytest.param("test,*", False, id="start match - no match"),
-    pytest.param("*le.submo*", True, id="inner match - match"),
-    pytest.param("les.submo*", False, id="inner match - no match"),
-]
-
-
-@pytest.mark.parametrize("match, expected_result", partial_match_test_cases)
-def test_partial_match(match: str, expected_result: bool) -> None:
-    assert (
-        EvaluableArchitectureGraph._partial_name_match(match, MODULE) == expected_result
-    )
-
-
-def test_module_matches(submodule_evaluable: EvaluableArchitectureGraph) -> None:
-    module_matches = [
-        Module(name="*D", partial_match=True),
-        Module(name="*A*", partial_match=True),
-    ]
-
-    calculated_matches = submodule_evaluable._convert_to_full_name_matches(
-        [module_matches]
-    )
-
-    assert len(calculated_matches) == 1
-    assert len(calculated_matches[0]) == 3
-
-    assert Module(name=MODULE_A) in calculated_matches[0]
-    assert Module(name=MODULE_B) in calculated_matches[0]
-    assert Module(name=MODULE_D) in calculated_matches[0]
-
-
-def test_non_partial_module_does_not_match_anything_but_itself(
-    submodule_evaluable: EvaluableArchitectureGraph,
-) -> None:
-    module_matches = [Module(name="*.*")]
-
-    calculated_matches = submodule_evaluable._convert_to_full_name_matches(
-        [module_matches]
-    )
-
-    assert len(calculated_matches) == 1
-    assert len(calculated_matches[0]) == 1
-
-    assert Module(name="*.*") in calculated_matches[0]
-
-
-def test_never_matched_match_raises_error(
-    evaluable: EvaluableArchitectureGraph,
-) -> None:
-    module_matches = [Module(name="I will not match", partial_match=True)]
-
-    with pytest.raises(
-        ImpossibleMatch, match="No modules found that match: I will not match"
-    ):
-        evaluable._convert_to_full_name_matches([module_matches])
-
-
-def test_module_matches_reported_separately_by_group(
-    submodule_evaluable: EvaluableArchitectureGraph,
-) -> None:
-    module_matches_1 = [
-        Module(name="*D", partial_match=True),
-    ]
-
-    module_matches_2 = [
-        Module(name="*A*", partial_match=True),
-    ]
-
-    calculated_matches = submodule_evaluable._convert_to_full_name_matches(
-        [module_matches_1, module_matches_2]
-    )
-
-    assert len(calculated_matches) == 2
-
-    assert len(calculated_matches[0]) == 1
-    assert len(calculated_matches[1]) == 3
-
-    assert Module(name=MODULE_D) in calculated_matches[0]
-    assert Module(name=MODULE_A) in calculated_matches[1]
-    assert Module(name=MODULE_B) in calculated_matches[1]
-    assert Module(name=MODULE_D) in calculated_matches[1]
diff --git a/tests/eval_structure_generation/__init__.py b/tests/eval_structure_generation/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/importer/test_converter.py b/tests/eval_structure_generation/test_converter.py
similarity index 84%
rename from tests/importer/test_converter.py
rename to tests/eval_structure_generation/test_converter.py
index 0fdb3a3..8d629de 100644
--- a/tests/importer/test_converter.py
+++ b/tests/eval_structure_generation/test_converter.py
@@ -2,8 +2,8 @@
 
 from util import MockFileFilter
 
-from pytestarch.importer.converter import ImportConverter
-from pytestarch.importer.parser import Parser
+from pytestarch.eval_structure_generation.file_import.converter import ImportConverter
+from pytestarch.eval_structure_generation.file_import.parser import Parser
 
 SOURCE_ROOT = Path(__file__).parent.parent
 RESOURCES_DIR = SOURCE_ROOT / "resources/importer/level0"
diff --git a/tests/importer/test_file_filter.py b/tests/eval_structure_generation/test_file_filter.py
similarity index 87%
rename from tests/importer/test_file_filter.py
rename to tests/eval_structure_generation/test_file_filter.py
index 7a9bfed..3f7bdfa 100644
--- a/tests/importer/test_file_filter.py
+++ b/tests/eval_structure_generation/test_file_filter.py
@@ -3,8 +3,8 @@
 
 import pytest
 
-from pytestarch.config.config import Config
-from pytestarch.importer.file_filter import FileFilter
+from pytestarch.eval_structure_generation.file_import.config import Config
+from pytestarch.eval_structure_generation.file_import.file_filter import FileFilter
 
 test_cases = [
     # ['A', 'B', 'a.main.b'],
diff --git a/tests/graph/test_graph_initialisation.py b/tests/eval_structure_generation/test_graph_initialisation.py
similarity index 82%
rename from tests/graph/test_graph_initialisation.py
rename to tests/eval_structure_generation/test_graph_initialisation.py
index 5848c1c..5a0e7cf 100644
--- a/tests/graph/test_graph_initialisation.py
+++ b/tests/eval_structure_generation/test_graph_initialisation.py
@@ -1,5 +1,5 @@
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.importer.import_types import AbsoluteImport
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
 
 
 def test_empty_graph_allowed() -> None:
diff --git a/tests/graph/test_graph_reduction.py b/tests/eval_structure_generation/test_graph_reduction.py
similarity index 95%
rename from tests/graph/test_graph_reduction.py
rename to tests/eval_structure_generation/test_graph_reduction.py
index dace89c..b1b444c 100644
--- a/tests/graph/test_graph_reduction.py
+++ b/tests/eval_structure_generation/test_graph_reduction.py
@@ -2,7 +2,7 @@
 import resources
 from resources import importer
 
-from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
+from pytestarch import EvaluableArchitecture
 from pytestarch.pytestarch import get_evaluable_architecture_for_module_objects
 
 
diff --git a/tests/importer/test_import.py b/tests/eval_structure_generation/test_import.py
similarity index 73%
rename from tests/importer/test_import.py
rename to tests/eval_structure_generation/test_import.py
index 9f122b0..0f6760b 100644
--- a/tests/importer/test_import.py
+++ b/tests/eval_structure_generation/test_import.py
@@ -1,4 +1,4 @@
-from pytestarch.importer.import_types import AbsoluteImport
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
 
 
 def test_parent_modules_as_expected() -> None:
diff --git a/tests/importer/test_import_filter.py b/tests/eval_structure_generation/test_import_filter.py
similarity index 79%
rename from tests/importer/test_import_filter.py
rename to tests/eval_structure_generation/test_import_filter.py
index d50b74f..4d31d74 100644
--- a/tests/importer/test_import_filter.py
+++ b/tests/eval_structure_generation/test_import_filter.py
@@ -1,7 +1,7 @@
 from pathlib import Path
 
-from pytestarch.importer.import_filter import ImportFilter
-from pytestarch.importer.import_types import AbsoluteImport
+from pytestarch.eval_structure_generation.file_import.import_filter import ImportFilter
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
 
 ROOT_PATH = Path("A.B")
 
diff --git a/tests/graph/test_module_graph.py b/tests/eval_structure_generation/test_module_graph.py
similarity index 90%
rename from tests/graph/test_module_graph.py
rename to tests/eval_structure_generation/test_module_graph.py
index bf906e9..21920d7 100644
--- a/tests/graph/test_module_graph.py
+++ b/tests/eval_structure_generation/test_module_graph.py
@@ -3,13 +3,16 @@
 
 import pytest
 
-from pytestarch.config.config import Config
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.importer.converter import ImportConverter
-from pytestarch.importer.file_filter import FileFilter
-from pytestarch.importer.import_types import Import, NamedModule
-from pytestarch.importer.importee_module_calculator import ImporteeModuleCalculator
-from pytestarch.importer.parser import Parser
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure.types import Import
+from pytestarch.eval_structure_generation.file_import.config import Config
+from pytestarch.eval_structure_generation.file_import.converter import ImportConverter
+from pytestarch.eval_structure_generation.file_import.file_filter import FileFilter
+from pytestarch.eval_structure_generation.file_import.import_types import NamedModule
+from pytestarch.eval_structure_generation.file_import.importee_module_calculator import (
+    ImporteeModuleCalculator,
+)
+from pytestarch.eval_structure_generation.file_import.parser import Parser
 
 ROOT_PATH = Path(__file__).parent.parent.parent.resolve()
 
diff --git a/tests/importer/test_parser.py b/tests/eval_structure_generation/test_parser.py
similarity index 85%
rename from tests/importer/test_parser.py
rename to tests/eval_structure_generation/test_parser.py
index 75e60ba..3c67676 100644
--- a/tests/importer/test_parser.py
+++ b/tests/eval_structure_generation/test_parser.py
@@ -1,8 +1,8 @@
 from pathlib import Path
 
-from pytestarch.config.config import Config
-from pytestarch.importer.file_filter import FileFilter
-from pytestarch.importer.parser import Parser
+from pytestarch.eval_structure_generation.file_import.config import Config
+from pytestarch.eval_structure_generation.file_import.file_filter import FileFilter
+from pytestarch.eval_structure_generation.file_import.parser import Parser
 
 SOURCE_ROOT = Path(__file__).parent.parent
 RESOURCES_DIR = SOURCE_ROOT / "resources/importer"
diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_integration.py b/tests/integration/interesting_rules_for_tests.py
similarity index 83%
rename from tests/test_integration.py
rename to tests/integration/interesting_rules_for_tests.py
index e165063..0b6e645 100644
--- a/tests/test_integration.py
+++ b/tests/integration/interesting_rules_for_tests.py
@@ -1,19 +1,20 @@
-import os
-
 import pytest
-from resources.test_project import src
-from resources.test_project.src import moduleA
-from resources.test_project.src.moduleA import submoduleA1
 
 from pytestarch import Rule
-from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
-from pytestarch.pytestarch import get_evaluable_architecture
 
-# from matplotlib import pyplot as plt
-# from matplotlib.pyplot import figure
+C = "src.moduleC"
+B = "src.moduleB"
+A = "src.moduleA"
+FILE_A2 = f"{A}.submoduleA2.fileA2"
+A2 = f"{A}.submoduleA2"
+A1 = f"{A}.submoduleA1"
+A11 = f"{A}.submoduleA1.submoduleA11"
+B1_MODULE = f"{B}.submoduleB1"
+B2 = f"{B}.submoduleB1.fileB2"
+FILE_C = f"{C}.fileC"
 
 
-rules_to_test = [
+rules_for_level_limits = [
     (
         Rule()
         .modules_that()
@@ -129,222 +130,7 @@
     ),
 ]
 
-
-@pytest.mark.parametrize("rule, expected_result, skip_with_level_limit", rules_to_test)
-def test_architecture_based_on_string_modules(
-    rule: Rule,
-    expected_result: bool,
-    skip_with_level_limit: bool,
-    graph_based_on_string_module_names: EvaluableArchitecture,
-) -> None:
-    if expected_result:
-        rule.assert_applies(graph_based_on_string_module_names)
-    else:
-        with pytest.raises(AssertionError):
-            assert rule.assert_applies(graph_based_on_string_module_names)
-
-
-@pytest.mark.parametrize("rule, expected_result, skip_with_level_limit", rules_to_test)
-def test_architecture_based_on_module_objects(
-    rule: Rule,
-    expected_result: bool,
-    skip_with_level_limit: bool,
-    graph_based_on_string_module_names: EvaluableArchitecture,
-) -> None:
-    if expected_result:
-        rule.assert_applies(graph_based_on_string_module_names)
-    else:
-        with pytest.raises(AssertionError):
-            assert rule.assert_applies(graph_based_on_string_module_names)
-
-
-def test_depending_on_module_does_not_imply_depending_on_submodule(
-    graph_including_tests: EvaluableArchitecture,
-) -> None:
-    rule_1 = (
-        Rule()
-        .modules_that()
-        .are_named("src.moduleC.cTest")
-        .should()
-        .import_modules_that()
-        .are_named("src.moduleB")
-    )
-    rule_2 = (
-        Rule()
-        .modules_that()
-        .are_named("src.moduleC.cTest")
-        .should_not()
-        .import_modules_that()
-        .are_named("src.moduleB.submoduleB1.fileB3")
-    )
-
-    rule_1.assert_applies(graph_including_tests)
-    rule_2.assert_applies(graph_including_tests)
-
-
-@pytest.mark.parametrize("rule, expected_result, skip_with_level_limit", rules_to_test)
-def test_identical_source_and_module_path_do_not_lead_to_errors(
-    rule: Rule,
-    expected_result: bool,
-    skip_with_level_limit: bool,
-    graph_with_identical_source_and_module_path: EvaluableArchitecture,
-) -> None:
-    if expected_result:
-        rule.assert_applies(graph_with_identical_source_and_module_path)
-    else:
-        with pytest.raises(AssertionError):
-            assert rule.assert_applies(graph_with_identical_source_and_module_path)
-
-
-@pytest.mark.parametrize("rule, expected_result, skip_with_level_limit", rules_to_test)
-def test_level_limit_flattens_dependencies_correctly(
-    rule: Rule,
-    expected_result: bool,
-    skip_with_level_limit: bool,
-    graph_with_level_limit_1: EvaluableArchitecture,
-) -> None:
-    if skip_with_level_limit:
-        return
-
-    if expected_result:
-        rule.assert_applies(graph_with_level_limit_1)
-    else:
-        with pytest.raises(AssertionError):
-            assert rule.assert_applies(graph_with_level_limit_1)
-
-
-# def test_exporting_as_image_does_not_raise_error(
-#     graph_based_on_string_module_names: EvaluableArchitecture,
-# ) -> None:
-#     figure(figsize=(12, 6), dpi=80)
-#
-#     graph_based_on_string_module_names.visualize(
-#         spacing=0.35,
-#         node_size=800,
-#         arrowsize=30,
-#         labels={
-#             "src": "src",
-#             "src.moduleA": "A",
-#             "src.moduleB": "B",
-#             "src.moduleC": "C",
-#             "src.moduleA.submoduleA1": "A1",
-#             "src.moduleA.submoduleA2": "A2",
-#             "src.moduleA.fileA": "fileA",
-#             "src.moduleA.submoduleA1.submoduleA11": "A11",
-#             "src.moduleA.submoduleA1.fileA1": "fileA1",
-#             "src.moduleA.submoduleA1.fileA1_b": "fileA1b",
-#             "src.moduleA.submoduleA1.submoduleA11.fileA11": "fileA11",
-#             "src.moduleA.submoduleA2.fileA2": "fileA2",
-#             "src.moduleB.submoduleB1": "B1",
-#             "src.moduleB.fileB": "fileB",
-#             "src.moduleB.submoduleB1.fileB1": "fileB1",
-#             "src.moduleB.submoduleB1.fileB2": "fileB2",
-#             "src.moduleC.fileC": "fileC",
-#         },
-#     )
-#     plt.savefig("test.png")
-
-
-def test_edges_correctly_calculated_for_level_2_module_path() -> None:
-    level_2_graph = get_evaluable_architecture(
-        os.path.dirname(src.__file__),
-        os.path.dirname(moduleA.__file__),
-        ("*__pycache__", "*__init__.py", "*Test.py"),
-    )
-
-    assert len(level_2_graph._graph._graph.edges) == 0  # no internal dependencies left
-
-
-def test_edges_correctly_calculated_for_level_2_module_path_no_external_dependencies_modified() -> None:
-    level_2_graph = get_evaluable_architecture(
-        os.path.dirname(src.__file__),
-        os.path.dirname(moduleA.__file__),
-        ("*__pycache__", "*__init__.py", "*Test.py"),
-        exclude_external_libraries=False,
-    )
-
-    assert len(level_2_graph._graph._graph.edges) == 16
-
-    for edge in [
-        ("src", "src.moduleA"),
-        ("src", "src.moduleB"),  # must not be src.moduleA.src.moduleB
-        ("src", "src.moduleC"),
-        ("src.moduleA", "src.moduleA.fileA"),
-        ("src.moduleA", "src.moduleA.submoduleA1"),
-        ("src.moduleA", "src.moduleA.submoduleA2"),
-        ("src.moduleA.fileA", "src.moduleC.fileC"),
-        ("src.moduleA.submoduleA1", "src.moduleA.submoduleA1.submoduleA11"),
-        (
-            "src.moduleA.submoduleA1.submoduleA11",
-            "src.moduleA.submoduleA1.submoduleA11.fileA11",
-        ),
-        (
-            "src.moduleA.submoduleA1.submoduleA11.fileA11",
-            "os",
-        ),  # must not be src.moduleA.os!
-        (
-            "src.moduleA.submoduleA1.submoduleA11.fileA11",
-            "src.moduleB.submoduleB1.fileB1",
-        ),
-        ("src.moduleA.submoduleA2", "src.moduleA.submoduleA2.fileA2"),
-        ("src.moduleA.submoduleA2.fileA2", "src.moduleC.fileC"),
-        ("src.moduleB", "src.moduleB.submoduleB1"),
-        ("src.moduleB.submoduleB1", "src.moduleB.submoduleB1.fileB1"),
-        ("src.moduleC", "src.moduleC.fileC"),
-    ]:
-        assert edge in level_2_graph._graph
-
-
-def test_edges_correctly_calculated_for_level_3_module_path() -> None:
-    level_3_graph = get_evaluable_architecture(
-        os.path.dirname(src.__file__),
-        os.path.dirname(submoduleA1.__file__),
-        ("*__pycache__", "*__init__.py", "*Test.py"),
-    )
-
-    assert len(level_3_graph._graph._graph.edges) == 0  # no internal dependencies left
-
-
-def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependencies_modified() -> None:
-    level_3_graph = get_evaluable_architecture(
-        os.path.dirname(src.__file__),
-        os.path.dirname(submoduleA1.__file__),
-        ("*__pycache__", "*__init__.py", "*Test.py"),
-        exclude_external_libraries=False,
-    )
-
-    assert len(level_3_graph._graph._graph.edges) == 7
-
-    for edge in [
-        ("src", "src.moduleB"),
-        ("src.moduleA.submoduleA1", "src.moduleA.submoduleA1.submoduleA11"),
-        (
-            "src.moduleA.submoduleA1.submoduleA11",
-            "src.moduleA.submoduleA1.submoduleA11.fileA11",
-        ),
-        ("src.moduleA.submoduleA1.submoduleA11.fileA11", "os"),
-        (
-            "src.moduleA.submoduleA1.submoduleA11.fileA11",
-            "src.moduleB.submoduleB1.fileB1",
-        ),
-        ("src.moduleB", "src.moduleB.submoduleB1"),
-        ("src.moduleB.submoduleB1", "src.moduleB.submoduleB1.fileB1"),
-    ]:
-        assert edge in level_3_graph._graph
-
-
-C = "src.moduleC"
-B = "src.moduleB"
-A = "src.moduleA"
-FILE_A2 = f"{A}.submoduleA2.fileA2"
-FILE_C = f"{C}.fileC"
-A2 = f"{A}.submoduleA2"
-A1 = f"{A}.submoduleA1"
-A11 = f"{A}.submoduleA1.submoduleA11"
-B1_MODULE = f"{B}.submoduleB1"
-B2 = f"{B}.submoduleB1.fileB2"
-
-test_cases = [
+single_rule_object_error_message_test_cases = [
     pytest.param(
         Rule().modules_that().are_named(C).should().import_modules_that().are_named(A),
         '"src.moduleC" does not import "src.moduleA".',
@@ -922,18 +708,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
     ),
 ]
 
-
-@pytest.mark.parametrize("rule, expected_error_message", test_cases)
-def test_rule_violated_raises_proper_error_message(
-    rule: Rule,
-    expected_error_message: str,
-    graph_based_on_string_module_names: EvaluableArchitecture,
-) -> None:
-    with pytest.raises(AssertionError, match=expected_error_message):
-        rule.assert_applies(graph_based_on_string_module_names)
-
-
-multiple_rule_objects_test_cases = [
+multiple_rule_objects_error_message_test_cases = [
     pytest.param(
         Rule()
         .modules_that()
@@ -1508,19 +1283,6 @@ def test_rule_violated_raises_proper_error_message(
     ),
 ]
 
-
-@pytest.mark.parametrize(
-    "rule, expected_error_message", multiple_rule_objects_test_cases
-)
-def test_rule_violated_with_multiple_rule_objects_raises_proper_error_message(
-    rule: Rule,
-    expected_error_message: str,
-    graph_based_on_string_module_names: EvaluableArchitecture,
-) -> None:
-    with pytest.raises(AssertionError, match=expected_error_message):
-        rule.assert_applies(graph_based_on_string_module_names)
-
-
 partial_name_match_test_cases = [
     pytest.param(
         Rule()
@@ -1623,17 +1385,3 @@ def test_rule_violated_with_multiple_rule_objects_raises_proper_error_message(
         id="submodule should only be imported by except named - forbidden import - partial name match object",
     ),
 ]
-
-
-@pytest.mark.parametrize("rule, violation", partial_name_match_test_cases)
-def test_rule_violation_correctly_detected_for_partial_name_matches(
-    rule: Rule,
-    violation: bool,
-    graph_based_on_string_module_names: EvaluableArchitecture,
-) -> None:
-    if violation:
-        with pytest.raises(AssertionError):
-            rule.assert_applies(graph_based_on_string_module_names)
-    else:
-        rule.assert_applies(graph_based_on_string_module_names)
-        # no exception
diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py
new file mode 100644
index 0000000..ec2456a
--- /dev/null
+++ b/tests/integration/test_integration.py
@@ -0,0 +1,46 @@
+import pytest
+from integration.interesting_rules_for_tests import (
+    multiple_rule_objects_error_message_test_cases,
+    partial_name_match_test_cases,
+    single_rule_object_error_message_test_cases,
+)
+
+from pytestarch import EvaluableArchitecture, Rule
+
+
+@pytest.mark.parametrize(
+    "rule, expected_error_message", single_rule_object_error_message_test_cases
+)
+def test_rule_violated_raises_proper_error_message(
+    rule: Rule,
+    expected_error_message: str,
+    graph_based_on_string_module_names: EvaluableArchitecture,
+) -> None:
+    with pytest.raises(AssertionError, match=expected_error_message):
+        rule.assert_applies(graph_based_on_string_module_names)
+
+
+@pytest.mark.parametrize(
+    "rule, expected_error_message", multiple_rule_objects_error_message_test_cases
+)
+def test_rule_violated_with_multiple_rule_objects_raises_proper_error_message(
+    rule: Rule,
+    expected_error_message: str,
+    graph_based_on_string_module_names: EvaluableArchitecture,
+) -> None:
+    with pytest.raises(AssertionError, match=expected_error_message):
+        rule.assert_applies(graph_based_on_string_module_names)
+
+
+@pytest.mark.parametrize("rule, violation", partial_name_match_test_cases)
+def test_rule_violation_correctly_detected_for_partial_name_matches(
+    rule: Rule,
+    violation: bool,
+    graph_based_on_string_module_names: EvaluableArchitecture,
+) -> None:
+    if violation:
+        with pytest.raises(AssertionError):
+            rule.assert_applies(graph_based_on_string_module_names)
+    else:
+        rule.assert_applies(graph_based_on_string_module_names)
+        # no exception
diff --git a/tests/integration/test_level_limits.py b/tests/integration/test_level_limits.py
new file mode 100644
index 0000000..0361a09
--- /dev/null
+++ b/tests/integration/test_level_limits.py
@@ -0,0 +1,188 @@
+import os
+
+import pytest
+from integration.interesting_rules_for_tests import rules_for_level_limits
+from resources.test_project import src
+from resources.test_project.src import moduleA
+from resources.test_project.src.moduleA import submoduleA1
+
+from pytestarch import EvaluableArchitecture, Rule, get_evaluable_architecture
+
+
+@pytest.mark.parametrize(
+    "rule, expected_result, skip_with_level_limit", rules_for_level_limits
+)
+def test_architecture_based_on_string_modules(
+    rule: Rule,
+    expected_result: bool,
+    skip_with_level_limit: bool,
+    graph_based_on_string_module_names: EvaluableArchitecture,
+) -> None:
+    if expected_result:
+        rule.assert_applies(graph_based_on_string_module_names)
+    else:
+        with pytest.raises(AssertionError):
+            assert rule.assert_applies(graph_based_on_string_module_names)
+
+
+@pytest.mark.parametrize(
+    "rule, expected_result, skip_with_level_limit", rules_for_level_limits
+)
+def test_architecture_based_on_module_objects(
+    rule: Rule,
+    expected_result: bool,
+    skip_with_level_limit: bool,
+    graph_based_on_string_module_names: EvaluableArchitecture,
+) -> None:
+    if expected_result:
+        rule.assert_applies(graph_based_on_string_module_names)
+    else:
+        with pytest.raises(AssertionError):
+            assert rule.assert_applies(graph_based_on_string_module_names)
+
+
+def test_depending_on_module_does_not_imply_depending_on_submodule(
+    graph_including_tests: EvaluableArchitecture,
+) -> None:
+    rule_1 = (
+        Rule()
+        .modules_that()
+        .are_named("src.moduleC.cTest")
+        .should()
+        .import_modules_that()
+        .are_named("src.moduleB")
+    )
+    rule_2 = (
+        Rule()
+        .modules_that()
+        .are_named("src.moduleC.cTest")
+        .should_not()
+        .import_modules_that()
+        .are_named("src.moduleB.submoduleB1.fileB3")
+    )
+
+    rule_1.assert_applies(graph_including_tests)
+    rule_2.assert_applies(graph_including_tests)
+
+
+@pytest.mark.parametrize(
+    "rule, expected_result, skip_with_level_limit", rules_for_level_limits
+)
+def test_identical_source_and_module_path_do_not_lead_to_errors(
+    rule: Rule,
+    expected_result: bool,
+    skip_with_level_limit: bool,
+    graph_with_identical_source_and_module_path: EvaluableArchitecture,
+) -> None:
+    if expected_result:
+        rule.assert_applies(graph_with_identical_source_and_module_path)
+    else:
+        with pytest.raises(AssertionError):
+            assert rule.assert_applies(graph_with_identical_source_and_module_path)
+
+
+@pytest.mark.parametrize(
+    "rule, expected_result, skip_with_level_limit", rules_for_level_limits
+)
+def test_level_limit_flattens_dependencies_correctly(
+    rule: Rule,
+    expected_result: bool,
+    skip_with_level_limit: bool,
+    graph_with_level_limit_1: EvaluableArchitecture,
+) -> None:
+    if skip_with_level_limit:
+        return
+
+    if expected_result:
+        rule.assert_applies(graph_with_level_limit_1)
+    else:
+        with pytest.raises(AssertionError):
+            assert rule.assert_applies(graph_with_level_limit_1)
+
+
+def test_edges_correctly_calculated_for_level_2_module_path() -> None:
+    level_2_graph = get_evaluable_architecture(
+        os.path.dirname(src.__file__),
+        os.path.dirname(moduleA.__file__),
+        ("*__pycache__", "*__init__.py", "*Test.py"),
+    )
+
+    assert len(level_2_graph._graph._graph.edges) == 0  # no internal dependencies left
+
+
+def test_edges_correctly_calculated_for_level_2_module_path_no_external_dependencies_modified() -> None:
+    level_2_graph = get_evaluable_architecture(
+        os.path.dirname(src.__file__),
+        os.path.dirname(moduleA.__file__),
+        ("*__pycache__", "*__init__.py", "*Test.py"),
+        exclude_external_libraries=False,
+    )
+
+    assert len(level_2_graph._graph._graph.edges) == 16
+
+    for edge in [
+        ("src", "src.moduleA"),
+        ("src", "src.moduleB"),  # must not be src.moduleA.src.moduleB
+        ("src", "src.moduleC"),
+        ("src.moduleA", "src.moduleA.fileA"),
+        ("src.moduleA", "src.moduleA.submoduleA1"),
+        ("src.moduleA", "src.moduleA.submoduleA2"),
+        ("src.moduleA.fileA", "src.moduleC.fileC"),
+        ("src.moduleA.submoduleA1", "src.moduleA.submoduleA1.submoduleA11"),
+        (
+            "src.moduleA.submoduleA1.submoduleA11",
+            "src.moduleA.submoduleA1.submoduleA11.fileA11",
+        ),
+        (
+            "src.moduleA.submoduleA1.submoduleA11.fileA11",
+            "os",
+        ),  # must not be src.moduleA.os!
+        (
+            "src.moduleA.submoduleA1.submoduleA11.fileA11",
+            "src.moduleB.submoduleB1.fileB1",
+        ),
+        ("src.moduleA.submoduleA2", "src.moduleA.submoduleA2.fileA2"),
+        ("src.moduleA.submoduleA2.fileA2", "src.moduleC.fileC"),
+        ("src.moduleB", "src.moduleB.submoduleB1"),
+        ("src.moduleB.submoduleB1", "src.moduleB.submoduleB1.fileB1"),
+        ("src.moduleC", "src.moduleC.fileC"),
+    ]:
+        assert edge in level_2_graph._graph
+
+
+def test_edges_correctly_calculated_for_level_3_module_path() -> None:
+    level_3_graph = get_evaluable_architecture(
+        os.path.dirname(src.__file__),
+        os.path.dirname(submoduleA1.__file__),
+        ("*__pycache__", "*__init__.py", "*Test.py"),
+    )
+
+    assert len(level_3_graph._graph._graph.edges) == 0  # no internal dependencies left
+
+
+def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependencies_modified() -> None:
+    level_3_graph = get_evaluable_architecture(
+        os.path.dirname(src.__file__),
+        os.path.dirname(submoduleA1.__file__),
+        ("*__pycache__", "*__init__.py", "*Test.py"),
+        exclude_external_libraries=False,
+    )
+
+    assert len(level_3_graph._graph._graph.edges) == 7
+
+    for edge in [
+        ("src", "src.moduleB"),
+        ("src.moduleA.submoduleA1", "src.moduleA.submoduleA1.submoduleA11"),
+        (
+            "src.moduleA.submoduleA1.submoduleA11",
+            "src.moduleA.submoduleA1.submoduleA11.fileA11",
+        ),
+        ("src.moduleA.submoduleA1.submoduleA11.fileA11", "os"),
+        (
+            "src.moduleA.submoduleA1.submoduleA11.fileA11",
+            "src.moduleB.submoduleB1.fileB1",
+        ),
+        ("src.moduleB", "src.moduleB.submoduleB1"),
+        ("src.moduleB.submoduleB1", "src.moduleB.submoduleB1.fileB1"),
+    ]:
+        assert edge in level_3_graph._graph
diff --git a/tests/query_language/rule/__init__.py b/tests/query_language/rule/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/query_language/rule/conftest.py b/tests/query_language/rule/conftest.py
new file mode 100644
index 0000000..f2cc5a3
--- /dev/null
+++ b/tests/query_language/rule/conftest.py
@@ -0,0 +1,47 @@
+import pytest
+
+from pytestarch import EvaluableArchitecture
+from pytestarch.eval_structure.evaluable_architecture import Module
+from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
+
+MODULE_1 = "Module1"
+MODULE_2 = "Module2"
+MODULE_3 = "Module3"
+MODULE_4 = "Module4"
+MODULE_5 = "Module5"
+MODULE_6 = "Module6"
+SUB_MODULE_OF_7 = "Module7.SubModule1"
+MODULE_7 = "Module7"
+SUB_MODULE_OF_1 = "Module1.SubModule1"
+SUB_SUB_MODULE_OF_1 = "Module1.SubModule1.SubModule1"
+MODULE_A = Module(name="A")
+
+
+@pytest.fixture(scope="session")
+def evaluable1() -> EvaluableArchitecture:
+    all_modules = [
+        MODULE_1,
+        MODULE_2,
+        MODULE_3,
+        MODULE_4,
+        MODULE_5,
+        MODULE_6,
+        SUB_MODULE_OF_7,
+        MODULE_7,
+        SUB_MODULE_OF_1,
+        SUB_SUB_MODULE_OF_1,
+    ]
+    imports = [
+        AbsoluteImport(MODULE_1, MODULE_2),
+        AbsoluteImport(MODULE_2, MODULE_3),
+        AbsoluteImport(MODULE_4, MODULE_2),
+        AbsoluteImport(MODULE_2, MODULE_4),
+        AbsoluteImport(MODULE_3, MODULE_5),
+        AbsoluteImport(MODULE_6, MODULE_3),
+        AbsoluteImport(SUB_MODULE_OF_7, SUB_MODULE_OF_1),
+        AbsoluteImport(MODULE_7, SUB_MODULE_OF_7),
+    ]
+
+    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
diff --git a/tests/query_language/rule/test_alias_conversion.py b/tests/query_language/rule/test_alias_conversion.py
new file mode 100644
index 0000000..0adb1b2
--- /dev/null
+++ b/tests/query_language/rule/test_alias_conversion.py
@@ -0,0 +1,131 @@
+import pytest
+from query_language.rule.conftest import MODULE_A
+
+from pytestarch import Rule
+from pytestarch.query_language.rule import RuleConfiguration
+
+config_alias_test_cases = [
+    [
+        RuleConfiguration(
+            should_not=True,
+            import_=True,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=True,
+        ),
+        RuleConfiguration(
+            should_not=True,
+            import_=True,
+            except_present=True,
+            module_to_check=MODULE_A,
+            modules_to_check_against=[MODULE_A],
+            rule_object_anything=False,
+        ),
+    ],
+    [
+        RuleConfiguration(
+            should_not=True,
+            import_=False,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=True,
+        ),
+        RuleConfiguration(
+            should_not=True,
+            import_=False,
+            except_present=True,
+            module_to_check=MODULE_A,
+            modules_to_check_against=[MODULE_A],
+            rule_object_anything=False,
+        ),
+    ],
+    [
+        rule := RuleConfiguration(
+            should_not=True,
+            import_=True,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should_not=True,
+            import_=False,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should_not=True,
+            import_=True,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should_not=True,
+            import_=False,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should_only=True,
+            import_=True,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should_only=True,
+            import_=False,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should=True,
+            import_=True,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+    [
+        rule := RuleConfiguration(
+            should=True,
+            import_=False,
+            except_present=False,
+            module_to_check=MODULE_A,
+            rule_object_anything=False,
+        ),
+        rule,
+    ],
+]
+
+
+@pytest.mark.parametrize("config_with_alias, expected_config", config_alias_test_cases)
+def test_aliases_converted(
+    config_with_alias: RuleConfiguration,
+    expected_config: RuleConfiguration,
+) -> None:
+    converted_config = Rule._convert_aliases(config_with_alias)
+    assert converted_config == expected_config
diff --git a/tests/query_language/rule/test_rule.py b/tests/query_language/rule/test_rule.py
new file mode 100644
index 0000000..ca3b8d7
--- /dev/null
+++ b/tests/query_language/rule/test_rule.py
@@ -0,0 +1,101 @@
+import pytest
+from query_language.rule.conftest import MODULE_1, MODULE_2
+
+from pytestarch import Rule
+from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
+from pytestarch.query_language.exceptions import ImproperlyConfigured
+
+
+def test_rule_to_str_as_expected() -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        "A name"
+    ).should().import_modules_that().are_sub_modules_of("Module 1")
+
+    rule_as_str = str(rule)
+
+    assert (
+        rule_as_str
+        == '"A name" should import modules that are sub modules of "Module 1".'
+    )
+
+
+def test_sub_modules_identification() -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of("A name")
+
+    assert rule.rule_subject.name is None
+    assert rule.rule_subject.parent_module == "A name"
+
+
+def test_module_name_identification() -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named("A name")
+
+    assert rule.rule_subject.name == "A name"
+    assert rule.rule_subject.parent_module is None
+
+
+def test_partially_configured_rule_raises_error(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    with pytest.raises(
+        ImproperlyConfigured,
+        match="Specify a RuleSubject, a BehaviorSpecification, "
+        "a DependencySpecification, a RuleObject.",
+    ):
+        rule.assert_applies(evaluable1)
+
+    x = rule.modules_that()
+
+    with pytest.raises(
+        ImproperlyConfigured,
+        match="Specify a RuleSubject, a BehaviorSpecification, "
+        "a DependencySpecification, a RuleObject.",
+    ):
+        rule.assert_applies(evaluable1)
+
+    y = x.are_named(MODULE_1)
+
+    with pytest.raises(
+        ImproperlyConfigured,
+        match="Specify a BehaviorSpecification, a "
+        "DependencySpecification, a RuleObject.",
+    ):
+        rule.assert_applies(evaluable1)
+
+    z = y.should()
+
+    with pytest.raises(
+        ImproperlyConfigured,
+        match="Specify a DependencySpecification, a RuleObject.",
+    ):
+        rule.assert_applies(evaluable1)
+
+    a = z.import_modules_that()
+
+    with pytest.raises(
+        ImproperlyConfigured,
+        match="Specify a RuleObject.",
+    ):
+        rule.assert_applies(evaluable1)
+
+    a.are_named(MODULE_2)
+
+    rule.assert_applies(evaluable1)
+
+    assert True
+
+
+def assert_rule_applies(rule: Rule, evaluable: EvaluableArchitecture) -> None:
+    rule.assert_applies(evaluable)
+
+
+def assert_rule_does_not_apply(rule: Rule, evaluable: EvaluableArchitecture) -> None:
+    with pytest.raises(AssertionError):
+        rule.assert_applies(evaluable)
diff --git a/tests/query_language/rule/test_should_not_rule.py b/tests/query_language/rule/test_should_not_rule.py
new file mode 100644
index 0000000..3428ca8
--- /dev/null
+++ b/tests/query_language/rule/test_should_not_rule.py
@@ -0,0 +1,447 @@
+from query_language.rule.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_3,
+    MODULE_4,
+    MODULE_5,
+    MODULE_6,
+    MODULE_7,
+)
+from query_language.rule.test_rule import (
+    assert_rule_applies,
+    assert_rule_does_not_apply,
+)
+
+from pytestarch import EvaluableArchitecture, Rule
+
+
+def test_should_not_be_imported_except_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_5
+    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_3)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_7
+    )
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_5
+    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_3)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_5
+    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_3
+    )
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_6)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_6
+    )
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_except_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_2
+    )
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_anything_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(MODULE_5).should_not().import_anything()
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_anything_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(MODULE_7).should_not().import_anything()
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_by_anything_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(MODULE_7).should_not().be_imported_by_anything()
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_by_anything_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(MODULE_5).should_not().be_imported_by_anything()
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_6
+    ).should_not().be_imported_by_modules_that().are_named(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_6
+    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_6
+    ).should_not().be_imported_by_modules_that().are_named(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_6
+    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_be_imported_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_5
+    ).should_not().be_imported_by_modules_that().are_named(MODULE_3)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_not().be_imported_by_modules_that().are_named(MODULE_7)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_be_imported_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_except_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_not().import_modules_except_modules_that().are_named(MODULE_5)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_except_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_7
+    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_except_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_3
+    ).should_not().import_modules_except_modules_that().are_named(MODULE_5)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_except_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_3
+    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_5)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_except_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_not().import_modules_except_modules_that().are_named(MODULE_4)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_except_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_4)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_except_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_not().import_modules_except_modules_that().are_named(MODULE_4)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_except_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_5)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_4
+    ).should_not().import_modules_that().are_named(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_4
+    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_4
+    ).should_not().import_modules_that().are_named(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_4
+    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_not_import_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should_not().import_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_7
+    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_not().import_modules_that().are_named(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_not_import_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
diff --git a/tests/query_language/rule/test_should_only_rule.py b/tests/query_language/rule/test_should_only_rule.py
new file mode 100644
index 0000000..a1d999a
--- /dev/null
+++ b/tests/query_language/rule/test_should_only_rule.py
@@ -0,0 +1,405 @@
+from query_language.rule.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_3,
+    MODULE_5,
+    MODULE_7,
+)
+from query_language.rule.test_rule import (
+    assert_rule_applies,
+    assert_rule_does_not_apply,
+)
+
+from pytestarch import EvaluableArchitecture, Rule
+
+
+def test_should_only_be_imported_except_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_5)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_5
+    )
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_5)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_5
+    )
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_7
+    )
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_7)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_except_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
+        MODULE_7
+    )
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_5
+    ).should_only().be_imported_by_modules_that().are_named(MODULE_3)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_only().be_imported_by_modules_that().are_named(MODULE_7)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_be_imported_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_only().be_imported_by_modules_that().are_named(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_2
+    ).should_only().be_imported_by_modules_that().are_named(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_be_imported_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_2
+    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_except_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_only().import_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_except_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_except_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_only().import_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_except_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_except_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_only().import_modules_except_modules_that().are_named(MODULE_3)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_except_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_7
+    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_except_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_only().import_modules_except_modules_that().are_named(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_except_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should_only().import_modules_that().are_named(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_7
+    ).should_only().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_only().import_modules_that().are_named(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should_only().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_only_import_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_only().import_modules_that().are_named(MODULE_3)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should_only().import_modules_that().are_sub_modules_of(MODULE_3)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_2
+    ).should_only().import_modules_that().are_named(MODULE_3)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_only_import_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_2
+    ).should_only().import_modules_that().are_sub_modules_of(MODULE_3)
+
+    assert_rule_does_not_apply(rule, evaluable1)
diff --git a/tests/query_language/rule/test_should_rule.py b/tests/query_language/rule/test_should_rule.py
new file mode 100644
index 0000000..6028baf
--- /dev/null
+++ b/tests/query_language/rule/test_should_rule.py
@@ -0,0 +1,396 @@
+from query_language.rule.conftest import (
+    MODULE_1,
+    MODULE_2,
+    MODULE_3,
+    MODULE_4,
+    MODULE_6,
+    MODULE_7,
+    SUB_MODULE_OF_1,
+    SUB_MODULE_OF_7,
+)
+from query_language.rule.test_rule import (
+    assert_rule_applies,
+    assert_rule_does_not_apply,
+)
+
+from pytestarch import EvaluableArchitecture, Rule
+
+
+def test_should_be_imported_except_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_except_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_except_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_except_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_except_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_4
+    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_except_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_7
+    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_except_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_4
+    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_except_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_4
+    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_3
+    ).should().be_imported_by_modules_that().are_named(MODULE_2)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should().be_imported_by_modules_that().are_named(MODULE_7)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_be_imported_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_6
+    ).should().be_imported_by_modules_that().are_named(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_6
+    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_6
+    ).should().be_imported_by_modules_that().are_named(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_be_imported_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_6
+    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_except_named_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should().import_modules_except_modules_that().are_named(MODULE_4)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_except_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_2
+    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_4)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_except_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should().import_modules_except_modules_that().are_named(MODULE_4)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_except_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_4)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_except_named_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_1
+    ).should().import_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_except_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        MODULE_7
+    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_except_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should().import_modules_except_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_except_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_1
+    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_named_named_positive(evaluable1: EvaluableArchitecture) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(MODULE_1).should().import_modules_that().are_named(
+        MODULE_2
+    )
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_named_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        SUB_MODULE_OF_7
+    ).should().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_submodule_named_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should().import_modules_that().are_named(SUB_MODULE_OF_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_submodule_submodule_positive(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        MODULE_7
+    ).should().import_modules_that().are_sub_modules_of(MODULE_1)
+
+    assert_rule_applies(rule, evaluable1)
+
+
+def test_should_import_named_named_negative(evaluable1: EvaluableArchitecture) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        SUB_MODULE_OF_1
+    ).should().import_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_named_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_named(
+        SUB_MODULE_OF_1
+    ).should().import_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_submodule_named_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        SUB_MODULE_OF_1
+    ).should().import_modules_that().are_named(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
+
+
+def test_should_import_submodule_submodule_negative(
+    evaluable1: EvaluableArchitecture,
+) -> None:
+    rule = Rule()
+
+    rule.modules_that().are_sub_modules_of(
+        SUB_MODULE_OF_1
+    ).should().import_modules_that().are_sub_modules_of(MODULE_2)
+
+    assert_rule_does_not_apply(rule, evaluable1)
diff --git a/tests/query_language/test_rule.py b/tests/query_language/test_rule.py
deleted file mode 100644
index 5de21a0..0000000
--- a/tests/query_language/test_rule.py
+++ /dev/null
@@ -1,1479 +0,0 @@
-import pytest
-
-from pytestarch import Rule
-from pytestarch.eval_structure.evaluable_architecture import (
-    EvaluableArchitecture,
-    Module,
-)
-from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.exceptions import ImproperlyConfigured
-from pytestarch.importer.import_types import AbsoluteImport
-from pytestarch.query_language.rule import RuleConfiguration
-
-MODULE_1 = "Module1"
-MODULE_2 = "Module2"
-MODULE_3 = "Module3"
-MODULE_4 = "Module4"
-MODULE_5 = "Module5"
-MODULE_6 = "Module6"
-SUB_MODULE_OF_7 = "Module7.SubModule1"
-MODULE_7 = "Module7"
-SUB_MODULE_OF_1 = "Module1.SubModule1"
-SUB_SUB_MODULE_OF_1 = "Module1.SubModule1.SubModule1"
-
-MODULE_A = Module(name="A")
-
-
-def test_rule_to_str_as_expected() -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        "A name"
-    ).should().import_modules_that().are_sub_modules_of("Module 1")
-
-    rule_as_str = str(rule)
-
-    assert (
-        rule_as_str
-        == '"A name" should import modules that are sub modules of "Module 1".'
-    )
-
-
-def test_sub_modules_identification() -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of("A name")
-
-    assert rule.rule_subject.name is None
-    assert rule.rule_subject.parent_module == "A name"
-
-
-def test_module_name_identification() -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named("A name")
-
-    assert rule.rule_subject.name == "A name"
-    assert rule.rule_subject.parent_module is None
-
-
-@pytest.fixture(scope="module")
-def evaluable1() -> EvaluableArchitecture:
-    all_modules = [
-        MODULE_1,
-        MODULE_2,
-        MODULE_3,
-        MODULE_4,
-        MODULE_5,
-        MODULE_6,
-        SUB_MODULE_OF_7,
-        MODULE_7,
-        SUB_MODULE_OF_1,
-        SUB_SUB_MODULE_OF_1,
-    ]
-    imports = [
-        AbsoluteImport(MODULE_1, MODULE_2),
-        AbsoluteImport(MODULE_2, MODULE_3),
-        AbsoluteImport(MODULE_4, MODULE_2),
-        AbsoluteImport(MODULE_2, MODULE_4),
-        AbsoluteImport(MODULE_3, MODULE_5),
-        AbsoluteImport(MODULE_6, MODULE_3),
-        AbsoluteImport(SUB_MODULE_OF_7, SUB_MODULE_OF_1),
-        AbsoluteImport(MODULE_7, SUB_MODULE_OF_7),
-    ]
-
-    return EvaluableArchitectureGraph(NetworkxGraph(all_modules, imports))
-
-
-def test_partially_configured_rule_raises_error(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    with pytest.raises(
-        ImproperlyConfigured,
-        match="Specify a RuleSubject, a BehaviorSpecification, "
-        "a DependencySpecification, a RuleObject.",
-    ):
-        rule.assert_applies(evaluable1)
-
-    x = rule.modules_that()
-
-    with pytest.raises(
-        ImproperlyConfigured,
-        match="Specify a RuleSubject, a BehaviorSpecification, "
-        "a DependencySpecification, a RuleObject.",
-    ):
-        rule.assert_applies(evaluable1)
-
-    y = x.are_named(MODULE_1)
-
-    with pytest.raises(
-        ImproperlyConfigured,
-        match="Specify a BehaviorSpecification, a "
-        "DependencySpecification, a RuleObject.",
-    ):
-        rule.assert_applies(evaluable1)
-
-    z = y.should()
-
-    with pytest.raises(
-        ImproperlyConfigured,
-        match="Specify a DependencySpecification, a RuleObject.",
-    ):
-        rule.assert_applies(evaluable1)
-
-    a = z.import_modules_that()
-
-    with pytest.raises(
-        ImproperlyConfigured,
-        match="Specify a RuleObject.",
-    ):
-        rule.assert_applies(evaluable1)
-
-    a.are_named(MODULE_2)
-
-    rule.assert_applies(evaluable1)
-
-    assert True
-
-
-def assert_rule_applies(rule: Rule, evaluable: EvaluableArchitecture) -> None:
-    rule.assert_applies(evaluable)
-
-
-def assert_rule_does_not_apply(rule: Rule, evaluable: EvaluableArchitecture) -> None:
-    with pytest.raises(AssertionError):
-        rule.assert_applies(evaluable)
-
-
-def test_should_import_named_named_positive(evaluable1: EvaluableArchitecture) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(MODULE_1).should().import_modules_that().are_named(
-        MODULE_2
-    )
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        SUB_MODULE_OF_7
-    ).should().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should().import_modules_that().are_named(SUB_MODULE_OF_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_named_named_negative(evaluable1: EvaluableArchitecture) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        SUB_MODULE_OF_1
-    ).should().import_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        SUB_MODULE_OF_1
-    ).should().import_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        SUB_MODULE_OF_1
-    ).should().import_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        SUB_MODULE_OF_1
-    ).should().import_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should_only().import_modules_that().are_named(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_7
-    ).should_only().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_only().import_modules_that().are_named(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_only().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_only().import_modules_that().are_named(MODULE_3)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_only().import_modules_that().are_sub_modules_of(MODULE_3)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_2
-    ).should_only().import_modules_that().are_named(MODULE_3)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_2
-    ).should_only().import_modules_that().are_sub_modules_of(MODULE_3)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_4
-    ).should_not().import_modules_that().are_named(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_4
-    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_4
-    ).should_not().import_modules_that().are_named(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_4
-    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should_not().import_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_7
-    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_not().import_modules_that().are_named(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_not().import_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_except_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should().import_modules_except_modules_that().are_named(MODULE_4)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_except_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_4)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_except_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should().import_modules_except_modules_that().are_named(MODULE_4)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_except_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_4)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_import_except_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should().import_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_except_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_7
-    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_except_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should().import_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_import_except_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should().import_modules_except_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_except_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_only().import_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_except_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_except_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_only().import_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_except_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_import_except_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_only().import_modules_except_modules_that().are_named(MODULE_3)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_except_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_7
-    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_except_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_only().import_modules_except_modules_that().are_named(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_import_except_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_only().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_except_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_not().import_modules_except_modules_that().are_named(MODULE_5)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_except_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_7
-    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_except_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_3
-    ).should_not().import_modules_except_modules_that().are_named(MODULE_5)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_except_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_3
-    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_5)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_except_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_not().import_modules_except_modules_that().are_named(MODULE_4)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_except_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_4)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_except_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_not().import_modules_except_modules_that().are_named(MODULE_4)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_except_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_7
-    ).should_not().import_modules_except_modules_that().are_sub_modules_of(MODULE_5)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should().be_imported_by_modules_that().are_named(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should().be_imported_by_modules_that().are_named(MODULE_7)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_6
-    ).should().be_imported_by_modules_that().are_named(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_6
-    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_6
-    ).should().be_imported_by_modules_that().are_named(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_6
-    ).should().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_5
-    ).should_only().be_imported_by_modules_that().are_named(MODULE_3)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_only().be_imported_by_modules_that().are_named(MODULE_7)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_only().be_imported_by_modules_that().are_named(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_2
-    ).should_only().be_imported_by_modules_that().are_named(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_2
-    ).should_only().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_6
-    ).should_not().be_imported_by_modules_that().are_named(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_6
-    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_6
-    ).should_not().be_imported_by_modules_that().are_named(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_6
-    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_5
-    ).should_not().be_imported_by_modules_that().are_named(MODULE_3)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_not().be_imported_by_modules_that().are_named(MODULE_7)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_not().be_imported_by_modules_that().are_sub_modules_of(MODULE_7)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_except_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_except_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_2
-    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_1)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_except_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_except_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_be_imported_except_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_4
-    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_except_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_7
-    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_except_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_4
-    ).should().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_be_imported_except_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_4
-    ).should().be_imported_by_modules_except_modules_that().are_sub_modules_of(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_5)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_5
-    )
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_5)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_5
-    )
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_7
-    )
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_only().be_imported_by_modules_except_modules_that().are_named(MODULE_7)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_only_be_imported_except_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_only().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_7
-    )
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_named_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_5
-    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_3)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_named_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_1
-    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_7
-    )
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_submodule_named_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_5
-    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_3)
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_submodule_submodule_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_5
-    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_3
-    )
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_named_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_6)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_named_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(
-        MODULE_3
-    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_6
-    )
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_submodule_named_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_not().be_imported_by_modules_except_modules_that().are_named(MODULE_2)
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_except_submodule_submodule_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_sub_modules_of(
-        MODULE_1
-    ).should_not().be_imported_by_modules_except_modules_that().are_sub_modules_of(
-        MODULE_2
-    )
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_import_anything_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(MODULE_5).should_not().import_anything()
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_import_anything_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(MODULE_7).should_not().import_anything()
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-def test_should_not_be_imported_by_anything_positive(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(MODULE_7).should_not().be_imported_by_anything()
-
-    assert_rule_applies(rule, evaluable1)
-
-
-def test_should_not_be_imported_by_anything_negative(
-    evaluable1: EvaluableArchitecture,
-) -> None:
-    rule = Rule()
-
-    rule.modules_that().are_named(MODULE_5).should_not().be_imported_by_anything()
-
-    assert_rule_does_not_apply(rule, evaluable1)
-
-
-config_alias_test_cases = [
-    [
-        RuleConfiguration(
-            should_not=True,
-            import_=True,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=True,
-        ),
-        RuleConfiguration(
-            should_not=True,
-            import_=True,
-            except_present=True,
-            module_to_check=MODULE_A,
-            modules_to_check_against=[MODULE_A],
-            rule_object_anything=False,
-        ),
-    ],
-    [
-        RuleConfiguration(
-            should_not=True,
-            import_=False,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=True,
-        ),
-        RuleConfiguration(
-            should_not=True,
-            import_=False,
-            except_present=True,
-            module_to_check=MODULE_A,
-            modules_to_check_against=[MODULE_A],
-            rule_object_anything=False,
-        ),
-    ],
-    [
-        rule := RuleConfiguration(
-            should_not=True,
-            import_=True,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should_not=True,
-            import_=False,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should_not=True,
-            import_=True,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should_not=True,
-            import_=False,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should_only=True,
-            import_=True,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should_only=True,
-            import_=False,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should=True,
-            import_=True,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-    [
-        rule := RuleConfiguration(
-            should=True,
-            import_=False,
-            except_present=False,
-            module_to_check=MODULE_A,
-            rule_object_anything=False,
-        ),
-        rule,
-    ],
-]
-
-
-@pytest.mark.parametrize("config_with_alias, expected_config", config_alias_test_cases)
-def test_aliases_converted(
-    config_with_alias: RuleConfiguration,
-    expected_config: RuleConfiguration,
-) -> None:
-    converted_config = Rule._convert_aliases(config_with_alias)
-    assert converted_config == expected_config
diff --git a/tests/rule_assessment/__init__.py b/tests/rule_assessment/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/query_language/test_RuleViolationMessageGenerator.py b/tests/rule_assessment/test_RuleViolationMessageGenerator.py
similarity index 94%
rename from tests/query_language/test_RuleViolationMessageGenerator.py
rename to tests/rule_assessment/test_RuleViolationMessageGenerator.py
index 2d1f2e3..2d14f69 100644
--- a/tests/query_language/test_RuleViolationMessageGenerator.py
+++ b/tests/rule_assessment/test_RuleViolationMessageGenerator.py
@@ -3,12 +3,14 @@
 import pytest
 
 from pytestarch.eval_structure.evaluable_architecture import (
-    LaxDependenciesByBaseModule,
+    DependenciesByBaseModules,
     Module,
-    StrictDependenciesByBaseModules,
+    UnexpectedDependenciesByBaseModule,
 )
-from pytestarch.query_language.message_generator import RuleViolationMessageGenerator
-from pytestarch.query_language.rule_matcher import RuleViolations
+from pytestarch.rule_assessment.error_message.message_generator import (
+    RuleViolationMessageGenerator,
+)
+from pytestarch.rule_assessment.rule_check.rule_violations import RuleViolations
 
 ORIGINAL_SUBJECT = "A"
 ORIGINAL_OBJECT_1 = "B"
@@ -193,12 +195,12 @@ def test_rule_violation_message_content(
     generator: RuleViolationMessageGenerator,
     violation: Dict[str, bool],
     expected_message: str,
-    strict_dependencies: StrictDependenciesByBaseModules,
-    lax_dependencies: LaxDependenciesByBaseModule,
+    strict_dependencies: DependenciesByBaseModules,
+    lax_dependencies: UnexpectedDependenciesByBaseModule,
 ) -> None:
     violations = RuleViolations(
-        strict_dependencies=strict_dependencies,
-        lax_dependencies=lax_dependencies,
+        dependencies=strict_dependencies,
+        unexpected_dependencies=lax_dependencies,
         **violation,
     )
     messages = generator.create_rule_violation_messages(violations)
@@ -360,12 +362,12 @@ def test_rule_violation_message_content(
 def test_violated_message_only_present_if_rule_actually_violated(
     generator: RuleViolationMessageGenerator,
     violation: Dict[str, bool],
-    strict_dependencies: StrictDependenciesByBaseModules,
-    lax_dependencies: LaxDependenciesByBaseModule,
+    strict_dependencies: DependenciesByBaseModules,
+    lax_dependencies: UnexpectedDependenciesByBaseModule,
 ) -> None:
     violations = RuleViolations(
-        strict_dependencies=strict_dependencies,
-        lax_dependencies=lax_dependencies,
+        dependencies=strict_dependencies,
+        unexpected_dependencies=lax_dependencies,
         **violation,
     )
     messages = generator.create_rule_violation_messages(violations)
@@ -449,12 +451,12 @@ def test_multiple_rule_objects_combined_in_one_message(
     generator: RuleViolationMessageGenerator,
     violation: Dict[str, bool],
     expected_message: str,
-    strict_dependencies: StrictDependenciesByBaseModules,
-    lax_dependencies: LaxDependenciesByBaseModule,
+    strict_dependencies: DependenciesByBaseModules,
+    lax_dependencies: UnexpectedDependenciesByBaseModule,
 ) -> None:
     violations = RuleViolations(
-        strict_dependencies=strict_dependencies,
-        lax_dependencies=lax_dependencies,
+        dependencies=strict_dependencies,
+        unexpected_dependencies=lax_dependencies,
         **violation,
     )
     messages = generator.create_rule_violation_messages(violations)
@@ -616,12 +618,12 @@ def test_multiple_rule_objects_in_multiple_message(
     violation: Dict[str, bool],
     expected_message_count: int,
     expected_messages: List[str],
-    strict_dependencies: StrictDependenciesByBaseModules,
-    lax_dependencies: LaxDependenciesByBaseModule,
+    strict_dependencies: DependenciesByBaseModules,
+    lax_dependencies: UnexpectedDependenciesByBaseModule,
 ) -> None:
     violations = RuleViolations(
-        strict_dependencies=strict_dependencies,
-        lax_dependencies=lax_dependencies,
+        dependencies=strict_dependencies,
+        unexpected_dependencies=lax_dependencies,
         **violation,
     )
     messages = generator.create_rule_violation_messages(violations)
@@ -667,12 +669,12 @@ def test_multiple_rule_objects_in_multiple_message(
 def test_multiple_messages_if_forbidden_and_no_import_both_present(
     violation: Dict[str, bool],
     expected_messages: List[str],
-    strict_dependencies: StrictDependenciesByBaseModules,
-    lax_dependencies: LaxDependenciesByBaseModule,
+    strict_dependencies: DependenciesByBaseModules,
+    lax_dependencies: UnexpectedDependenciesByBaseModule,
 ) -> None:
     violations = RuleViolations(
-        strict_dependencies=strict_dependencies,
-        lax_dependencies=lax_dependencies,
+        dependencies=strict_dependencies,
+        unexpected_dependencies=lax_dependencies,
         **violation,
     )
     messages = single_object_import_generator.create_rule_violation_messages(violations)
diff --git a/tests/query_language/test_rule_matcher.py b/tests/rule_assessment/test_rule_matcher.py
similarity index 97%
rename from tests/query_language/test_rule_matcher.py
rename to tests/rule_assessment/test_rule_matcher.py
index 4120856..2179272 100644
--- a/tests/query_language/test_rule_matcher.py
+++ b/tests/rule_assessment/test_rule_matcher.py
@@ -4,13 +4,13 @@
 
 from pytestarch import Rule
 from pytestarch.eval_structure.evaluable_architecture import (
-    LaxDependenciesByBaseModule,
+    DependenciesByBaseModules,
     Module,
-    StrictDependenciesByBaseModules,
+    UnexpectedDependenciesByBaseModule,
 )
 from pytestarch.eval_structure.evaluable_graph import EvaluableArchitectureGraph
-from pytestarch.eval_structure_impl.networkxgraph import NetworkxGraph
-from pytestarch.importer.import_types import AbsoluteImport
+from pytestarch.eval_structure.networkxgraph import NetworkxGraph
+from pytestarch.eval_structure_generation.file_import.import_types import AbsoluteImport
 
 MODULE_1 = "1"
 MODULE_2 = "2"
@@ -656,12 +656,12 @@ def test_multiple_violations_due_to_multiple_rule_objects(
     imports: List[AbsoluteImport],
     rule: Rule,
     expected_violated: List[str],
-    strict_dependencies: StrictDependenciesByBaseModules,
-    lax_dependencies: LaxDependenciesByBaseModule,
+    strict_dependencies: DependenciesByBaseModules,
+    lax_dependencies: UnexpectedDependenciesByBaseModule,
 ) -> None:
     evaluable = EvaluableArchitectureGraph(NetworkxGraph(ALL_MODULES, imports))
     matcher = rule._prepare_rule_matcher()
-    violations = matcher.match(evaluable)
+    violations = matcher._find_rule_violations(evaluable)
 
     flags = violations._bool_field_names()
 
@@ -672,5 +672,5 @@ def test_multiple_violations_due_to_multiple_rule_objects(
         else:
             assert not violated
 
-    assert violations.strict_dependencies == strict_dependencies
-    assert violations.lax_dependencies == lax_dependencies
+    assert violations.dependencies == strict_dependencies
+    assert violations.unexpected_dependencies == lax_dependencies
diff --git a/tests/test_architecture.py b/tests/test_architecture.py
new file mode 100644
index 0000000..d738594
--- /dev/null
+++ b/tests/test_architecture.py
@@ -0,0 +1,74 @@
+from pathlib import Path
+
+import pytest
+
+from pytestarch import EvaluableArchitecture, Rule, get_evaluable_architecture
+
+
+@pytest.fixture(scope="session")
+def pytestarch_architecture() -> EvaluableArchitecture:
+    src_folder = str(Path.cwd() / "src/pytestarch")
+    return get_evaluable_architecture(
+        src_folder,
+        src_folder,
+        ("*__pycache__", "*__init__.py"),
+    )
+
+
+BASE_MODULE = "pytestarch"
+DIAGRAM = f"{BASE_MODULE}.diagram_extension"
+STRUCTURE = f"{BASE_MODULE}.eval_structure"
+GENERATION = f"{BASE_MODULE}.eval_structure_generation"
+LANGUAGE = f"{BASE_MODULE}.query_language"
+ASSESSMENT = f"{BASE_MODULE}.rule_assessment"
+
+
+top_level_rules = [
+    pytest.param(
+        Rule()
+        .modules_that()
+        .are_named(DIAGRAM)
+        .should_only()
+        .import_modules_that()
+        .are_named(LANGUAGE),
+        id="diagram_extension",
+    ),
+    pytest.param(
+        Rule().modules_that().are_named(STRUCTURE).should_not().import_anything(),
+        id="eval_structure",
+    ),
+    pytest.param(
+        Rule()
+        .modules_that()
+        .are_named(GENERATION)
+        .should_only()
+        .import_modules_that()
+        .are_named(STRUCTURE),
+        id="eval_structure_generation",
+    ),
+    pytest.param(
+        Rule()
+        .modules_that()
+        .are_named(LANGUAGE)
+        .should_only()
+        .import_modules_that()
+        .are_named([STRUCTURE, ASSESSMENT]),
+        id="query_language",
+    ),
+    pytest.param(
+        Rule()
+        .modules_that()
+        .are_named(ASSESSMENT)
+        .should_only()
+        .import_modules_that()
+        .are_named(STRUCTURE),
+        id="rule_assessment",
+    ),
+]
+
+
+@pytest.mark.parametrize("rule", top_level_rules)
+def test_top_level_module_structure(
+    rule: Rule, pytestarch_architecture: EvaluableArchitecture
+) -> None:
+    rule.assert_applies(pytestarch_architecture)
diff --git a/tests/util.py b/tests/util.py
index 108ff46..d538ad9 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -1,7 +1,7 @@
 from pathlib import Path
 
-from pytestarch.config.config import Config
-from pytestarch.importer.file_filter import FileFilter
+from pytestarch.eval_structure_generation.file_import.config import Config
+from pytestarch.eval_structure_generation.file_import.file_filter import FileFilter
 
 
 class MockFileFilter(FileFilter):