Processing math: 100%

프로그래밍 언어/python

unittest, Test-driven develope를 위한 라이브러리

이현찬 2022. 7. 26. 21:46
728x90

Test-driven developTDD는 개발이 끝난 후에 테스트를 진행하는 것이 아니라, 작은 단위의 기능을 수행하는지 여부를 테스트를 통과한 코드를 전체 코드에 리팩토링해 병합하는 방식의 개발 방법을 이야기합니다. TDD의 시작은 unittest를 작성하는 것입니다.

Unit test

  • code를 테스트 하는 것은 bug가 없이 의도한 바를 구현하는데 중요하지만 데이터 사이언스에서 쉽게 간과됨
  • 프로젝트가 커지고 복잡해짐에 따라 예상치 못한 버그가 발생할 가능성이 매우 높음
  • unittest는 작성한 코드가 의도한대로 작동하는지 여부를 검증하는 과정

unit test의 필요성

  • testing을 작성하는 것은 문제가 없이 clean하고 사용성 높은 코드를 작성하는데 필수적임
  • 어느 이상의 양을 가지는 복잡한 코드는 불가피하게 버그를 가지게 됨
  • 의도한 결과를 만드는 코드를 작성하고 유지하는 것은 포괄적인 테스트를 얼마나 잘하는지에 달려있음
  • 더 효율적이고 강건한 코드를 작성할 수 있음

unit test의 원칙

  • Unit test는 독립된 하나의 method에 대해서 이뤄짐
  • 알고있는 고정된 input과 output에 대해서 테스트를 진행해야 함

Assertion

  • 이전 assertion에 관한 내용을 포스팅에서 확인할 수 있습니다.
  • 주어진 조건의 참 거짓을 확인하고 에러를 발생시키는 assertion을 이용하는 것이 가장 기본적인 방법
  • def apply_discount(product, discount): price = int(product['price'] * (1 - discount)) assert 0 <= price <= product['price'], 'Invalid Discount!!!' #Assertion here return price

unittest libs

  • test는 각각 unit에 대해서 독립적으로 실행하고, 메모리를 효율적으로 관리할 수 있도록 해야함
  • 이를 위해 python의 내장라이브러리인 unittest를 사용할 수 있음

unittest 작성

  • 테스트를 하고자하는 함수를 포함한 스크립트 functions.py와 테스트를 위한 스크립트 test_functions.py가 필요
  • test_functions.pyunittest.TestCase를 상속받는 새로운 클래스를 만들어 코드를 실행
  • 만든 클래스에서 테스트할 method의 이름 앞에 test를 붙여 새로 정의해야 test가 진행됨
  • method의 output과 예상한 기대값 expected를 비교해 assert을 발생시킴
  • unittest.TestCase에 정의되어있는 여러 종류의 assert를 활용할 수 있다.1

setUp tearDown3

  • unittest로 작성된 테스트는 method별로 독립적으로 수행되지만 모든 테스트의 시작과 끝에서 같은 명령을 수행하고자 할 수 있음
  • setUp : 각 test 전에 수행할 명령어 / 변수 선언, data base 활성화 등의 작업을 수행
  • tearDown : 각 test 후에 수행할 명령어 / test 이전의 상황으로 돌려놓는 모든 종류의 명령 수행

Edge case 테스트 4

  • 코드를 작성한 후에 최소한 두가지 케이스에 대해 테스트를 진행을 해야함
    1. 안정적으로 작동을 해야하는 케이스
    2. 입력값으로 주어질 수 있는 케이스 중 extreme한 케이스edgecase
  • 어떤 경우를 edge case로 정의할지와 같은 어려움이 있지만 다양한 edge case에 대한 테스트는 전체적인 프로그램의 신뢰성에 큰 도움이 됨

Example

  • 공부한 내용을 적용해보기 위해 python 언어 강의 과제를 활용해 unittest 연습을 해봄
  • 연도를 입력받아 윤년인지 아닌지 알려주는 프로그램

import check_module
import output_message
print("""This program will tell you if a year is a leap year or not
Type in a year equal to or greater than 0.
It terminates if the year is 0.
""")
while True:
print"=========================================="
year = intinput(Typeinapositiveinteger:)
leap_year = None
# check positive number
if not check_module.validity_checkyear:
continue
# check leak year
leap_year = check_module.leap_year_checkyear
# Print information
output_message.print_resultyear,leapyear
if year ==0:
break
print"==========================================\n\n\n"
  • main 코드는 다음과 같음
    1. 입력으로 0을 받으면 프로그램을 종료
    2. 0이 아니고 양의 정수가 아닌 입력을 받으면 입력이 아니라는 메시지를 띄우고 다시 입력을 받음
    3. 양의 정수인 입력에 대해 윤년 인지 아닌지 여부를 알려줌

def validity_checkyear:
if year < 0 or intyear != year:
printf"yearisnotavalidinput"
printTryagain.
return False
else :
printf"yearisavalidinput"
return True
def leap_year_checkyear:
if (year and year) or year:
leap_year = True
else :
leap_year = False
return leap_year
view raw check_module.py hosted with ❤ by GitHub
  • 각 기능을 수행하는 코드는 check_module에 함수로 만듬
    1. validity_check는 입력이 음수이거나 정수가 아닐 때 메시지를 print하고 False를, 양의 정수 입력은 True를 return
    2. leak_year_check는 입력이 윤년인 경우 True를 return

import unittest
import check_module as check
class TestModuleunittest.TestCase:
def setUpself:
self.year = 2000
def tearDownself:
printtearDown
def test_validity_checkself:
expected = True
answer = check.validity_checkself.year
self.assertEqualanswer,expected
def test_leap_year_checkself:
expected = True
answer = check.leap_year_checkself.year
self.assertEqualanswer,expected
if __name__ == '__main__':
unittest.main
  • 이 모듈의 함수들을 테스트하기 위한 코드를 위와 같이 작성
    1. setUp에서 각 테스트를 시작하기 전에 공통적으로 실행할 코드로 입력 연도를 선언
    2. testDown에서 각 테스트를 마친 후에 실행시킬 코드 작성
    3. test_로 시작하는 테스트 메소드를 정의
  • 오류가 없는 경우에는 마지막에 커멘드 상에 OK만 출력됨

  • 오류가 발생한 경우에는 오류가 발생한 위치를 띄워줌


Reference

[1] unittest docs
[2] Leveling Up Your Python Code: The Importance of Testing - medium
[3] Explain the “setUp” and “tearDown” Python methods used in test cases - stack overflow
[4] Tips for How to Succeed in Coding Interviews - medium
[5] Introduction to Unit Testing in Python Using unittest Framework - medium
[6] Effective Unit Testing by Eliotte Rusty Harold - youtube