4.5.13 · Coding › Software Engineering
Software parts ka ek tower hai. Tests woh checks hain jo ek brick ko pakad lete hain poora tower girne se pehle.
Trick yeh hai ki kahan aur kab check karo:
Har brick ko akele check karo → unit
Check karo ki bricks ek saath fit hoti hain → integration
Poore tower ko waisa check karo jaise ek user dekhta hai → system
Check karo ki customer actually yahi tower chahta tha → acceptance
Ek jaldi "kya yeh khada bhi hai?" wali nazar → smoke
"Kya meri nayi brick ne koi purani tod di?" → regression
WHY yeh matter karta hai: ek bug ki cost har stage par ~10× badhti hai jab woh escape karta hai. Ek bug jo unit test mein pakda gaya uski cost cents hoti hai; wohi bug production mein ek customer ko cost karta hai.
Ek guideline ki har tarah ke kitne tests likhne chahiye: neeche bahut saare fast unit tests, beech mein kam integration tests, aur upar bahut kam slow end-to-end/system tests.
Intuition WHY ek pyramid hai aur square nahin?
Lower tests fast, cheap, deterministic hote hain, aur fault ko pinpoint karte hain (ek failing unit test = ek broken function).
Higher tests slow, flaky, aur vague hote hain (ek failing system test kuch bhi ho sakta hai).
Isliye aap apni 80% effort un 20% tests mein lagate ho jo neeche hain aur sabse zyada bugs sabse saste mein pakad lete hain.
Sabse chhoti isolated piece (ek function/method/class) ko test karta hai jisme saari dependencies ko mocks/stubs se replace kar diya jaata hai.
WHY isolate karo? Taaki ek failure ka matlab ho ki yeh unit galat hai, uska neighbour nahin.
HOW: function ko inputs ke saath call karo, output assert karo.
Definition Integration test
Test karta hai ki do ya zyada units ek saath kaam karte hain (jaise aapka code + real database, ya module A module B ko call karta hai).
WHY: units akele pass kar sakti hain phir bhi seam par tod sakti hain (galat data format, galat API call).
HOW: real components wire karo, unke beech ka interface exercise karo.
Poori assembled application ko ek black box ki tarah uski requirements ke against test karta hai (UI → backend → DB end-to-end).
WHY: validate karta hai ki jo product bana hai woh overall sahi kaam karta hai.
HOW: ise us tarah drive karo jaise ek user/automated UI karta hai; observable behaviour check karo.
Definition Acceptance test
Check karta hai ki system customer/business requirements ko meet karta hai — "kya humne sahi cheez banayi?"
WHY: system test puchta hai "sahi kaam karta hai?"; acceptance puchta hai "kya yeh wohi hai jo manga gaya tha ?" (often user stories / "Given–When–Then" ke roop mein likha jaata hai).
HOW: stakeholders ya BDD specs pass criteria define karte hain; UAT = User Acceptance Testing.
Tests ka ek chhota, fast subset jo check karta hai ki build fundamentally broken nahin hai ("kya yeh on bhi hota hai?").
WHY: poora 2-ghante ka suite run karne ka koi faida nahin agar login turant crash kare. Smoke pehle run karo.
HOW: kuch critical-path checks (app start hoti hai, homepage load hoti hai, log in ho sakta hai).
Origin: hardware — plug in karo, agar smoke nikle, testing band karo.
Definition Regression test
Kisi change ke baad existing tests dobara run karna taaki ensure ho ki purane features abhi bhi kaam karte hain (change ne pehle kaam karne wali cheez ko regress / tod nahin diya).
WHY: code fix/add karna silently unrelated features tod sakta hai.
HOW: tests rakhho, har change par run karo (CI). Often automated hota hai aur har commit par trigger hota hai.
Common mistake Steel-man: "Verification vs Validation" ki confusion
Galat idea jo tempting lagta hai: "system test aur acceptance test same hain — dono poori app run karte hain."
Kyun sahi lagta hai: dono end-to-end aur black-box hain.
Fix: V&V yaad karo:
Verification = "Kya hum product sahi tarike se bana rahe hain?" → system test (spec ko meet karta hai).
Validation = "Kya hum sahi product bana rahe hain?" → acceptance test (user ki real need ko meet karta hai).
Ek system har system test pass kar sakta hai aur phir bhi galat product ho sakta hai.
Common mistake Steel-man: smoke ≠ regression
Galat idea: "smoke test bas ek chhota regression test hai, same cheez."
Kyun sahi lagta hai: dono ek set of checks dobara run karte hain.
Fix: smoke = breadth-first, shallow, baaki ko gate karne ke liye pehle run karo. Regression = change ke baad existing behaviour protect karne ke liye purane tests dobara run karo. Alag purpose, alag scope.
Common mistake Steel-man: integration test as a fat unit test
Galat idea: "Main apne integration test mein bhi sab kuch mock kar lunga."
Kyun sahi lagta hai: mocks tests ko fast aur stable banate hain.
Fix: agar aap DB integration test mein database mock karte ho, toh aap wapas unit test par aa jaate ho — aapne real seam test hi nahin ki. Integration tests jaanbujhkar us boundary par real collaborators use karte hain jis par aapko dhyan hai.
Worked example Example 1 — ek unit test
Function: def is_even(n): return n % 2 == 0
def test_is_even ():
assert is_even( 4 ) == True # Why? happy path, even number
assert is_even( 3 ) == False # Why? odd, the negative case
assert is_even( 0 ) == True # Why? boundary/edge case 0
Kyun teen asserts? Ek value se correctness prove nahin hoti — aap true case, false case, aur ek edge cover karte ho. Koi DB, koi network nahin → pure unit.
Worked example Example 2 — "save user" feature par unit vs integration
Unit: validate_email("a@b.com") ko test karo ki True return karta hai, DB mocked away ke saath. Why? Hum sirf validation logic test kar rahe hain.
Integration: repository.save(user) ko real (test) database ke against call karo, phir wapas read karo. Why? Yeh seam par SQL, schema, aur serialization check karta hai — woh cheezein jo ek mock nahin pakad sakta.
Worked example Example 3 — regression action mein
Aap total() mein ek rounding bug fix karte ho. Aap fix ke liye ek test add karte ho, phir poora existing suite run karte ho.
Ek pehle-pass-hone-wala test test_discount() ab fail karta hai. Yeh step kyun matter karta hai: aapki "fix" ne shared rounding change kar di aur discounts tod diye — regression suite ne ise release se pehle pakad liya. Iske bina, bug ship ho jaata.
Worked example Example 4 — CI pipeline mein run karne ka order
commit → smoke (30s) → unit (2m) → integration (5m) → system (20m) → acceptance (manual/UAT)
Yeh order kyun? Sabse sasta aur sabse zyada likely-to-fail-fast pehle. Agar smoke fail kare, ruko — 27 minute waste mat karo.
Unit test kya isolate karta hai aur kaise? Sabse chhoti piece (function/class) ko dependencies ko mocks/stubs se replace karke.
Integration test — yeh specifically kya check karta hai? Ki do ya zyada units apne seam/interface par sahi tarike se saath kaam karte hain (often real collaborators jaise DB ke saath).
System test kaun sa V&V question answer karta hai? Verification — "kya hum product sahi tarike se bana rahe hain?" (spec ko meet karta hai, full app black-box).
Acceptance test kaun sa V&V question answer karta hai? Validation — "kya hum sahi product bana rahe hain?" (user/business need ko meet karta hai; UAT).
Smoke test ka purpose kya hai? Ek chhota fast check ki build fundamentally broken nahin hai; poore suite ko gate karne ke liye pehle run karo.
Regression test ka purpose kya hai? Change ke baad existing tests dobara run karna taaki ensure ho ki pehle kaam karne wale features abhi bhi kaam karte hain.
Test pyramid neeche wide kyun hoti hai? Unit tests fast, cheap, deterministic hote hain aur faults pinpoint karte hain; high-level tests slow/flaky/vague hote hain — isliye bahut saare cheap wale likho.
Ek bug ke n stages escape karne ki cost (formula)? Cost = c ⋅ k n , roughly har stage par 10×.
DB integration test mein database mock kyun nahin karna chahiye? Aap mock test kar rahe hoge, real seam nahin — yeh unit test mein degenerate ho jaata hai.
n independent tests ke liye suite trust probability jisme har ek p reliable hai? P = p n — flaky tests tezi se compound karte hain.
Recall Feynman: ek 12-saal-ke bacche ko samjhao
Socho tum ek LEGO spaceship bana rahe ho.
Unit test: tum check karte ho ki har LEGO brick cracked nahin hai.
Integration test: tum do bricks snap karte ho aur kheenchte ho — kya woh hold karti hain?
System test: tum poori spaceship ko room mein udaate ho — kya yeh kaam karta hai?
Acceptance test: tum apne dost ko dikhate ho jisne kaha tha "mujhe ek laal spaceship chahiye" — kya yeh actually unki mangi hui laal hai?
Smoke test: kuch bhi karne se pehle, tum bas check karte ho ki yeh uthate hi bikhar nahin jaati.
Regression test: nayi wing add karne ke baad, tum check karte ho ki purani wing pop off nahin hui.
Har brick check karna sasta hai; crack tab dhundhna jab spaceship crash kar chuki ho yeh expensive hai — isliye hum pehle choti cheezein check karte hain aur aksar karte hain.
Mnemonic Chhe ko yaad karo
"U I S A S R" → "U I S ee A S oftware R unning."
Aur har ek kaun sa question answer karta hai: System = Spec (right-ly), Acceptance = Asked-for.
"Many small, few tall." (bahut saare unit, bahut kam system/e2e)
Test-Driven Development (TDD) — failing unit test pehle likho.
Mocks Stubs and Fakes — woh tools jo unit isolation possible banate hain.
Continuous Integration — jahan smoke + regression automatically har commit par run hote hain.
Verification and Validation — system vs acceptance ka V&V framing.
Code Coverage — measure karna ki aapke tests code ko kitna exercise karte hain.
Behaviour-Driven Development (BDD) — acceptance tests ke liye Given/When/Then.
Defect Cost of Delay — jaldi testing ke peeche ki c ⋅ k n economics.