pytest: راهنمای جامع برای تستنویسی در پایتون
در دنیای توسعه نرمافزار، تستنویسی بخش جداییناپذیر از فرآیند تولید نرمافزار با کیفیت است. پایتون، به عنوان یک زبان برنامهنویسی محبوب، ابزارهای قدرتمندی برای تستنویسی در اختیار توسعهدهندگان قرار میدهد. pytest یکی از این ابزارهاست که به دلیل سادگی، انعطافپذیری و قابلیتهای پیشرفته، به طور گستردهای مورد استفاده قرار میگیرد. این مقاله به بررسی جامع pytest، مفاهیم کلیدی آن و نحوه استفاده از آن در پروژههای پایتون میپردازد. این آموزش در سطح ‘مفاهیم متوسط’ قرار دارد و فرض بر این است که خواننده با اصول اولیه پایتون و تستنویسی آشنایی دارد.
چرا pytest؟
قبل از پرداختن به جزئیات pytest، بد نیست بدانیم چرا این ابزار نسبت به سایر فریمورکهای تستنویسی پایتون مانند unittest محبوبیت بیشتری دارد. دلایل متعددی برای این امر وجود دارد:
- سادگی و خوانایی: pytest نیازی به boilerplate code (کد تکراری و اضافی) ندارد. تستها به صورت توابع ساده با نامهای گویا نوشته میشوند.
- کشف خودکار تستها: pytest به طور خودکار فایلهای تست را شناسایی میکند (فایلهایی که نام آنها با
test_شروع میشود یا تابعهایی که نام آنها باtest_شروع میشود). - Fixtures: pytest از مفهوم fixtures برای مدیریت منابع تست (مانند اتصال به پایگاه داده، ایجاد فایلهای موقت و غیره) استفاده میکند.
- Parametrization: pytest امکان اجرای یک تست با مجموعهای از ورودیهای مختلف را فراهم میکند.
- Plugins: pytest دارای اکوسیستم گستردهای از پلاگینها است که قابلیتهای آن را گسترش میدهند.
نصب pytest
نصب pytest بسیار ساده است. میتوانید از pip، مدیر بسته پایتون، برای نصب آن استفاده کنید:
pip install pytest
نوشتن اولین تست
برای شروع، یک فایل پایتون با نام test_example.py ایجاد کنید و کد زیر را در آن قرار دهید:
def add(x, y):
return x + y
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
در این مثال، یک تابع به نام add تعریف شده است که دو عدد را با هم جمع میکند. سپس یک تابع تست به نام test_add تعریف شده است که از دستور assert برای بررسی صحت خروجی تابع add استفاده میکند. دستور assert یک عبارت بولی را ارزیابی میکند و اگر عبارت نادرست باشد، یک استثنا (AssertionError) ایجاد میکند.
برای اجرای تستها، کافی است در ترمینال به دایرکتوری حاوی فایل test_example.py بروید و دستور pytest را اجرا کنید. pytest به طور خودکار فایلهای تست را شناسایی و اجرا میکند و نتایج را نمایش میدهد.
Fixtures: مدیریت منابع تست
Fixtures ابزاری قدرتمند برای مدیریت منابع تست هستند. آنها به شما امکان میدهند منابع مورد نیاز برای تستها (مانند اتصال به پایگاه داده، ایجاد فایلهای موقت و غیره) را به طور خودکار ایجاد و پاکسازی کنید. برای تعریف یک fixture، از دکوراتور @pytest.fixture استفاده کنید:
import pytest
@pytest.fixture
def tmp_file(tmpdir):
file = tmpdir.join("test.txt")
file.write("Hello, pytest!")
return file
def test_tmp_file(tmp_file):
content = tmp_file.read()
assert content == "Hello, pytest!"
در این مثال، یک fixture به نام tmp_file تعریف شده است که یک فایل موقت ایجاد میکند و محتوای آن را با رشته “Hello, pytest!” پر میکند. سپس این فایل به عنوان آرگومان به تابع تست test_tmp_file ارسال میشود. pytest به طور خودکار fixture را قبل از اجرای تابع تست ایجاد میکند و پس از اتمام اجرای تابع تست، آن را پاکسازی میکند.
Parametrization: اجرای تست با ورودیهای مختلف
Parametrization به شما امکان میدهد یک تست را با مجموعهای از ورودیهای مختلف اجرا کنید. این کار میتواند به شما کمک کند تا تستهای خود را جامعتر و کارآمدتر کنید. برای parametrization، از دکوراتور @pytest.mark.parametrize استفاده کنید:
import pytest
@pytest.mark.parametrize("input, expected", [
(2, 4),
(3, 9),
(4, 16)
])
def test_square(input, expected):
assert input * input == expected
در این مثال، یک تست به نام test_square تعریف شده است که مربع یک عدد را محاسبه میکند. دکوراتور @pytest.mark.parametrize این تست را با سه مجموعه ورودی مختلف اجرا میکند: (2, 4)، (3, 9) و (4, 16). pytest برای هر مجموعه ورودی، یک بار تست را اجرا میکند و نتایج را نمایش میدهد.
Marks: دستهبندی و فیلتر کردن تستها
Marks به شما امکان میدهند تستها را دستهبندی کنید و آنها را بر اساس دستهبندی فیلتر کنید. این کار میتواند به شما کمک کند تا تستهای خود را سازماندهی کنید و فقط تستهای مورد نیاز را اجرا کنید. برای اعمال یک mark به یک تست، از دکوراتور @pytest.mark.<mark_name> استفاده کنید:
import pytest
@pytest.mark.slow
def test_slow_function():
# ...
pass
@pytest.mark.database
def test_database_connection():
# ...
pass
# برای اجرای فقط تستهای با mark "slow":
# pytest -m slow
# برای اجرای فقط تستهای با mark "database":
# pytest -m database
در این مثال، دو تست با نامهای test_slow_function و test_database_connection تعریف شدهاند. تست test_slow_function با mark “slow” و تست test_database_connection با mark “database” علامتگذاری شدهاند. میتوانید از دستور pytest -m <mark_name> برای اجرای فقط تستهای با mark مشخص شده استفاده کنید.
Plugins: گسترش قابلیتهای pytest
pytest دارای اکوسیستم گستردهای از پلاگینها است که قابلیتهای آن را گسترش میدهند. برخی از پلاگینهای محبوب pytest عبارتند از:
- pytest-cov: برای اندازهگیری پوشش کد (code coverage).
- pytest-xdist: برای اجرای تستها به صورت موازی.
- pytest-django: برای تستنویسی در پروژههای Django.
- pytest-mock: برای mock کردن وابستگیها.
برای نصب یک پلاگین، از pip استفاده کنید:
pip install pytest-cov
نتیجهگیری
pytest یک ابزار قدرتمند و انعطافپذیر برای تستنویسی در پایتون است. سادگی، قابلیتهای پیشرفته و اکوسیستم گسترده پلاگینها، آن را به یک انتخاب محبوب در بین توسعهدهندگان پایتون تبدیل کرده است. با استفاده از pytest، میتوانید تستهای با کیفیت بالا بنویسید و از صحت و قابلیت اطمینان کد خود اطمینان حاصل کنید. این مقاله تنها یک مقدمه بر pytest بود. برای یادگیری بیشتر، میتوانید به مستندات رسمی pytest مراجعه کنید.

بدون دیدگاه