समय पर निर्भर कोड का यूनिट टेस्ट कैसे करें

वर्तमान समय पर निर्भर code का परीक्षण इस बात पर गहरे design प्रश्न उठाता है कि software external state के साथ कैसे interact करे। Commenters dependency-injected clocks, pure functions में timestamps पास करने, time APIs को monkey‑patch करने, और libfaketime जैसे system-level shims जैसे approaches की तुलना करते हैं, और बताते हैं कि choices भाषा के अनुसार तथा unit या integration tests के अनुसार बदलती हैं। कई लोगों का तर्क है कि समय को first-class dependency मानने से testability और architecture दोनों बेहतर होते हैं, जबकि दूसरे लोग third-party libraries, performance characteristics, या real hardware timing शामिल होने पर मौजूद कठोर सीमाओं की ओर इशारा करते हैं।

मुख्य सिद्धांत: समय को एक निर्भरता की तरह मानें

  • कई लोग तर्क देते हैं कि “समय भी किसी और निर्भरता की तरह है।”
  • सुझाए गए पैटर्न: एक clock/timer interface inject करें, now() फ़ंक्शन पास करें, या लॉजिक में स्पष्ट timestamp पास करें।
  • कुछ के लिए प्राथमिकता क्रम:
    • सबसे अच्छा: लॉजिक समय को डेटा के रूप में argument ले।
    • अगला: लॉजिक एक time-producing function ले।
    • फिर: DI के ज़रिए एक clock/timer object inject करें।

भाषा- और framework-विशिष्ट tooling

  • C++ लेख को संकीर्ण माना गया; अन्य भाषाएँ आसान mechanisms देती हैं।
  • Dynamic भाषाएँ (JS, Python, Ruby) अक्सर time को monkey-patch करती हैं या libraries का उपयोग करती हैं: Jest fake timers, freezegun/time-machine (Python), Timecop/Rails travel_to (Ruby)।
  • Java में आम तौर पर Clock inject किया जाता है। .NET 8 में TimeProvider और FakeTimeProvider जोड़े गए हैं। Go code अक्सर time.Now को function parameter के रूप में पास करता है।

Databases और multiple clocks

  • SQL में NOW() का उपयोग अपने-आप बुरा नहीं है, लेकिन यह एक दूसरी clock ला सकता है।
  • समस्याएँ तब आती हैं जब app time mocked हो लेकिन DB time real हो, या जब scheduler और executor अलग machines/clocks इस्तेमाल करें।
  • कई लोग consistency के लिए queries में time पास करने का सुझाव देते हैं।

Third‑party libraries और testing scope

  • यदि code जिस पर आपका नियंत्रण नहीं है real time call करता है, तो अपनी clock inject करना असंभव हो सकता है।
  • सुझाए गए जवाब:
    • Integration tests उपयोग करें और धीमे/कम isolated checks को स्वीकार करें।
    • Library को अपनी interface के पीछे wrap करें और test implementation दें।
    • इस पर बहस कि क्या first-party tests को कभी explicitly third-party behavior test करना चाहिए; यहाँ कड़ा मतभेद है।

System-level time interception

  • libfaketime जैसे tools (और इसी तरह की experimental libraries) system calls या vDSO functions को intercept करके process level पर time को fake करते हैं।
  • इन्हें शक्तिशाली माना जाता है, लेकिन कभी-कभी awkward भी (env vars, LD_PRELOAD) और सरल unit tests के लिए overkill।

समय पर निर्भर integration tests

  • Naive sleep()-based tests धीमे और load के तहत flaky होते हैं।
  • सामान्य workaround: fixed durations का इंतज़ार करने के बजाय observable side effects के लिए poll करना।
  • अन्य प्रस्ताव: process level पर faketime, test harness द्वारा नियंत्रित tenant-local clocks, या उच्च architectural level पर inject किए गए “test clocks”।

Mocks, DI complexity, और लेख की आलोचना

  • कुछ लोगों को चिंता है कि clocks और mocks inject करने से dependencies बढ़ती हैं और code के साथ काम करना कठिन हो जाता है; दूसरों का कहना है कि injected clocks testing और debugging दोनों में बहुत मदद करते हैं।
  • Mocks को ठीक माना गया है यदि वे public, well-defined interfaces का परीक्षण करें और उनका अत्यधिक उपयोग न हो।
  • कुछ लोग लेख को बहुत सरल मानते हैं: performance, hardware, multimedia जैसी real time-sensitive systems में चुनौतियाँ clock factories और templates से कहीं आगे जाती हैं।