مقدمه

در درس قبل، نحوه تست کردن یک تابع ساده و ایزوله را یاد گرفتیم. اکنون به سراغ تست کردن کلاس‌ها می‌رویم. تست کردن یک کلاس کمی پیچیده‌تر است، زیرا یک کلاس هم داده (اتریبیوت) و هم رفتار (متد) را در خود کپسوله می‌کند و ما باید مطمئن شویم که تمام این بخش‌ها به درستی با هم کار می‌کنند.

یک کلاس برای تست کردن

بیایید یک کلاس ساده برای مدیریت پاسخ‌های یک نظرسنجی بسازیم. این کلاس به ما اجازه می‌دهد تا پاسخ‌های جدید را ذخیره کنیم.

Copy Icon PYTHON
class AnonymousSurvey:
    """Collect anonymous answers to a survey question."""

    def __init__(self, question):
        """Store a question, and prepare to store responses."""
        self.question = question
        self.responses = []

    def show_question(self):
        """Show the survey question."""
        print(self.question)

    def store_response(self, new_response):
        """Store a single response to the survey."""
        self.responses.append(new_response)

این کلاس یک سوال را در سازنده خود دریافت کرده و یک لیست خالی برای ذخیره پاسخ‌ها ایجاد می‌کند. متد store_response یک پاسخ جدید را به این لیست اضافه می‌کند.

نوشتن تست برای کلاس

حالا بیایید یک تست برای کلاس AnonymousSurvey بنویسیم تا مطمئن شویم که متد store_response به درستی کار می‌کند. ما می‌خواهیم بررسی کنیم که آیا یک پاسخ پس از فراخوانی این متد، واقعاً در لیست responses ذخیره می‌شود یا خیر.

Copy Icon test_survey.py
from survey import AnonymousSurvey

def test_store_single_response():
    """Test that a single response is stored properly."""
    question = "What language did you first learn to speak?"
    my_survey = AnonymousSurvey(question)
    my_survey.store_response('English')
    assert 'English' in my_survey.responses

در این تست، ما ابتدا یک نمونه از کلاس AnonymousSurvey می‌سازیم. سپس یک پاسخ را با store_response ذخیره می‌کنیم. در نهایت، با استفاده از assert و عملگر in، بررسی می‌کنیم که آیا پاسخ ما در لیست responses نمونه مورد نظر وجود دارد یا خیر.

اجرای pytest در ترمینال نشان می‌دهد که این تست با موفقیت پاس می‌شود.

فیکسچرها (Fixtures) در pytest

در مثال بالا، ما برای هر تست یک نمونه جدید از AnonymousSurvey ساختیم. اگر تست‌های زیادی داشته باشیم، این کار منجر به تکرار کد می‌شود. «فیکسچرها» یا Fixtures در pytest راهی برای استخراج و به اشتراک‌گذاری کدهای آماده‌سازی تست هستند.

یک فیکسچر، تابعی است که با دکوراتور pytest.fixture@ علامت‌گذاری شده و معمولاً یک شیء را ساخته و آن را برمی‌گرداند. سپس، توابع تست می‌توانند نام این فیکسچر را به عنوان یکی از پارامترهای خود دریافت کرده و از آن شیء آماده استفاده کنند.

Copy Icon test_survey.py
import pytest
from survey import AnonymousSurvey

@pytest.fixture
def language_survey():
    """A survey that will be available to all test functions."""
    question = "What language did you first learn to speak?"
    language_survey = AnonymousSurvey(question)
    return language_survey

def test_store_single_response(language_survey):
    """Test that a single response is stored properly."""
    language_survey.store_response('English')
    assert 'English' in language_survey.responses

def test_store_three_responses(language_survey):
    """Test that three individual responses are stored properly."""
    responses = ['English', 'Spanish', 'Mandarin']
    for response in responses:
        language_survey.store_response(response)

    for response in responses:
        assert response in language_survey.responses

در این نسخه بهبودیافته، ما یک فیکسچر به نام language_survey تعریف کرده‌ایم که یک نمونه آماده از AnonymousSurvey را می‌سازد.

هر دو تابع تست ما این فیکسچر را به عنوان آرگومان دریافت می‌کنند. pytest قبل از اجرای هر تست، فیکسچر را اجرا کرده و مقدار بازگشتی آن را به تابع تست تزریق می‌کند. این کار نه تنها از تکرار کد جلوگیری می‌کند، بلکه باعث می‌شود تست‌های ما تمیزتر و متمرکزتر بر روی منطق اصلی باشند.

در این درس با نحوه نوشتن تست‌های مؤثر برای کلاس‌ها با استفاده از pytest آشنا شدیم. دیدیم که چگونه می‌توانیم با ساختن نمونه‌ها و فراخوانی متدها، رفتار یک کلاس را بررسی کنیم و چگونه با استفاده از فیکسچرها، کدهای تست خود را سازماندهی و تمیز کنیم. با این درس، فصل «آزمایش کدها» به پایان می‌رسد. شما اکنون می‌توانید با نوشتن تست‌های خودکار، از کیفیت و پایداری کدهای پایتون خود اطمینان حاصل کنید. در فصل بعدی، وارد یک پروژه بزرگ و هیجان‌انگیز خواهیم شد و «ساخت بازی هجوم بیگانگان» را آغاز خواهیم کرد.