حالت آفلاین — محتوا از حافظهٔ کش نمایش داده می‌شود
آموزش دیباگ و تست‌نویسی در پایتون؛ رفع خطا با تمرین

پروژه نهایی تست پایتون؛ مجموعه کامل فاکتور و رد هشت باگ

پروژه دیباگ پایتون؛ تعمیر فاکتور و جلوگیری از بازگشت باگ · 0٪

آخرین گام، ساخت یک مجموعه تستیه که از قرارداد کامل فاکتور محافظت کنه. این بار فقط یک جواب نمونه کافی نیست؛ باید نسخه سالم رو قبول کنی و چند رفتار خراب متفاوت رو رد کنی. این روش کمک می‌کنه قدرت واقعی تست‌ها رو ببینی: اگر نسخه دارای باگ از مجموعه عبور کنه، هنوز یک انتظار مهم ثبت نشده.

مثال، بررسی ورودی معتبر و نامعتبر رو در دو تابع جدا می‌ذاره. برای پروژه هم می‌تونی تست‌های معتبر و خطادار رو جدا بنویسی و از test_candidate هر دو رو اجرا کنی. خطای رایج اینه که بعد از اضافه‌کردن تست استثنا، بررسی حفظ فهرست فراموش بشه. هر fixture باید مستقل ساخته بشه و وضعیتش بعد از فراخوانی هم سنجیده بشه. wrapper فقط نام متنی نسخه رو به تابع وصل می‌کنه و True را برای عبور کامل گزارش می‌ده؛ بنابراین تستی که فقط پیام موفقیت چاپ کنه همه نسخه‌های خراب رو هم می‌پذیره و قابل قبول نیست. این پروژه به unittest، کلاس یا بسته خارجی نیاز نداره.

✍️ مثال حل‌شده:

def test_valid(candidate):
    assert candidate(2) == 4

def test_invalid(candidate):
    try:
        candidate(-1)
    except ValueError:
        pass
    else:
        raise AssertionError("invalid accepted")

def test_all(candidate):
    test_valid(candidate)
    test_invalid(candidate)

حالا نوبت توئه: test_candidate(candidate) مجموعه کامل فاکتور را اجرا کند. candidate(prices,percent) برای [100,200] با10=>270، با0=>300 و با100=>0؛ [] با10=>0 و [50] با20=>40 بدهد. درصدهای -1 و101، هم با [100] و هم با []، باید ValueError بدهند. فهرست ورودی در مسیر موفق و خطادار تغییر نکند. run_tests("correct") باید True و هشت نام دیگر در CANDIDATES باید False شوند. wrapper و نسخه‌ها را نگه دار؛ آزمون‌ها باید candidate واقعی را با assert و بررسی ValueError بسنجند، نه بر اساس نام نسخه تصمیم بگیرند. مبلغ تخفیف در این پروژه همان حاصل عددی فرمول است و گردکردن مالی انجام نمی‌شود؛ مثال‌های آزمون عمداً نتیجه عددی دقیق دارند.

فعالیت شما

test_candidate(candidate) مجموعه کامل فاکتور را اجرا کند. candidate(prices,percent) برای [100,200] با10=>270، با0=>300 و با100=>0؛ [] با10=>0 و [50] با20=>40 بدهد. درصدهای -1 و101، هم با [100] و هم با []، باید ValueError بدهند. فهرست ورودی در مسیر موفق و خطادار تغییر نکند. run_tests("correct") باید True و هشت نام دیگر در CANDIDATES باید False شوند. wrapper و نسخه‌ها را نگه دار؛ آزمون‌ها باید candidate واقعی را با assert و بررسی ValueError بسنجند، نه بر اساس نام نسخه تصمیم بگیرند. مبلغ تخفیف در این پروژه همان حاصل عددی فرمول است و گردکردن مالی انجام نمی‌شود؛ مثال‌های آزمون عمداً نتیجه عددی دقیق دارند.

مطالعهٔ این گام برای همه آزاد است

برای پاسخ‌دادن، بررسی پاسخ، ثبت پیشرفت و استفاده از دستیار باید شرایط شرکت در فعالیت‌ها را داشته باشید.

برای انجام فعالیت وارد شوید

فعالیت‌های این بخش به اشتراک فعال نیاز دارند. تهیهٔ اشتراک

برای انجام فعالیت‌ها ابتدا این دوره‌های پیش‌نیاز را تکمیل کنید:

کد اولیهٔ فعالیت

def correct(prices, percent):
    if percent < 0 or percent > 100:
        raise ValueError("discount outside range")
    return sum(prices) * (1 - percent / 100)

def wrong_formula(prices, percent):
    if percent < 0 or percent > 100:
        raise ValueError("discount outside range")
    return sum(prices) - percent / 100

def excludes_zero(prices, percent):
    if percent == 0:
        raise ValueError("zero rejected")
    return correct(prices, percent)

def excludes_hundred(prices, percent):
    if percent == 100:
        raise ValueError("hundred rejected")
    return correct(prices, percent)

def accepts_invalid(prices, percent):
    return sum(prices) * (1 - percent / 100)

def empty_bug(prices, percent):
    if not prices:
        return None
    return correct(prices, percent)

def mutates(prices, percent):
    total = correct(prices, percent)
    prices.clear()
    return total

def first_only(prices, percent):
    return correct(prices[:1], percent)

def wrong_exception(prices, percent):
    if percent < 0 or percent > 100:
        raise TypeError("wrong exception")
    return correct(prices, percent)

CANDIDATES = {
    "correct": correct, "wrong_formula": wrong_formula,
    "excludes_zero": excludes_zero, "excludes_hundred": excludes_hundred,
    "accepts_invalid": accepts_invalid, "empty_bug": empty_bug,
    "mutates": mutates, "first_only": first_only,
    "wrong_exception": wrong_exception,
}

def test_candidate(candidate):
    # مجموعه آزمون معتبر، مرزی، نامعتبر و حفظ ورودی
    pass

def run_tests(candidate_name):
    candidate = CANDIDATES[candidate_name]
    try:
        test_candidate(candidate)
        return True
    except Exception:
        return False