पाठ 13 / 25

सार्थक Tests बनवाना

जाँचें कि बनाए गए tests कोड ग़लत होने पर सचमुच विफल होंगे।

खोखले tests किसी भी कोड पर पास होते हैं

Assistants तेज़ी से कई tests बना सकते हैं, पर कुछ लगभग कुछ भी assert नहीं करते: वे सिर्फ़ यह जाँचते हैं कि function कुछ लौटाता है, या implementation का ही तर्क दोहराते हैं। त्वरित जाँच है कोड को जानबूझकर तोड़ना और देखना कि tests विफल होते हैं या नहीं। जो test टूटे कोड पर भी हरा रहे वह झूठा भरोसा देता है। छूटे मामले भी देखें: खाली input, सीमाएँ, अमान्य input और error रास्ते।

प्रमाणित करें, फिर समझाएँ

Assistants tests और docs जल्दी लिखते हैं, पर आपको पक्का करना है कि वे कुछ असली जाँचें।

तीन चरण: बनाएँ, जानबूझकर तोड़ें, दस्तावेज़ लिखें।
चित्र 4.1 — बनाएँ, जानबूझकर तोड़ें और दस्तावेज़ लिखें।

कमज़ोर test बनाम मज़बूत test

मैंने यह चलाया। सही function पर दोनों पास होते हैं। is_even को हमेशा True लौटाने वाला बना देने पर कमज़ोर test फिर भी पास होता है और सिर्फ़ मज़बूत test विफल होता है।

def is_even(n): return n % 2 == 0
def weak_test():   assert is_even(2) in (True, False)      # always passes
def strong_test(): assert is_even(2) is True and is_even(3) is False

def broken_is_even(n): return True
is_even = broken_is_even
for name, fn in (("weak", weak_test), ("strong", strong_test)):
    try: fn(); print(name, "passes on BROKEN code")
    except AssertionError: print(name, "fails on broken code")

Output:

weak passes on BROKEN code
strong fails on broken code

हाथ से mutation

> को >= कर दें, कोई शर्त पलट दें या स्थिर मान लौटाएँ, फिर tests चलाएँ। कुछ विफल न हो तो tests उस पंक्ति की रक्षा नहीं कर रहे। Mutation testers नाम के tools इसी विचार को स्वचालित करते हैं।

त्वरित जाँच: आप कैसे जाँचें कि बनाया गया test सार्थक है?

  • देखें कि उसमें कितनी पंक्तियाँ हैं
  • कोड जानबूझकर तोड़ें और देखें कि वह विफल होता है या नहीं
  • देखें कि उसका नाम लंबा है
  • उसे हटा दें
Answer

कोड जानबूझकर तोड़ें और देखें कि वह विफल होता है या नहीं — सार्थक test तब विफल होता है जब उसका बचाया व्यवहार टूट जाए।