티스토리 뷰
기능 테스트(Functional test, FT)
실제 웹 브라우저를 실행해서 애플리케이션이 어떻게 동작(functions)하는지 사용자 관점에서 확인
용어: 기능 테스트 == 승인 테스트 == 종단간 테스트
Functional Test, Acceptance Test, End-to-End Test로 부르기도 함. 중요한 것은 이 테스트들이 전체 애플리케이션이 어떻게 동작하는지를 외부 사용자 관점에서 확인하는 테스트라는 것. BlackBox 테스트라는 용어를 사용하는 경우도, 시스템 내부에 대해선 전혀 알지 못하기 때문
FT는 사람이 이해할 수 잇ㄴ느 스토리를 가지고 있어야 한다.
이것을 분명하게 정의하기 위해 테스트 코드에 주석을 기록
from selenium import webdriver
browser = webdriver.Firefox()
# 에디스는 멋진 작업 목록 온라인 앱이 나왔다는 소식을 듣고 해당 웹 사이트를 확인하러 간다.
browser.get('http://localhost:8000')
# 웹 페이지 타이틀과 헤더가 'To-Do'를 표시하고 있다.
assert 'To-Do' in browser.title
# 그녀는 바로 작업을 추가하기로 한다.
# "공작깃털 사기"라고 텍스트 상자에 입력한다.
# 엔터키를 치면 페이지가 갱신되고 작업 목록에
# "1: 공작깃털 사기" 아이템이 추가된다.
# 추가 아이템을 입력할 수 있는 여분의 텍스트 상자가 존재한다.
# 다시 "공작깃털을 이용해서 그물 만들기"라고 입력한다.
# 페이지는 다시 갱신되고, 두 개 아이템이 목록에 보인다.
# 에디스는 사이트가 입력한 목록을 저장하고 있는지 궁금하다
# 사이트는 그녀를 위한 특정 URL을 생성해 준다
# 이때 URL에 대한 설명도 함께 제공된다.
# 해당 URL에 접속하면 그녀가 만든 작업 목록이 그대로 있는 것을 확인할 수 있다.
browser.quit()
python manage.py runserver
python functional_tests.py
AssertionError
파이썬 기본 라이브러리의 unittest 모듈
import unittest
from selenium import webdriver
class NewVisitorTest(unittest.TestCase):
"""
unittest.TestCase를 상속해서 테스트를 클래스 형태로 만듬
"""
def setUp(self) -> None:
"""
특수한 메소드
각 테스트 시작 전에 실행
"""
self.browser = webdriver.Firefox()
def tearDown(self) -> None:
"""
특수한 메소드
각 테스트 시작 후에 실행
try/except과 비슷한 구조로 테스트에 에러가 발생해도 실행.(setUp 내에 exception이 있는 경우는 실행 되지 않음)
:return:
"""
self.browser.quit()
def test_can_start_a_list_and_retireve_it_later(self):
"""
테스트 메인 코드는 이 메소드
test라는 명칭으로 시작하는 모든 메소드는 테스트 메소드이며 테스트 실행자에 의해 실행됨.
클래스당 하나 이상의 테스트 메소드를 작성할 수 있다.
가능한 테스트 내용을 알 수 있는 테스트 메소드 명칭을 사용하는 것이 좋다.
"""
# 에디스는 멋진 작업 목록 온라인 앱이 나왔다는 소식을 듣고 해당 웹 사이트를 확인하러 간다.
self.browser.get('http://localhost:8000')
# 웹 페이지 타이틀과 헤더가 'To-Do'를 표시하고 있다.
# unittest는 테스트 assertion을 만들기 위해 assertIn 같은 유용한 함수를 다수 제공
# assertEqual, assertTrue, assertFalse 같은 것
# http://docs.python.org/3/library/unittest.html
self.assertIn('To-Do', self.browser.title)
# 강제적으로 테스트 실패를 발생시켜서 에러 메시지를 출력
self.fail('Finish the test!')
# 그녀는 바로 작업을 추가하기로 한다.
# "공작깃털 사기"라고 텍스트 상자에 입력한다.
# 엔터키를 치면 페이지가 갱신되고 작업 목록에
# "1: 공작깃털 사기" 아이템이 추가된다.
# 추가 아이템을 입력할 수 있는 여분의 텍스트 상자가 존재한다.
# 다시 "공작깃털을 이용해서 그물 만들기"라고 입력한다.
# 페이지는 다시 갱신되고, 두 개 아이템이 목록에 보인다.
# 에디스는 사이트가 입력한 목록을 저장하고 있는지 궁금하다
# 사이트는 그녀를 위한 특정 URL을 생성해 준다
# 이때 URL에 대한 설명도 함께 제공된다.
# 해당 URL에 접속하면 그녀가 만든 작업 목록이 그대로 있는 것을 확인할 수 있다.
if __name__ == '__main__':
# 파이썬 스크립트가 다른 스크립트에 임포트된 것이 아니라 커맨드라인을 통해 실행 됐다는 것을 확인하는 코드
# unittest.main()을 호출해서 unittest 테스트 실행자를 가동
# 이것은 자동으로 파일 내 테스트 클래스와 메소드를 찾아서 실행해 주는 역할
# "warnings='ignore'"는 테스트 작성 시에 발생하는 불필요한 리소스 경고를 제거
unittest.main(warnings='ignore')
python functional_test.py
F
======================================================================
FAIL: test_can_start_a_list_and_retireve_it_later (__main__.NewVisitorTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "functional_test.py", line 43, in test_can_start_a_list_and_retireve_it_later
self.assertIn('To-Do', self.browser.title)
AssertionError: 'To-Do' not found in 'Django: the Web framework for perfectionists with deadlines.'
----------------------------------------------------------------------
Ran 1 test in 7.869s
FAILED (failures=1)
암묵적 대기
implicitly_wait(암묵적 대기) 기능을 setUp에 추가
self.browser.implicitly_wait(3)
필요에 따라 지정한 시간(초 단위)만큼 동작을 대기 상태로 둘 수 있다.
implicitly_wait가 항상 제대로 동작하는 것은 아니다. 복잡한 애플리케이션에서는 '명시적인' 대기 알고리즘을 별도로 작성해야 한다.
git diff
git commit -a -m "success first test and using unittest"
유용한 TDD 개념
- User story
사용자 관점에서 어떻게 애플리케이션이 동작해야 하는지 기술한 것. 기능 테스트 구조화를 위해 사용 - Expected failure
의도적으로 구현한 테스트 실패를 의미
'Test Driven Development' 카테고리의 다른 글
예비 코딩 Spiking (0) | 2019.07.11 |
---|---|
Test Drive Development Process (0) | 2019.07.10 |
Refactoring (0) | 2019.07.10 |
단위 테스트를 이용한 간단한 홈페이지 테스트 (0) | 2019.07.09 |
기능 테스트를 이용한 Django 설치 (0) | 2019.07.08 |