Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

रूबी नेटवर्क सर्विस टेस्टिंग को सरल बनाएं: सिद्ध रणनीतियाँ और टूल्स

आपने एक नया प्रोजेक्ट शुरू किया है और आपके कोड के लिए किसी थर्ड-पार्टी सर्विस पर निर्भर होने का समय आ गया है। ये इलास्टिकसर्च, रेसक्यू, बिलिंग प्रोवाइडर, या सिर्फ एक मनमाना HTTP API जैसा कुछ हो सकता है। आप एक अच्छे डेवलपर हैं, इसलिए आप इस कोड को अच्छी तरह से टेस्ट करना चाहते हैं। लेकिन आप उस कोड को कैसे टेस्ट करते हैं जो आपके नियंत्रण से पूरी तरह बाहर एक सर्विस पर रिक्वेस्ट भेजता है?

आप टेस्ट छोड़ सकते हैं, लेकिन आप जल्द ही एक अस्थिर नींव पर अधिक कोड जमा कर रहे होंगे। अनटेस्टेड कोड अधिक जटिल कोड को आकर्षित करता है, और आप अंततः महसूस करेंगे कि कोड रिफैक्टर करने के लिए बहुत खतरनाक है क्योंकि आपके पास सुरक्षित महसूस करने के लिए आवश्यक टेस्ट कवरेज नहीं है। आप अपने भविष्य के काम के लिए एक स्थिर नींव बनाना चाहते हैं, लेकिन इसके बजाय आप एक अनरखरखाव योग्य गड़बड़ के साथ समाप्त हो गए हैं।

इस स्थिति से बचना जितना लगता है उससे कहीं ज्यादा आसान है! कुछ टूल्स और थोड़े से अग्रिम प्रयास के साथ, आप अपने टेस्ट्स को उन सर्विसेज से अलग कर सकते हैं जिन पर आपका कोड निर्भर करता है, सरल कोड लिख सकते हैं, और आपके द्वारा लिखे गए कोड को सुधारने का आत्मविश्वास रख सकते हैं - बग्स पेश किए बिना। उन अगले टेस्ट्स को लिखने के तरीके पर टालमटोल करने के बजाय क्योंकि आप नहीं जानते कि कैसे दृष्टिकोण अपनाएं, आप अपने कोड और बाहरी दुनिया के बीच एक इंटरैक्शन को देख सकते हैं, और ठीक से जान सकते हैं कि इसके बीच में कैसे कूदना है।

मोचा: त्वरित-और-गंदा दृष्टिकोण

मोचा आपके कोड और बाहरी दुनिया के बीच आने का सबसे आसान तरीका है।

एक उदाहरण के रूप में, मान लें कि आपके पास एक Cart ऑब्जेक्ट है जो चेक आउट होने पर क्रेडिट कार्ड चार्ज को ट्रिगर करता है। आप यह सुनिश्चित करना चाहते हैं कि अगर चार्ज विफल होता है तो कार्ट में एक एरर मैसेज जुड़ा हुआ है।

आप शायद नहीं चाहेंगे कि आपके टेस्ट वास्तव में हर बार टेस्ट चलने पर बिलिंग सिस्टम को हिट करें. भले ही आप चाहें, उस सर्विस को विफलता वापस करने के लिए मजबूर करना कठिन हो सकता है। यहाँ मोचा के साथ ये कैसा दिखेगा:

def test_error_message_set_on_charge_failure
  cart = Cart.new(items)
  cart.stubs(:charge!).returns(false) # मोचा एक्शन में
  cart.checkout!
  assert_equal "The credit card could not be charged", cart.credit_card_error
end

मोचा आपके टेस्ट्स को भी फेल कर सकता है अगर मेथड्स को उस तरह से नहीं बुलाया जाता जैसा आप उम्मीद करते हैं:

def test_only_bill_once_per_cart
  cart = Cart.new(items)
  cart.expects(:charge!).once # डबल-बिल न करें, चाहे हम कितनी बार चेक आउट करें
  cart.checkout!
  cart.checkout!
end

मोचा उपयोग करने में सरल है, लेकिन अविश्वसनीय रूप से आसान हो सकता है। आपको सावधान रहना होगा कि आप केवल उस व्यवहार को मॉक कर रहे हैं जो आप नहीं होने देना चाहते - बहुत ज्यादा मॉक करना आसान है और वास्तविक बग्स को छुपा देता है। आप इस दृष्टिकोण के साथ ओवरबोर्ड भी नहीं जाना चाहते: expects और stubs से भरे टेस्ट पढ़ने और सोचने में कठिन होते हैं।

टेस्ट फेक्स: मेरा पसंदीदा दृष्टिकोण

अगर आप उन्हीं ऑब्जेक्ट्स पर उन्हीं मेथड्स को हर समय मॉक या स्टब करते हैं, तो आप अपने मॉक्स को पूर्ण विकसित ऑब्जेक्ट्स (कभी-कभी टेस्ट फेक्स कहलाते हैं) में प्रोमोट कर सकते हैं, जैसे ये:

def test_billed_full_amount_minus_discount
  test_payment_provider = TestPaymentProvider.new # एक नकली पेमेंट प्रोवाइडर
  cart = Cart.new(items, discount: 30, provider: test_payment_provider)
  cart.checkout!
  assert_equal items.sum(:&price) * 0.7, test_payment_provider.total_charges
end

फेक्स महान हैं:

  • आपका फेक इसकी आंतरिक स्थिति को ट्रैक कर सकता है

    फेक में कस्टम असर्शन मैसेज और हेल्पर फंक्शन्स हो सकते हैं जो आपके टेस्ट लिखना आसान बनाते हैं, जैसे ऊपर के उदाहरण में total_charges मेथड।

  • एक पूर्ण विकसित ऑब्जेक्ट के रूप में, आपको अतिरिक्त एडिटर और भाषा समर्थन मिलता है

    अगर आप एक ऐसे एडिटर का उपयोग कर रहे हैं जो इसका समर्थन करता है, तो आपको ऑटोकम्प्लीट, इनलाइन डॉक्यूमेंटेशन, और अन्य चीजें मिल सकती हैं जो आपको मोचा के साथ इंडिविजुअल मेथड्स को स्टब करके नहीं मिलेंगी। आपको बेहतर वैलिडेशन, एक्सेप्शन हैंडलिंग, और जो कुछ भी आप अपने फेक में बनाना चाहते हैं वो मिलेगा।

  • अगर आप डेवलपमेंट मोड में एक फेक का उपयोग करते हैं, तो आपको असली सर्विस से कनेक्शन की आवश्यकता नहीं है

    आप बस में अपना ऐप लिख सकते हैं, आपको अपने लैपटॉप की बैटरी खत्म करने वाले सर्विसेज के जंगल की आवश्यकता नहीं है, और आप इन फेक सर्विसेज को सेट कर सकते हैं ताकि वे बहुत सारे सेटअप के बिना एज केस के माध्यम से काम करने के लिए आपको आवश्यक डेटा वापस करें।

  • ये ऑब्जेक्ट्स आपके टेस्ट्स के बाहर उपयोग किए जा सकते हैं

    ये शायद फेक्स का मेरा पसंदीदा हिस्सा है। आप एक लॉगिंग क्लाइंट को एक थर्ड-पार्टी सर्विस और आपके फेक दोनों पर लॉग कर सकते हैं, जो एक इन-मेमोरी ऐरे द्वारा समर्थित है। आप फिर इस ऐरे की सामग्री को अपनी साइट पर एक एडमिन व्यू में डंप कर सकते हैं, जिससे यह सत्यापित करना बहुत आसान हो जाता है कि आप वही लॉग कर रहे हैं जो आपको लगता है कि आप लॉग कर रहे हैं।

आप ऐसा कुछ कर सकते हैं:

fake_backend = FakeBackend.new
LoggingService.backends = [RealBackend.new, fake_backend]
LoggingService.debug("TEST MESSAGE PLEASE IGNORE")
fake_backend.messages.first # => [:debug, "TEST MESSAGE PLEASE IGNORE"]

एक फेक लिखने में इंडिविजुअल मेथड्स को स्टब करने की तुलना में अधिक प्रयास लगता है, लेकिन अभ्यास के साथ इसमें एक या दो घंटे से अधिक नहीं लगने चाहिए एक उपयोगी फेक बनाने के लिए। अगर आप एक ऐसा बनाते हैं जो अन्य लोगों के लिए उपयोगी होगा, तो इसे साझा करें! मैंने बहुत समय पहले resque-unit बनाया था, और बहुत सारे लोग आज भी इसका उपयोग करते हैं।

मुझे वैसे भी ये ऑब्जेक्ट्स इंजेक्ट कैसे मिलते हैं?

आपको अपने टेस्ट के तहत ऑब्जेक्ट्स को इन फेक्स से बात करवाना होगा। सौभाग्य से, रूबी को गाली देना इतना आसान है कि फेक्स इंजेक्ट करना आमतौर पर कठिन नहीं है।

अगर आप टेस्ट के तहत ऑब्जेक्ट के API को नियंत्रित करते हैं, तो एक डिफ़ॉल्ट पैरामीटर, एक एट्रिब्यूट, या एक कंस्ट्रक्टर विकल्प जोड़ना सबसे अच्छा है जहां आप अपना फेक सेट कर सकते हैं:

class Card
  attr_reader :provider
  def initialize(items, options={})
    @provider = options.fetch(:provider) { RealProvider.new }
  end
end

ये तब साफ होता है जब आप असली सर्विस से बात कर रहे होते हैं और आपको बाद में लचीलापन जोड़ने के लिए एक हुक देता है।

अगर आप ऑब्जेक्ट को नियंत्रित नहीं करते या अतिरिक्त पैरामीटर नहीं जोड़ना चाहते, तो आप हमेशा मंकी पैच कर सकते हैं:

# अगर टेस्ट मोड में
Card.class_eval do
  def provider
    @provider ||= TestProvider.new
  end
end

ये टेस्ट में बदसूरत है, लेकिन उन वातावरणों में साफ है जो फेक का उपयोग नहीं करते।

अभी अपना खुद का फेक बनाना शुरू करें

फेक्स बनाना अभ्यास के साथ आसान हो जाता है, तो आपको इसे अभी आज़माना चाहिए:

  • एक ऐसा टेस्ट खोजें जो किसी बाहरी सर्विस से बात करता है। टेस्ट जो इंटरनेट से डिस्कनेक्ट होने पर विफल होंगे, अच्छे उम्मीदवार हैं।
  • पता लगाएं कि कौन सा ऑब्जेक्ट वास्तव में कम्युनिकेशन करता है, और आपका कोड उस ऑब्जेक्ट पर कौन से कॉल करता है।
  • उस ऑब्जेक्ट की क्लास का एक ज्यादातर खाली डुप्लीकेट बनाएं, और इसे आपके द्वारा किए गए कॉल्स को एक ऐरे में लॉग करने दें।
  • अपने फेक में एक मेथड जोड़ें जो किए गए कॉल्स की सूची वापस करता है।
  • असली ऑब्जेक्ट को अपने नए फेक ऑब्जेक्ट से स्वैप करें, और अपने कोड द्वारा किए गए कॉल्स के खिलाफ कुछ असर्शन लिखें।

अगर आप इसे आज़माते हैं, तो मुझे बताएं कि ये कैसा रहा!

इन तकनीकों के साथ, ये ज्यादा समय नहीं होगा जब तक कि आप अपने एप्लिकेशन और बाहरी दुनिया के बीच सबसे पागल इंटरैक्शन को वश में करने में सक्षम न हों। सही जगह पर एक साधारण स्टब आपको अपने अच्छी तरह से टेस्टेड कोड को आत्मविश्वास के साथ शिप करने देगा।

  1. टेस्ट-कमिट-रिवर्ट: लिगेसी रूबी कोड को सुरक्षित रूप से टेस्ट करने के लिए एक व्यावहारिक वर्कफ़्लो टेस्ट-कमिट-रिवर्ट: लिगेसी रूबी कोड को सुरक्षित रूप से टेस्ट करने के लिए एक व्यावहारिक वर्कफ़्लो

    यह हम सभी के साथ होता है। जैसे-जैसे सॉफ़्टवेयर प्रोजेक्ट बढ़ते हैं, कोडबेस के कुछ हिस्से एक व्यापक टेस्ट सूट के बिना प्रोडक्शन में चले जाते हैं। जब आप कुछ महीनों बाद कोड के उसी क्षेत्र को फिर से देखते हैं, तो इसे समझना मुश्किल हो सकता है; इससे भी बदतर, इसमें एक बग हो सकता है, और हमें नहीं पता कि इसे

  1. रूबी में स्टैटिक एनालिसिस में महारत: पार्सर जेम के साथ मेथड्स और पैरामीटर्स निकालें रूबी में स्टैटिक एनालिसिस में महारत: पार्सर जेम के साथ मेथड्स और पैरामीटर्स निकालें

    मान लीजिए कि आप अपने सोर्स कोड को पार्स करके अपने सभी मेथड्स ढूंढना चाहते हैं, वे कहां परिभाषित हैं और वे कौन से तर्क लेते हैं। आप यह कैसे कर सकते हैं? आपका पहला विचार इसके लिए एक रेगेक्स लिखना हो सकता है… लेकिन क्या कोई बेहतर तरीका है? हाँ! स्टैटिक एनालिसिस एक तकनीक है जिसका उपयोग आप तब कर सकते है

  1. रूबी नेटवर्क प्रोग्रामिंग में मास्टर करें: सॉकेट्स के साथ कस्टम क्लाइंट्स और सर्वर्स बनाएं रूबी नेटवर्क प्रोग्रामिंग में मास्टर करें: सॉकेट्स के साथ कस्टम क्लाइंट्स और सर्वर्स बनाएं

    क्या आप रूबी में कस्टम नेटवर्क क्लाइंट्स और सर्वर्स बनाना चाहते हैं? या बस यह समझना चाहते हैं कि यह कैसे काम करता है? तब आपको सॉकेट्स से निपटना होगा। मेरे साथ रूबी नेटवर्क प्रोग्रामिंग के इस दौरे में शामिल हों ताकि मूल बातें सीख सकें, और रूबी का उपयोग करके अन्य सर्वरों और क्लाइंट्स से बात करना शुरू