آزمودن یک تابع

می‌توانید برای تابع یا کلاسی که نوشته‌اید کد آزمون هم بنویسید. آزمودنِ کد ثابت می‌کند که کد شما در پاسخ به تمام ورودی‌هایی که برای دریافت آن طرّاحی شده، همان‌گونه که باید، کار می‌کند. با طرّاحی آزمون‌ها می‌توانید مطمئن باشید که حتی اگر افراد مختلفی هم از برنامه‌ی شما استفاده کنند، به درستی کار خواهد کرد. همچنین می‌توانید هر کدِ جدیدی را، همزمان با افزوده شدن، بیازمایید تا مطمئن باشید که تغییراتِ اعمالی، رفتارِ فعلی برنامه را تحت‌الشعاع قرار نمی‌دهد. هر برنامه‌نویسی اشتباه می کند بنابراین باید کد خود را مرتّباً مورد آزمون قرار دهد تا پیش از برخوردن کاربران به مشکلی، آن را پیدا و رفع کند.

در این فصل می‌آموزید که چگونه با ابزارهای موجود در ماژول unittest پایتون کد خود را بیازمایید. یاد می‌گیرید که یک مورد آزمایشی بسازید که در آن مجموعه‌ای از ورودی‌ها به تولید خروجی‌هایی که می‌خواهید منجر می‌شوند. خواهید دید که قبول یا رد شدن در یک آزمون به چه شکل است و همچنین رد شدن در یک آزمون چگونه به بهبودِ کد شما کمک می‌کند. آزمودنِ تابع‌ها و کلاس‌ها را می‌آموزید و به تدریج درخواهید یافت که برای هر پروژه چه تعداد آزمون باید بنویسید.

برای آموختنِ چگونگیِ آزمودنِ کد، به کدی برای آزمایش نیاز داریم. اینجا تابعی ساده وجود دارد که نام و نام خانوادگی را می‌گیرد و نام کامل را به شکلی منظّم برمی‌گرداند:

1
2
3
4
def get_formatted_name(first, last):
    """Generate a neatly formatted full name."""
    full_name = f"{first} {last}"
    return full_name.title()

تابع get_formatted_name() بین نام و نام خانوادگی یک فاصله قرار می‌دهد، آن‌ها را در قالبِ یک نام کامل ترکیب می‌کند و پس از بزرگ کردن حرف‌های اوّل هر کدام، نتیجه را برمی‌گرداند. برای بررسی این که get_formatted_name() کار می‌کند یا نه برنامه‌ای می‌نویسیم که از این تابع استفاده کند. برنامه‌ی names.py به کاربران امکان ورود نام و نام خانوادگی می‌دهد و سپس نام کامل را به شکلی مرتّب به آن‌ها نشان می‌دهد:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from name_function import get_formatted_name

print("Enter 'q' at any time to quit.")

while True:
    first = input("\nPlease give me a first name: ")
    if first == 'q':
        break
    last = input("Please give me a last name: ")
    if last == 'q':
        break
    formatted_name = get_formatted_name(first, last)
    print(f"\tNeatly formatted name: {formatted_name}.")

این برنامه تابع get_formatted_name() را از name_function.py وارد می‌کند. کاربران می‌توانند دنباله‌ای از نام‌ها و نام‌های خانوادگی را وارد کنند و نام کامل تولیدشده را در خروجی ببینند:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Enter 'q' at any time to quit.

Please give me a first name: janis
Please give me a last name: joplin
	Neatly formatted name: Janis Joplin.

Please give me a first name: bob
Please give me a last name: dylan
	Neatly formatted name: Bob Dylan.

Please give me a first name: q

می‌بینیم که نام‌های تولیدشده درست‌اند. حال فرض کنید که می‌خواهیم تابع get_formatted_name() را طوری تغییر دهیم که بتواند نام‌های میانی را هم مدیریّت کند. همچنان‌که این کار را انجام می‌دهیم می‌خواهیم مطمئن باشیم که نحوه‌ی عملکرد تابع هنگام کار کردن با نام‌هایی که تنها از نام و نام خانوادگی تشکیل شده، به هم نمی‌خورد. می‌توانیم هر بار که get_formatted_name() را تغییر دادیم، names.py را اجرا کنیم و با وارد کردن نامی مانند Janis Joplin آن را آزمایش کنیم، امّا این کار به تدریج تکراری می‌شود. خوشبختانه پایتون راهی موثّر برای خودکارسازی فرآیندِ آزمایشِ خروجیِ یک تابع ارائه می‌کند. اگر آزمودن get_formatted_name() را خودکار کنیم، می‌توانیم همیشه مطمئن باشیم که تابع ما با انواع نام‌هایی که برای آن‌ها آزمون نوشته‌ایم کار می‌کند.

آزمون 103 102 ‌های واحد و موارد آزمایشی

ماژول unittest در کتابخانه‌ی استاندارد پایتون ابزارهایی برای آزم}103 یش کد در اختیار شما قرار می‌دهد. آزمون واحد درستیِ یک جنبه از رفتار یک تابع را می‌سنجد. مورد آزمایشی مجموعه‌ای از آزمون‌های واحد است که در کنار هم ثابت می‌کنند تابع در بازه‌ی کاملی از وضعیّت‌هایی که باید مدیرّیت کند، آن‌گونه که انتظار می‌رود کار می‌کند. یک مورد آزمایشی خوب تمام انواع ورودی‌های ممکن یک تابع را در نظر می‌گیرد و آزمون‌هایی را برای نمایش هر کدام از آن‌ها دربرمی‌گیرد. مورد آزمایشی با پوشش کامل گستره‌ی کاملی از آزمون‌های واحد را شامل می‌شود که تمام راه‌های ممکن استفاده از یک تابع را پوشش می‌دهد. دست‌یافتن به پوشش کامل در یک پروژه بزرگ ممکن است ترسناک باشد. اغلب کافی است که آزمون‌هایی برای رفتارهای حیاتی کد بنویسیم و تنها زمانی به سراغ پوشش کامل برویم که پروژه برای کاربری بسیار گسترده آماده می‌شود.