برای شروع تستنویسی، ابتدا باید محیط کاربری و ابزارهای مورد نیازمان را آماده کنیم. در این درس، فریمورک pytest را روی سیستم نصب میکنیم و ساختار استاندارد فایلهای پروژه را میچینیم تا پایتون دقیقاً بداند کدهای اصلی کجا قرار دارند و فایلهای تست را چطور پیدا کند.
یادگیری قوانین نامگذاری در pytest یکی از حیاتیترین بخشهای این درس است؛ زیرا این فریمورک بر پایه یک مکانیزم شناسایی خودکار (Test Discovery) کار میکند و اگر اصول نامگذاری پوشهها و توابع را رعایت نکنید، تستهای شما هرگز اجرا نخواهند شد.
در ادامه، قدم به قدم ابزارهای لازم را پیکربندی میکنیم تا پروژه کیف پول دیجیتال ما ساختاری حرفهای و آماده برای توسعه پیدا کند. بدون اتلاف وقت، ترمینال خود را باز کنید تا وارد فاز عملیاتی شویم.
ساخت محیط مجازی (Virtual Environment) و دلیل اهمیت آن
قبل از اینکه سراغ نصب pytest برویم، باید فضای کاری خودمان را ایزوله کنیم. در دنیای پایتون، پروژههای مختلف به نسخههای متفاوتی از پکیجها نیاز دارند. اگر تمام ابزارها را به صورت مستقیم و سراسری روی سیستمعامل خود نصب کنید، بعد از مدتی با تداخل نسخهها (Dependency Conflicts) مواجه میشوید؛ اتفاقی که میتواند کدهای قدیمی شما را به کل از کار بیندازد.
محیط مجازی یا همان Virtual Environment یک جعبه ابزار اختصاصی و کاملاً مستقل برای پروژه شما میسازد. با این کار، ابزارهایی که برای پروژه کیف پول دیجیتال نصب میکنید، هیچ ارتباطی با بقیه بخشهای سیستم یا پروژههای دیگر شما نخواهند داشت.
برای ساخت این محیط ایزوله، ابتدا ترمینال یا پاورشل را در پوشه اصلی پروژه خود باز کنید و دستور زیر را بنویسید:
python -m venv .venv
اجرای این دستور چند ثانیه زمان میبرد. پایتون یک پوشه مخفی به نام .venv درون دایرکتوری پروژه شما میسازد که حاوی یک نسخه مستقل از مفسر پایتون و ابزار مدیریت پکیج pip است.
حالا که این محیط ساخته شده، باید آن را فعال (Activate) کنید تا سیستم بفهمد از این به بعد باید از این ابزار استفاده کند. بسته به سیستمعاملی که استفاده میکنید، دستور فعالسازی متفاوت است.
اگر از ویندوز و خط فرمان استاندارد استفاده میکنید، دستور زیر را وارد کنید:
.venv\Scripts\activate
اما اگر از سیستمعامل مک یا لینوکس استفاده میکنید، این دستور را در ترمینال بنویسید:
source .venv/bin/activate
پس از اجرای این دستور، نام محیط مجازی یعنی (.venv) را در ابتدای خط ترمینال خود مشاهده خواهید کرد. این نشانه یعنی شما با موفقیت وارد محیط ایزوله خود شدهاید و حالا با خیال راحت میتوانید روند مدیریت پکیجها و پیکربندی ابزارهای تستنویسی پایتون را بدون صدمه زدن به بقیه سیستم جلو ببرید.
نصب فریمورک pytest و تایید اصالت نصب
پس از فعالسازی محیط مجازی، نوبت به نصب فریمورک pytest میرسد. در حال حاضر، این ابزار به عنوان محبوبترین و قدرتمندترین ابزار تستنویسی پایتون شناخته میشود. ساختار ساده و در عین حال توسعهپذیر آن باعث شده تا اکثر تیمهای برنامهنویسی بزرگ، ابزارهای قدیمی مانند unittest را کنار بگذارند و از این پکیج برای ارزیابی کدهای خود استفاده کنند.
برای شروع فرآیند نصب، مطمئن شوید که خط فرمان شما همچنان در حالت فعال (.venv) قرار دارد. سپس دستور زیر را برای دانلود و نصب آخرین نسخه پایدار ابزار وارد کنید:
pip install pytest
ابزار مدیریت پکیج pip، ابزار pytest را همراه با چند وابستگی فنی دیگر دانلود و در محیط ایزوله شما نصب میکند. این فرآیند معمولاً کمتر از یک دقیقه طول میکشد.
وقتی نصب به پایان رسید، هرگز کار را همینجا رها نکنید. یک توسعهدهنده حرفهای همیشه اصالت و صحت نصب ابزارها را بررسی میکند تا مطمئن شود خط فرمان به درستی به پکیج دسترسی دارد. برای تایید این موضوع، دستور زیر را اجرا کنید تا نسخه نصبشده را ببینید:
pytest --version
اگر پیکربندی محیط برنامهنویسی و مراحل نصب بدون مشکل انجام شده باشد، پایتون نسخه دقیق ابزار را همراه با مسیر نصب آن در ترمینال چاپ میکند؛ چیزی شبیه به این خروجی:
pytest 3.15 (یا نسخههای جدیدتر)
مشاهده این خروجی به این معنی است که موتور پردازش تستهای شما آماده است. حالا میتوانیم دایرکتوریها را مرتب کنیم و اولین فایلهای تست را برای سیستم کیف پول دیجیتال بسازیم.
معماری و ساختار استاندارد پوشهها در یک پروژه تستمحور
چیدمان فایلها در پروژههای نرمافزاری بزرگ اهمیت زیادی دارد. اگر کدهای اصلی و فایلهای تست را بدون نظم مشخصی در کنار هم رها کنید، با بزرگتر شدن برنامه، مدیریت دایرکتوری پروژه به یک کلاف سردرگم تبدیل میشود. در اکوسیستم پایتون، چند الگوی استاندارد برای معماری پوشهها وجود دارد که فرآیند توسعه و تستنویسی پایتون را کاملاً تفکیک میکند.
برای پروژه کیف پول دیجیتال، ما از معماری مستقل فایلهای تست استفاده میکنیم. در این ساختار، تمام کدهای اصلی برنامه در ریشه پروژه یا یک پوشه اختصاصی قرار میگیرند و فایلهای مربوط به ارزیابی کدهای نرمافزار، درون یک پوشه کاملاً مجزا ذخیره میشوند.
پوشهها و فایلهای پروژه خود را مطابق با الگوی زیر ایجاد کنید:
digital_wallet_project/
│
├── .venv/ # محیط مجازی ایزوله پروژه
├── wallet.py # کدهای اصلی و منطق کیف پول دیجیتال
└── tests/ # پوشه اختصاصی برای ذخیره تستها
├── __init__.py # فایل خالی برای معرفی پوشه به عنوان پکیج
└── test_wallet.py # فایل سناریوهای تست مربوط به کیف پول
بیایید جزییات این ساختار و دلیل این چیدمان را بررسی کنیم:
دلیل تفکیک پوشه کدهای اصلی از بخش تست
فایل wallet.py در ریشه پروژه قرار دارد تا دسترسی کدهای اصلی برنامه به آن راحت باشد. در مقابل، یک دایرکتوری مجزا به نام tests ساختهایم. این جداسازی به شما کمک میکند که زمان دپلوی و انتقال پروژه به سرور اصلی، فایلهای تست را همراه با کدهای عملیاتی پکیج نکنید و حجم پروژه نهایی را سبک نگه دارید.
نقش فایل init.py در دایرکتوری تست
قرار دادن یک فایل خالی به نام __init__.py درون پوشه tests یک ترفند فنی مهم در پایتون است. این فایل به مفسر پایتون اعلام میکند که این پوشه را به عنوان یک پکیج داخلی (Package) بشناسد. با این کار، وقتی ابزار pytest شروع به اسکن دایرکتوری میکند، به راحتی میتواند فایل wallet.py را از محیط بیرونی ایمپورت کند و رفتارهای کدهای آن را بسنجد. این ساختار ساده، پایه و اساس هر پروژه استاندارد و ماژولار در پایتون است.
قوانین طلایی نامگذاری (Test Discovery) در pytest
وقتی در ترمینال دستور اجرای تست را وارد میکنید، ابزار pytest کل پوشهها و زیرپوشههای پروژه شما را اسکن میکند تا فایلهای تست را پیدا و اجرا کند. به این فرآیند هوشمند، مکانیزم کشف تست یا اصطلاحاً Test Discovery میگویند. اما این ابزار چطور تشخیص میدهد که کدام فایل حاوی کدهای تست است و کدام یک کدهای اصلی برنامه؟
پاسخ ساده است: pytest بر اساس یک سری کنوانسیونها و قوانین نامگذاری مشخص عمل میکند. اگر این اصول را در ساختار پروژه خود رعایت نکنید، فایلهای تست شما نادیده گرفته میشوند.
برای اینکه سناریوهای ارزیابی نرمافزار شما به درستی توسط فریمورک شناسایی شوند، باید سه قانون طلایی را رعایت کنید:
۱. نامگذاری فایلهای تست
تمام فایلهای حاوی کدهای تست پایتون باید با پیشوند test_ شروع شوند یا با پسوند _test.py خاتمه یابند. به عنوان مثال، ابزار pytest فایل test_wallet.py را به عنوان یک پکیج تست اسکن میکند، اما فایلی با نام wallet_test_file.py را کاملاً نادیده میگیرد.
۲. نامگذاری توابع تست
توابعی که درون این فایلها مینویسید و وظیفه سنجش بخشهای مختلف کدهای اصلی (مثل متد واریز یا برداشت) را دارند، حتماً باید با پیشوند test_ تعریف شوند. به عنوان نمونه، تابعی با نام def test_deposit_action(): اجرا خواهد شد، اما نام def check_deposit(): برای فریمورک معنایی ندارد.
۳. نامگذاری کلاسهای تست
اگر ترجیح میدهید برای سازماندهی سناریوهای پیچیدهتر، توابع تست خود را درون کلاسها دستهبندی کنید، نام کلاس شما باید با پیشوند Test (با حرف T بزرگ) شروع شود. نکته فنی مهم این است که این کلاسها نباید متد سازنده یا همان __init__ داشته باشند. نمونه استاندارد آن به این صورت است: class TestWalletOperations:.
این نامگذاریهای دقیق به ابزار pytest اجازه میدهد تا بدون نیاز به پیکربندیهای دستی و پیچیده، در کسری از ثانیه ساختار پروژه را تحلیل کرده و گزارش درستی از وضعیت سلامت نرمافزار به شما تحویل دهد.
اجرای اولین تست خالی و تحلیل خروجی ترمینال
حالا که فایلها را چیدهایم و ابزارها آماده هستند، وقت آن است که موتور pytest را روشن کنیم. برای شروع، یک تست بسیار ساده و اولیه مینویسیم تا مطمئن شویم فرآیند شناسایی تستها (Test Discovery) بدون نقص کار میکند.
فایل tests/test_wallet.py را باز کنید و این چند خط کد ساده را درون آن بنویسید:
def test_always_passes():
assert True
این تابع عملاً کار خاصی انجام نمیدهد. کلمه کلیدی assert بررسی میکند که آیا عبارت جلوی آن درست (True) است یا خیر. چون خود مقدار را True گذاشتهایم، این تست همیشه با موفقیت پاس میشود.
حالا ترمینال خود را باز کنید، مطمئن شوید که محیط مجازی (.venv) فعال است و در ریشه پروژه، دستور زیر را تایپ کنید و اینتر را بزنید:
pytest
فریمورک در چند میلیثانیه پروژه را اسکن کرده و گزارشی را در ترمینال به شما نشان میدهد. بیایید بخشهای مهم این خروجی را با هم کالبدشکافی کنیم:
تحلیل گزارش خط فرمان
در خطوط اولیه خروجی، اطلاعاتی درباره سیستمعامل، نسخه پایتون و نسخه ابزار pytest نصبشده نمایش داده میشود. کمی پایینتر، بخش اصلی گزارش را میبینید که شبیه به متن زیر است:
plugins: ...
collected 1 item
tests/test_wallet.py . [100%]
============================== 1 passed in 0.01s ==============================
عبارت collected 1 item نشان میدهد که مکانیزم هوشمند ابزار، موفق شده یک تابع تست استاندارد را در دایرکتوری پروژه پیدا کند. آن نقطه سبزرنگی (.) که جلوی نام فایل قرار گرفته، در زبان pytest یعنی تست با موفقیت پاس شده است. خط پایانی هم با رنگ سبز به شما میگوید که چه تعداد تست در چه مدت زمانی اجرا شدهاند.
اگر به هر دلیلی تست شما خراب میشد، به جای نقطه، علامت F (مخفف Failed) را با رنگ قرمز میدیدید. این خروجی سبز یعنی زیرساخت و پیکربندی ابزارهای تستنویسی پایتون در پروژه کیف پول دیجیتال شما کاملاً بدون نقص راهاندازی شده و از درس بعدی میتوانیم با خیال راحت منطق واقعی کدهای مالی را بسنجیم.