Я пытаюсь написать код для Moore Machine. Он работает, а тестовое покрытие составляет 100%. Но когнитивная сложность функционального теста () слишком высока - 11 (мне нужно, чтобы это было
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()
< /code>
Я попытался добавить дополнительные функции, такие как: < /p>
def assert_raises(exception_type, message, func, *args):
try:
func(*args)
except exception_type as e:
assert e.message == message
return True
return False
< /code>
Во -первых, я добавил эту функцию - тестовое покрытие упало. Затем мой друг посоветовал добавить другие функции внутри Test () - они не работали из -за некоторых неприятностей с Pytest (я не знаю, что случилось). Затем я добавил те же функции Owler Test (), и тесты перестали работать.
Подробнее здесь: https://stackoverflow.com/questions/796 ... s-too-high
Когнитивная сложность функции слишком высока ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Какова временная сложность функции, если существует верхний предел переменной?
Anonymous » » в форуме C++ - 0 Ответы
- 20 Просмотры
-
Последнее сообщение Anonymous
-