단위 테스트는 독립적인 작은 단위의 기능을 테스트하는 방식이다. 단위 테스트에 필요한 코드를 따로 작성해두는 것은 각각의 기능이 잘 작동하는지 확인할 수 있는 좋은 습관이다.
텍스트 픽스쳐(test fixture): 테스트 설정을 위한 코드
테스트 케이스(test case): 테스트의 기본 단위
테스트 스위트(test suite): 테스트 케이스의 집합 (unittest 모듈 참고)
테스트 러너(test runner): 테스트 스위트를 실행하는 객체
unittest
unittest는 테스트에 필요한 기능을 제공한다. unittest.TestCase를 상속 받은 클래스 내부에 test로 시작하는 메서드를 생성하면 테스트를 진행 할 수 있다. 클래스에 기본으로 생성되어 있는 메소드는 아래와 같다.
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | bool(x) is True |
assertFalse(x) | bool(x) is False |
assertIs(a, b) | a is b |
assertIsNot(a, b) | a is not b |
assertIsNone(x) | x is None |
assertIsNotNone(x) | x is not None |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertIsInstance(a, b) | isinstance(a, b) |
assertNotIsInstance(a, b) | not isinstance(a, b) |
예시:
import unittest
class MathTest(unittest.TestCase):
def test_add(self):
self.assertEqual(3+3, 7)
def test_add_true(self):
self.assertTrue(3+5 == 8)
if __name__ == "__main__":
unittest.main()
결과:
F.
======================================================================
FAIL: test_add (__main__.MathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "c:\Users\music\Desktop\LAB\ex.py", line 6, in test_add
self.assertEqual(3+3, 7)
AssertionError: 6 != 7
----------------------------------------------------------------------
Ran 2 tests in 0.004s
FAILED (failures=1)
테스트 2개를 실행하고, 테스트 여부, 에러 내용, 소요 시간 등 내용을 보여준다.
테스트 케이스를 특정해서 추가할 수도 있다.
import unittest
class TestOne(unittest.TestCase):
# 생략
pass
class TestTwo(unittest.TestCase):
# 생략
pass
class TestThree(unittest.TestCase):
# 생략
pass
if __name__ == '__main__':
# 테스트 케이스 생성
case_1 = unittest.makeSuite(TestOne)
case_2 = unittest.makeSuite(TestTwo)
# suite 생성, 케이스 등록
suite = unittest.TestSuite()
suite.addTests((case_1, case_2))
# 실행
runner = unittest.TextTestRunner()
runner.run(suite)
makeSuite로 테스트할 클래스를 인스턴스로 등록한다. TestSuite를 생성하고 등록한 후, runner로 실행시켜주면 된다. 위 예시의 경우, 등록되지 않은 TestThree의 메서드는 테스트되지 않는다.
doctest
doctest는 docstring에 작성된 내용을 테스트해 주는 모듈이다. >>>뒤에 실행할 코드를 작성하고 아래 줄에 예상값을 적는다.
def add_num(a, b):
"""Add two numbers
>>> add_num(3, 6)
9
>>> add_num(0, 2)
5
"""
return a + b
if __name__ == "__main__":
# 실행
import doctest
doctest.testmod()
실행할 때는 -v 옵션을 사용해야 테스트 내용을 확인할 수 있다.
> python 파일이름.py -v
Trying:
add_num(3, 6)
Expecting:
9
ok
Trying:
add_num(0, 2)
Expecting:
5
**********************************************************************
File "ex.py", line 10, in __main__.add_num
Failed example:
add_num(0, 2)
Expected:
5
Got:
2
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
1 of 2 in __main__.add_num
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.
예상값과 실행값이 같지 않으면 세부 내용을 표시해준다.
pytest
pytest는 외부 모듈이기 때문에 설치가 필요하다. pytest는 test로 시작하는 파일을 찾아 test로 시작하는 함수를 실행한다.
# test_math.py
def add_num(a, b):
return a + b
def test_add_num():
assert add_num(5, 3) == 8
아래 명령어를 통해 실행한다. (python -m pytest 또는 py.test)
> py.test
============================================= test session starts ==============================================
platform win32 -- Python 3.8.11, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: C:\Users\user\Desktop\LAB
collected 1 item
test_math.py . [100%]
============================================== 1 passed in 0.04s ===============================================
실행한 디렉토리 내의 test_math.py를 찾아 실행한 모습이다.