`test::nginx` का कम ज्ञात उपयोग

API7.ai

November 24, 2022

OpenResty (NGINX + Lua)

पिछले दो लेखों में, आपने test::nginx के अधिकांश उपयोग को महारत हासिल कर लिया है, और मुझे विश्वास है कि आप OpenResty प्रोजेक्ट में अधिकांश टेस्ट केस सेट को समझ सकते हैं। यह OpenResty और इसके आसपास की लाइब्रेरीज़ को सीखने के लिए पर्याप्त से अधिक है।

लेकिन अगर आप OpenResty कोड योगदानकर्ता बनने में रुचि रखते हैं, या यदि आप अपने प्रोजेक्ट्स में टेस्ट केस लिखने के लिए test::nginx का उपयोग कर रहे हैं, तो आपको कुछ और उन्नत और जटिल उपयोग सीखने की आवश्यकता है।

आज का लेख शायद इस श्रृंखला का सबसे "अलोकप्रिय" हिस्सा होगा क्योंकि यह कुछ ऐसा है जिसे पहले किसी ने साझा नहीं किया है। OpenResty में कोर मॉड्यूल lua-nginx-module को उदाहरण के रूप में लें, जिसके दुनिया भर में 70 से अधिक योगदानकर्ता हैं, लेकिन हर योगदानकर्ता ने टेस्ट केस नहीं लिखा है। इसलिए यदि आप आज का लेख पढ़ते हैं, तो आपकी test::nginx की समझ दुनिया भर में टॉप 100 में प्रवेश कर जाएगी।

टेस्ट में डिबगिंग

सबसे पहले, आइए कुछ सबसे सरल और सामान्य रूप से उपयोग किए जाने वाले सेक्शन्स को देखें जो डेवलपर्स सामान्य डिबगिंग में उपयोग करते हैं। यहां, हम इन डिबगिंग-संबंधित सेक्शन्स के उपयोग के परिदृश्यों को एक-एक करके पेश करेंगे।

ONLY

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

तो, क्या कोई तरीका है कि आप केवल एक टेस्ट केस को चला सकें जिसे आप निर्दिष्ट करते हैं? यह ONLY सेक्शन के साथ आसानी से किया जा सकता है।

=== TEST 1: sanity === TEST 2: get --- ONLY

उपरोक्त स्यूडोकोड दिखाता है कि इस सेक्शन का उपयोग कैसे करें। --- ONLY को उस टेस्ट केस की अंतिम पंक्ति में डालकर जिसे अकेले चलाने की आवश्यकता है, तो जब आप prove का उपयोग करके टेस्ट केस फ़ाइल चलाते हैं, तो अन्य सभी टेस्ट केस को अनदेखा किया जाएगा, और केवल यह एक टेस्ट चलेगा।

हालांकि, यह केवल तब उपयुक्त है जब आप डिबगिंग कर रहे हों। इसलिए, जब prove कमांड ONLY सेक्शन को पाता है, तो यह आपको यह भी याद दिलाएगा कि कोड को कमिट करते समय इसे हटाना न भूलें।

SKIP

केवल एक टेस्ट केस को चलाने की आवश्यकता के अनुरूप, एक विशेष टेस्ट केस को अनदेखा करने की आवश्यकता है। SKIP सेक्शन, जो आमतौर पर उस फंक्शनलिटी को टेस्ट करने के लिए उपयोग किया जाता है जो अभी तक लागू नहीं की गई है:

=== TEST 1: sanity === TEST 2: get --- SKIP

इस स्यूडोकोड से आप देख सकते हैं, इसका उपयोग ONLY के समान है। क्योंकि हम टेस्ट-ड्रिवेन डेवलपमेंट कर रहे हैं, हमें पहले टेस्ट केस लिखने की आवश्यकता है; और जब हम सामूहिक रूप से इम्प्लीमेंटेशन कोडिंग कर रहे हैं, तो हमें इम्प्लीमेंटेशन की कठिनाई या प्राथमिकता के कारण किसी फीचर के इम्प्लीमेंटेशन को टालने की आवश्यकता हो सकती है। फिर, आप संबंधित टेस्ट केस सेट को पहले छोड़ सकते हैं, और जब इम्प्लीमेंटेशन पूरा हो जाए तो SKIP सेक्शन को हटा सकते हैं।

LAST

एक और सामान्य सेक्शन है LAST, जिसका उपयोग भी सरल है, क्योंकि इससे पहले के टेस्ट केस चलाए जाएंगे और इसके बाद के टेस्ट केस को अनदेखा किया जाएगा।

=== TEST 1: sanity === TEST 2: get --- LAST === TEST 3: set

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

plan

सभी test::nginx फंक्शन्स में, plan सबसे परेशान करने वाला और समझने में कठिन है। यह Perl के Test::Plan मॉड्यूल से लिया गया है, जिसका डॉक्यूमेंटेशन test::nginx में नहीं है, और इसकी व्याख्या ढूंढना आसान नहीं है। इसलिए, मैं इसे शुरुआती भाग में पेश करूंगा। मैंने कई OpenResty कोड योगदानकर्ताओं को देखा है जो इस गड्ढे में गिर गए और बाहर भी नहीं निकल सके।

यहां एक उदाहरण है जो आप OpenResty के आधिकारिक टेस्ट सेट में हर फ़ाइल की शुरुआत में देख सकते हैं:

plan tests => repeat_each() * (3 * blocks());

यहां plan का अर्थ है कि पूरे टेस्ट फ़ाइल में योजना के अनुसार कितने टेस्ट किए जाने चाहिए। यदि अंतिम रन का परिणाम योजना से मेल नहीं खाता है, तो टेस्ट विफल हो जाएगा।

इस उदाहरण के लिए, यदि repeat_each का मान 2 है और 10 टेस्ट केस हैं, तो plan का मान 2 x 3 x 10 = 60 होना चाहिए। एकमात्र चीज जो आपको भ्रमित कर सकती है वह है संख्या 3 का अर्थ, जो एक जादुई संख्या की तरह लगता है!

चिंता न करें, आइए उदाहरण को देखना जारी रखें, आप इसे कुछ ही समय में समझ जाएंगे। सबसे पहले, क्या आप निम्नलिखित टेस्ट केस में plan का सही मान निर्धारित कर सकते हैं?

=== TEST 1: sanity --- config location /t { content_by_lua_block { ngx.say("hello") } } --- request GET /t --- response_body hello

मुझे विश्वास है कि हर कोई यह निष्कर्ष निकालेगा कि plan = 1, क्योंकि टेस्ट केवल response_body की जांच करता है।

लेकिन ऐसा नहीं है! सही उत्तर है कि plan = 2। क्यों? क्योंकि test::nginx में एक निहित जांच है, यानी --- error_code: 200, जो डिफ़ॉल्ट रूप से HTTP रिस्पांस कोड 200 की जांच करता है।

तो, उपरोक्त जादुई संख्या 3 का वास्तविक अर्थ है कि प्रत्येक टेस्ट को स्पष्ट रूप से दो बार जांचा जाता है, उदाहरण के लिए body और error log के लिए, और निहित रूप से response code के लिए।

चूंकि यह इतना त्रुटि-प्रवण है, मैं आपको निम्नलिखित तरीके से plan को बंद करने की सलाह देता हूं।

use Test::Nginx::Socket 'no_plan';

यदि आप इसे बंद नहीं कर सकते हैं, उदाहरण के लिए, यदि आप OpenResty के आधिकारिक टेस्ट सेट में एक गलत plan का सामना करते हैं, तो यह अनुशंसा की जाती है कि आप कारण की गहराई में न जाएं, बल्कि केवल plan के एक्सप्रेशन में संख्याओं को जोड़ें या घटाएं।

plan tests => repeat_each() * (3 * blocks()) + 2;

यह भी आधिकारिक तरीका है जिसका उपयोग किया जाएगा।

प्रीप्रोसेसर

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

इस समय, आप add_block_preprocessor निर्देश का उपयोग करके एक पीस Perl कोड जोड़ सकते हैं, जैसे निम्नलिखित:

add_block_preprocessor(sub { my $block = shift; if (!defined $block->config) { $block->set_value("config", <<'_END_'); location = /t { echo $arg_a; } _END_ } });

यह प्रीप्रोसेसर सभी टेस्ट केस में एक config सेक्शन जोड़ता है, और सामग्री location /t है, ताकि आपके बाद के टेस्ट केस में, आप config को छोड़ सकें और सीधे इसे एक्सेस कर सकें।

=== TEST 1: --- request GET /t?a=3 --- response_body 3 === TEST 2: --- request GET /t?a=blah --- response_body blah

कस्टम फंक्शन्स

प्रीप्रोसेसर में Perl कोड जोड़ने के अलावा, आप run_tests फंक्शन से पहले मनमाने Perl फंक्शन्स, या जैसा कि हम कहते हैं, कस्टम फंक्शन्स भी जोड़ सकते हैं।

यहां एक उदाहरण है जो एक फ़ाइल को पढ़ने वाला फंक्शन जोड़ता है और इसे eval निर्देश के साथ जोड़कर एक POST फ़ाइल को लागू करता है:

sub read_file { my $infile = shift; open my $in, $infile or die "cannot open $infile for reading: $!"; my $content = do { local $/; <$in> }; close $in; $content; } our $CONTENT = read_file("t/test.jpg"); run_tests; __DATA__ === TEST 1: sanity --- request eval "POST /\n$::CONTENT"

शफल

उपरोक्त के अलावा, test::nginx में एक कम ज्ञात गड्ढा है: यह डिफ़ॉल्ट रूप से टेस्ट केस को यादृच्छिक क्रम में चलाता है, बजाय टेस्ट केस के क्रम और नंबरिंग का पालन करने के।

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

निचले स्तर के प्रोजेक्ट्स के लिए, यह सच है। हालांकि, एप्लिकेशन-स्तर के प्रोजेक्ट्स के लिए, बाहरी रूप से डेटाबेस जैसे स्थायी संग्रहण मौजूद हैं। एक अव्यवस्थित निष्पादन गलत परिणाम दे सकता है। चूंकि यह हर बार यादृच्छिक होता है, यह त्रुटि की रिपोर्ट कर सकता है या नहीं भी कर सकता है, और त्रुटि हर बार अलग हो सकती है। यह स्पष्ट रूप से डेवलपर्स के लिए भ्रम पैदा करता है, जिसमें मैं भी शामिल हूं, क्योंकि मैं यहां कई बार फंस चुका हूं।

इसलिए, मेरी सलाह है: कृपया इस सुविधा को बंद कर दें। आप इसे निम्नलिखित दो लाइन कोड के साथ बंद कर सकते हैं:

no_shuffle(); run_tests;

विशेष रूप से, no_shuffle का उपयोग यादृच्छिकता को अक्षम करने के लिए किया जाता है और टेस्ट को टेस्ट केस के क्रम में सख्ती से चलाने की अनुमति देता है।

reindex

OpenResty के टेस्ट केस सेट में सख्त फॉर्मेटिंग आवश्यकताएं हैं। प्रत्येक टेस्ट केस को तीन नई लाइनों से अलग किया जाना चाहिए, और टेस्ट केस नंबरिंग को सख्ती से स्व-बढ़ती होनी चाहिए।

सौभाग्य से, हमारे पास इस थकाऊ काम को करने के लिए एक स्वचालित टूल, reindex है, जो openresty-devel-utils प्रोजेक्ट में छिपा हुआ है। चूंकि इसके बारे में कोई डॉक्यूमेंटेशन नहीं है, केवल कुछ लोग ही इसके बारे में जानते हैं।

यदि आप रुचि रखते हैं, तो आप टेस्ट केस नंबरिंग को गड़बड़ करने की कोशिश कर सकते हैं, या लाइन ब्रेक की संख्या को जोड़ या हटा सकते हैं, और फिर इस टूल का उपयोग करके इसे सही कर सकते हैं और देख सकते हैं कि क्या आप इसे पुनर्स्थापित कर सकते हैं।

सारांश

यह test::nginx का परिचय समाप्त करता है। बेशक, और भी कई फंक्शन्स हैं, हमने केवल कोर और सबसे महत्वपूर्ण फंक्शन्स के बारे में बात की है। "एक व्यक्ति को मछली दो और आप उसे एक दिन के लिए खिलाओ; उसे मछली पकड़ना सिखाओ और आप उसे जीवन भर के लिए खिलाओ।" मैंने आपको टेस्टिंग सीखने के लिए बुनियादी तरीके और सावधानियां सिखाई हैं, फिर आप आधिकारिक टेस्ट केस सेट में गहराई से जाकर बेहतर समझ प्राप्त कर सकते हैं।

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