چگونه در پایتون کد هایمان را تست کنیم؟

تست نویسی فرایندی هست که می تونیم کد هامونو تست کنیم و ببینیم درست کار می کنن یا نه
مثلا ببینیم 2+2 که به برنامه می دیم جوابش رو چهار محاسبه می کنه یا پنج؟!
تست نویسی در وهله اول هزینه کد نویسی شما رو زیاد می کنه (منظورم از هزینه فقط پول نیست! شامل زمان کد نویسی و حوصله برنامه نویس و اینجور چیزا میشه!). شما مجبوری یه عالمه کد بنویسی که کد اصلی کار کنه!
جالبه همین کار طاقت فرسا، خودشو در طول زمان نشون می ده. به خصوص زمان نگهداری کد

به نظر من سه تا دیدگاه وجود داره :
اول : بعضی از برنامه نویسا به تست نویسی به چشم یک واجب عینی نگاه می کنند!
دوم : بعضی ها می گن مستحبه!
سوم : بعضی ها هم که می گن برو بابا تست چیه؟! پروژه رو بنویس زودتر پولشو بگیر!

امروز می خوام با یک سناریو ساده قضیه رو از دیدگاه نفر اول بررسی کنم :

سناریو ما به اینصورته : قراره برنامه ای بنویسیم که
1- دو تا عدد رو از کاربر بگیره و با هم جمعشون کنه
2- جواب رو ذخیره کنه

همین!!!

کدی که براش نوشتم به صورت زیر هست :
توی کانستراکتور، یک دیکشنری تعریف کردم.
تابع add میاد دوتا عددی که کاربر وارد کرده رو با هم جمع می کنه و میریزه توی tmp. بعد توی هیستوری ذخیره می کنه و در آخر tmp که جمع دو تا عدد هست رو بر می گردونه.
تابع history هم اگه فراخونده بشه، تاریخچه رو بر می گردونه.

آیا کدمون کار می کنه؟! صد در صد!!!

جمع دو تا عدد
جمع دو تا عدد
 تاریخچه
تاریخچه

حالا می خوایم واسه همین برنامه ای که نوشتم تست بنویسم و برای این منظور از کتابخونه unittest استفاده کردم (نیازی به نصب کتابخونه نیست. خود پایتون داره!)

خب اول باید کتابخونه رو import کنم :

واسه تست کردن یک کلاس می نویسم که از unittest.TestCase ارث بری می کنه.

حالا می خوایم تست کنیم :
آیا با موفقیت، می تونیم شیئی از کلاس Add ایجاد کنیم ؟
برای اینکار مطابق شکل زیر، تابعی می نویسیم که اومدم یک نمونه از کلاس Add درست کردم و در خط بعد پرسیدم که آیا با موفقیت نمونه ساخته شده؟!

نکته مهم : وقتی می خوایم تست بنویسیم، اول اسم هر تابعی، با _test شروع میشه.

بعد از نوشتن تست، باید با استفاده از دستورات زیر، تست رو اجرا کنیم :

جهت اجرا در ترمینال یا کامند لاین :

python -m unittest

و جهت اجرا در محیط ژوپیتر نوت بوک، یک بلاک جدید ایجاد می کنیم و دستور زیر رو داخش قرار می دیم :

unittest.main(argv=[''], verbosity=2, exit=False)

من توی ژوپیتر اجرا می کنم اینطوریه :

از همون اول توضیح می دم : اسم تابع رو می نویسه و تهش می گه ok . یعنی این تابع تستش با موفقیت پاس شده
در قسمت پایین هم می نویسه در مدت زمان فلان ثانیه، یک تست اجرا شده و نتیجه کلی ok هست!

سوالات دیگه رو همین طوری می پرسم :
آیا 2 + 2 میشه 4؟! (تابع دوم)

تست
تست
جواب
جواب

2 + 2 نباید بشه 5 (تابع سوم) :

تست
تست
جواب
جواب

همونطور که مشاهده می کنید، بعضی چیزا هی داره تکرار میشه. مثل : ()jam=Add
برای اینکه هی نیازی نباشه ما بنویسیمش می ذاریمش توی تابع ستاپ :

تست
تست
جواب
جواب

یک نکته : همونطور که در نتایج می بینید به ازای هر بار اجرا شدن کلاس ، همه ی تست ها اجرا می شن. چجوری میشه جلو اینکار رو گرفت؟ جواب : با استفاده از skip
داخل آرگومان skip ، دلیل اجرا نشدن رو هم می نویسیم :

تست
تست
جواب
جواب

همونطور که در تصویر بالا مشاهده می کنید، دو تست اسکیپ شده و دلیلش رو هم نوشته :چون دلم می خواد!!!

ادامه می دیم :


آیا 2+2 در تاریخچه وجود داره؟

تست
تست
جواب
جواب


اگه هیچ عددی بهش ندم، منطقا باید ارور TypeError بده. آیا اینطوریه؟؟؟

تست
تست
جواب
جواب

خب به آخر این نوشته رسیدیم تو این نوشته سعی کردم حداقل unnittest رو پوشش بدم.
امیدوارم براتون مفید بوده باشه
از همراهیتون صمیمانه سپاسگزارم