TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 웹개발>

[파이썬] 플라스크(Flask) - 테스팅(testing)

by 기록자_Recordian 2024. 7. 22.
728x90
반응형
시작에 앞서
해당 내용은 <가장 빠른 풀스택을 위한 Flask & FastAPI>, Dave Lee 지음. BJ Public 출판.
내용을 토대로 작성되었습니다. 보다 자세한 사항은 해당 교재를 참고하시기 바랍니다.

테스팅(testing)

 

[테스팅이란?]

개발한 소프트웨어가 예상대로 작동하는지 검증하는 과정.

버그를 미리 찾아 수정하거나 새로운 기능을 추가했을 때 기존 기능에 문제가 발생하지 않는지 확인하는 과정.

 

테스팅 없이 코드를 배포하면 사용자가 버그를 만나거나 시스템이 예상치 못한 방식으로 작동할 위험이 있다.

테스팅은 이러한 문제를 미리 발견하고, 높은 품질의 소프트웨어를 제공하는 데 도움을 준다.


플라스크에서의 테스팅

 

플라스크에서는 pytest나 플라스크 자체의 unittest를 이용하여 테스팅할 수 있다.

my_app.py라는 파일을 만들고 하단의 코드를 입력하여 저장한다.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello, World!'

 

이 코드를 하단의 명령어로 실행하고

flask --app my_app.py run

 

http://127.0.0.1:5000/ 링크에 접속하면


플라스크 애플리케이션 테스트를 위한 테스트 케이스를 작성해본다. (test_app.py 파일)

※ 테스트 케이스: 특정 기능이 예상한 대로 동작하는지 확인하는 코드

import unittest
from my_app import app # my_app 모듈에서 플라스크 애플리케이션 가져옴

# BasicTestCase 클래스는 unittest.TestCase를 상속받음
class BasicTestCase(unittest.TestCase):
    
    # index 라우트를 테스트하는 메서드
    def test_index(self):
        # 플라스크 애플리케이션을 위한 테스트 클라이언트 인스턴스 생성
        tester = app.test_client(self)
        # 테스트 클라이언트를 사용하여 루트 URL로 GEET 요청
        response = tester.get('/', content_type='html/text')
        # 응답받은 상태 코드가 200인지 확인
        self.assertEqual(response.status_code, 200)

 

[코드 설명]

  • app.test_client() 메서드: 플라스크 애플리케이션을 테스트하기 위한 테스트 클라이언트를 생성
  • 테스트 클라이언트는 실제 웹 서버를 실행하지 않고도 애플리케이션에 요청을 보내고 그 응답을 확인할 수 있게 해줌
  • tester.get() 메서드: 지정된 경로로 HTTP GET 요청을 보내는 데 사용.
  • response.status_code: 서버가 반환한 HTTP 상태 코드 나타냄
  • self.assertEqual() 메서드: unittest의 기능으로, 두 값을 비교하여 같으면 테스트 통과

[테스팅 관련 주요 문법]

  • import unittest: unittest 프레임워크를 가져옴. 파이썬의 표준 라이브러리에 포함되어 있으며 테스트를 작성하고 실행하는 데 필요한 도구 제공
  • unittest.TestCase: 모든 테스트 케이스는 이 클래스를 상속받아야 하며, 여러 가지 어설션 메서드(assertion methods)를 제공하여 테스트를 쉽게 작성할 수 있게 한다
  • 어설션 메서드(assertion methods): unittest.TestCase 클레스가 제공하는 메서드의 한 종류. 테스트 중에 조건이 참인지 확인하기 위해 사용.

★ 기본적인 assertion methods

- assertEqual(a, b): a와 b가 같은지 확인

- assertTrue(x): x가 True 인지 확인

- assertFalse(x): x가 False 인지 확인

- assertRaises(Error): 지정된 예외가 발생하는지 확인

- assertIn(a, b): a가 b 컨테이너에 포함되어 있는지 확인

- assertIsNone(x): x가 None 인지 확인

▶ 이러한 메서드들은 테스트를 작성할 때 기대하는 결과를 명확히 표현하고, 코드가 올바르게 동작하는지 자동으로 검증할 수 있게 해주는 강력한 도구이다.

 

unittest 프레임워크는 테스트 실패 시 테스트 결과에 대한 자세한 정보를 출력하여 디버깅을 돕는다.

  • test_client(): 플라스크 애플리케이션의 테스트 클라이언트 인스턴스 생성. 이를 사용하여 실제 서버를 구동하지 않고도 HTTP 요청을 애플리케이션에 보낼 수 있다
  • get(): 테스트 클라이언트의 메서드. HTTP GET 요청을 보내고 응답을 받는 데 사용된다.
  • assertEqual(): 어설션 메서드 중 하나. 두 값이 같은지 확인하는 메서드. 테스트하려는 값이 예상과 다르면 테스트가 실패한다.

테스트 실행하기

 

작성한 테스트 케이스를 실행하기 위해 터미널에 하단의 명령 입력

python -m unittest test_app.BasicTestCase
  • -m unittest: -m 옵션은 모듈을 스크립트로 실행하려고 할 때 사용. -m unittest 명령은 unittest 모듈을 명령줄에서 실행하도록 한다
  • test_app.BasicTestCase: test_app.py 파일에 정의된 BasicTestCase 클래스를 지정. 해당 클래스 내의 모든 테스트 메서드가 실행된다

해당 명령어를 실행하면 BasicTestCase 클래스에 있는 모든 테스트 메서드가 실행된다.

테스트가 성공적으로 완료되면, 터미널에 'OK' 가 출력된다. (테스트 결과가 예상한 결과와 일치함을 의미)


unittest의 다양한 기능

 

unittest는 파이썬 프로그램을 테스트하는 대표적인 라이브러리로서, 다양한 기능을 갖고 있다.

import unittest
from my_app import app # my_app 모듈에서 플라스크 애플리케이션 가져옴

class AdvancedTestCase(unittest.TestCase):
    
    def setUp(self):
        # 플라스크 애플리케이션의 테스트 클라이언트 생성
        # self.tester는 테스트 동안 사용할 가상의 클라이언트 객체
        self.tester = app.test_client(self)
        
    def tearDown(self):
        # 테스트가 끝난 후 정리 작업 수행. 현재는 비어 있는 상태
        pass
    
    def test_index(self):
        # self.tester 객체를 사용하여 루트 URL('/')로 HTTP GET 요청 보냄
        response = self.tester.get('/', content_type='html/text')
        # 응답의 상태 코드가 200인지 확인
        self.assertEqual(response.status_code, 200)

 

◆ unittest의 주요 메서드

 

setUp() 메서드

  • 테스트 클래스 내에서 각 테스트 메서드가 실행되기 전에 먼저 실행된다
  • 테스트에 필요한 객체 생성, 테스트 환경 구성 등의 작업 수행
  • 위 코드에서는 app.test_client()를 호출하여 self.tester 객체 생성 (테스트를 위한 가상의 클라이언트 역할)

tearDown() 메서드

  • 각 테스트 메서드 실행 후 호출되며, setUp() 에서 생성된 객체를 정리하거나 테스트 환경을 초기 상태로 복구하는 데 사용
  • 데이터베이스 세션을 닫거나 임시 파일을 삭제하는 등의 작업 수행

테스트 메서드

  • test_로 시작하는 메서드는 unittest에 의해 자동으로 테스트 메서드로 인식
  • 이 메서드들 내에서 실제 테스트 수행. (HTTP 요청을 보내고, 응답 확인 등의 작업)

터미널에서 하단의 명령어를 수행하면

python -m unittest test_app.AdvancedTestCase

unittest 테스트 러너가 지정된 테스트 클래스의 모든 테스트 메서드를 자동으로 찾아 실행한다.

- setUp() 메서드는 AdvancedTestCase 클래스의 각 테스트 메서드 실행 전에 self.tester 객체를 생성하여 할당.

- self.tester 객체는 test_index() 메서드에서 루트 URL로 GET 요청을 보내는 데 사용되며, 그 결과로 받은 응답의 상태 코드를 확인하여 테스트가 성공했는지 검증.

 

OK가 출력되면 테스트가 성공적으로 실행된 것을 의미한다.


다수의 테스트 케이스 실행

 

import unittest
from my_app import app # my_app 모듈에서 플라스크 애플리케이션 가져옴

# AdvancedTestCase 클래스는 unittest.TestCase를 상속받아 여러 테스트 케이스를 정의
class AdvancedTestCase(unittest.TestCase):
    
    # setUp 메서드는 각 테스트 메서드를 실행하기 전에 호출
    def setUp(self):
        # self.tester는 플라스크의 test_client 인스턴스를 참조
        # 이를 통해 실제 HTTP 서버를 구동하지 않고도 HTTP 요청 테스트 가능
        self.tester = app.test_client(self)
        
    # test_index 메서드는 루트 경로('/')에 대한 테스트 정의
    def test_index(self):
        # self.tester 객체를 사용하여 루트 URL('/')로 HTTP GET 요청 보냄
        response = self.tester.get('/', content_type='html/text')
        # 응답의 상태 코드가 200인지 확인
        self.assertEqual(response.status_code, 200)
        
    # test_index_text 메서드는 루트 경로의 응답 텍스트를 테스트
    def test_index_test(self):
        # 루트 경로에 GET 요청을 보내고 응답 데이터 검증
        response = self.tester.get('/', content_type='html/text')
        # 응답 데이터가 'Hello, World!'와 일치하는지 바이트 문자열로 확인
        self.assertEqual(response.data, b'Hello, World!')
    
    # test_another_route 메서드는 다른 경로('/another') 에 대한 테스트를 정의
    def test_another_route(self):
        # '/another' 경로에 GET 요청을 보내고 상태 코드를 검증
        response = self.tester.get('/another', content_type='html/text')
        # 해당 경로가 존재하지 않으므로 상태 코드가 404 (찾을 수 없음) 인지 확인
        self.assertEqual(response.status_code, 404)

 

해당 코드를 입력한 후, 터미널의 하단의 명령어를 입력하면

python -m unittest test_app.AdvancedTestCase

AdvancedTestCase 클래스에 정의된 모든 테스트 메서드 (test_ 로 시작하는 메서드)가 실행되며,

모든 테스트가 통과하면 터미널에 OK 가 출력되며,

실패하는 경우에는 실패한 테스트에 대한 정보와 여러 메시지가 출력된다.

728x90
반응형