unittest — 단위 테스트 프레임워크
unittest — 단위 테스트 프레임워크
(이미 테스트의 기본 개념에 익숙하다면 assert 메서드 목록으로 건너뛰어도 좋아요.)
unittest 단위 테스트 프레임워크는 원래 JUnit에서 영감을 받았으며, 다른 언어의 주요 단위 테스트 프레임워크와 비슷한 특성을 가져요. 테스트 자동화, 테스트의 setup/shutdown 코드 공유, 테스트의 컬렉션으로의 집계, 보고 프레임워크로부터의 테스트 독립성을 지원해요.
본문
이를 달성하기 위해 unittest는 객체 지향 방식으로 몇 가지 중요한 개념을 지원해요:
- test fixture(테스트 픽스처) — 하나 이상의 테스트를 수행하는 데 필요한 준비와 관련 정리 작업을 나타내요. 예를 들어 임시 데이터베이스, 디렉터리, 프록시 데이터베이스를 만들거나 서버 프로세스를 시작하는 것이 포함될 수 있어요.
- test case(테스트 케이스) — 테스트의 개별 단위예요. 특정 입력 집합에 대한 특정 응답을 확인해요.
unittest는 새 테스트 케이스를 만드는 데 사용할 수 있는 기본 클래스TestCase를 제공해요. - test suite(테스트 스위트) — 테스트 케이스, 테스트 스위트, 또는 둘 다의 모음이에요. 함께 실행되어야 하는 테스트를 집계하는 데 사용돼요.
- test runner(테스트 러너) — 테스트의 실행을 조율하고 결과를 사용자에게 제공하는 구성 요소예요. 러너는 그래픽 인터페이스나 텍스트 인터페이스를 사용하거나, 테스트 실행 결과를 나타내는 특수 값을 반환할 수 있어요.
기본 예제 (Basic example)
unittest 모듈은 테스트를 구성하고 실행하기 위한 풍부한 도구 세트를 제공해요. 다음은 세 문자열 메서드를 테스트하는 짧은 스크립트예요:
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# s.split이 구분자가 문자열이 아닐 때 실패하는지 확인
with self.assertRaises(TypeError):
s.split(2)
if __name__ == '__main__':
unittest.main()
테스트 케이스는 unittest.TestCase를 하위 클래스화해 만들어요. 세 개의 개별 테스트는 이름이 test로 시작하는 메서드로 정의돼요. 이 이름 규칙은 어떤 메서드가 테스트를 나타내는지 테스트 러너에 알려줘요.
각 테스트의 핵심은 예상 결과를 확인하는 assertEqual() 호출, 조건을 검증하는 assertTrue()/assertFalse(), 특정 예외가 발생하는지 확인하는 assertRaises()예요. 이 메서드들은 assert 문 대신 사용되어 테스트 러너가 모든 테스트 결과를 축적하고 보고서를 만들 수 있게 해요. setUp()과 tearDown() 메서드는 각 테스트 메서드 전후에 실행될 지시사항을 정의할 수 있게 해줘요.
명령줄에서 실행하면 위 스크립트는 다음과 같은 출력을 생성해요:
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
-v 옵션을 전달하면 더 높은 수준의 상세도를 활성화해요.
명령줄 인터페이스 (Command-Line Interface)
unittest 모듈은 명령줄에서 모듈, 클래스, 심지어 개별 테스트 메서드에서 테스트를 실행하는 데 사용할 수 있어요:
python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
모듈 이름, 정규화된 클래스 또는 메서드 이름의 조합을 가진 목록을 전달할 수 있어요. 테스트 모듈은 파일 경로로도 지정할 수 있어요. -v 플래그로 더 자세히 (더 높은 상세도로) 테스트를 실행할 수 있어요. 인자 없이 실행하면 테스트 발견(Test Discovery)이 시작돼요. 모든 명령줄 옵션 목록은 python -m unittest -h를 참고해요.
명령줄 옵션 (Command-line options)
-b,--buffer— 테스트 실행 중 표준 출력과 표준 오류 스트림을 버퍼링. 통과하는 테스트 중 출력은 버려지고, 실패나 오류에서 출력이 에코됨.-c,--catch— 테스트 실행 중 Control-C는 현재 테스트가 끝나기를 기다린 다음 지금까지의 모든 결과를 보고.-f,--failfast— 첫 오류나 실패에서 테스트 실행을 중지.-k— 패턴이나 부분 문자열과 일치하는 테스트 메서드와 클래스만 실행.--locals— traceback에서 지역 변수를 표시.--durations N— 가장 느린 N개 테스트 케이스 표시(N=0이면 전부).
테스트 발견 (Test Discovery)
unittest는 간단한 테스트 발견을 지원해요. 테스트 발견과 호환되려면 모든 테스트 파일이 프로젝트의 최상위 디렉터리에서 import 가능한 모듈 또는 패키지여야 해요(파일 이름이 유효한 식별자여야 함을 의미). 테스트 발견은 TestLoader.discover()에 구현되어 있지만 명령줄에서도 사용할 수 있어요:
cd project_directory
python -m unittest discover
python -m unittest는 python -m unittest discover와 동등한 지름길이에요. discover 하위 명령은 다음 옵션을 가져요: -v/--verbose, -s/--start-directory directory(발견 시작 디렉터리, 기본 .), -p/--pattern pattern(테스트 파일 일치 패턴, 기본 test*.py), -t/--top-level-directory directory(프로젝트 최상위 디렉터리).
테스트 발견은 import로 테스트를 로드해요. 시작 디렉터리에서 모든 테스트 파일을 찾으면 경로를 import할 패키지 이름으로 바꿔요.
관련 도구 (Related tools)
- Module doctest — 성격이 매우 다른 또 다른 테스트 지원 모듈
- pytest — 더 가벼운 문법의 서드파티 unittest 프레임워크
- The Python Testing Tools Taxonomy — 기능 테스트 프레임워크와 mock 객체 라이브러리를 포함한 광범위한 Python 테스트 도구 목록
- Tools/unittestgui/unittestgui.py — 테스트 발견과 실행용 GUI 도구
TestLoader, TestCase, TestSuite, TestResult 같은 클래스와 다양한 assert 메서드(assertEqual, assertTrue, assertRaises, assertIn, assertAlmostEqual, assertIsInstance, assertRegex 등)가 프레임워크의 핵심 구성 요소예요.