Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
🟡 Advanced Python  ·  Lesson 29

Python Code Testing और Debugging

Testing और debugging क्यों ज़रूरी

Debugging यह पता लगाना है कि program ग़लत क्यों चल रहा है। Testing छोटे programs लिखना है जो आपका code अपने-आप जाँचें, ताकि वही bug दोबारा न आए। Professional developers नया code लिखने से ज़्यादा समय इन दो skills पर लगाते हैं।

Step 1: traceback नीचे से पढ़ें

Python – traceback_demo.py
def average(marks):
    return sum(marks) / len(marks)

def report(student):
    avg = average(student["marks"])
    return f"{student['name']}: {avg:.1f}"

print(report({"name": "Asha", "marks": [91, 88]}))
print(report({"name": "Ravi", "marks": []}))
Asha: 89.5 Traceback (most recent call last): File "~/project/traceback_demo.py", line 9, in <module> print(report({"name": "Ravi", "marks": []})) ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "~/project/traceback_demo.py", line 5, in report avg = average(student["marks"]) File "~/project/traceback_demo.py", line 2, in average return sum(marks) / len(marks) ~~~~~~~~~~~^~~~~~~~~~~~ ZeroDivisionError: division by zero
  1. आख़िरी line = error का प्रकार और message: ZeroDivisionError: division by zero।
  2. उसके ऊपर की line = जो line fail हुई (average के अंदर)।
  3. ऊपर की ओर पढ़ें कि किसने बुलाया: report → आपकी script की line 9।
  4. पूछें: किस value से यह fail हुआ? यहाँ marks ख़ाली list थी।
Errorआम कारण
NameErrorSpelling ग़लती या assign से पहले variable
TypeErrorग़लत type, जैसे "5" + 3 या argument छूटा
KeyError / IndexErrorDict में key नहीं / list के अंत से आगे index
AttributeErrorग़लत object पर method, अक्सर None
IndentationErrorTabs/spaces मिले हुए या indent छूटा

Step 2: print() बनाम logging

जल्दी जाँच के लिए print ठीक है, पर असली programs में logging इस्तेमाल करें: level से messages चालू/बंद कर सकते हैं, समय जोड़ सकते हैं और file में लिख सकते हैं – बाद में lines delete किए बिना।

Python – logging_demo.py
import logging

logging.basicConfig(level=logging.INFO, format="%(levelname)-8s %(funcName)s: %(message)s")
log = logging.getLogger(__name__)

def apply_discount(price, percent):
    log.debug("raw input price=%r percent=%r", price, percent)   # hidden at INFO level
    if not 0 <= percent <= 50:
        log.warning("discount %s%% looks wrong, using 0", percent)
        percent = 0
    final = round(price * (100 - percent) / 100, 2)
    log.info("final price %s", final)
    return final

apply_discount(1200, 10)
apply_discount(1200, 90)
INFO apply_discount: final price 1080.0 WARNING apply_discount: discount 90% looks wrong, using 0 INFO apply_discount: final price 1200.0
Levelकिसके लिए
DEBUGDevelopment के दौरान विस्तृत values
INFOसामान्य पड़ाव (“order saved”)
WARNINGकुछ अजीब पर program चलता रहता है
ERRORकोई काम fail हुआ
CRITICALProgram आगे नहीं चल सकता

Step 3: breakpoint() से program रोकें

किसी भी line पर breakpoint() लगाएँ। Python वहाँ पहुँचते ही program रोककर terminal में debugger खोलता है। आप variables छाप सकते हैं, अगली line चला सकते हैं और आगे बढ़ सकते हैं।

Python – debug_me.py
def grade(marks):
    total = sum(marks)
    breakpoint()            # execution stops here
    percent = total / len(marks)
    return "A" if percent >= 85 else "B"

print(grade([91, 88, 79]))
> ~/project/debug_me.py(3)grade() -> breakpoint() # execution stops here (Pdb) p total 258 (Pdb) p len(marks) 3 (Pdb) n > ~/project/debug_me.py(4)grade() -> percent = total / len(marks) (Pdb) n > ~/project/debug_me.py(5)grade() -> return "A" if percent >= 85 else "B" (Pdb) p percent 86.0 (Pdb) c A
Commandअर्थ
p xx की value छापो
nअगली line चलाओ
sfunction call के अंदर जाओ
lमौजूदा line के आस-पास का code
cअगले breakpoint तक चलाओ
qबाहर निकलो
💡 VS Code debugger

VS Code में line number के बाईं ओर click करके लाल breakpoint लगाएँ, फिर F5 → “Python File”। Variables panel हर value दिखाता है और F10/F11 से step कर सकते हैं – कोई command याद नहीं रखनी।

Step 4: assert – सबसे छोटा test

Python – assert_demo.py
def to_paise(rupees):
    return round(rupees * 100)

assert to_paise(10) == 1000
assert to_paise(0.1 + 0.2) == 30          # floats are tricky – round() saves us
assert to_paise(99.99) == 9999
print("all checks passed")
all checks passed

assert की condition false हो तो Python AssertionError से रुक जाता है। Asserts tests में और “यह कभी नहीं होना चाहिए” checks में लगाएँ – user input जाँचने में नहीं (python -O से asserts बंद हो सकते हैं)।

Step 5: pytest से automated tests

यह दुकान का छोटा billing function है। नियम: coupon SAVE10 ₹500 या उससे ज़्यादा के bill पर चलता है, ₹1,000 से delivery मुफ़्त।

Python – bill.py
def bill_total(items, coupon=None):
    """items: list of (price, qty). SAVE10 gives 10% off on bills of Rs 500 or more."""
    subtotal = sum(price * qty for price, qty in items)
    if coupon == "SAVE10" and subtotal > 500:
        subtotal = subtotal * 0.9
    delivery = 0 if subtotal >= 1000 else 40
    return round(subtotal + delivery)

Tests साधारण functions हैं जिनके नाम test_ से शुरू होते हैं, test_*.py नाम की files में। pytest एक बार install करें (pip install pytest) और लिखें:

Python – test_bill.py
import pytest
from bill import bill_total

def test_small_order_pays_delivery():
    assert bill_total([(100, 2)]) == 240

def test_free_delivery_from_1000():
    assert bill_total([(500, 2)]) == 1000

def test_coupon_on_exactly_500():
    assert bill_total([(250, 2)], coupon="SAVE10") == 490   # 450 + 40 delivery

@pytest.mark.parametrize("items, expected", [
    ([], 40),
    ([(99.5, 2)], 239),
    ([(300, 1), (200, 1)], 540),
])
def test_many_cases(items, expected):
    assert bill_total(items) == expected
..F... [100%] =================================== FAILURES =================================== __________________________ test_coupon_on_exactly_500 __________________________ def test_coupon_on_exactly_500(): > assert bill_total([(250, 2)], coupon="SAVE10") == 490 # 450 + 40 delivery ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E AssertionError: assert 540 == 490 E + where 540 = bill_total([(250, 2)], coupon='SAVE10') test_bill.py:11: AssertionError =========================== short test summary info ============================ FAILED test_bill.py::test_coupon_on_exactly_500 - AssertionError: assert 540 ... 1 failed, 5 passed in 0.02s

एक test fail हुआ, और pytest ठीक-ठीक कारण दिखाता है: coupon के साथ ₹500 पर 490 चाहिए था पर 540 मिला। Bug है subtotal > 500; नियम कहता है “500 या ज़्यादा”। इसे >= 500 करें और फिर चलाएँ:

Python – bill.py (fixed), then run python -m pytest -q again
def bill_total(items, coupon=None):
    """items: list of (price, qty). SAVE10 gives 10% off on bills of Rs 500 or more."""
    subtotal = sum(price * qty for price, qty in items)
    if coupon == "SAVE10" and subtotal >= 500:
        subtotal = subtotal * 0.9
    delivery = 0 if subtotal >= 1000 else 40
    return round(subtotal + delivery)
...... [100%] 6 passed in 0.01s
💡 Edge cases test करें

Bugs किनारों पर रहते हैं: ख़ाली lists, ठीक 500, ठीक 1,000, decimals, zero, negative numbers। अच्छा test suite हर boundary एक बार जाँचता है।

Errors उठने की जाँच

Python – test_bank.py
import pytest

def withdraw(balance, amount):
    if amount <= 0:
        raise ValueError("amount must be positive")
    if amount > balance:
        raise ValueError("insufficient balance")
    return balance - amount

def test_normal_withdraw():
    assert withdraw(1000, 300) == 700

def test_overdraw_is_blocked():
    with pytest.raises(ValueError, match="insufficient"):
        withdraw(100, 500)
.. [100%] 2 passed in 0.00s

Built-in विकल्प: unittest

Python – test_pin.py
import unittest

def is_valid_pin(pin):
    return len(pin) == 6 and pin.isdigit() and pin[0] != "0"

class PinTests(unittest.TestCase):
    def test_valid(self):
        self.assertTrue(is_valid_pin("302001"))

    def test_invalid(self):
        for pin in ["02001", "0123456", "30200A", ""]:
            with self.subTest(pin=pin):
                self.assertFalse(is_valid_pin(pin))

if __name__ == "__main__":
    unittest.main(verbosity=2)
test_invalid (__main__.PinTests.test_invalid) ... ok test_valid (__main__.PinTests.test_valid) ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK

unittest को install नहीं करना पड़ता और कई पुराने projects में इस्तेमाल होता है। pytest unittest tests भी चला सकता है, इसलिए दोनों मिला सकते हैं।

हमेशा काम करने वाली debugging routine

  1. सबसे छोटे input से bug दोबारा पैदा करें।
  2. Traceback नीचे से पढ़ें।
  3. logging, breakpoint() या VS Code debugger से values देखें।
  4. एक अनुमान बनाकर जाँचें – एक बार में एक बदलाव।
  5. ऐसा test लिखें जो bug की वजह से fail हो।
  6. Test pass होने तक code ठीक करें, फिर सारे tests चलाएँ।

अभ्यास

  1. ऊपर वाले average() को ठीक करें ताकि ख़ाली list पर 0 लौटे, और उसका pytest test लिखें।
  2. समय के साथ (%(asctime)s) app.log file में logging जोड़ें।
  3. is_valid_mobile(number) (10 digits, 6–9 से शुरू) के लिए 5 pytest tests लिखें।
  4. breakpoint() से पता लगाएँ कि total में "10" + str(5) से 105 क्यों आता है।

सारांश

  • Traceback नीचे से पढ़ें: error type → fail हुई line → बुलाने वाले।
  • बिखरे prints की जगह logging levels।
  • breakpoint() या VS Code debugger से रोककर values देखें।
  • pytest: files test_*.py, functions test_*, साधारण assert; parametrize और pytest.raises।
  • हर ठीक किए bug का test बनाएँ ताकि वह लौटे नहीं।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

pytest या unittest – कौन सा सीखें?
नए projects के लिए pytest सीखें: tests छोटे, error messages साफ़ और plugins बहुत। unittest की basics जानें क्योंकि पुराने projects और कुछ interviews इसे इस्तेमाल करते हैं; pytest दोनों चलाता है।
कितने tests काफ़ी हैं?
हर ज़रूरी नियम और हर boundary (ख़ाली, zero, सीमाएँ, ग़लत input) test करें। ऊँचे coverage number की जगह ऐसे tests का लक्ष्य रखें जो असली bug पकड़ें।
← Back to Python Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 लाइव कोड एडिटर

इस पेज के प्रोग्राम यहीं तैयार हैं — चलाएँ, बदलें और सीखें। कुछ भी इंस्टॉल किए बिना।
OneCompiler द्वारा संचालित। कोड एडिटर में अपने आप आ जाता है — Run दबाकर आउटपुट देखें। अगर एडिटर न खुले तो नए टैब में खोलें.
अगला topicPython Best Practices आपकी प्रगति: 29 / 66 (44%) · Lesson 30 / 66 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें