매일 업데이트
2022-11-12 22:56 9 min

Python unittest 모듈을 사용한 단위 테스트

개발자의 필수 덕목: 철저한 단위 테스트

훌륭한 개발자라면 코드 배포 전 철저한 테스트를 거치는 것은 필수입니다. 특히 단위 테스트는 대규모 프로그램에서 개별 모듈을 검증하는 중요한 과정입니다.

본 글에서는 Python의 `unittest` 모듈을 활용하여 코드의 단위 테스트를 실행하는 방법을 자세히 알아봅니다. 먼저 테스트 유형에 대한 기본적인 이해부터 시작해 보겠습니다.

테스트는 크게 수동 테스트와 자동 테스트로 나눌 수 있습니다. 수동 테스트는 개발이 완료된 후 사람이 직접 테스트를 수행하는 방식이며, 자동 테스트는 프로그램이 자동으로 테스트를 실행하고 그 결과를 제공하는 방식입니다.

수동 테스트는 많은 시간과 노력이 소요되므로, 개발자들은 코드 테스트를 자동화하는 방향으로 나아가고 있습니다. 자동 테스트에는 단위 테스트, 통합 테스트, 엔드 투 엔드 테스트, 스트레스 테스트 등 다양한 종류가 있습니다.

일반적인 테스트 흐름은 다음과 같습니다.

  • 코드를 작성하거나 수정합니다.
  • 해당 코드에 대한 다양한 테스트 시나리오를 추가하거나 업데이트합니다.
  • 테스트를 실행합니다 (수동 또는 테스트 러너 사용).
  • 테스트 결과를 확인하고, 오류가 발견되면 코드를 수정하고 테스트를 다시 실행합니다.

본 글에서는 단위 테스트라는 가장 기본적이고 중요한 테스트 유형에 대해 집중적으로 다룰 것입니다. 더 이상 지체하지 않고 바로 실습 튜토리얼로 들어가 봅시다.

단위 테스트란 무엇인가?

단위 테스트는 독립적인 코드 블록을 검증하는 방법입니다. 일반적으로 '코드 블록'은 함수를 의미하며, '독립적'이라는 것은 해당 코드가 프로젝트 내 다른 코드에 의존하지 않는다는 것을 의미합니다.

예를 들어, 주어진 문자열이 "koreantech.org"와 같은지 확인하는 함수를 생각해 봅시다. 이 함수는 문자열을 인자로 받아 "koreantech.org"와 비교한 결과를 반환합니다.

  
  def is_equal_to_geekflare(string):
   return string == "koreantech.org"
  
 

위 함수는 다른 코드에 종속되지 않으므로, 다양한 입력을 제공하여 독립적으로 테스트할 수 있습니다. 이렇게 독립적인 코드 조각은 프로젝트 전체에서 재사용될 수 있습니다.

단위 테스트의 중요성

독립적인 코드 블록은 프로젝트 전체에서 널리 사용될 가능성이 높으므로, 신중하게 작성하고 테스트해야 합니다. 단위 테스트는 이러한 독립적인 코드 블록을 검증하는 데 필수적인 도구입니다. 단위 테스트를 생략하면 어떻게 될까요?

만약 프로젝트에서 여러 곳에 사용되는 핵심 코드 블록을 제대로 테스트하지 않으면, 통합 테스트나 엔드 투 엔드 테스트와 같은 다른 테스트들이 실패할 가능성이 높아집니다. 이는 곧 애플리케이션 전체의 오류로 이어질 수 있습니다. 따라서 코드의 기본 구성 요소를 철저히 테스트하는 것이 매우 중요합니다.

이제 모든 독립적인 코드 블록에 대한 단위 테스트의 필요성을 이해했을 것입니다. 단위 테스트를 성공적으로 수행하면, 다른 테스트 단계에서 핵심 코드 블록으로 인한 오류 발생 가능성을 크게 줄일 수 있습니다.

다음 섹션에서는 Python의 `unittest` 모듈이 무엇인지, 그리고 이를 사용하여 단위 테스트를 작성하는 방법을 자세히 살펴보겠습니다.

참고: Python의 클래스, 모듈 등에 대한 기본적인 지식이 있다고 가정합니다. 관련 개념에 익숙하지 않다면 다음 내용을 이해하기 어려울 수 있습니다.

Python unittest 란 무엇인가?

Python `unittest`는 Python 코드를 테스트하기 위해 특별히 설계된 내장 프레임워크입니다. 테스트 실행 기능을 제공하므로, 별도의 노력 없이 테스트를 수행할 수 있습니다. 즉, 외부 라이브러리 없이도 내장 모듈을 사용하여 테스트를 시작할 수 있습니다. 물론 필요에 따라 외부 라이브러리를 사용할 수도 있습니다. 하지만 `unittest` 모듈은 Python에서 테스트를 시작하기에 매우 적합합니다.

`unittest` 모듈을 사용하여 Python 코드를 테스트하려면 다음과 같은 단계를 따릅니다.

#1. 테스트할 코드를 작성합니다.

#2. `unittest` 모듈을 가져옵니다.

#3. `test`로 시작하는 이름의 파일을 만듭니다. 예를 들어 `test_prime.py`와 같이 이름 짓습니다. `test` 키워드는 테스트 파일을 식별하는 데 사용됩니다.

#4. `unittest.TestCase` 클래스를 상속하는 테스트 클래스를 생성합니다.

#5. 클래스 내에 테스트 메소드를 정의합니다. 각 메소드는 특정 테스트 시나리오를 다룹니다. 메소드 이름은 `test` 키워드로 시작해야 합니다.

#6. 테스트를 실행합니다. 테스트 실행 방법에는 여러 가지가 있습니다.

  • `python -m unittest test_filename.py` 명령어를 사용하여 실행합니다.
  • `python test_filename.py` 명령어를 사용하여 일반 Python 파일처럼 실행합니다. 이 방법은 테스트 파일 내에서 `unittest` 모듈의 기본 메소드를 호출해야 합니다.
  • `python -m unittest discover` 명령어를 사용하여 테스트 파일을 자동으로 찾아 실행할 수 있습니다. 이 명령어는 `test` 키워드로 시작하는 파일 이름을 기준으로 테스트 파일을 검색합니다.

일반적으로 테스트에서는 코드의 결과와 예상 결과를 비교합니다. 이를 위해 `unittest` 모듈은 다양한 비교 메소드를 제공합니다. 비교 메소드 목록은 여기에서 확인할 수 있습니다.

이러한 메소드는 매우 간단하고 쉽게 이해할 수 있습니다.

이론적인 설명은 이쯤에서 마무리하고, 이제 실제 코딩을 시작해 봅시다.

참고: `unittest` 모듈에 대한 추가 정보가 필요하면, 공식 문서를 참조하여 궁금증을 해결할 수 있습니다. 더 지체하지 말고, 지금 바로 `unittest` 모듈을 사용해 봅시다.

unittest를 이용한 Python 단위 테스트 실습

먼저 몇 가지 함수를 작성한 후, 테스트 코드를 작성하는 데 집중하겠습니다. 여러분이 선호하는 코드 편집기를 열고 `utils.py`라는 파일을 생성합니다. 그리고 다음 코드를 파일에 붙여넣습니다.

  
  import math
  def is_prime(n):
   if n < 0:
    return 'Negative numbers are not allowed'
   if n <= 1:
    return False
   if n == 2:
    return True
   if n % 2 == 0:
    return False
   for i in range(2, int(math.sqrt(n)) + 1):
    if n % i == 0:
     return False
   return True
  def cubic(a):
   return a * a * a
  def say_hello(name):
   return "Hello, " + name
  
 

`utils.py` 파일에는 세 개의 함수가 정의되어 있습니다. 이제 각 함수를 다양한 테스트 시나리오로 검증해야 합니다. 먼저 `is_prime` 함수에 대한 테스트 코드를 작성해 보겠습니다.

#1. `utils.py`와 동일한 폴더에 `test_utils.py` 파일을 생성합니다.

#2. `utils`와 `unittest` 모듈을 import 합니다.

#3. `unittest.TestCase` 클래스를 상속하는 `TestUtils` 클래스를 생성합니다. 클래스 이름은 원하는 대로 지정할 수 있지만, 의미 있는 이름을 사용하는 것이 좋습니다.

#4. 클래스 내부에 `self`를 인자로 받는 `test_is_prime` 메소드를 정의합니다.

#5. `is_prime` 함수에 다양한 인수를 적용하여 여러 테스트 케이스를 작성하고, 반환 값을 예상 결과와 비교합니다.

#6. 예를 들어, `self.assertFalse(utils.is_prime(1))` 과 같은 테스트 케이스를 작성합니다.

#7. 위 코드는 `is_prime(1)`의 결과가 `False`일 것으로 예상한다는 의미입니다.

#8. 테스트할 함수에 따라 다양한 테스트 케이스를 추가합니다.

다음은 작성된 테스트 코드입니다.

  
  import unittest
  import utils
  class TestUtils(unittest.TestCase):
   def test_is_prime(self):
    self.assertFalse(utils.is_prime(4))
    self.assertTrue(utils.is_prime(2))
    self.assertTrue(utils.is_prime(3))
    self.assertFalse(utils.is_prime(8))
    self.assertFalse(utils.is_prime(10))
    self.assertTrue(utils.is_prime(7))
    self.assertEqual(utils.is_prime(-3),
              "Negative numbers are not allowed")
  if __name__ == '__main__':
   unittest.main()
  
 

`python filename.py` 명령으로 테스트를 실행하기 위해, `unittest` 모듈의 `main` 메소드를 호출합니다. 이제 테스트를 실행해 봅시다.

다음과 유사한 결과가 표시됩니다.

  
  $ python test_utils.py
  .
  ----------------------------------------------------------------------
  Ran 1 test in 0.001s
  OK
  
 

이제 다른 함수들에 대한 테스트 케이스도 작성해 봅시다. 각 함수에 대한 다양한 시나리오를 고려하여 테스트 코드를 작성해야 합니다. 다음은 위 클래스에 추가된 테스트 코드입니다.

  
  ...
  class TestUtils(unittest.TestCase):
   def test_is_prime(self):
    ...
   def test_cubic(self):
    self.assertEqual(utils.cubic(2), 8)
    self.assertEqual(utils.cubic(-2), -8)
    self.assertNotEqual(utils.cubic(2), 4)
    self.assertNotEqual(utils.cubic(-3), 27)
   def test_say_hello(self):
    self.assertEqual(utils.say_hello("koreantech.org"), "Hello, koreantech.org")
    self.assertEqual(utils.say_hello("Chandan"), "Hello, Chandan")
    self.assertNotEqual(utils.say_hello("Chandan"), "Hi, Chandan")
    self.assertNotEqual(utils.say_hello("Hafeez"), "Hi, Hafeez")
  ...
  
 

여기서는 `unittest` 모듈의 비교 함수 중 일부만 사용했습니다. 전체 목록은 여기에서 확인할 수 있습니다.

이제 `unittest` 모듈을 사용하여 단위 테스트를 작성하는 방법을 배웠습니다. 다음으로는 테스트를 실행하는 다양한 방법을 알아보겠습니다.

unittest를 사용하여 테스트를 실행하는 방법

앞선 섹션에서 이미 테스트를 실행하는 한 가지 방법을 살펴보았습니다. 이제 `unittest` 모듈을 사용하여 테스트를 실행하는 다른 두 가지 방법을 소개합니다.

#1. 파일 이름과 `unittest` 모듈 사용

이 방법은 `unittest` 모듈과 테스트 파일 이름을 함께 사용하여 테스트를 실행합니다. 테스트 실행 명령어는 `python -m unittest filename.py` 입니다. 따라서 이 경우 명령어는 `python -m unittest test_utils.py` 입니다.

#2. Discover 메소드 사용

`unittest` 모듈의 `discover` 메소드를 사용하면 모든 테스트 파일을 자동으로 찾아 실행할 수 있습니다. 자동으로 테스트 파일을 찾기 위해서는 파일 이름을 `test` 키워드로 시작해야 합니다.

`discover` 메소드를 사용하여 테스트를 실행하는 명령어는 `python -m unittest discover` 입니다. 이 명령어는 이름이 `test`로 시작하는 모든 파일을 찾아 실행합니다.

결론 👩‍💻

단위 테스트는 프로그래밍 세계에서 가장 기본적인 테스트입니다. 실제로는 훨씬 더 다양한 테스트들이 존재합니다. 앞으로 차근차근 학습해 나가면 됩니다. 이 튜토리얼이 `unittest` 모듈을 사용하여 Python에서 기본적인 테스트를 작성하는 데 도움이 되었기를 바랍니다. `pytest`, `Robot Framework`, `nose`, `nose2`, `slash` 등과 같은 외부 라이브러리도 존재하니, 프로젝트 요구 사항에 따라 필요한 라이브러리를 선택하여 활용할 수 있습니다.

즐거운 테스트 되세요! 😎

Python 인터뷰 질문 및 답변에도 관심이 있을 수 있습니다.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.