I am trying to write the code for Moore machine. It is working and the test coverage is 100%. But the cognitive complexity of the function test() is too high - 11 (I need it to be <10). How do I fix this? I've tried several methods, but then test coverage falls. class MachineException(Exception): def __init__(self, message): super().__init__(message) self.message = message class MooreMachine: def __init__(self): self.state = "S0" self.v = None self.visited_methods = set() self.visited_states = {self.state} self.transitions = set() self._init_graph() self._init_outputs() def _init_graph(self): self.graph = { "S0": {"sit": ["S1"], "view": ["S3"], "pan": ["S4"]}, "S1": {"sit": ["S2"]}, "S2": {}, "S3": {"sit": ["S5"]}, "S4": {"pan": ["S3"], "hike": ["S5"]}, "S5": {"speed": ["S2"]} } def _init_outputs(self): self.outputs = { "S0": "m5", "S1": "m4", "S2": "m2", "S3": "m3", "S4": "m4", "S5": "m3" } def assign_v(self, value): self.v = value def get_output(self): return self.outputs.get(self.state, "unknown") def seen_method(self, method_name): return method_name in self.visited_methods def _can_transition(self, method_name): return method_name in self.graph.get(self.state, {}) def _method_exists(self, method_name): return any(method_name in methods for methods in self.graph.values()) def _execute_transition(self, method_name): target = self.graph[self.state][method_name][0] self._make_transition(method_name, target) def _make_transition(self, method_name, target_state): self.transitions.add((self.state, method_name, target_state)) self.visited_methods.add(method_name) self.state = target_state self.visited_states.add(target_state) def has_path_to(self, target_state): if target_state == self.state: return True visited = set() return self._dfs_path_check(self.state, target_state, visited) def _dfs_path_check(self, current, target, visited): if current == target: return True if current in visited: return False visited.add(current) for method in self.graph.get(current, {}): for neighbor in self.graph[current][method]: if self._dfs_path_check(neighbor, target, visited): return True return False def __getattr__(self, name): if not name.startswith("select_"): raise MachineException("unknown") method_name = name[7:] if not self._method_exists(method_name): raise MachineException("unknown") if not self._can_transition(method_name): raise MachineException("unsupported") return lambda: self._execute_transition(method_name) def test(): obj = MooreMachine() # Initial state assert obj.state == "S0" assert obj.get_output() == "m5" assert not obj.seen_method("sit") # Basic sit transition obj.select_sit() assert obj.state == "S1" assert obj.get_output() == "m4" assert obj.seen_method("sit") # Second sit transition obj.select_sit() assert obj.state == "S2" assert obj.get_output() == "m2" # Path checking from S2 assert not obj.has_path_to("S0") assert not obj.has_path_to("S1") assert obj.has_path_to("S2") # self # View transition obj.state = "S0" obj.select_view() assert obj.state == "S3" assert obj.get_output() == "m3" # Sit from S3 obj.select_sit() assert obj.state == "S5" assert obj.get_output() == "m3" # Speed transition obj.select_speed() assert obj.state == "S2" assert obj.get_output() == "m2" # Pan transition obj.state = "S0" obj.select_pan() assert obj.state == "S4" assert obj.get_output() == "m4" # Hike transition with v=0 obj.assign_v(0) obj.select_hike() assert obj.state == "S5" assert obj.get_output() == "m3" # Path checking from S4 obj.state = "S4" assert obj.has_path_to("S2") assert obj.has_path_to("S3") assert obj.has_path_to("S5") assert not obj.has_path_to("S0") assert not obj.has_path_to("S1") # Pan from S4 obj.select_pan() assert obj.state == "S3" # Invalid method exception_raised = False try: obj.select_invalid() except MachineException as e: assert e.message == "unknown" exception_raised = True assert exception_raised # Unsupported method exception_raised = False try: obj.state = "S2" obj.select_speed() except MachineException as e: assert e.message == "unsupported" exception_raised = True assert exception_raised # Check transitions recording obj.state = "S0" obj.select_sit() obj.select_sit() assert ("S0", "sit", "S1") in obj.transitions assert ("S1", "sit", "S2") in obj.transitions # Check visited states assert "S0" in obj.visited_states assert "S1" in obj.visited_states assert "S2" in obj.visited_states # Check method existence assert any("sit" in methods for methods in obj.graph.values()) assert not any("invalid" in methods for methods in obj.graph.values()) # Check can_transition obj.state = "S0" assert obj._can_transition("sit") assert not obj._can_transition("speed") # Check getattr with non-select exception_raised = False try: obj.non_select_method() except MachineException as e: assert e.message == "unknown" exception_raised = True assert exception_raised # Check assign_v obj.assign_v(1) assert obj.v == 1 # Full cycle coverage obj.state = "S0" obj.select_sit() # S0 -> S1 obj.select_sit() # S1 -> S2 obj.state = "S0" obj.select_view() # S0 -> S3 obj.select_sit() # S3 -> S5 obj.select_speed() # S5 -> S2 obj.state = "S0" obj.select_pan() # S0 -> S4 obj.select_hike() # S4 -> S5 (with v=1) # Check main function machine = main() assert isinstance(machine, MooreMachine) assert machine.state == "S0" return True def main(): return MooreMachine() I've tried adding additional functions, such as: def assert_raises(exception_type, message, func, *args): try: func(*args) except exception_type as e: assert e.message == message return True return False Firstly, I added this function - the test coverage fell. Then, my friend adviced adding other functions inside test() - they didn't work because of some troubles with pytest (I don't know what happened). Then, I added these same functions outside test() and tests stopped working. Continue reading...