Юнит тест на unittest в python
В общем, хочу влиться в автотесты, и начал с простого - калькулятора и автотеста для него, в итоге - хренасдва а не юнит-тесты. Вот код калькулятора:
import math
print("Данный калькулятор создан для операций только с двумя целыми числами, а для вычисления факториала, нужно ввести любые числа")
x = int(input("Первое число: "))
y = int(input("Второе число: "))
action = input("Действие (+ - * / !): ")
class calc:
def add(x, y):
return x + y
def sub(x, y):
return x - y
def mul(x, y):
return x * y
def div(x, y):
return x / y
def fac(z):
return math.factorial(z)
if action == "+":
("Сумма =", calc.add(x, y))
elif action == "-":
(calc.sub(x, y))
elif action == "*":
("Произведение =", calc.mul(x, y))
elif action == "/":
("Деление =", calc.div(x, y))
elif action == "!":
z = int(input("Введите целое число: "))
("Факториал числа =", calc.fac(z))
else:
("Wenk!")
input("\n\nНажмите Enter, чтобы выйти.")
И вот код автотестов (неполный, там не хватает факториала)
import unittest
import calc
class calcTest(unittest.TestCase):
def test_add(self):
self.assertEqual(self.calc.add(4,7), 11)
def test_subtract(self):
self.assertEqual(self.calc.sub(10,5), 5)
def test_multiply(self):
self.assertEqual(self.calc.mul(3,7), 21)
def test_divide(self):
self.assertEqual(self.calc.div(10,2), 5)
if __name__ == "__main__":
unittest.main()
Проблема в том, что при прогоне тестов через IDLE он ругается с сообщениями:
EEEE
======================================================================
ERROR: test_add (__main__.calcTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\richa\Desktop\utest_calc.py", line 5, in test_add
self.assertEqual(self.calc.add(4,7), 11)
AttributeError: 'calcTest' object has no attribute 'calc'
======================================================================
ERROR: test_divide (__main__.calcTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\richa\Desktop\utest_calc.py", line 11, in test_divide
self.assertEqual(self.calc.div(10,2), 5)
AttributeError: 'calcTest' object has no attribute 'calc'
======================================================================
ERROR: test_multiply (__main__.calcTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\richa\Desktop\utest_calc.py", line 9, in test_multiply
self.assertEqual(self.calc.mul(3,7), 21)
AttributeError: 'calcTest' object has no attribute 'calc'
======================================================================
ERROR: test_subtract (__main__.calcTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\richa\Desktop\utest_calc.py", line 7, in test_subtract
self.assertEqual(self.calc.sub(10,5), 5)
AttributeError: 'calcTest' object has no attribute 'calc'
----------------------------------------------------------------------
Ran 4 tests in 0.009s
FAILED (errors=4)
А если пытаюсь вывести через командную строку, то это:
C:\Windows\system32>python -m unittest utest_calc -v
utest_calc (unittest.loader._FailedTest) ... ERROR
======================================================================
ERROR: utest_calc (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: utest_calc
Traceback (most recent call last):
File "C:\Users\richa\AppData\Local\Programs\Python\Python38-32\lib\unittest\loader.py", line 154, in loadTestsFromName
module = __import__(module_name)
ModuleNotFoundError: No module named 'utest_calc'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
Что делать - ума не приложу. Я не то чтобы новичок в пайтоне - я ещё ниже, у меня 0-ой уровень, как у По и Кунг-Фу Панды
Ответы (1 шт):
self.calc - это попытка обращения к полю текущего объекта (упрощенно - объекта, которому принадлежит метод, в котором происходит это обращение). По сути вы пытаетесь обратиться к полю calc юнит-теста. Такого поля у юнит-теста нет, отсюда ошибка.
Вам нужно убрать этот self перед calc (например, self.assertEqual(calc.add(4,7), 11)) и импортировать класс calc из модуля, где он объявлен, пример:
from имя_модуля import calc
Вместо имя_модуля подставьте имя файла, где находится класс calc, но без расширения .py.
Также внутри модуля с классом calc нужно чтобы все действия взаимодействия с пользователем не выполнялись при импорте модуля (в том числе при импорте внутри тестового модуля), для этого их нужно расположить в блоке if __name__ == "__main__":
import math
class calc:
def add(x, y):
return x + y
def sub(x, y):
return x - y
def mul(x, y):
return x * y
def div(x, y):
return x / y
def fac(z):
return math.factorial(z)
if __name__ == "__main__":
print("Данный калькулятор создан для операций только с двумя целыми числами, а для вычисления факториала, нужно ввести любые числа")
x = int(input("Первое число: "))
y = int(input("Второе число: "))
action = input("Действие (+ - * / !): ")
if action == "+":
("Сумма =", calc.add(x, y))
elif action == "-":
(calc.sub(x, y))
elif action == "*":
("Произведение =", calc.mul(x, y))
elif action == "/":
("Деление =", calc.div(x, y))
elif action == "!":
z = int(input("Введите целое число: "))
("Факториал числа =", calc.fac(z))
else:
("Wenk!")
input("\n\nНажмите Enter, чтобы выйти.")