Django Web Framework/Django Pytest

pytest에서 class를 사용할 때 이점을 보여주는 경우에 대한 정리

bluebamus 2023. 6. 8.

* 해당 글은 문뜩 class로 pytest를 좀 더 효율적으로 사용할 수 있는 방법이 있지 않을까란 생각에 chatGPT로 대화를 나누다 얻은 코드로 정리 및 기록으로 남겨야 겠다는 의지로 작성함

 

1. 테스트 클래스를 사용할때 얻을 수 있는 이점

   1. 구성 구조: 클래스는 관련 테스트 방법을 함께 구성하는 데 도움이 될 수 있습니다. 이렇게 하면 특히 복잡한 테스트 시나리오 또는 특정 기능에 대한 여러 테스트 사례를 처리할 때 테스트 스위트를 더 읽기 쉽고 유지 관리할 수 있습니다.


   2. 설정 및 해제: 클래스에서는 setUp 및 tearDown(또는 __init__ 및 __del__)과 같은 특수 메서드를 사용할 수 있습니다. 각 테스트 방법 후. 이것은 코드 중복을 줄이고 테스트 코드를 깨끗하게 유지하는 데 도움이 될 수 있습니다.


   3. 공유 상태: 테스트 클래스는 여러 테스트 메서드 간에 상태를 공유할 수 있습니다. 예를 들어 setUp 메서드에서 테스트 중인 클래스의 인스턴스를 생성할 수 있으며 여러 테스트 메서드에서 각 테스트에 대해 인스턴스를 다시 생성할 필요 없이 이 인스턴스를 사용할 수 있습니다. 이는 설정 프로세스에 비용이 많이 들거나 시간이 많이 소요될 때 유용할 수 있습니다.


   4. 테스트별 픽스처: pytest를 사용하면 픽스처를 사용하여 테스트별 종속성 또는 리소스를 제공할 수 있습니다. 클래스를 사용할 때 클래스 내의 모든 테스트 메서드에서 공유되는 클래스 수준 고정 장치를 정의할 수 있습니다. 이는 여러 테스트 방법에 동일한 고정 장치 세트가 필요한 경우에 유용할 수 있습니다.

 

2. 가상의 시나리오를 기반으로 한 예시

   1. 시나리오 :  전자 상거래 애플리케이션에서 사용자의 쇼핑 카트를 나타내는 ShoppingCart 클래스를 테스트

   2. 코드 : 

# myapp/models.py
class ShoppingCart:
    def __init__(self):
        self.items = []

    def add_item(self, item):
        self.items.append(item)

    def remove_item(self, item):
        self.items.remove(item)

    def calculate_total(self):
        return sum(item.price for item in self.items)


# tests/test_shopping_cart.py
import pytest
from myapp.models import ShoppingCart


@pytest.mark.django_db
class TestShoppingCart:
    @classmethod
    def setup_class(cls):
        cls.shopping_cart = ShoppingCart()

    def teardown_method(self):
        self.shopping_cart.items = []

    def test_add_item(self):
        item = "Product A"
        self.shopping_cart.add_item(item)
        assert item in self.shopping_cart.items

    def test_remove_item(self):
        item = "Product B"
        self.shopping_cart.add_item(item)
        self.shopping_cart.remove_item(item)
        assert item not in self.shopping_cart.items

    def test_calculate_total(self):
        items = ["Product C", "Product D", "Product E"]
        for item in items:
            self.shopping_cart.add_item(item)
        total = self.shopping_cart.calculate_total()
        assert total == pytest.approx(30.0, rel=1e-2)

   1. 구성 구조: TestShoppingCart 클래스는 관련 테스트 메서드(test_add_item, test_remove_item, test_calculate_total)를 함께 구성하여 테스트 메서드의 수가 증가함에 따라 테스트 스위트를 더 쉽게 이해하고 유지 관리할 수 있도록 합니다.

 

   2. 설정 및 해제: setup_class 메서드는 테스트 메서드가 실행되기 전에 ShoppingCart 클래스(self.shopping_cart)의 인스턴스를 생성하는 클래스 수준 설정 메서드입니다. teardown_method 메서드는 각 테스트 메서드 후에 장바구니의 항목 목록을 재설정하여 각 테스트에 대해 깨끗한 상태를 보장하는 테스트 메서드별 분해 메서드입니다.

 

   3. 공유 상태: self.shopping_cart 인스턴스는 TestShoppingCart 클래스 내의 모든 테스트 메서드 간에 공유됩니다. 이를 통해 테스트 메서드가 동일한 장바구니 인스턴스에서 작동할 수 있으므로 각 테스트 메서드에 대해 다시 생성할 필요가 없습니다.

 

   4. 테스트 관련 고정 장치: 이 예제에서는 고정 장치의 사용을 명시적으로 보여주지 않았지만 pytest는 클래스 수준에서 고정 장치의 정의를 허용합니다. 클래스 수준 픽스처는 클래스 내의 여러 테스트 메서드에 필요한 공유 종속성 또는 리소스를 제공하는 데 사용할 수 있습니다.

 

3. setup_class 및 teardown_method 함수에 대해 자세히 살펴보기

   1. setup_class(cls): 이것은 pytest의 클래스 수준 설정 방법입니다. @classmethod 데코레이터를 사용하여 TestShoppingCart 클래스 내의 클래스 메소드로 정의됩니다. 이 메서드의 목적은 클래스 내의 모든 테스트 메서드 간에 공유되어야 하는 필수 리소스 또는 상태를 설정하는 것입니다. 이 경우에는 ShoppingCart 클래스의 인스턴스를 생성하고 클래스 속성 shopping_cart에 할당합니다.

      1. 실행: setup_class 메소드는 클래스 내의 테스트 메소드가 실행되기 전에 자동으로 한 번 실행됩니다.

          TestShoppingCart 클래스에 대한 전체 테스트 실행 중에 한 번만 호출됩니다.


   2. teardown_method(self): pytest의 테스트별 메서드 분해 방법입니다. 'TestShoppingCart' 클래스 내의 인스턴스 메서드로 정의됩니다. 이 메서드의 목적은 테스트 메서드를 실행하는 동안 수정되었을 수 있는 리소스나 상태를 정리하는 것입니다. 이 경우 shopping_cart 인스턴스의 items 목록을 다시 빈 목록으로 재설정합니다.

      1. 실행: teardown_method 메소드는 클래스 내의 각 테스트 메소드가 실행된 후 자동으로 실행됩니다. 다음 테스트가 실행되기 전에 테스트 중에 수정된 사항이 정리되도록 테스트 메서드당 한 번씩 호출됩니다.


   3. 요약:

      1. setup_class는 클래스 내의 테스트 메서드가 실행되기 전에 자동으로 한 번 실행됩니다. 테스트 메서드에 필요한 공유 리소스 또는 상태를 설정합니다.

      2. teardown_method는 클래스 내의 각 테스트 메서드가 실행된 후 자동으로 실행됩니다. 다음 테스트를 위해 깨끗한 상태를 보장하기 위해 테스트 중에 수정된 사항을 정리합니다.

 

      * 이러한 메서드를 사용하면 클래스 수준 설정/해제(클래스당 한 번 실행) 및 테스트 메서드별 설정/해제(각 테스트 메서드 전후에 실행)와 같은 다양한 세분화 수준에서 설정 및 해제 프로세스를 정의하고 제어할 수 있습니다. ). 이는 공유 리소스를 관리하고 테스트를 격리된 상태로 유지하며 테스트 실행 전체에서 깨끗한 상태를 유지하는 데 도움이 됩니다.

댓글