프로그래밍/Python

테스트 및 디버깅: 단위 테스트(Unit Testing) 완벽 가이드

shimdh 2025. 2. 28. 09:21
728x90

소프트웨어 개발에서 단위 테스트(Unit Testing) 는 각 구성 요소(함수, 클래스, 모듈)가 의도한 대로 작동하는지 확인하는 과정입니다. 단위 테스트를 수행하면 코드 품질을 향상시키고, 버그를 조기에 발견할 수 있으며, 리팩토링 시 기존 기능이 유지되는지 검증할 수 있습니다.

Python에서는 unittest 모듈을 활용하여 쉽고 체계적으로 단위 테스트를 수행할 수 있습니다. 이번 글에서는 단위 테스트의 개념, 중요성, unittest 모듈을 활용한 테스트 방법, 예제 코드, 그리고 실전 팁까지 자세히 다루겠습니다.


1. 단위 테스트란 무엇인가?

🔹 단위 테스트의 정의

단위 테스트(Unit Test)는 소프트웨어의 개별 구성 요소(함수, 클래스, 모듈)를 독립적으로 검증하는 테스트 방법입니다.

🔹 단위 테스트의 목적

✔️ 코드 안정성 확보 – 코드 수정 시 기존 기능이 의도치 않게 변경되는 것을 방지
✔️ 디버깅 속도 향상 – 오류가 발생한 위치를 빠르게 파악 가능
✔️ 리팩토링 시 안정성 유지 – 코드 구조를 개선하더라도 기능이 올바르게 유지되는지 검증
✔️ 자동화된 테스트 환경 구축 – 지속적인 통합 및 배포(CI/CD)에 활용 가능


2. 단위 테스트가 중요한 이유

단위 테스트를 작성하면 개발 및 유지보수 과정에서 다음과 같은 장점이 있습니다.

1) 코드 안정성 향상

  • 새로운 기능을 추가하거나 기존 코드를 수정할 때, 기존 기능이 정상적으로 동작하는지 확인할 수 있습니다.
  • 회귀 테스트(Regression Test) 역할을 하여 버그가 다시 발생하는 것을 방지할 수 있습니다.

2) 유지보수 및 리팩토링 용이

  • 테스트 코드를 작성하면 리팩토링 시 의도하지 않은 기능 변경을 방지할 수 있습니다.
  • 코드가 변경될 때마다 테스트를 실행하여 안정성을 유지할 수 있습니다.

3) 개발 속도 향상

  • 코드 작성 후 직접 실행하며 확인하는 것보다 자동화된 테스트를 실행하는 것이 훨씬 효율적입니다.
  • 개발자들이 빠르게 피드백을 받을 수 있어 디버깅 속도가 빨라집니다.

4) 문서화 기능

  • 테스트 케이스는 코드의 사용법을 설명하는 역할도 합니다.
  • 다른 개발자가 테스트 코드를 보면 해당 기능이 어떻게 동작하는지 쉽게 이해할 수 있습니다.

3. Python unittest 모듈을 활용한 단위 테스트

Python의 표준 라이브러리인 unittest 모듈을 활용하면 쉽게 단위 테스트를 작성할 수 있습니다.

🔹 기본적인 단위 테스트 구조

  1. unittest.TestCase 클래스를 상속받아 테스트 클래스를 생성합니다.
  2. 각 테스트 메소드는 반드시 test_ 로 시작해야 합니다.
  3. assertEqual, assertTrue, assertRaises 등의 assertion 메소드를 사용하여 예상 결과를 검증합니다.

4. 단위 테스트 실습: 계산기 클래스 테스트

우선 간단한 계산기(Calculator) 클래스를 작성한 후, 이를 테스트해 보겠습니다.

🔹 테스트 대상: Calculator 클래스

# 계산기 클래스
class Calculator:
    def add(self, a, b):
        return a + b

    def subtract(self, a, b):
        return a - b

    def multiply(self, a, b):
        return a * b

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

5. unittest를 활용한 단위 테스트 코드

이제 위에서 만든 Calculator 클래스에 대한 단위 테스트를 작성해 보겠습니다.

import unittest

class TestCalculator(unittest.TestCase):

    def setUp(self):
        """각 테스트 전에 실행될 코드"""
        self.calc = Calculator()

    def test_add(self):
        """덧셈 테스트"""
        self.assertEqual(self.calc.add(10, 5), 15)

    def test_subtract(self):
        """뺄셈 테스트"""
        self.assertEqual(self.calc.subtract(10, 5), 5)

    def test_multiply(self):
        """곱셈 테스트"""
        self.assertEqual(self.calc.multiply(10, 5), 50)

    def test_divide_valid(self):
        """나눗셈 테스트 (정상적인 경우)"""
        self.assertEqual(self.calc.divide(10, 2), 5)

    def test_divide_by_zero(self):
        """0으로 나누었을 때 ValueError 발생 테스트"""
        with self.assertRaises(ValueError) as context:
            self.calc.divide(10, 0)
        self.assertTrue('Cannot divide by zero' in str(context.exception))

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

6. 테스트 코드 설명

🔹 핵심 테스트 구성 요소

1️⃣ setUp() 메소드

  • 각 테스트 실행 전에 실행되며, 테스트 환경을 설정하는 역할을 합니다.
  • self.calc = Calculator()를 통해 테스트마다 새로운 객체를 생성합니다.

2️⃣ 각 테스트 메소드 (test_로 시작)

  • test_add(), test_subtract()각각의 연산을 검증하는 개별 테스트 함수를 작성합니다.

3️⃣ Assertion 메소드 활용

  • assertEqual(a, b) → 두 값이 같은지 확인
  • assertRaises(ValueError) → 특정 예외가 발생하는지 확인

7. 추가적인 테스트 기법

단위 테스트를 작성할 때 다음과 같은 기법을 활용하면 더 강력한 테스트를 구성할 수 있습니다.

🔹 1) 여러 개의 입력값을 테스트하기 (파라미터화 테스트)

여러 개의 값을 한 번에 테스트하는 방법입니다.

def test_add_multiple_cases(self):
    test_cases = [(1, 1, 2), (2, 2, 4), (-1, 1, 0)]
    for a, b, expected in test_cases:
        with self.subTest(a=a, b=b):
            self.assertEqual(self.calc.add(a, b), expected)

🔹 2) Mocking을 활용한 외부 의존성 제거

테스트 시 데이터베이스, 네트워크 요청 등의 외부 요소를 제외하고 테스트할 때 unittest.mock을 활용할 수 있습니다.

from unittest.mock import MagicMock

def test_external_dependency(self):
    self.calc.external_service = MagicMock(return_value=42)
    self.assertEqual(self.calc.external_service(), 42)

🔥 결론: 단위 테스트는 필수적인 개발 습관

단위 테스트는 코드 품질을 높이고, 유지보수를 용이하게 하며, 개발 속도를 향상시키는 필수적인 도구입니다.

🎯 핵심 정리

✔️ 단위 테스트는 코드의 개별 구성 요소가 올바르게 작동하는지 검증
✔️ unittest 모듈을 사용하면 간단하고 체계적인 테스트 코드 작성 가능
✔️ 자동화된 테스트 환경을 구축하면 리팩토링과 디버깅이 더욱 쉬워짐

테스트 주도 개발(TDD) 방식으로 코드를 작성하고, 지속적인 테스트 습관을 기르면 더 나은 개발자로 성장할 수 있습니다! 🚀

728x90