यह सांख्यिकीय रूप से टाइप किए जाने के बजाय गतिशील रूप से होगा । बत्तख टाइपिंग फिर वही काम करेगा जो इंटरफेस टाइप की गई भाषाओं में करते हैं। इसके अलावा, इसकी कक्षाएं रनटाइम के दौरान परिवर्तनीय होंगी ताकि एक परीक्षण ढांचा मौजूदा कक्षाओं पर आसानी से ठूंठ या नकली तरीकों का उपयोग कर सके। रूबी एक ऐसी भाषा है; TDD के लिए rspec इसका प्रमुख परीक्षण ढांचा है।
कैसे गतिशील टाइपिंग एड्स परीक्षण
डायनेमिक टाइपिंग के साथ, आप केवल एक वर्ग बनाकर नकली वस्तुओं का निर्माण कर सकते हैं, जिसमें एक ही इंटरफ़ेस (विधि हस्ताक्षर) होता है, जिस सहयोगी वस्तु का आपको मजाक बनाने की आवश्यकता होती है। उदाहरण के लिए, मान लीजिए कि आपके पास संदेश भेजने वाले कुछ वर्ग थे:
class MessageSender
def send
# Do something with a side effect
end
end
मान लें कि हमारे पास एक MessageSenderUser है जो MessageSender का एक उदाहरण का उपयोग करता है:
class MessageSenderUser
def initialize(message_sender)
@message_sender = message_sender
end
def do_stuff
...
@message_sender.send
...
@message_sender.send
...
end
end
यहाँ निर्भरता इंजेक्शन के उपयोग पर ध्यान दें , इकाई परीक्षण का एक मुख्य आधार। हम उस पर वापस आएंगे।
आप परीक्षण करना चाहते हैं कि MessageSenderUser#do_stuff
कॉल दो बार भेजें। जैसे आप वैधानिक रूप से टाइप की गई भाषा में हैं, आप एक नकली मैसेजएन्डर बना सकते हैं जो यह बताता है कि कितनी बार send
कॉल किया गया था। लेकिन सांख्यिकीय रूप से टाइप की गई भाषा के विपरीत, आपको कोई इंटरफ़ेस वर्ग नहीं चाहिए। आप बस आगे बढ़ें और इसे बनाएं:
class MockMessageSender
attr_accessor :send_count
def initialize
@send_count = 0
end
def send
@send_count += 1
end
end
और अपने परीक्षण में इसका उपयोग करें:
mock_sender = MockMessageSender.new
MessageSenderUser.new(mock_sender).do_stuff
assert_equal(mock_sender.send_count, 2)
अपने आप में, गतिशील रूप से टाइप की गई भाषा का "डक टाइपिंग" सांख्यिकीय रूप से टाइप की गई भाषा की तुलना में परीक्षण में उतना अधिक नहीं जोड़ता है। लेकिन क्या होगा अगर कक्षाएं बंद नहीं होती हैं, लेकिन रनटाइम में संशोधित की जा सकती हैं? वह गेम चेंजर है। आइए देखें कैसे।
क्या होगा अगर आपको क्लास टेस्ट करने योग्य बनाने के लिए निर्भरता इंजेक्शन का उपयोग नहीं करना पड़े?
मान लीजिए कि MessageSenderUser संदेश भेजने के लिए केवल MessageSender का उपयोग करेगा, और आपको किसी अन्य वर्ग के साथ MessageSender के प्रतिस्थापन की अनुमति देने की कोई आवश्यकता नहीं है। एक कार्यक्रम के भीतर अक्सर ऐसा होता है। चलिए MessageSenderUser को फिर से लिखते हैं ताकि यह केवल एक निर्भरता इंजेक्शन के साथ एक MessageSender बनाता और उपयोग करता है।
class MessageSenderUser
def initialize
@message_sender = MessageSender.new
end
def do_stuff
...
@message_sender.send
...
@message_sender.send
...
end
end
MessageSenderUser अब उपयोग करने के लिए एक सरल है: कोई भी इसे बनाने के लिए इसका उपयोग करने के लिए एक MessageSender बनाने की आवश्यकता है। यह इस सरल उदाहरण में एक बड़े सुधार की तरह नहीं दिखता है, लेकिन अब कल्पना करें कि MessageSenderUser एक से अधिक स्थानों में बनाया गया है, या इसमें तीन निर्भरताएं हैं। अब सिस्टम के पास इकाई परीक्षणों को खुश करने के लिए पूरे आस-पास के कई उदाहरण हैं, इसलिए नहीं कि यह आवश्यक रूप से डिजाइन को बेहतर बनाता है।
खुली कक्षाएं आपको निर्भरता इंजेक्शन के बिना परीक्षण करने देती हैं
डायनामिक टाइपिंग और ओपन क्लास वाली भाषा में एक टेस्ट फ्रेमवर्क TDD को काफी अच्छा बना सकता है। यहाँ MessageSenderUser के लिए एक rspec परीक्षण से एक कोड स्निपेट है:
mock_message_sender = mock MessageSender
MessageSender.should_receive(:new).and_return(mock_message_sender)
mock_message_sender.should_receive(:send).twice.with(no_arguments)
MessageSenderUser.new.do_stuff
वह पूरी परीक्षा है। यदि ठीक दो बार MessageSenderUser#do_stuff
आह्वान नहीं MessageSender#send
किया जाता है, तो यह परीक्षण विफल हो जाता है। वास्तविक MessageSender वर्ग को कभी भी लागू नहीं किया जाता है: हमने परीक्षण से कहा कि जब भी कोई व्यक्ति MessageSender बनाने का प्रयास करता है, तो उन्हें इसके बजाय हमारा नकली MessageSender प्राप्त करना चाहिए। कोई निर्भरता इंजेक्शन आवश्यक नहीं है।
इस तरह के एक सरल परीक्षण में इतना अच्छा है। जब तक यह वास्तव में आपके डिज़ाइन के लिए समझ में नहीं आता, तब तक निर्भरता इंजेक्शन का उपयोग न करना कभी अच्छा नहीं है।
लेकिन खुले वर्गों के साथ इसका क्या करना है? को कॉल नोट करें MessageSender.should_receive
। जब हमने MessageSender लिखा था, तो हमने #should_receive को परिभाषित नहीं किया था, इसलिए किसने किया? इसका उत्तर यह है कि टेस्ट फ्रेमवर्क, सिस्टम कक्षाओं के कुछ सावधान संशोधनों को बनाते हुए, यह प्रकट करने में सक्षम है जैसा कि #should_receive के माध्यम से प्रत्येक वस्तु पर परिभाषित किया गया है। अगर आपको लगता है कि सिस्टम कक्षाओं को संशोधित करना कुछ सावधानी की आवश्यकता है, तो आप सही हैं। लेकिन यह सही बात है कि टेस्ट लाइब्रेरी यहाँ क्या कर रही है, और खुली कक्षाएं इसे संभव बनाती हैं।