프로그래밍/Python

[python] TestCase를 활용한 기본적인 유닛 테스트 작성하기

채윤아빠 2024. 7. 21. 16:30

개요

안녕하세요. 오늘은 Python에서 unittest 모듈의 TestCase를 활용하여 기본적인 테스트 케이스를 작성하는 방법에 대해 알아보겠습니다.

Python의 unittest는 단위 테스트를 위한 표준 라이브러리입니다. 이 모듈은 테스트 자동화, 테스트 코드 설정 및 종료 공유, 테스트를 컬렉션으로 집계하는 기능을 제공합니다.

unittest의 핵심은 TestCase 클래스입니다. 이 클래스를 상속하여 테스트 케이스를 작성합니다.


TestCase 기본 사용법

TestCase를 사용하기 위해서는 먼저 unittest 모듈을 임포트해야 합니다.

다음은 간단하게 문자열 함수를 시험하는 테스트 케이스 예제입니다.

from unittest import main, TestCase


class TestStringMethods(TestCase):

    def test_upper(self) -> None:
        self.assertEqual('hello'.upper(), 'HELLO')

    def test_isupper(self) -> None:
        self.assertTrue('HELLO'.isupper())
        self.assertFalse('Hello'.isupper())

    def test_split(self) -> None:
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # split 시 separator를 지정하는 경우
        self.assertEqual(s.split('o'), ['hell', ' w', 'rld'])


if (__name__ == '__main__'):
    main()

위 소스를 실행하면 다음과 같은 결과가 표시됩니다.

...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

테스트 메소드 작성 규칙

TestCase 클래스에서 테스트 메소드는 항상 'test'로 시작해야 합니다. 이 명명 규칙을 통해 unittest는 어떤 메소드가 테스트인지 식별합니다.

각 테스트 메소드는 독립적으로 실행되며, 테스트 간에 상태가 공유되지 않습니다.


setUp과 tearDown 메소드

테스트 메소드 실행 전후에 특정 작업을 수행하고 싶다면 setUp과 tearDown 메소드를 활용할 수 있습니다.

from unittest import main, TestCase


def create_database_connection() -> Connection:
    # 데이터베이스 연결 만들기
    # ...
    pass


class TestDatabase(TestCase):

    def setUp(self) -> None:
        # 각 테스트 메소드 실행 전에 호출됩니다.
        self._connection = create_database_connection()

    def tearDown(self) -> None:
        # 각 테스트 메소드 실행 후에 호출됩니다.
        self._connection.close()

    def test_database_query(self) -> None:
        result = self._connection.execute("SELECT * FROM users")
        self.assertIsNotNone(result)


if (__name__ == '__main__'):
    main()

주요 assertion 메소드

TestCase 클래스는 다양한 assertion 메소드를 제공합니다.

assertion 메소드 설명
assertEqual(a, b) a와 b가 같은지 확인합니다.
assertNotEqual(a, b) a와 b가 다른지 확인합니다.
assertTrue(x) x가 True인지 확인합니다.
assertFalse(x) x가 False인지 확인합니다.
assertIs(a, b) a가 b와 동일한 객체인지 확인합니다.
assertIsNot(a, b) a가 b와 다른 객체인지 확인합니다.
assertIsNone(x) x가 None인지 확인합니다.
assertIsNotNone(x) x가 None이 아닌지 확인합니다.
assertIn(a, b) a가 b에 포함되어 있는지 확인합니다.
assertNotIn(a, b) a가 b에 포함되어 있지 않은지 확인합니다.
assertRaises(exception, callable, *args, **kwds) 특정 예외가 발생하는지 확인합니다.

예외 테스트

함수가 특정 조건에서 예외를 발생시키는지 테스트하기 위해 assertRaises를 사용할 수 있습니다.

from unittest import main, TestCase


def divide(a, b) -> float:
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b


class TestDivision(TestCase):

    def test_division(self) -> None:
        self.assertEqual(divide(10, 2), 5)

    def test_zero_division(self) -> None:
        # divide(10, 0)이 ValueError를 발생시키는지 확인합니다.
        with self.assertRaises(ValueError):
            divide(10, 0)


if (__name__ == '__main__'):
    main()

테스트 실행하기

테스트를 실행하는 방법은 여러 가지가 있습니다.

파이썬 스크립트로 직접 실행

python test_module.py

unittest 명령줄 인터페이스 사용

python -m unittest test_module

특정 테스트 클래스나 메소드만 실행

python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

테스트 작성 권장 방법

테스트 메소드를 작성할 때 다음 사항들을 고민하여 작성하면 프로그램의 안정성 및 유지보수성 등을 높이는데 유리합니다.

  • 각 테스트 메소드는 하나의 기능만 테스트합니다.
  • 테스트 메소드 이름은 테스트하는 내용을 명확히 나타냅니다.
  • 테스트는 독립적이고 반복 가능해야 합니다.
  • 테스트 코드도 실제 코드처럼 깔끔하게 작성합니다.
  • 테스트 커버리지를 높이기 위해 다양한 경계 조건을 테스트합니다.

맺는말

이상으로 Python의 unittest 모듈과 TestCase 클래스를 활용한 기본적인 테스트 작성법에 대해 알아보았습니다. 테스트 코드는 프로그램의 안정성을 높이고 리팩토링을 용이하게 만드는 중요한 요소입니다. 작은 프로젝트부터 테스트 코드 작성을 습관화하면 큰 도움이 될 것입니다.

Python unittest는 이외에도 더 많은 기능을 제공하니, 공식 문서를 참조하여 필요한 기능을 활용해 보시기 바랍니다.

끝까지 읽어주셔서 감사합니다!


728x90
반응형