Когнитивная сложность функции слишком высокаPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Когнитивная сложность функции слишком высока

Сообщение Anonymous »

Я пытаюсь написать код для 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»