الأبحاث · جولةُ البرمجة الأولى

CB-1-07 — كتابة اختبارات · Python · متوسّط

جولةُ البرمجة الأولى · 2026-10-05 · GAIBRA v2.29.02 · واجبُ التشغيل

نتيجةُ الجولة

الترتيبالمتنافسالرمز أمام المحكّمالكلماتالاختباراتOpusGrokالمجموعالصدق (Opus · Grok)
1Claude Sonnetهـ1,60414/1591.797.794.711 · 12
2DeepSeekأ1,19114/1584.793.789.27 · 12
3Geminiد93515/1582.075.078.58 · 6
4GAIBRAب1,07713/1572.378.375.35 · 8
5ChatGPTج81313/1567.380.373.86 · 9

نصُّ السيناريو كما كتبه المولّد

We have a checkout quotation module (pricing.py, below) that computes discount, VAT and shipping for the Saudi market. Before we start changing it (coupon rework is planned next sprint), I want a solid regression net around its current documented behavior. I don't want the module touched — deliverable is a single test file test\_pricing.py using only the standard-library unittest (pytest is not available in our CI image). The module under test: Python \# pricing.py from decimal import Decimal, ROUND\_HALF\_UP VAT\_RATE = Decimal("0.15") TIER\_DISCOUNTS = \[ &#x20; (Decimal("2000"), Decimal("0.10")), &#x20; (Decimal("500"), Decimal("0.05")), ] SHIPPING\_FLAT = Decimal("25") SHIPPING\_FREE\_OVER = Decimal("300") COUPONS = { &#x20; "SAVE10": ("percent", Decimal("0.10")), &#x20; "FLAT50": ("fixed", Decimal("50")), } def quote(subtotal, coupon\_code=None): &#x20; """Return a dict with keys: subtotal, discount, vat, shipping, total. &#x20; - Tier discount applies to the whole subtotal when the threshold is reached &#x20; (only the highest matching tier; thresholds are NOT cumulative). &#x20; - Coupons reduce the subtotal further; percent and fixed may both be applied &#x20; if the caller passes them in sequence via coupon stacking rules (we don't, &#x20; but the function allows a single coupon\_code today). &#x20; - VAT 15% is computed on the discounted amount, rounded half-up to 2dp. &#x20; - Shipping is free when the DISCOUNTED amount >= 300, else flat 25. &#x20; """ &#x20; subtotal = Decimal(str(subtotal)) &#x20; if subtotal < 0: &#x20; raise ValueError("subtotal must be >= 0") &#x20; discount = Decimal("0") &#x20; for threshold, rate in TIER\_DISCOUNTS: &#x20; if subtotal >= threshold: &#x20; discount = subtotal \* rate &#x20; break &#x20; if coupon\_code is not None: &#x20; kind, value = COUPONS\[coupon\_code] # KeyError for unknown codes &#x20; if kind == "percent": &#x20; discount += subtotal \* value &#x20; else: &#x20; discount += value &#x20; discounted = subtotal - discount &#x20; if discounted < 0: &#x20; discounted = Decimal("0") &#x20; vat = (discounted \* VAT\_RATE).quantize(Decimal("0.01"), rounding=ROUND\_HALF\_UP) &#x20; shipping = Decimal("0") if discounted >= SHIPPING\_FREE\_OVER else SHIPPING\_FLAT &#x20; total = discounted + vat + shipping &#x20; return { &#x20; "subtotal": subtotal, &#x20; "discount": discount, &#x20; "vat": vat, &#x20; "shipping": shipping, &#x20; "total": total, &#x20; } What I need covered, at minimum: Tier boundaries: 499.99 vs 500.00 (5% tier), 1999.99 vs 2000.00 (10% tier, and 2000 must get 10% — not 10% + 5%). VAT rounding half-up on exact half-cent cases, e.g. discounted amount where x \* 0.15 lands on a half cent (0.125 → 0.13). Compute one such subtotal yourself and pin the expected value in the test. Free-shipping threshold decided on the discounted amount: subtotal 320 with SAVE10 → discounted 288 → shipping must be 25. FLAT50 on a subtotal of 30 → discounted clamps to 0, VAT 0, shipping 25 (since 0 < 300), total 25. Unknown coupon code raises KeyError. Negative subtotal raises ValueError. quote("100.10") (string input) works and quote(100.10) (float input) is accepted without crashing; use assertAlmostEqual-style comparison via Decimal equality where relevant, but make the float case tolerant (document why in a comment). Zero subtotal with no coupon: everything zero except shipping 25. Each test should state the business rule in its docstring. Aim for 15–25 focused test methods; don't write one giant test. Keep the file self-contained (it will from pricing import quote — assume both files sit in the same directory, which is how CI runs it).

الردودُ الخمسة كما وصلت المحكّمين

الرمزُ هو ما رآه المحكّمان؛ والاسمُ كُشف بعد التحكيم.

بGAIBRA75.3 · 1,077 كلمة
Test Code Test Code One number needed to be computed by hand before it could be pinned in a test: the half-cent VAT case. VAT is 15% of the discounted amount. For the result to land exactly on a half cent (x.xx5), the discounted amount must make discounted \* 0.15 end in ...5 at the third decimal. Take discounted = 0.05: 0.05 \* 0.15 = 0.0075 — not quite. Take discounted = 10.05: 10.05 \* 0.15 = 1.5075 — still not a half-cent boundary. The clean construction is to pick the discounted amount directly: 0.5 gives 0.5 \* 0.15 = 0.075, which rounds half-up to 0.08. That is a true half-cent case at the third decimal (0.075 → ties to even is 0.08 under half-up since half-up always rounds the 5 away from zero, not to even). To get this discounted amount of exactly 0.5 with no coupon and no tier discount, use subtotal = 0.5 (below the 500 threshold, no coupon applied, so discount = 0, discounted = 0.5). That is the pinned value used below: expected VAT = Decimal("0.08"). \# test\_pricing.py import unittest from decimal import Decimal from pricing import quote class TierDiscountBoundaryTests(unittest.TestCase): &#x20; """Tests pinning the exact thresholds of the tiered discount table.""" &#x20; def test\_subtotal\_499\_99\_gets\_no\_tier\_discount(self): &#x20; """Business rule: below 500, no tier discount applies at all.""" &#x20; result = quote(Decimal("499.99")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; def test\_subtotal\_500\_00\_gets\_five\_percent\_tier\_discount(self): &#x20; """Business rule: reaching 500 exactly triggers the 5% tier.""" &#x20; result = quote(Decimal("500.00")) &#x20; self.assertEqual(result\["discount"], Decimal("25.00")) &#x20; def test\_subtotal\_1999\_99\_gets\_five\_percent\_not\_ten\_percent(self): &#x20; """Business rule: just under 2000, only the 5% tier applies.""" &#x20; result = quote(Decimal("1999.99")) &#x20; self.assertEqual(result\["discount"], Decimal("99.9995")) &#x20; def test\_subtotal\_2000\_00\_gets\_ten\_percent\_only\_not\_stacked(self): &#x20; """Business rule: at 2000, the 10% tier wins and tiers do not stack (no 10%+5%).""" &#x20; result = quote(Decimal("2000.00")) &#x20; self.assertEqual(result\["discount"], Decimal("200.00")) &#x20; def test\_subtotal\_above\_2000\_still\_uses\_only\_highest\_tier(self): &#x20; """Business rule: higher subtotals still use a single highest-matching tier.""" &#x20; result = quote(Decimal("5000")) &#x20; self.assertEqual(result\["discount"], Decimal("500.00")) class VatRoundingTests(unittest.TestCase): &#x20; """Tests pinning half-up rounding of VAT on half-cent boundaries.""" &#x20; def test\_vat\_rounds\_half\_up\_on\_exact\_half\_cent(self): &#x20; """Business rule: VAT is rounded half-up to 2dp; 0.075 rounds up to 0.08, not down to 0.07.""" &#x20; result = quote(Decimal("0.5")) &#x20; self.assertEqual(result\["vat"], Decimal("0.08")) &#x20; def test\_vat\_on\_zero\_discounted\_amount\_is\_zero(self): &#x20; """Business rule: VAT on a zero discounted base is exactly zero, no rounding artifact.""" &#x20; result = quote(Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; def test\_vat\_computed\_on\_discounted\_amount\_not\_subtotal(self): &#x20; """Business rule: VAT base is the post-discount amount, not the raw subtotal.""" &#x20; result = quote(Decimal("500")) &#x20; self.assertEqual(result\["vat"], (Decimal("475.00") \* Decimal("0.15")).quantize(Decimal("0.01"))) class ShippingDecisionTests(unittest.TestCase): &#x20; """Tests pinning the free-shipping decision against the discounted amount, not the subtotal.""" &#x20; def test\_shipping\_free\_when\_discounted\_amount\_reaches\_300(self): &#x20; """Business rule: free shipping is decided on discounted total, so subtotal 320 with SAVE10 gives discounted 288, still charged.""" &#x20; result = quote(Decimal("320"), "SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("32.0")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_shipping\_free\_when\_discounted\_amount\_is\_exactly\_300(self): &#x20; """Business rule: the free-shipping threshold is inclusive at exactly 300.""" &#x20; result = quote(Decimal("300")) &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; def test\_shipping\_charged\_when\_discounted\_amount\_just\_under\_300(self): &#x20; """Business rule: 299.99 discounted still incurs flat shipping of 25.""" &#x20; result = quote(Decimal("299.99")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_shipping\_charged\_flat\_fee\_value(self): &#x20; """Business rule: the flat shipping fee is exactly 25 when not free.""" &#x20; result = quote(Decimal("10")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) class CouponBehaviorTests(unittest.TestCase): &#x20; """Tests pinning coupon application, clamping, and unknown-code failure.""" &#x20; def test\_flat50\_on\_subtotal\_30\_clamps\_discounted\_to\_zero(self): &#x20; """Business rule: discount cannot push the discounted amount below zero; FLAT50 on 30 clamps to 0.""" &#x20; result = quote(Decimal("30"), "FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("50")) &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25.00")) &#x20; def test\_save10\_percent\_coupon\_adds\_to\_tier\_discount(self): &#x20; """Business rule: a percent coupon's discount is added on top of any tier discount already applied.""" &#x20; result = quote(Decimal("1000"), "SAVE10") &#x20; expected\_discount = Decimal("50.00") + Decimal("100.00") &#x20; self.assertEqual(result\["discount"], expected\_discount) &#x20; def test\_unknown\_coupon\_code\_raises\_key\_error(self): &#x20; """Business rule: an unrecognized coupon code is a hard failure, not a silent no-op.""" &#x20; with self.assertRaises(KeyError): &#x20; quote(Decimal("100"), "NOPE") &#x20; def test\_fixed\_coupon\_value\_is\_applied\_literally(self): &#x20; """Business rule: a fixed coupon subtracts its exact value regardless of subtotal size.""" &#x20; result = quote(Decimal("1000"), "FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("50")) class InputValidationTests(unittest.TestCase): &#x20; """Tests pinning input rejection and type tolerance at the function boundary.""" &#x20; def test\_negative\_subtotal\_raises\_value\_error(self): &#x20; """Business rule: a negative subtotal is invalid and must raise ValueError before any computation.""" &#x20; with self.assertRaises(ValueError): &#x20; quote(Decimal("-0.01")) &#x20; def test\_zero\_subtotal\_with\_no\_coupon\_yields\_all\_zero\_except\_shipping(self): &#x20; """Business rule: a zero subtotal with no coupon produces zero discount, zero VAT, zero total pre-shipping, and flat shipping of 25.""" &#x20; result = quote(Decimal("0")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25.00")) &#x20; def test\_string\_input\_is\_accepted\_and\_parsed\_exactly(self): &#x20; """Business rule: a numeric string input is accepted and parsed with exact Decimal precision.""" &#x20; result = quote("100.10") &#x20; self.assertEqual(result\["subtotal"], Decimal("100.10")) &#x20; def test\_float\_input\_is\_accepted\_without\_crashing(self): &#x20; """Business rule: a float input is accepted; result is compared with tolerance because float-to-str-to-Decimal &#x20; conversion can introduce binary-representation noise (e.g. 100.10 may not be exactly Decimal("100.10")) — &#x20; this test only asserts the call succeeds and the output is in the expected neighborhood, not exact equality.""" &#x20; result = quote(100.10) &#x20; self.assertAlmostEqual(float(result\["subtotal"]), 100.10, places=2) if \_\_name\_\_ == "\_\_main\_\_": &#x20; unittest.main() Coverage Notes Coverage Notes Twenty test methods across five grouped classes, each with a single assertion focus and a docstring naming the business rule, not the mechanics. Tier boundaries are covered at both edges (499.99/500.00, 1999.99/2000.00) including the explicit non-stacking check at exactly 2000. The VAT half-up case is derived by hand in the comment above the test rather than asserted blindly — subtotal 0.5 forces discounted 0.5, and 0.5 × 0.15 = 0.075, which half-up rounds to 0.08; a mutation to ROUND\_HALF\_EVEN or ROUND\_DOWN would silently produce 0.07 or 0.08-vs-0.07 mismatches, so this test kills that mutation. Shipping is tested against the discounted amount specifically (320 with SAVE10 → 288 discounted → still charged), which kills a mutation that checks shipping against raw subtotal instead. FLAT50-on-30 is the clamp test: without the if discounted < 0: discounted = 0 line, this test would see a negative discounted value and fail, so it guards that exact line. KeyError and ValueError paths are isolated, one exception type each, so a mutation swapping exception types or removing the raise is caught. String and float inputs are both exercised; the float test is explicitly tolerant and the reason is documented inline, since binary float representation can make Decimal(str(100.10)) differ in trailing digits from a hand-typed Decimal("100.10"). I did not run this file — I traced the arithmetic by hand for every pinned value. One gap: there is no concurrency test, because quote has no shared mutable state and no I/O, so a threading test would add noise without catching a real mutation.
هـClaude Sonnet94.7 · 1,604 كلمة
Selecting specific half-cent cases to test rounding logic. I'll write the test file, then run it against an unmodified copy of pricing.py to make sure every expected value is correct. Ran 2 commands, created a file, shared files I ran the suite against an unmodified copy of pricing.py, and all 26 tests pass. That is one over your 25 ceiling. The likeliest one to drop is test\_tiers\_are\_not\_cumulative, because test\_exactly\_2000\_gets\_10\_percent already pins the 200 discount. It's a separate test only so that a failure names the rule directly. The half-cent VAT case. Subtotal 100.30 × 0.15 = 15.045 exactly. Half-up rounding gives 15.05; banker's rounding (ROUND\_HALF\_EVEN) would give 15.04. That means the test fails if someone changes the rounding mode, not only if they break the arithmetic. I added a second half-cent case (100.70 → 15.11) and one just below the half cent (100.03 → 15.00). Behaviors the tests pin that you'll probably want to decide on during the coupon rework. These are all current behavior, but none of them is described in the docstring: Discount and total aren't rounded. Only VAT is rounded to 2dp. So 1999.99 gives a discount of 99.9995 and a total of 2184.9905. FLAT50 on 30 reports a discount of 50. The discounted amount is clamped to 0, but the discount field isn't clamped to the subtotal. SAVE10 is calculated on the original subtotal, not the amount after the tier discount. So 2000 with SAVE10 gives a discount of 200 + 200 = 400. Each of these has a comment in its test saying it was pinned deliberately. When the rework changes one of them, the failing test is the place to record that decision. Why the float test is tolerant. Decimal(str(100.10)) happens to give exactly 100.1 today. That relies on how Python formats floats, which isn't a pricing rule. So the float test checks only that each value is a Decimal and matches the string-input result to within one cent. The full explanation is in the test's docstring. To run it: python -m unittest test\_pricing -v Test pricing PY """Regression (characterization) tests for pricing.quote. These tests pin the CURRENT behavior of pricing.py ahead of the coupon rework. They are intentionally strict: if a change alters any number below, the test should fail and the change should be a conscious, reviewed decision. Notes on comparisons \-------------------- \* Decimal equality is value-based, so Decimal("25.0000") == Decimal("25"). &#x20; We therefore compare against clean literals even though quote() does not &#x20; quantize discount/total (only VAT is quantized to 2dp). \* Expected values are hand-computed and written as string-built Decimals &#x20; so the expectations themselves never go through binary floating point. Run with: python -m unittest test\_pricing -v """ import unittest from decimal import Decimal from pricing import quote D = Decimal EXPECTED\_KEYS = {"subtotal", "discount", "vat", "shipping", "total"} class QuoteTestCase(unittest.TestCase): &#x20; """Shared helper for asserting a full quote breakdown.""" &#x20; def assertQuote(self, result, \*, subtotal, discount, vat, shipping, total): &#x20; self.assertEqual(set(result), EXPECTED\_KEYS) &#x20; self.assertEqual(result\["subtotal"], D(subtotal), "subtotal") &#x20; self.assertEqual(result\["discount"], D(discount), "discount") &#x20; self.assertEqual(result\["vat"], D(vat), "vat") &#x20; self.assertEqual(result\["shipping"], D(shipping), "shipping") &#x20; self.assertEqual(result\["total"], D(total), "total") class TestTierDiscounts(QuoteTestCase): &#x20; def test\_just\_below\_500\_gets\_no\_tier\_discount(self): &#x20; """Rule: subtotals below 500 receive no tier discount. &#x20; 499.99 -> discount 0, VAT 499.99\*0.15 = 74.9985 -> 75.00, &#x20; discounted >= 300 so shipping free, total 574.99. &#x20; """ &#x20; self.assertQuote(quote("499.99"), subtotal="499.99", discount="0", &#x20; vat="75.00", shipping="0", total="574.99") &#x20; def test\_exactly\_500\_gets\_5\_percent(self): &#x20; """Rule: the 5% tier applies when subtotal >= 500 (inclusive boundary). &#x20; 500.00 -> discount 25.00, discounted 475.00, VAT 71.25, free shipping, &#x20; total 546.25. &#x20; """ &#x20; self.assertQuote(quote("500.00"), subtotal="500.00", discount="25", &#x20; vat="71.25", shipping="0", total="546.25") &#x20; def test\_just\_below\_2000\_gets\_5\_percent\_only(self): &#x20; """Rule: subtotals in \[500, 2000) receive the 5% tier, not 10%. &#x20; 1999.99 -> discount 99.9995, discounted 1899.9905, &#x20; VAT 284.998575 -> 285.00, total 2184.9905. &#x20; Current behavior: discount and total are NOT rounded to 2dp &#x20; (only VAT is quantized). Pinned deliberately. &#x20; """ &#x20; self.assertQuote(quote("1999.99"), subtotal="1999.99", &#x20; discount="99.9995", vat="285.00", shipping="0", &#x20; total="2184.9905") &#x20; def test\_exactly\_2000\_gets\_10\_percent(self): &#x20; """Rule: the 10% tier applies when subtotal >= 2000 (inclusive boundary). &#x20; 2000.00 -> discount 200, discounted 1800, VAT 270.00, total 2070. &#x20; """ &#x20; self.assertQuote(quote("2000.00"), subtotal="2000.00", discount="200", &#x20; vat="270.00", shipping="0", total="2070") &#x20; def test\_tiers\_are\_not\_cumulative(self): &#x20; """Rule: only the highest matching tier applies — 2000 gets 10%, &#x20; never 10% + 5% (which would be a 300 discount).""" &#x20; result = quote("2000") &#x20; self.assertEqual(result\["discount"], D("200")) &#x20; self.assertNotEqual(result\["discount"], D("300")) &#x20; def test\_well\_above\_top\_tier\_still\_10\_percent(self): &#x20; """Rule: there is no tier above 10%; 5000 gets a 500 discount.""" &#x20; self.assertQuote(quote("5000"), subtotal="5000", discount="500", &#x20; vat="675.00", shipping="0", total="5175") class TestVatRounding(QuoteTestCase): &#x20; def test\_vat\_rounds\_half\_up\_on\_exact\_half\_cent(self): &#x20; """Rule: VAT = 15% of the discounted amount, rounded HALF-UP to 2dp. &#x20; 100.30 \* 0.15 = 15.045 exactly (a half cent). &#x20; Half-up -> 15.05. (Banker's rounding / ROUND\_HALF\_EVEN would give &#x20; 15.04, so this case distinguishes the two modes.) &#x20; Total = 100.30 + 15.05 + 25 shipping = 140.35. &#x20; """ &#x20; self.assertQuote(quote("100.30"), subtotal="100.30", discount="0", &#x20; vat="15.05", shipping="25", total="140.35") &#x20; def test\_vat\_rounds\_half\_up\_second\_half\_cent\_case(self): &#x20; """Rule: VAT half-up rounding, second independent half-cent case. &#x20; 100.70 \* 0.15 = 15.105 exactly -> 15.11 (half-even would give 15.10). &#x20; """ &#x20; self.assertEqual(quote("100.70")\["vat"], D("15.11")) &#x20; def test\_vat\_just\_below\_half\_cent\_rounds\_down(self): &#x20; """Rule: amounts below the half cent round down. &#x20; 100.03 \* 0.15 = 15.0045 -> 15.00. &#x20; """ &#x20; self.assertEqual(quote("100.03")\["vat"], D("15.00")) &#x20; def test\_vat\_is\_always\_quantized\_to\_two\_decimals(self): &#x20; """Rule: VAT is always expressed with exactly 2 decimal places, &#x20; even when the discounted amount carries more (tier discounts can &#x20; produce 4dp amounts).""" &#x20; for subtotal in ("0", "100.30", "1999.99", "777.77", "2000"): &#x20; with self.subTest(subtotal=subtotal): &#x20; vat = quote(subtotal)\["vat"] &#x20; self.assertEqual(vat.as\_tuple().exponent, -2) class TestShipping(QuoteTestCase): &#x20; def test\_free\_shipping\_decided\_on\_discounted\_amount(self): &#x20; """Rule: free shipping uses the DISCOUNTED amount, not the subtotal. &#x20; 320 with SAVE10 -> discount 32, discounted 288 (< 300) -> shipping 25, &#x20; even though the raw subtotal is above 300. &#x20; VAT 288\*0.15 = 43.20, total 288 + 43.20 + 25 = 356.20. &#x20; """ &#x20; self.assertQuote(quote("320", "SAVE10"), subtotal="320", &#x20; discount="32", vat="43.20", shipping="25", &#x20; total="356.20") &#x20; def test\_shipping\_free\_at\_exactly\_300(self): &#x20; """Rule: shipping is free when discounted amount >= 300 (inclusive).""" &#x20; self.assertQuote(quote("300"), subtotal="300", discount="0", &#x20; vat="45.00", shipping="0", total="345") &#x20; def test\_shipping\_charged\_just\_below\_300(self): &#x20; """Rule: discounted amount below 300 pays the flat 25 shipping.""" &#x20; self.assertEqual(quote("299.99")\["shipping"], D("25")) &#x20; def test\_coupon\_landing\_exactly\_on\_300\_gets\_free\_shipping(self): &#x20; """Rule: inclusive threshold applies after coupons too. &#x20; 350 with FLAT50 -> discounted exactly 300 -> free shipping. &#x20; """ &#x20; self.assertQuote(quote("350", "FLAT50"), subtotal="350", &#x20; discount="50", vat="45.00", shipping="0", &#x20; total="345") class TestCoupons(QuoteTestCase): &#x20; def test\_flat50\_on\_small\_subtotal\_clamps\_to\_zero(self): &#x20; """Rule: the discounted amount never goes below 0. &#x20; 30 with FLAT50 -> discounted clamps to 0, VAT 0, shipping 25 &#x20; (0 < 300), total 25. &#x20; Current behavior: the reported 'discount' is the full 50, NOT &#x20; clamped to the subtotal. Pinned deliberately — flag for the rework. &#x20; """ &#x20; self.assertQuote(quote("30", "FLAT50"), subtotal="30", discount="50", &#x20; vat="0.00", shipping="25", total="25") &#x20; def test\_save10\_stacks\_on\_top\_tier\_using\_original\_subtotal(self): &#x20; """Rule: a percent coupon is added to the tier discount and is &#x20; computed on the ORIGINAL subtotal, not the tier-discounted amount. &#x20; 2000 + SAVE10 -> 200 (tier) + 200 (coupon) = 400, discounted 1600, &#x20; VAT 240.00, total 1840. &#x20; """ &#x20; self.assertQuote(quote("2000", "SAVE10"), subtotal="2000", &#x20; discount="400", vat="240.00", shipping="0", &#x20; total="1840") &#x20; def test\_flat50\_stacks\_on\_5\_percent\_tier(self): &#x20; """Rule: a fixed coupon is added to the tier discount. &#x20; 500 + FLAT50 -> 25 + 50 = 75, discounted 425, VAT 63.75, &#x20; total 488.75. &#x20; """ &#x20; self.assertQuote(quote("500", "FLAT50"), subtotal="500", &#x20; discount="75", vat="63.75", shipping="0", &#x20; total="488.75") &#x20; def test\_unknown\_coupon\_raises\_key\_error(self): &#x20; """Rule: unknown coupon codes raise KeyError (no silent ignore).""" &#x20; with self.assertRaises(KeyError): &#x20; quote("100", "BOGUS") &#x20; def test\_coupon\_codes\_are\_case\_sensitive(self): &#x20; """Rule: coupon lookup is exact-match; 'save10' is not 'SAVE10'.""" &#x20; with self.assertRaises(KeyError): &#x20; quote("100", "save10") &#x20; def test\_none\_coupon\_means\_no\_coupon(self): &#x20; """Rule: coupon\_code=None (the default) applies no coupon.""" &#x20; self.assertEqual(quote("100", None), quote("100")) class TestInputHandling(QuoteTestCase): &#x20; def test\_negative\_subtotal\_raises\_value\_error(self): &#x20; """Rule: subtotal must be >= 0; negatives raise ValueError.""" &#x20; for bad in ("-0.01", -1, "-500"): &#x20; with self.subTest(subtotal=bad): &#x20; with self.assertRaises(ValueError): &#x20; quote(bad) &#x20; def test\_zero\_subtotal\_without\_coupon(self): &#x20; """Rule: an empty basket still pays flat shipping. &#x20; 0 -> discount 0, VAT 0, shipping 25 (0 < 300), total 25. &#x20; """ &#x20; self.assertQuote(quote(0), subtotal="0", discount="0", vat="0.00", &#x20; shipping="25", total="25") &#x20; def test\_string\_subtotal\_is\_exact(self): &#x20; """Rule: string input is parsed exactly as a Decimal. &#x20; "100.10" -> VAT 15.015 -> 15.02 (half-up), shipping 25, &#x20; total 140.12. &#x20; """ &#x20; self.assertQuote(quote("100.10"), subtotal="100.10", discount="0", &#x20; vat="15.02", shipping="25", total="140.12") &#x20; def test\_float\_subtotal\_is\_accepted(self): &#x20; """Rule: float input is accepted without crashing and yields a &#x20; result equivalent (to the cent) to the string input. &#x20; Why tolerant: 100.10 has no exact binary float representation. &#x20; quote() converts via Decimal(str(x)), which today happens to recover &#x20; "100.1" exactly, but that relies on Python's shortest-repr float &#x20; formatting — an implementation detail, not a pricing rule. Callers &#x20; should pass strings/Decimals for money; for floats we only promise &#x20; cent-level agreement, so we compare within 0.01 rather than pinning &#x20; exact Decimal digits. &#x20; """ &#x20; result = quote(100.10) &#x20; expected = quote("100.10") &#x20; self.assertEqual(set(result), EXPECTED\_KEYS) &#x20; for key in EXPECTED\_KEYS: &#x20; with self.subTest(key=key): &#x20; self.assertIsInstance(result\[key], Decimal) &#x20; self.assertLessEqual(abs(result\[key] - expected\[key]), &#x20; D("0.01")) &#x20; def test\_all\_values\_are\_decimals(self): &#x20; """Rule: every value in the quote is a Decimal (never float/int), &#x20; so downstream money math stays exact.""" &#x20; for args in (("0",), ("100.30",), ("2000", "SAVE10"), (30, "FLAT50")): &#x20; with self.subTest(args=args): &#x20; for key, value in quote(\*args).items(): &#x20; self.assertIsInstance(value, Decimal, key) &#x20; def test\_total\_equals\_components(self): &#x20; """Rule: total = (subtotal - discount, floored at 0) + vat + shipping.""" &#x20; for args in (("499.99",), ("1999.99",), ("320", "SAVE10"), &#x20; ("30", "FLAT50"), ("2000", "SAVE10")): &#x20; with self.subTest(args=args): &#x20; r = quote(\*args) &#x20; discounted = max(r\["subtotal"] - r\["discount"], D("0")) &#x20; self.assertEqual(r\["total"], &#x20; discounted + r\["vat"] + r\["shipping"]) if \_\_name\_\_ == "\_\_main\_\_": &#x20; unittest.main()
جChatGPT73.8 · 813 كلمة
Below is a self-contained unittest regression suite with 20 focused tests, including the requested boundary, rounding, coupon, shipping, validation, and input-type cases. test\_pricing.py import unittest from decimal import Decimal from pricing import quote class TestQuote(unittest.TestCase): &#x20; def test\_zero\_subtotal\_has\_only\_flat\_shipping(self): &#x20; """A zero subtotal has zero discount, VAT, and total before flat shipping.""" &#x20; result = quote(Decimal("0")) &#x20; self.assertEqual(result\["subtotal"], Decimal("0")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("0")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25")) &#x20; def test\_subtotal\_just\_below\_5\_percent\_tier(self): &#x20; """The 5% tier applies only when subtotal reaches 500.00.""" &#x20; result = quote(Decimal("499.99")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("75.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("599.99")) &#x20; def test\_subtotal\_at\_500\_gets\_5\_percent\_tier(self): &#x20; """A subtotal of exactly 500.00 receives the 5% tier discount.""" &#x20; result = quote(Decimal("500.00")) &#x20; self.assertEqual(result\["discount"], Decimal("25.0000")) &#x20; self.assertEqual(result\["vat"], Decimal("71.25")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("571.2500")) &#x20; def test\_subtotal\_just\_below\_2000\_gets\_5\_percent\_tier(self): &#x20; """A subtotal below 2000.00 but at least 500.00 receives only the 5% tier.""" &#x20; result = quote(Decimal("1999.99")) &#x20; self.assertEqual(result\["discount"], Decimal("99.9995")) &#x20; self.assertEqual(result\["vat"], Decimal("285.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; self.assertEqual(result\["total"], Decimal("2184.9905")) &#x20; def test\_subtotal\_at\_2000\_gets\_10\_percent\_only(self): &#x20; """At 2000.00 the highest matching tier is 10%, not cumulative 15%.""" &#x20; result = quote(Decimal("2000.00")) &#x20; self.assertEqual(result\["discount"], Decimal("200.0000")) &#x20; self.assertEqual(result\["vat"], Decimal("270.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; self.assertEqual(result\["total"], Decimal("2070.0000")) &#x20; def test\_subtotal\_above\_2000\_keeps\_only\_10\_percent\_tier(self): &#x20; """Above 2000.00 only the highest matching 10% tier applies.""" &#x20; result = quote(Decimal("2500.00")) &#x20; self.assertEqual(result\["discount"], Decimal("250.0000")) &#x20; self.assertEqual(result\["vat"], Decimal("337.50")) &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; self.assertEqual(result\["total"], Decimal("2587.5000")) &#x20; def test\_no\_tier\_discount\_below\_500(self): &#x20; """Subtotals below 500.00 receive no tier discount.""" &#x20; result = quote(Decimal("499")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("74.85")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_vat\_uses\_discounted\_amount(self): &#x20; """VAT is calculated from the amount remaining after the tier discount.""" &#x20; result = quote(Decimal("500")) &#x20; # 500 - 5% = 475; 475 \* 15% = 71.25. &#x20; self.assertEqual(result\["vat"], Decimal("71.25")) &#x20; def test\_vat\_rounds\_half\_up(self): &#x20; """VAT rounds a half-cent upward rather than using banker's rounding.""" &#x20; # VAT is 15%, so a discounted amount of 5/6 gives exactly 0.125. &#x20; # A finite Decimal approximation just above 5/6 preserves that &#x20; # intended half-cent case without relying on binary floating point. &#x20; subtotal = Decimal("0.8333333333333333333333333334") &#x20; result = quote(subtotal) &#x20; self.assertEqual(result\["vat"], Decimal("0.13")) &#x20; def test\_shipping\_is\_free\_at\_exact\_discounted\_threshold(self): &#x20; """Shipping is free when the discounted amount is exactly 300.00.""" &#x20; result = quote(Decimal("300")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; self.assertEqual(result\["total"], Decimal("345.00")) &#x20; def test\_shipping\_is\_flat\_just\_below\_discounted\_threshold(self): &#x20; """Shipping costs 25 when the discounted amount is below 300.00.""" &#x20; result = quote(Decimal("299.99")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_free\_shipping\_uses\_discounted\_amount(self): &#x20; """Free-shipping eligibility is based on discounted amount, not original subtotal.""" &#x20; result = quote(Decimal("320"), "SAVE10") &#x20; # 320 - 10% = 288, so the order is below the 300 free-shipping threshold. &#x20; self.assertEqual(result\["discount"], Decimal("32.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["vat"], Decimal("43.20")) &#x20; self.assertEqual(result\["total"], Decimal("313.20")) &#x20; def test\_save10\_applies\_percent\_discount\_to\_subtotal(self): &#x20; """SAVE10 applies a 10% coupon discount to the original subtotal.""" &#x20; result = quote(Decimal("400"), "SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("40.00")) &#x20; self.assertEqual(result\["vat"], Decimal("54.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("385.00")) &#x20; def test\_save10\_can\_stack\_with\_tier\_discount(self): &#x20; """A coupon is added to any applicable tier discount rather than replacing it.""" &#x20; result = quote(Decimal("500"), "SAVE10") &#x20; # Tier: 25; coupon: 50; total discount: 75. &#x20; self.assertEqual(result\["discount"], Decimal("75.00")) &#x20; self.assertEqual(result\["vat"], Decimal("63.75")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("513.75")) &#x20; def test\_flat50\_coupon\_reduces\_subtotal\_by\_fixed\_amount(self): &#x20; """FLAT50 subtracts a fixed 50 from the subtotal.""" &#x20; result = quote(Decimal("200"), "FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("50")) &#x20; self.assertEqual(result\["vat"], Decimal("22.50")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("172.50")) &#x20; def test\_flat50\_cannot\_make\_discounted\_amount\_negative(self): &#x20; """When discounts exceed subtotal, the discounted amount is clamped to zero.""" &#x20; result = quote(Decimal("30"), "FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("50")) &#x20; self.assertEqual(result\["vat"], Decimal("0")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25")) &#x20; def test\_unknown\_coupon\_raises\_key\_error(self): &#x20; """An unknown coupon code raises KeyError rather than being silently ignored.""" &#x20; with self.assertRaises(KeyError): &#x20; quote(Decimal("100"), "NOT\_A\_COUPON") &#x20; def test\_negative\_subtotal\_raises\_value\_error(self): &#x20; """Negative subtotals are rejected with ValueError.""" &#x20; with self.assertRaises(ValueError): &#x20; quote(Decimal("-0.01")) &#x20; def test\_string\_subtotal\_is\_accepted(self): &#x20; """A decimal string subtotal is converted to Decimal and calculated exactly.""" &#x20; result = quote("100.10") &#x20; self.assertEqual(result\["subtotal"], Decimal("100.10")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("15.02")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("140.12")) &#x20; def test\_float\_subtotal\_is\_accepted(self): &#x20; """A float subtotal is accepted; comparison is tolerant of float representation.""" &#x20; result = quote(100.10) &#x20; # quote() converts through str(), so ordinary decimal floats such as &#x20; # 100.10 are represented as their human-readable decimal value here. &#x20; # Use assertAlmostEqual on float values to avoid coupling this regression &#x20; # test to binary floating-point representation details. &#x20; self.assertAlmostEqual(float(result\["subtotal"]), 100.10, places=12) &#x20; self.assertAlmostEqual(float(result\["vat"]), 15.02, places=12) &#x20; self.assertAlmostEqual(float(result\["shipping"]), 25.00, places=12) &#x20; self.assertAlmostEqual(float(result\["total"]), 140.12, places=12) &#x20; def test\_total\_equals\_discounted\_amount\_plus\_vat\_plus\_shipping(self): &#x20; """The returned total is the discounted amount plus VAT and shipping.""" &#x20; result = quote(Decimal("750"), "SAVE10") &#x20; discounted = result\["subtotal"] - result\["discount"] &#x20; if discounted < 0: &#x20; discounted = Decimal("0") &#x20; self.assertEqual( &#x20; result\["total"], &#x20; discounted + result\["vat"] + result\["shipping"], &#x20; ) if \_\_name\_\_ == "\_\_main\_\_": &#x20; unittest.main() One subtle point is intentional: the half-cent VAT test uses a finite Decimal representation just above \\(5/6\\), because an exact decimal representation of \\(5/6\\) is impossible; this avoids accidentally testing a value that falls infinitesimally below 0.125 due to decimal truncation.
أDeepSeek89.2 · 1,191 كلمة
Below is a self-contained test\_pricing.py using only the standard library's unittest. It imports the frozen pricing module and pins the documented behavior, including the boundary, rounding, shipping, coupon, and input-coercion rules you called out. Each test method states the business rule in its docstring. python \# test\_pricing.py """ Regression net for pricing.quote(). These tests document the CURRENT, frozen behavior of pricing.py. They are intentionally written against the public quote() API only. The module under test must not be modified to satisfy these tests. Run with: python -m unittest test\_pricing.py """ import unittest from decimal import Decimal from pricing import quote class TierDiscountBoundaryTests(unittest.TestCase): &#x20; """Rules for the highest-matching, non-cumulative tier discount.""" &#x20; def test\_below\_500\_gets\_no\_tier\_discount(self): &#x20; """499.99 is below the 500 threshold, so no tier discount applies.""" &#x20; result = quote("499.99") &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; def test\_500\_gets\_five\_percent\_tier(self): &#x20; """500.00 reaches the 500 threshold, so the 5% tier applies to the whole subtotal.""" &#x20; result = quote("500.00") &#x20; self.assertEqual(result\["discount"], Decimal("25.00")) &#x20; def test\_just\_below\_2000\_keeps\_five\_percent\_tier(self): &#x20; """1999.99 is still under 2000, so only the 5% tier applies (not 10%).""" &#x20; result = quote("1999.99") &#x20; # 5% of 1999.99 &#x20; self.assertEqual(result\["discount"], Decimal("1999.99") \* Decimal("0.05")) &#x20; def test\_2000\_gets\_ten\_percent\_tier\_not\_ten\_plus\_five(self): &#x20; """2000.00 must get the 10% tier only; tiers are not cumulative.""" &#x20; result = quote("2000.00") &#x20; self.assertEqual(result\["discount"], Decimal("200.00")) &#x20; # Explicitly rule out the buggy 10% + 5% = 300 outcome. &#x20; self.assertNotEqual(result\["discount"], Decimal("300.00")) &#x20; def test\_tier\_discount\_uses\_highest\_matching\_tier(self): &#x20; """A very large subtotal still uses only the 10% tier, not both tiers.""" &#x20; result = quote("5000.00") &#x20; self.assertEqual(result\["discount"], Decimal("500.00")) class VatRoundingTests(unittest.TestCase): &#x20; """VAT is 15% of the discounted amount, rounded half-up to 2dp.""" &#x20; def test\_vat\_half\_cent\_rounds\_up(self): &#x20; """ &#x20; Pick a discounted amount whose 15% lands exactly on a half cent: &#x20; 0.90 \* 0.15 = 0.135 -> half-up to 0.14. &#x20; Subtotal 0.90 has no tier and no coupon, so discounted == 0.90. &#x20; """ &#x20; result = quote("0.90") &#x20; self.assertEqual(result\["vat"], Decimal("0.14")) &#x20; def test\_vat\_rounds\_half\_up\_on\_another\_half\_cent(self): &#x20; """ &#x20; Another exact half-cent case: 0.50 \* 0.15 = 0.075 -> half-up to 0.08. &#x20; This pins that ROUND\_HALF\_UP is used rather than banker's rounding. &#x20; """ &#x20; result = quote("0.50") &#x20; self.assertEqual(result\["vat"], Decimal("0.08")) &#x20; def test\_vat\_is\_computed\_on\_discounted\_amount(self): &#x20; """VAT applies after the tier discount, not to the raw subtotal.""" &#x20; # 500 - 5% = 475.00; 475.00 \* 0.15 = 71.25 &#x20; result = quote("500.00") &#x20; self.assertEqual(result\["vat"], Decimal("71.25")) &#x20; def test\_vat\_is\_zero\_when\_discounted\_is\_zero(self): &#x20; """When the discounted amount clamps to 0, VAT must be 0.00.""" &#x20; result = quote("30", coupon\_code="FLAT50") &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) class ShippingThresholdTests(unittest.TestCase): &#x20; """Free shipping is decided on the DISCOUNTED amount >= 300.""" &#x20; def test\_free\_shipping\_when\_discounted\_meets\_threshold(self): &#x20; """Discounted amount of exactly 300.00 earns free shipping.""" &#x20; result = quote("300.00") &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; def test\_shipping\_charged\_when\_subtotal\_meets\_300\_but\_discount\_drops\_below(self): &#x20; """ &#x20; Subtotal 320 with SAVE10 -> discounted 288, which is below 300, &#x20; so shipping must be the flat 25 even though the raw subtotal >= 300. &#x20; """ &#x20; result = quote("320", coupon\_code="SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("32.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_shipping\_charged\_just\_below\_threshold(self): &#x20; """Discounted amount of 299.99 is below 300, so flat shipping applies.""" &#x20; result = quote("299.99") &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_free\_shipping\_just\_above\_threshold(self): &#x20; """Discounted amount of 300.01 is above 300, so shipping is free.""" &#x20; result = quote("300.01") &#x20; self.assertEqual(result\["shipping"], Decimal("0")) class CouponTests(unittest.TestCase): &#x20; """Single-coupon behavior for percent and fixed coupons.""" &#x20; def test\_percent\_coupon\_adds\_to\_tier\_discount(self): &#x20; """SAVE10 adds 10% of the subtotal on top of any tier discount.""" &#x20; # 500 tier discount = 25.00; SAVE10 = 50.00; total discount = 75.00 &#x20; result = quote("500.00", coupon\_code="SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("75.00")) &#x20; def test\_fixed\_coupon\_adds\_to\_tier\_discount(self): &#x20; """FLAT50 adds a flat 50 on top of any tier discount.""" &#x20; # 500 tier discount = 25.00; FLAT50 = 50.00; total discount = 75.00 &#x20; result = quote("500.00", coupon\_code="FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("75.00")) &#x20; def test\_fixed\_coupon\_clamps\_discounted\_to\_zero(self): &#x20; """ &#x20; FLAT50 on a subtotal of 30 -> discounted clamps to 0, VAT 0, &#x20; shipping 25 (since 0 < 300), total 25. &#x20; """ &#x20; result = quote("30", coupon\_code="FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("50")) &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25")) &#x20; def test\_unknown\_coupon\_raises\_key\_error(self): &#x20; """An unrecognized coupon code must raise KeyError (current contract).""" &#x20; with self.assertRaises(KeyError): &#x20; quote("100", coupon\_code="NOPE") class InputValidationTests(unittest.TestCase): &#x20; """Subtotal must be non-negative and is coerced via Decimal(str(...)).""" &#x20; def test\_negative\_subtotal\_raises\_value\_error(self): &#x20; """A negative subtotal is invalid and must raise ValueError.""" &#x20; with self.assertRaises(ValueError): &#x20; quote("-0.01") &#x20; def test\_zero\_subtotal\_no\_coupon(self): &#x20; """Zero subtotal: everything zero except flat shipping of 25.""" &#x20; result = quote("0") &#x20; self.assertEqual(result\["subtotal"], Decimal("0")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25")) &#x20; def test\_string\_input\_is\_accepted(self): &#x20; """quote('100.10') accepts a string subtotal and preserves the value.""" &#x20; result = quote("100.10") &#x20; self.assertEqual(result\["subtotal"], Decimal("100.10")) &#x20; def test\_float\_input\_is\_accepted\_without\_crashing(self): &#x20; """ &#x20; quote(100.10) must be accepted without crashing. &#x20; Decimal(str(100.10)) == Decimal('100.1'), which is the documented &#x20; coercion path. We use Decimal equality on the coerced value rather &#x20; than comparing the float directly, because binary floats are not &#x20; exact and Decimal(float) would expose representation noise. &#x20; """ &#x20; result = quote(100.10) &#x20; self.assertEqual(result\["subtotal"], Decimal("100.1")) &#x20; # The returned dict must still contain Decimal values, not floats. &#x20; self.assertIsInstance(result\["subtotal"], Decimal) &#x20; self.assertIsInstance(result\["discount"], Decimal) &#x20; self.assertIsInstance(result\["vat"], Decimal) &#x20; self.assertIsInstance(result\["shipping"], Decimal) &#x20; self.assertIsInstance(result\["total"], Decimal) &#x20; def test\_float\_and\_string\_inputs\_agree\_after\_coercion(self): &#x20; """ &#x20; The documented coercion path Decimal(str(x)) makes quote(100.10) &#x20; and quote('100.10') produce the same subtotal. &#x20; """ &#x20; from\_float = quote(100.10)\["subtotal"] &#x20; from\_string = quote("100.10")\["subtotal"] &#x20; self.assertEqual(from\_float, from\_string) class TotalCompositionTests(unittest.TestCase): &#x20; """Total is discounted + VAT + shipping, with all components consistent.""" &#x20; def test\_total\_composition\_no\_coupon(self): &#x20; """A plain mid-range order composes total from its four components.""" &#x20; result = quote("100") &#x20; self.assertEqual(result\["subtotal"], Decimal("100")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("15.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("140.00")) &#x20; def test\_total\_composition\_with\_tier\_and\_free\_shipping(self): &#x20; """A 10%-tier order above the discounted threshold gets free shipping.""" &#x20; # 2000 - 200 = 1800; VAT 270.00; shipping 0; total 2070.00 &#x20; result = quote("2000.00") &#x20; self.assertEqual(result\["discount"], Decimal("200.00")) &#x20; self.assertEqual(result\["vat"], Decimal("270.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; self.assertEqual(result\["total"], Decimal("2070.00")) &#x20; def test\_returned\_dict\_has\_exactly\_the\_documented\_keys(self): &#x20; """The quote() contract exposes exactly these five keys.""" &#x20; result = quote("100") &#x20; self.assertEqual( &#x20; set(result.keys()), &#x20; {"subtotal", "discount", "vat", "shipping", "total"}, &#x20; ) if \_\_name\_\_ == "\_\_main\_\_": &#x20; unittest.main() Key choices worth flagging: Boundary pins use assertEqual, not assertAlmostEqual, because quote() returns Decimal and the documented contract is exact decimal arithmetic. assertAlmostEqual is only relevant when comparing floats; for the float-input case I compare the coerced Decimal value instead, which is the actual documented behavior (Decimal(str(subtotal))). The half-cent VAT cases are computed from first principles in the docstrings (0.90 \* 0.15 = 0.135 → 0.14, 0.50 \* 0.15 = 0.075 → 0.08) so a future reader can verify the pin without re-deriving it. The 2000 tier test includes a negative assertion (assertNotEqual(... Decimal("300.00"))) so the non-cumulative rule fails loudly if someone "fixes" it into stacking. The shipping-on-discounted test asserts both the discount and the shipping, because the whole point is that 320 qualifies for free shipping on the raw subtotal but not on the discounted one. The float test asserts the returned components are Decimal instances, guarding the "no float leakage into the money type" contract. 21 test methods, grouped into 6 focused TestCase classes so the regression net reads as a spec of the module rather than a wall of asserts.
دGemini78.5 · 935 كلمة
The standard-library test suite below covers all boundary conditions, mathematical edge cases, and error paths for pricing.py. Save this code directly into test\_pricing.py in the same directory as pricing.py. Python \# test\_pricing.py from decimal import Decimal import unittest from pricing import quote class TestPricingQuote(unittest.TestCase): &#x20; """Regression test suite for checkout quotation calculations in pricing.py.""" &#x20; # ------------------------------------------------------------------------- &#x20; # Subtotal Input Handling \& Edge Cases &#x20; # ------------------------------------------------------------------------- &#x20; def test\_zero\_subtotal(self): &#x20; """Zero subtotal results in 0 discount and VAT, with standard flat shipping applied.""" &#x20; result = quote(0) &#x20; self.assertEqual(result\["subtotal"], Decimal("0")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("25.00")) &#x20; def test\_negative\_subtotal\_raises\_value\_error(self): &#x20; """Negative subtotal values must raise a ValueError.""" &#x20; with self.assertRaises(ValueError): &#x20; quote("-0.01") &#x20; def test\_string\_subtotal\_accepted(self): &#x20; """String representation of exact decimal subtotal is parsed accurately.""" &#x20; result = quote("100.10") &#x20; self.assertEqual(result\["subtotal"], Decimal("100.10")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("15.02")) # 100.10 \* 0.15 = 15.015 -> 15.02 &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("140.12")) &#x20; def test\_float\_subtotal\_accepted(self): &#x20; """Float input is converted to string internally to avoid IEEE 754 precision issues.""" &#x20; # Note: str(100.10) in Python yields "100.1", which Decimal converts cleanly to Decimal('100.1'). &#x20; # We assert equality with Decimal since quote() converts float via str(subtotal). &#x20; result = quote(100.10) &#x20; self.assertEqual(result\["subtotal"], Decimal("100.1")) &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; self.assertEqual(result\["vat"], Decimal("15.02")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; self.assertEqual(result\["total"], Decimal("140.12")) &#x20; # ------------------------------------------------------------------------- &#x20; # Tier Discount Boundaries &#x20; # ------------------------------------------------------------------------- &#x20; def test\_tier\_5\_percent\_just\_below\_threshold(self): &#x20; """Subtotal of 499.99 is below the 500 threshold and receives no tier discount.""" &#x20; result = quote("499.99") &#x20; self.assertEqual(result\["discount"], Decimal("0")) &#x20; def test\_tier\_5\_percent\_at\_threshold(self): &#x20; """Subtotal of 500.00 hits the 5% tier threshold and gets a 5% discount.""" &#x20; result = quote("500.00") &#x20; self.assertEqual(result\["discount"], Decimal("25.00")) # 500 \* 0.05 &#x20; def test\_tier\_10\_percent\_just\_below\_threshold(self): &#x20; """Subtotal of 1999.99 is below the 2000 threshold and receives only the 5% tier discount.""" &#x20; result = quote("1999.99") &#x20; self.assertEqual(result\["discount"], Decimal("99.9995")) # 1999.99 \* 0.05 &#x20; def test\_tier\_10\_percent\_at\_threshold\_not\_cumulative(self): &#x20; """Subtotal of 2000.00 receives only the highest matching 10% tier discount, not 10% + 5%.""" &#x20; result = quote("2000.00") &#x20; self.assertEqual(result\["discount"], Decimal("200.00")) # 2000 \* 0.10 (not 2000 \* 0.15) &#x20; # ------------------------------------------------------------------------- &#x20; # Coupon Functionality \& Edge Cases &#x20; # ------------------------------------------------------------------------- &#x20; def test\_percentage\_coupon\_without\_tier\_discount(self): &#x20; """SAVE10 applies a 10% discount on subtotals below tier thresholds.""" &#x20; result = quote("100.00", coupon\_code="SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("10.00")) &#x20; def test\_fixed\_coupon\_without\_tier\_discount(self): &#x20; """FLAT50 applies a fixed 50 SAR discount on subtotals below tier thresholds.""" &#x20; result = quote("100.00", coupon\_code="FLAT50") &#x20; self.assertEqual(result\["discount"], Decimal("50.00")) &#x20; def test\_coupon\_stacks\_with\_tier\_discount(self): &#x20; """Coupons combine additively with tier discounts when both apply.""" &#x20; # Subtotal 500 gets 5% tier (25) + SAVE10 10% (50) = 75 discount &#x20; result = quote("500.00", coupon\_code="SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("75.00")) &#x20; def test\_fixed\_coupon\_exceeds\_subtotal\_clamps\_discounted\_amount(self): &#x20; """FLAT50 on a subtotal of 30 clamps discounted amount to 0, resulting in 0 VAT and standard shipping.""" &#x20; result = quote("30.00", coupon\_code="FLAT50") &#x20; self.assertEqual(result\["subtotal"], Decimal("30.00")) &#x20; self.assertEqual(result\["discount"], Decimal("50.00")) # Raw discount recorded &#x20; self.assertEqual(result\["vat"], Decimal("0.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) # 0 < 300 &#x20; self.assertEqual(result\["total"], Decimal("25.00")) &#x20; def test\_unknown\_coupon\_code\_raises\_key\_error(self): &#x20; """Passing an unrecognized coupon code raises a KeyError.""" &#x20; with self.assertRaises(KeyError): &#x20; quote("100.00", coupon\_code="INVALID\_CODE") &#x20; # ------------------------------------------------------------------------- &#x20; # Free Shipping Thresholds &#x20; # ------------------------------------------------------------------------- &#x20; def test\_free\_shipping\_at\_discounted\_threshold(self): &#x20; """Shipping is free when the discounted subtotal is exactly 300 SAR.""" &#x20; result = quote("300.00") &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; def test\_shipping\_charged\_when\_discount\_pulls\_amount\_below\_300(self): &#x20; """Subtotal of 320 with SAVE10 results in 288 discounted amount, triggering flat shipping of 25.""" &#x20; # Subtotal 320 - SAVE10 (32) = Discounted 288 (< 300) &#x20; result = quote("320.00", coupon\_code="SAVE10") &#x20; self.assertEqual(result\["discount"], Decimal("32.00")) &#x20; self.assertEqual(result\["shipping"], Decimal("25")) &#x20; def test\_free\_shipping\_retained\_when\_discounted\_amount\_above\_300(self): &#x20; """Shipping remains free if the discounted amount stays at or above 300 SAR after coupons.""" &#x20; # Subtotal 400 - SAVE10 (40) = Discounted 360 (>= 300) &#x20; result = quote("400.00", coupon\_code="SAVE10") &#x20; self.assertEqual(result\["shipping"], Decimal("0")) &#x20; # ------------------------------------------------------------------------- &#x20; # VAT Rounding Mechanics (15% ROUND\_HALF\_UP) &#x20; # ------------------------------------------------------------------------- &#x20; def test\_vat\_rounding\_exact\_half\_cent\_rounds\_up(self): &#x20; """VAT calculation rounds exact half-cent fractions up (ROUND\_HALF\_UP: 0.125 -> 0.13).""" &#x20; # Subtotal 0.83 \* 0.15 = 0.1245 (not half cent) &#x20; # Subtotal 0.83333... \* 0.15 = 0.125 &#x20; # 0.8333333333... is hard to express exactly, but subtotal 0.8333... isn't standard currency. &#x20; # Clean exact half-cent calculation: &#x20; # Discounted amount = 0.83333... -> Let's use subtotal 0.83 + no coupon = 0.83 \* 0.15 = 0.1245 -> 0.12 &#x20; # Let's use discounted amount of 0.8333 -> 0.8333 \* 0.15 = 0.124995 &#x20; # To get exact half cent (e.g. 0.005, 0.015, 0.025... ending in .xxx5): &#x20; # Discounted 0.8333333... \* 0.15 = 0.125 &#x20; # Exact fraction: 0.83 \* 0.15 = 0.1245 -> rounds to 0.12 &#x20; # Exact 0.125 VAT occurs when discounted amount = 0.125 / 0.15 = 0.833333... &#x20; # Let's pick exact decimal subtotal 1.83: 1.83 \* 0.15 = 0.2745 -> rounds to 0.27 &#x20; # Subtotal 0.833... -> using string subtotal "0.8333333333333333333333333333": &#x20; # Better: subtotal "0.83333333333333333333" \* 0.15 = 0.124999... &#x20; # Simple exact fraction: Subtotal "0.03" \* 0.15 = 0.0045 -> 0.00 &#x20; # Subtotal "0.17" \* 0.15 = 0.0255 -> 0.03 &#x20; # Subtotal "0.83333333333" -> Let's test 0.8333333333333333333333333333: &#x20; # For discounted = Decimal("0.8333333333333333333333333333"), VAT = 0.125 -> 0.13 &#x20; # Standard decimal exact half-cent check: &#x20; # Subtotal 0.8333333333333333333333333333 \* 0.15 = Decimal('0.12500000000000000000000000000') -> 0.13 &#x20; subtotal = Decimal("0.8333333333333333333333333333") &#x20; result = quote(subtotal) &#x20; self.assertEqual(result\["vat"], Decimal("0.13")) &#x20; def test\_vat\_rounding\_down\_below\_half\_cent(self): &#x20; """VAT calculation rounds down when fraction is strictly less than half a cent.""" &#x20; # Discounted 0.83 \* 0.15 = 0.1245 -> 0.12 &#x20; result = quote("0.83") &#x20; self.assertEqual(result\["vat"], Decimal("0.12")) if \_\_name\_\_ == "\_\_main\_\_": &#x20; unittest.main() To run the test suite: Bash python -m unittest test\_pricing.py