Сама задача:
Реализовать конечный автомат Мили в виде класса. Начальным состоянием автомата является A. Методы возвращают числовые значения.
Если вызываемый метод не реализован для некоторого состояния, необходимо вызвать пользовательское исключение MealyError. При возникновении исключения должно передаваться имя метода, вызвавшего это исключение.
Реализовать в отдельной функции test автоматическое тестирование автомата Мили на основе покрытия ветвей. Требуемая степень покрытия: 100%.
В примерах ниже функция main возвращает объект созданного класса. Далее последовательно вызываются методы полученного объекта.
Пример 1
o = main()
o.amass() # 0
o.amass() # 1
o.stare() # 4
o.amass() # 3
o.stare() # 5
o.amass() # 8
o.amass() # 3
o.stare() # 5
o.stare() # 7
o.stare() # 2
o.stare() # 5
o.mute() # 6
Пример 2
o = main()
o.amass() # 0
o.amass() # 1
o.amass() # 3
o.stare() # 5
o.stare() # 7
o.stare() # 2
o.stare() # 5
o.amass() # 8
o.stare() # 4
o.stare() # 4
o.amass() # 3
o.stare() # 5
Мое решение:
class MealyError(Exception):
def __init__(self, method_name):
self.method_name = method_name
super().__init__(f"Method {method_name} not allowed in current state")
class MealyMachine:
def __init__(self):
self.state = 'A'
def amass(self):
if self.state == 'A':
self.state = 'B'
return 0
if self.state == 'B':
self.state = 'C'
return 1
if self.state == 'C':
self.state = 'D'
return 3
if self.state == 'E':
self.state = 'C'
return 8
raise MealyError("amass")
def stare(self):
if self.state == 'B':
self.state = 'D'
return 2
elif self.state == 'C':
self.state = 'C'
return 4
elif self.state == 'D':
self.state = 'E'
return 5
elif self.state == 'E':
self.state = 'B'
return 7
elif self.state == 'E':
self.state = 'F'
return 6
else:
raise MealyError("stare")
def mute(self):
if self.state == 'E':
self.state = 'F'
return 6
else:
raise MealyError("mute")
def main():
return MealyMachine()
def test_state_a(m):
# State A
assert m.state == 'A'
assert m.amass() == 0
assert m.state == 'B'
test_state_b(m)
m.state = 'A'
try:
m.mute()
except MealyError:
pass
m.state = 'A'
try:
m.stare()
except MealyError:
pass
def test_state_b(m):
assert m.amass() == 1
assert m.state == 'C'
test_state_c(m)
m.state = 'B'
assert m.stare() == 2
assert m.state == 'D'
test_state_d(m)
m.state = 'B'
try:
m.mute()
except MealyError:
pass
def test_state_c(m):
assert m.amass() == 3
assert m.state == 'D'
test_state_d(m)
m.state = 'C'
assert m.stare() == 4
assert m.state == 'C'
try:
m.mute()
except MealyError:
pass
def test_state_d(m):
m.state = 'D'
assert m.stare() == 5
assert m.state == 'E'
test_state_e(m)
m.state = 'D'
try:
m.amass()
except MealyError:
pass
try:
m.mute()
except MealyError:
pass
def test_state_e(m):
assert m.amass() == 8
assert m.state == 'C'
m.state = 'E'
assert m.stare() == 7
assert m.state == 'B'
m.state = 'E'
assert m.mute() == 6
assert m.state == 'F'
test_state_f(m)
def test_state_f(m):
# State F
try:
m.amass()
except MealyError:
pass
try:
m.stare()
except MealyError:
pass
try:
m.mute()
except MealyError:
pass
def test():
m = main()
m.state = 'A'
test_state_a(m)
m = main()
m.state = 'B'
test_state_b(m)
m = main()
m.state = 'C'
test_state_c(m)
m = main()
m.state = 'D'
test_state_d(m)
m = main()
m.state = 'E'
test_state_e(m)
m = main()
m.state = 'F'
test_state_f(m)
Однако при выполнении функции test(), сайт показывает что покрытие не 100%, а “Недостаточное тестовое покрытие ветвей (98.125%)”
Что нужно изменить/добавить к тестам чтобы было 100%?