راهاندازی یک مجموعه آزمایشی برای کد شما ممکن است مانند یک مانع باشد که برای آن آماده نیستید، اما این کتابخانه فشار زیادی را متحمل میشود.
تست بخشی ضروری از توسعه نرم افزار است. این به تشخیص زودهنگام اشکالات کمک می کند و احتمال خطاها را کاهش می دهد.
Pytest یکی از محبوب ترین فریم ورک های تست پایتون است. این به شما امکان میدهد تستهای کوچک و خواندنی بنویسید که میتوانند با رشد برنامه شما مقیاس شوند. نحوه راه اندازی و استفاده از Pytest با کد پایتون خود را بیاموزید.
راه اندازی Pytest
قبل از نصب Pytest، بهتر است یک محیط مجازی ایجاد کنید تا محیط آزمایشی خود را ایزوله کند، تا بتوانید از درگیری با سایر بسته ها و وابستگی ها جلوگیری کنید.
برای ایجاد یک محیط مجازی قبل از نصب Pytest دستور زیر را اجرا کنید.
python -m venv tests
این یک محیط مجازی جدید به نام tests در فهرست فعلی شما ایجاد می کند. برای فعال کردن محیط، اگر از لینوکس یا مک استفاده می کنید، این دستور را اجرا کنید:
source tests/bin/activate
برای ویندوز این دستور را اجرا کنید:
tests\\Scripts\\activate
برای نصب Pytest، می توانید از pip، مدیر بسته Python، با این دستور در ترمینال خود استفاده کنید:
pip install pytest
اگر Pip ندارید، نگران نباشید. می توانید Pip را در ویندوز، مک و لینوکس نصب کنید.
برای بررسی اینکه آیا Pytest را به درستی نصب کرده اید، دستور زیر را اجرا کنید.
pytest --version
این باید شماره نسخه نصب شده را برگرداند.
ایجاد اولین آزمون شما
تابع زیر را در نظر بگیرید که دو عدد را جمع کرده و نتیجه را برمی گرداند.
def add_numbers(a, b):
return a + b
چندین چیز ممکن است با این عملکرد اشتباه باشد. برای مثال، در نظر بگیرید که اگر تابعی را با مقادیر غیر عددی مانند None یا مقداری از نوع رشته فراخوانی کنید چه اتفاقی میافتد. اینها برخی از موارد لبه بالقوه هستند که ممکن است باعث از کار افتادن عملکرد شوند.
یکی از اولین تست هایی که می نویسید باید بررسی کند که آیا تابع نتیجه مورد انتظار را برمی گرداند یا خیر. برای این کار می توانید از کلمه کلیدی assert برای مقایسه خروجی واقعی تابع با خروجی مورد انتظار استفاده کنید. در مورد تابع add_numbers، تابع تست ممکن است به شکل زیر باشد:
def test_add_numbers():
assert add_numbers(2, 3) == 5
assert add_numbers(-1, 1) == 0
assert add_numbers(0, 0) == 0
این تابع تست شامل سه عبارت اظهارنظر است که هر کدام خروجی تابع add_numbers را با مقدار مورد انتظار مقایسه می کند. تست اول بررسی می کند که با جمع کردن 2 و 3 عدد 5 برمی گردد، تست دوم بررسی می کند که با جمع کردن 1- و 1 عدد 0 برمی گردد و تست سوم بررسی می کند که با جمع 0 و 0 عدد 0 برمی گردد.
نحوه اجرای تست ها با Pytest
بعد از اینکه تست های خود را نوشتید، مرحله بعدی اجرای آنهاست. برای انجام این کار با Pytest، به دایرکتوری حاوی فایل تست خود بروید و دستور pytest را اجرا کنید:
pytest
اگر همه چیز همانطور که انتظار می رود کار کند، پیامی خواهید دید که نشان می دهد تمام تست ها با موفقیت پشت سر گذاشته شده اند. با این حال، اگر هر یک از ادعاها شکست بخورد، Pytest یک خطا را گزارش میکند و مقادیر ورودی را که باعث خرابی شده است را به شما نشان میدهد.
به عنوان مثال، فرض کنید تابع تست زیر را برای تابع add_numbers اجرا کرده اید:
def test_add_numbers():
assert add_numbers(2, 3) == 6
assert add_numbers(-1, 1) == 0
assert add_numbers(0, 0) == 0
ادعای اول ناموفق خواهد بود زیرا مقدار مورد انتظار 6 بود، اما مقدار واقعی 5 بود (مجموع 2 و 3). Pytest پیام زیر را برمی گرداند:
این پیام مقادیر ورودی که باعث ایجاد مقدار شده اند را به شما نشان می دهد و همچنین به شما می گوید که مقدار واقعی چقدر باید باشد. این باعث می شود تا به سرعت خطاهای کد خود را شناسایی و رفع کنید.
استفاده از Pytest.raises برای بیان استثناها
حالا بیایید یک تست بنویسیم تا یکی از موارد لبه تابع add_numbers را پوشش دهد. وقتی یک آرگومان غیر عددی مانند None را به تابع ارسال می کنید، پایتون باید یک استثنا TypeError ایجاد کند.
از قبل باید استثناها را در برنامه های پایتون خود مدیریت کنید، و می توانید آزمایش کنید که کد شما آنها را نیز به درستی افزایش می دهد.
برای این کار تابع تست زیر را در فایل خود کپی کنید. از مدیر زمینه pytest.raises استفاده می کند تا بررسی کند که آیا فراخوانی تابع add_number با “None” یک استثنا TypeError ایجاد می کند یا خیر.
import pytest
def test_add_numbers_with_invalid_inputs():
with pytest.raises(TypeError):
add_numbers(None, 2)
سپس Pytest را از خط فرمان اجرا کنید. اگر استثنا مطرح نشود، آزمون ناموفق خواهد بود.
می توانید بیشتر بروید و جزئیات پیام استثنا را بررسی کنید. مدیر زمینه یک شی ExceptionInfo با جزئیات تولید می کند.
به عنوان مثال، در این تابع تست، پیام استثنا را مانند زیر وارد کنید:
def test_add_numbers_with_invalid_inputs():
with pytest.raises(TypeError) as exc_info:
add_numbers(None, 2)
assert exc_info.value.args[0] == "unsupported operand type(s) for +: 'NoneType' and 'int'"
اگر پیام با پیام موجود در تست مطابقت نداشته باشد، Pytest نشان دهنده شکست است.
نحوه استفاده از تست پارامتری برای آزمایش چندین ورودی در یک زمان
به جای فراخوانی دستی یک تابع با چندین ورودی مانند این:
def test_add_numbers():
assert add_numbers(2, 3) == 6
assert add_numbers(-1, 1) == 0
assert add_numbers(0, 0) == 0
Pytest یک ویژگی تست پارامتری را ارائه می دهد که به شما امکان می دهد همین کار را راحت تر انجام دهید. در اینجا نحوه بازنویسی تابع تست بالا آمده است:
import pytest
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(-1, 1, 0),
(0, 0, 0)
])
def test_add_numbers(a, b, expected):
assert add_numbers(a, b) == expected
نحوه اجرای چندین تست
تا کنون، شما فقط دو تست برای تابع add_numbers نوشته اید. برای توابع پیچیده تر با تست های بیشتر، ممکن است بخواهید آنها را در یک کلاس گروه بندی کنید.
برای مثال، در اینجا نحوه ایجاد یک کلاس آزمایشی برای تابع add است.
class TestAddFunction:
@pytest.mark.parametrize("a, b, expected", [
(2, 3, 5),
(-1, 1, 0),
(0, 0, 0),
])
def test_addition_with_numbers(self, a, b, expected):
assert add_numbers(a, b) == expected
def test_add_numbers_with_invalid_inputs(self):
with pytest.raises(TypeError) as exc_info:
add_numbers(None, 2)
assert exc_info.value.args[0] == "unsupported operand type(s) for +: 'NoneType' and 'int'"
توجه داشته باشید که باید نام کلاس را با “Test” پیشوند بگذارید تا Pytest بتواند آن را به عنوان یک کلاس آزمایشی شناسایی کرده و اجرا کند.
Pytest دارای بسیاری از ویژگی های بیشتر است
با استفاده از Pytest، می توانید به طور خودکار تأیید کنید که کد شما همانطور که انتظار دارید کار می کند. Pytest بسیاری از ویژگیهای دیگر مانند فیکسچرها را ارائه میکند که به شما امکان میدهد دادههای تست و علامتهایی را برای تنظیم متادیتا در عملکردهای آزمایشی خود تنظیم و از بین ببرید.
علاوه بر این، می توانید Pytest را در خط لوله CI خود ادغام کنید و زمانی که کد خود را تغییر می دهید، آزمایش ها را به طور خودکار و مداوم شروع کنید.