Logo

[파이썬] 단위 테스트의 기본 (unittest)

어느 언어로 코딩을 하든 단위 테스트는 신뢰할 수 있는 애플리케이션을 개발하기 위해서 필수적으로 습득해야하는 기술입니다. 파이썬에서는 내장 모듈인 unittest을 통해서 다른 라이브러리 없이 비교적 간단하게 단위 테스트를 작성할 수 있습니다.

unittest 모듈

unittest 모듈은 Java의 JUnit, JavaScript의 Jest 또는 Mocha와 같은 단위 테스트 프레임워크입니다. 다만 다른 언어와 달리 기본적으로 언어에 내장되어 있기 때문에 파이썬만 설치가 되어 있다면 바로 모듈을 불러와서(import) 사용할 수 있습니다.

import unittest

# 바로 단위 테스트 작성

TestCase 클래스

unittest 모듈의 TestCase 클래스는 단위 테스트에 필요한 다양한 유틸리티 메소드를 제공합니다. 따라서 새로운 테스트를 작성할 때는 TestCase 클래스를 상속하는 클래스를 먼저 작성해야 합니다. 그리고 그 클래스 안에 테스트를 수행하는 로직을 메서드로 추가해주면 됩니다.

예를 들어, 12를 더해서, 3이 나오는지를 검증하는 테스트는 다음과 같이 작성할 수 있습니다.

  • my_tests.py
from unittest import TestCase


class MyTests(TestCase):
    def test_one_plus_two(self):
        self.assertEqual(1 + 2, 3)

여기서 주의할 점은 테스트 메서드의 이름은 반드시 test로 시작을 해야 한다는 것입니다. 그래야 테스트를 실행할 때 해당 메서드가 누락되지 않고 정확히 테스트 케이스로 인식이 됩니다.

테스트 실행

작성한 테스트는 터미널에서 간단하게 실행해볼 수 있습니다.

$ python -m unittest my_tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

테스트 실패

이번에는 한 번 실패하는 테스트를 작성해보겠습니다. 1 + 2의 결과 값으로 3 대신에 5를 넘겨보겠습니다.

from unittest import TestCase


class MyTests(TestCase):
    def test_one_plus_two(self):
        self.assertEqual(1 + 2, 5)

다시 테스트를 실행해보면 테스트가 실패했다고 피드백을 줍니다.

$ python -m unittest my_tests.py
F
======================================================================
FAIL: test_one_plus_two (my_tests.MyTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dale/examples/python-unittest-testcase/my_tests.py", line 6, in test_one_plus_two
    self.assertEqual(1 + 2, 5)
AssertionError: 3 != 5

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

asseretion 메소드

unittest 모듈의 TestCase 클래스는 assertEqual 말고도 assert로 시작하는 많은 메서드를 제공합니다. 그 중에서 많이 쓰이는 메서드를 이용해서 테스트를 추가로 작성해보았습니다.

from unittest import TestCase


class MyTests(TestCase):
    def test_one_plus_two(self):
        self.assertEqual(1 + 2, 3)

    def test_other_assertions(self):
        self.assertTrue(1 == 1)
        self.assertFalse(1 == 2)
        self.assertGreater(2, 1)
        self.assertLess(1, 2)
        self.assertIn(1, [1, 2])
        self.assertIsInstance(1, int)

MyTests 클래스는 TestCase 클래스를 상속하고 있기 때문에 부모 클래스인 TestCase가 제공하는 모든 메서드를 self를 통해 접근하여 호출할 수 있습니다.

작성한 테스트를 실행해보면 이번에는 두개의 메서드가 통과했기 때문에 점(.)이 2개가 찍히는 것을 알 수 있습니다. 테스트가 성공했을 때는 일반적으로 세부 사항이 크게 관심이 없기 때문에 이렇게 기본적인 피드백만 주도록 되어있습니다.

$ python -m unittest my_tests.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

참고로 이렇게 점(.) 대신에 좀 더 자세한 피드백을 받고 싶다면 -v 옵션을 붙여서 테스트를 실행하면 됩니다.

$ python -m unittest -v my_tests.py
test_one_plus_two (my_tests.MyTests) ... ok
test_other_assertions (my_tests.MyTests) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

파일의 일부로 테스트 실행

매번 터미널에 긴 커맨드를 쓰기가 불편하다면 파일이 실행될 때 테스트를 실행할 수 있습니다. 파일 제일 하단에 다음과 같이 unittest 모듈의 main 메서드를 호출해주면 됩니다.

from unittest import TestCase, main


class MyTests(TestCase):
    def test_one_plus_two(self):
        self.assertEqual(1 + 2, 3)


if __name__ == '__main__':
    main()

이제 그냥 파일만 실행하면 테스트가 실행됩니다.

$ python my_tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

예외 발생 테스트

예외가 발생하는지를 검증해야 할 때는 assertRaises(exception) 메서드를 사용합니다. context manager(컨텍스트 매니저)를 리턴하기 때문에 사용법이 약간 생소할 수 있는데요.

with self.assertRaises(예상 예외): 식으로 발생해야하는 예외를 먼저 명시하고, 실제로 그 예외를 일으켜야 하는 로직을 with 절 안에 들여쓰기 하여 작성해주면 됩니다.

class MyTests(TestCase):
    def test_exceptions(self):
        with self.assertRaises(ZeroDivisionError):
            1 / 0
        with self.assertRaises(TypeError):
            1 + '2'

전체 코드

https://github.com/DaleSeo/examples/tree/master/python-unittest-testcase

마치면서

이상으로 파이썬의 unittest 모듈을 이용해서 테스트를 작성하는 매우 기본적인 방법에 대해서 알아보았습니다. unittest 모듈에 대한 좀 더 자세한 내용은 아래 공식 레퍼런스를 참고바라겠습니다.