رگرسیون یعنی یک اصلاح، رفتاری رو که قبلاً درست بوده خراب کنه. برای جلوگیری از اون، تستهای قبلی رو نگه میداریم و فقط تست باگ جدید رو اضافه نمیکنیم. در فاکتور ما، فرمول تخفیف، مرزهای مجاز، ورودی نامعتبر، سبد خالی و حفظ قیمتها همگی باید همزمان برقرار بمونن. درستشدن یکی مجوز خرابشدن دیگری نیست.
مثال یک تابع جمع رو بدون pop یا remove مینویسه تا داده منبع حفظ بشه. در فعالیت، subtotal و discounted_total رو کنار هم کامل میکنی. خطای رایج مصرفکردن فهرست با pop برای جمعزدنه؛ مبلغ درست حساب میشه ولی بعداً ردیفهای فاکتور ناپدید میشن. تابع کمکی آماده بعد از اجرا خود فهرست رو هم پس میده، پس این اثر جانبی قابل بررسیه. اعتبارسنجی باید پیش از هر تغییر یا محاسبه انجام بشه. قیمتها در این پروژه صحیح نامنفیاند؛ مدیریت قیمت نامعتبر موضوع این قرارداد نیست. مجموعه مثالهای قبلی رو راهنمای اصلاح نگه دار و کد رو به شاخههای کوتاه و روشن محدود کن.
✍️ مثال حلشده:
def total_without_consuming(values):
total = 0
for value in values:
total += value
return total
items = [7, 9]
assert total_without_consuming(items) == 16
assert items == [7, 9]
حالا نوبت توئه: subtotal(prices) و discounted_total(prices,percent) را کامل کن؛ جمع و تخفیف درست، بدون تغییر فهرست ورودی. بازه 0..100 بسته معتبر و بیرون آن ValueError است، حتی برای []. run_invoice([100,200],10) باید {"value":270,"prices":[100,200]} بدهد؛ تخفیف 0=>300 و100=>0، سبد خالی با10=>0. درصد -1 یا101 باید دیکشنری error با ValueError و همان prices اولیه بدهد. wrapper را حفظ کن. مبلغ تخفیف در این پروژه همان حاصل عددی فرمول است و گردکردن مالی انجام نمیشود؛ مثالهای آزمون عمداً نتیجه عددی دقیق دارند.
فعالیت شما
subtotal(prices) و discounted_total(prices,percent) را کامل کن؛ جمع و تخفیف درست، بدون تغییر فهرست ورودی. بازه 0..100 بسته معتبر و بیرون آن ValueError است، حتی برای []. run_invoice([100,200],10) باید {"value":270,"prices":[100,200]} بدهد؛ تخفیف 0=>300 و100=>0، سبد خالی با10=>0. درصد -1 یا101 باید دیکشنری error با ValueError و همان prices اولیه بدهد. wrapper را حفظ کن. مبلغ تخفیف در این پروژه همان حاصل عددی فرمول است و گردکردن مالی انجام نمیشود؛ مثالهای آزمون عمداً نتیجه عددی دقیق دارند.