क्या यूनिट परीक्षणों में मैजिक नंबर स्वीकार्य हैं यदि संख्याओं का कोई मतलब नहीं है?


59

अपने यूनिट परीक्षणों में, मैं अक्सर अपने कोड पर मनमाने ढंग से मान फेंक देता हूं कि यह क्या करता है। उदाहरण के लिए, अगर मुझे पता है कि foo(1, 2, 3)17 को वापस जाना है, तो मैं यह लिख सकता हूं:

assertEqual(foo(1, 2, 3), 17)

ये संख्या विशुद्ध रूप से मनमानी है और इसका कोई व्यापक अर्थ नहीं है (वे उदाहरण के लिए, सीमा की स्थिति नहीं हैं, हालांकि मैं उन पर भी परीक्षण करता हूं)। मैं इन नंबरों के लिए अच्छे नामों के साथ आने के लिए संघर्ष करूंगा, और ऐसा कुछ लिखना const int TWO = 2;स्पष्ट रूप से अनहेल्दी है। क्या इस तरह के परीक्षणों को लिखना ठीक है, या मुझे संख्याओं को स्थिरांक में बदलना चाहिए?

में सभी जादू संख्या एक ही बनाया? , हमने सीखा कि जादू संख्या ठीक है यदि अर्थ संदर्भ से स्पष्ट है, लेकिन इस मामले में संख्याओं का वास्तव में कोई अर्थ नहीं है।


9
यदि आप मान डाल रहे हैं और उन समान मानों को वापस पढ़ने में सक्षम होने की उम्मीद कर रहे हैं, तो मैं कहूंगा कि मैजिक नंबर ठीक हैं। तो अगर, कहते हैं, 1, 2, 33 डी सरणी सूचकांक हैं, जहां आपने पहले मूल्य संग्रहीत किया था 17, तो मुझे लगता है कि यह परीक्षण बांका होगा (जब तक आपके पास कुछ नकारात्मक परीक्षण भी हैं)। लेकिन अगर यह एक गणना का परिणाम है, तो आपको यह सुनिश्चित करना चाहिए कि इस परीक्षण को पढ़ने वाला कोई भी समझ जाएगा कि क्यों foo(1, 2, 3)होना चाहिए 17, और जादू की संख्याएं शायद उस लक्ष्य को प्राप्त नहीं करेंगी।
जो सफेद

24
const int TWO = 2;केवल उपयोग करने से भी बदतर है 2। यह आत्मा के उल्लंघन के इरादे से नियम के शब्दों के अनुरूप है।
Agent_L 12

4
एक संख्या क्या है जो "कुछ भी मतलब नहीं है"? यदि आपके पास कुछ नहीं है तो यह आपके कोड में क्यों होगा?
टिम ग्रांट

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

5
आपका उदाहरण भ्रामक है - जब आपका फ़ंक्शन नाम वास्तव fooमें होगा, तो इसका कोई मतलब नहीं होगा, और इसलिए पैरामीटर। लेकिन वास्तविकता में, मैं बहुत यकीन है कि समारोह है कि नाम नहीं है हूँ, और मानकों के नाम की जरूरत नहीं है bar1, bar2और bar3। अधिक यथार्थवादी उदाहरण बनाएं जहां नामों का अर्थ है, तो यह चर्चा करने के लिए बहुत अधिक समझ में आता है कि क्या परीक्षण डेटा मानों को भी नाम की आवश्यकता है।
डॉक ब्राउन

जवाबों:


81

आपके पास वास्तव में ऐसी संख्याएँ कब हैं जिनका कोई मतलब नहीं है?

आमतौर पर, जब संख्याओं का कोई अर्थ होता है, तो आपको कोड को अधिक पठनीय और आत्म-समझाने के लिए परीक्षण विधि के स्थानीय चर के लिए उन्हें असाइन करना चाहिए। चर के नाम कम से कम यह दर्शाते हैं कि चर का क्या मतलब है, जरूरी नहीं कि इसका मूल्य।

उदाहरण:

const int startBalance = 10000;
const float interestRate = 0.05f;
const int years = 5;

const int expectedEndBalance = 12840;

assertEqual(calculateCompoundInterest(startBalance, interestRate, years),
            expectedEndBalance);

ध्यान दें कि पहले चर का नाम नहीं है HUNDRED_DOLLARS_ZERO_CENT, लेकिन startBalanceयह बताने के लिए कि चर का अर्थ क्या है लेकिन यह नहीं कि इसका मूल्य किसी भी तरह से विशेष है।


3
@ केविन - आप किस भाषा में परीक्षण कर रहे हैं? कुछ परीक्षण रूपरेखाएँ आपको डेटा प्रदाता सेट करती हैं जो परीक्षण के लिए मानों की सारणी की एक सरणी
लौटाते हैं

10
हालांकि मैं विचार से सहमत हैं, सावधान रहना है कि इस अभ्यास नई त्रुटियां भी लागू कर सकते हैं, अगर आप गलती से की तरह एक मूल्य निकालने की तरह 0.05fएक करने के लिए int। :)
जेफ बोमन

5
+1 - बढ़िया सामान। सिर्फ इसलिए कि आप परवाह नहीं करते हैं कि एक विशेष मूल्य क्या है, इसका मतलब यह नहीं है कि यह अभी भी एक जादू की संख्या नहीं है ...
रोबी डी

2
@ पीटर: AFAIK सी और सी ++ की गलती है, जिसने एक constचर की धारणा को औपचारिक रूप दिया ।
स्टीव जेसोप

2
क्या आपने अपने चरों का नामकरण मानकों के नाम के समान किया है calculateCompoundInterest? यदि ऐसा है, तो अतिरिक्त टाइपिंग एक प्रूफ-ऑफ-वर्क है जिसे आप अपने द्वारा परीक्षण किए गए फ़ंक्शन के लिए दस्तावेज़ीकरण पढ़ चुके हैं, या कम से कम आपके आईडीई द्वारा आपको दिए गए नामों की नकल करते हैं। मुझे यकीन नहीं है कि यह पाठक को कोड के इरादे के बारे में कितना बताता है, लेकिन यदि आप मापदंडों को गलत क्रम में पास करते हैं तो वे कम से कम यह बता सकते हैं कि क्या इरादा था।
स्टीव जेसोप

20

यदि आप मनमाने ढंग से संख्याओं का उपयोग कर रहे हैं, तो केवल यह देखने के लिए कि वे क्या करते हैं, तो आप वास्तव में जो खोज रहे हैं वह शायद बेतरतीब ढंग से उत्पन्न परीक्षण डेटा, या संपत्ति-आधारित परीक्षण है।

उदाहरण के लिए, हाइपोथीसिस इस तरह के परीक्षण के लिए एक शांत पायथन लाइब्रेरी है, और क्विकचेक पर आधारित है ।

निम्नलिखित की तरह कुछ होने के नाते एक सामान्य इकाई परीक्षण के बारे में सोचें:

  1. कुछ डेटा सेट करें।
  2. डेटा पर कुछ ऑपरेशन करें।
  3. परिणाम के बारे में कुछ बताएं।

परिकल्पना आपको परीक्षण लिखने देती है जो इसके बजाय इस तरह दिखते हैं:

  1. कुछ विनिर्देशन से मेल खाते सभी डेटा के लिए।
  2. डेटा पर कुछ ऑपरेशन करें।
  3. परिणाम के बारे में कुछ बताएं।

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

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

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


11
रैंडम परीक्षण में ऐसे कीड़े मिल सकते हैं जो प्रजनन के लिए कठिन होते हैं लेकिन बेतरतीब ढंग से परीक्षण करने से शायद ही कभी प्रजनन योग्य कीड़े मिलते हैं। एक विशिष्ट प्रतिलिपि प्रस्तुत करने योग्य परीक्षण मामले के साथ किसी भी परीक्षण विफलताओं को पकड़ने के लिए सुनिश्चित करें।
JBRWilkinson

5
और आप कैसे जानते हैं कि जब आप "परिणाम के बारे में कुछ मुखर करते हैं" तो इस इकाई का परीक्षण खराब नहीं होता है (इस मामले में, कंप्यूटिंग क्या fooहै) को पुनः स्थापित करें ...? यदि आप 100% सुनिश्चित थे कि आपका कोड सही उत्तर देता है, तो आप बस उस कोड को प्रोग्राम में डालेंगे और उसका परीक्षण नहीं करेंगे। यदि आप नहीं हैं, तो आपको परीक्षण का परीक्षण करने की आवश्यकता है, और मुझे लगता है कि हर कोई देखता है कि यह कहां जा रहा है।

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

7
@NajibIdrissi - जरूरी नहीं। उदाहरण के लिए, आप परीक्षण कर सकते हैं कि आप जिस परिक्षण में परीक्षण कर रहे हैं उसका उलटा लगाने से आपके द्वारा शुरू किया गया प्रारंभिक मूल्य वापस मिल जाता है। या आप अपेक्षित आक्रमणकारियों का परीक्षण कर सकते हैं (जैसे dदिनों में सभी ब्याज गणना के लिए, dदिन + 1 महीने की गणना एक ज्ञात मासिक प्रतिशत दर अधिक होना चाहिए), आदि
जूल्स

12
@ क्रिस - कई मामलों में, परिणाम की जाँच करना परिणाम उत्पन्न करने की तुलना में सही है। हालांकि यह सभी परिस्थितियों में सच नहीं है , वहाँ बहुत सारे हैं जहाँ यह है। उदाहरण: संतुलित बाइनरी ट्री में एक प्रविष्टि जोड़ने के परिणामस्वरूप एक नया पेड़ होना चाहिए जो संतुलित भी हो ... परीक्षण में आसान, व्यवहार में लागू करने के लिए काफी मुश्किल।
जूल्स

11

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

यदि वह पर्याप्त नहीं है, तो दस्तावेज़ का थोड़ा सा हिस्सा इसे प्रदान करने में सक्षम होना चाहिए (चाहे चर नाम या डॉकस्ट्रिंग के माध्यम से)। ध्यान रखें कि फ़ंक्शन में स्वयं पैरामीटर हैं जो उम्मीद करते हैं कि सार्थक नाम हैं। तर्कों को नाम देने के लिए उन्हें अपने परीक्षण में कॉपी करना व्यर्थ है।

और अंतिम, यदि आपके unittests पर्याप्त जटिल हैं कि यह कठिन है / व्यावहारिक नहीं है तो संभवतः आपके पास कार्यों के बहुत जटिल हैं और विचार कर सकते हैं कि ऐसा क्यों है।

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


यह उत्तर एक परीक्षण के उद्देश्य का उल्लेख करने में कठिनाई के बारे में प्रतीत होता है जबकि वास्तविक सवाल विधि मापदंडों में जादू की संख्या के बारे में है ...
रोबी डी

@RobbieDee एक परीक्षण के लिए नाम / दस्तावेज़ीकरण परीक्षण के भीतर जो भी जादू नंबर मौजूद हैं, उनका उपयुक्त संदर्भ और स्पष्टीकरण दिया जाना चाहिए। यदि नहीं, तो या तो दस्तावेज़ जोड़ें या परीक्षण को अधिक स्पष्ट होने के लिए नाम बदलें।
एंडरलैंड

मैजिक नंबरों को नाम देना अभी भी बेहतर होगा। यदि मापदंडों की संख्या बदलनी थी, तो दस्तावेज़ के जोखिम ख़त्म हो जाते हैं।
रॉबी डे

1
@RobbieDee फ़ंक्शन को ध्यान में रखते हैं पैरामीटर में उम्मीद है कि सार्थक नाम हैं। तर्कों को नाम देने के लिए उन्हें अपने परीक्षण में कॉपी करना व्यर्थ है।
एंडरलैंड

"उम्मीद है" हुह? क्यों न सिर्फ चीज़ को सही तरीके से कोड करें और न ही उस चीज़ से दूर रहें जो कि एक जादुई संख्या है जैसा कि फिलिप ने पहले ही रेखांकित किया है ...
रोबी डी

9

यह उस फ़ंक्शन पर बहुत निर्भर करता है जिसका आप परीक्षण कर रहे हैं। मैं ऐसे बहुत से मामलों को जानता हूँ जहाँ व्यक्तिगत संख्याओं का अपने आप में कोई विशेष अर्थ नहीं है, लेकिन एक पूरे के रूप में परीक्षण मामले का निर्माण सोच-समझकर किया गया है और इसलिए इसका एक विशिष्ट अर्थ है। यही किसी को किसी तरह से दस्तावेज करना चाहिए। उदाहरण के लिए, यदि fooवास्तव में एक ऐसी विधि है testForTriangleजो यह तय करती है कि तीन संख्याएँ त्रिभुज के किनारों की वैध लंबाई हो सकती हैं, तो आपके परीक्षण इस तरह दिख सकते हैं:

// standard triangle with area >0
assertEqual(testForTriangle(2, 3, 4), true);

// degenerated triangle, length of two edges match the length of the third
assertEqual(testForTriangle(1, 2, 3), true);  

// no triangle
assertEqual(testForTriangle(1, 2, 4), false); 

// two sides equal
assertEqual(testForTriangle(2, 2, 3), true);

// all three sides equal
assertEqual(testForTriangle(4, 4, 4), true);

// degenerated triangle / point
assertEqual(testForTriangle(0, 0, 0), true);  

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

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


संवेदनशील समाधान।
user1725145

6

हम संख्याओं के बजाय नामांकित स्थिरांक का उपयोग क्यों करना चाहते हैं?

  1. DRY - अगर मुझे 3 स्थानों पर मूल्य की आवश्यकता है, तो मैं केवल इसे एक बार परिभाषित करना चाहता हूं, इसलिए मैं इसे एक स्थान पर बदल सकता हूं, अगर यह बदल जाए।
  2. संख्याओं को अर्थ दें।

यदि आप कई यूनिट परीक्षण लिखते हैं, तो प्रत्येक में 3 नंबर (प्रारंभ, ब्याज, वर्ष) का वर्गीकरण होता है - मैं बस स्थानीय-चर के रूप में यूनिट-टेस्ट में मानों को पैक करूँगा। सबसे छोटा दायरा जहां वे हैं।

testBigInterest()
  var startBalance = 10;
  var interestInPercent = 100
  var years = 2
  assert( calcCreditSum( startBalance, interestInPercent, years ) == 40 )

testSmallInterest()
  var startBalance = 50;
  var interestInPercent = .5
  var years = 1
  assert( calcCreditSum( startBalance, interestInPercent, years ) == 50.25 )

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

testBigInterest()
  assert( calcCreditSum( startBalance:       10
                        ,interestInPercent: 100
                        ,years:               2 ) = 40 )

या एक परीक्षण-फ्रेमवर्क का उपयोग करें, जो आपको कुछ सरणी या मानचित्र प्रारूप में परीक्षण मामलों को परिभाषित करने की अनुमति देगा:

testcases = { {
                Name: "BigInterest"
               ,StartBalance:       10
               ,InterestInPercent: 100
               ,Years:               2
              }
             ,{ 
                Name: "SmallInterest"
               ,StartBalance:       50
               ,InterestInPercent:  .5
               ,Years:               1
              }
            }

3

... लेकिन इस मामले में संख्याओं का वास्तव में कोई मतलब नहीं है

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


1
यह आवश्यक रूप से सच नहीं है, हालांकि - जैसा कि मैंने हाल ही में लिखी गई इकाई परीक्षण के उदाहरण में ( assertEqual "Returned value" (makeKindInt 42) (runTest "lvalue_operators"))। इस उदाहरण में, 42बस एक प्लेसहोल्डर मान है जिसे परीक्षण स्क्रिप्ट नाम में कोड द्वारा निर्मित किया गया है lvalue_operatorsऔर फिर जब यह स्क्रिप्ट द्वारा लौटाया जाता है तो इसकी जाँच की जाती है। इसका कोई अर्थ नहीं है, इसके अलावा दो अलग-अलग जगहों पर एक ही मूल्य होता है। यहां एक उपयुक्त नाम क्या होगा जो वास्तविक कोई उपयोगी अर्थ देता है?
जूल्स

3

यदि आप इनपुट के एक सेट पर एक शुद्ध फ़ंक्शन का परीक्षण करना चाहते हैं जो सीमा की स्थिति नहीं है, तो आप लगभग निश्चित रूप से इनपुट के सेट के एक पूरे समूह पर इसका परीक्षण करना चाहते हैं जो (और) सीमा की स्थिति नहीं है। और मेरे लिए इसका मतलब है कि फ़ंक्शन को कॉल करने के लिए मानों की एक तालिका होनी चाहिए , और एक लूप:

struct test_foo_values {
    int bar;
    int baz;
    int blurf;
    int expected;
};
const struct test_foo_values test_foo_with[] = {
   { 1, 2, 3, 17 },
   { 2, 4, 9, 34 },
   // ... many more here ...
};

for (size_t i = 0; i < ARRAY_SIZE(test_foo_with); i++) {
    const struct test_foo_values *c = test_foo_with[i];
    assertEqual(foo(c->bar, c->baz, c->blurf), c->expected);
}

Dannnno के उत्तर में सुझाए गए जैसे उपकरण आपको परीक्षण करने के लिए मूल्यों की तालिका बनाने में मदद कर सकते हैं। bar, bazऔर फिलीपीन के उत्तरblurf में चर्चा के अनुसार सार्थक नामों द्वारा प्रतिस्थापित किया जाना चाहिए ।

(यहां तर्कपूर्ण सामान्य सिद्धांत: संख्याएं हमेशा "मैजिक नंबर" नहीं होती हैं, जिन्हें नाम की आवश्यकता होती है; इसके बजाय, संख्याएं डेटा हो सकती हैं । यदि यह आपके संख्याओं को एक सरणी में रखना संभवत: एक रिकॉर्ड की एक सरणी है, तो वे संभवतः डेटा हैं। इसके विपरीत, यदि आपको संदेह है कि आपके हाथों पर डेटा हो सकता है, तो इसे एक सरणी में रखें और इसे अधिक प्राप्त करने पर विचार करें।)


1

परीक्षण उत्पादन कोड से अलग हैं और, कम से कम स्पॉक में लिखी गई इकाइयों के परीक्षणों में, जो संक्षिप्त हैं और इस बिंदु पर, मेरे पास जादू स्थिरांक का उपयोग करने का कोई मुद्दा नहीं है।

यदि एक परीक्षण 5 लाइनों लंबा है, और मूल दिए गए / जब / फिर योजना का अनुसरण करता है, तो ऐसे मूल्यों को स्थिरांक में निकालने से कोड केवल लंबे समय तक और पढ़ने में कठिन हो जाएगा। यदि तर्क है "जब मैं स्मिथ नाम के उपयोगकर्ता को जोड़ता हूं, तो मैं देखता हूं कि उपयोगकर्ता स्मिथ उपयोगकर्ता सूची में वापस आ गया है", निरंतर के लिए "स्मिथ" को निकालने का कोई मतलब नहीं है।

यह निश्चित रूप से लागू होता है यदि आप "दिए गए" (सेटअप) ब्लॉक में उपयोग किए गए मानों को "जब" और "तब" ब्लॉक में पाए गए मूल्यों से आसानी से मिलान कर सकते हैं। यदि आपके परीक्षण सेटअप को डेटा का उपयोग किए जाने वाले स्थान से अलग (कोड में) किया गया है, तो यह स्थिर हो सकता है कि स्थिरांक का उपयोग करना बेहतर होगा। लेकिन चूंकि परीक्षण सर्वश्रेष्ठ आत्म-निहित होते हैं, सेटअप आमतौर पर उपयोग के स्थान के करीब होता है और पहला मामला लागू होता है, जिसका अर्थ है कि इस मामले में जादू स्थिरांक काफी स्वीकार्य हैं।


1

सबसे पहले आइए सहमति दें कि "यूनिट टेस्ट" का उपयोग अक्सर सभी स्वचालित परीक्षणों को कवर करने के लिए किया जाता है जो एक प्रोग्रामर लिखता है, और यह कि यह बहस करना व्यर्थ है कि प्रत्येक परीक्षण को क्या कहा जाना चाहिए ...।

मैंने एक ऐसी प्रणाली पर काम किया है, जहां सॉफ्टवेयर ने बहुत सारे इनपुट लिए और एक "समाधान" काम किया, जिसमें कुछ बाधाओं को पूरा करना था, जबकि अन्य संख्याओं का अनुकूलन करना। कोई सही उत्तर नहीं थे, इसलिए सॉफ्टवेयर को उचित जवाब देना था।

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

हमारे पास बहुत सारे परीक्षण थे जो ऊपर किए गए थे, और जाँच की कि परिणाम समान थे, इसने हमें बताया कि हमने बदला नहीं था कि सिस्टम के उस हिस्से ने गलती से क्या किया था, जबकि रिफलेक्टरिंग आदि ने हमें सही होने के बारे में कुछ नहीं बताया। सिस्टम के उस हिस्से ने क्या किया।

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

जैसा कि हमने डेटाबेस का "मजाक" किया था, आप इन परीक्षणों को "इकाई परीक्षण" कह सकते हैं, लेकिन "इकाई" बड़ा नहीं था।

अक्सर जब आप बिना किसी परीक्षण के सिस्टम पर काम कर रहे होते हैं, तो आप ऊपर जैसा कुछ करते हैं, ताकि आप पुष्टि कर सकें कि आपकी रिफैक्टरिंग आउटपुट को नहीं बदलती है; उम्मीद है कि नए कोड के लिए बेहतर परीक्षण लिखे गए हैं!


1

मुझे लगता है कि इस मामले में संख्याओं को मैजिक नंबरों की बजाय आर्बिटवर्ट नंबरों की संज्ञा दी जानी चाहिए, और लाइन को "मनमाना परीक्षण" के रूप में टिप्पणी करना चाहिए।

निश्चित रूप से, कुछ मैजिक नंबर भी अनियंत्रित हो सकते हैं, जैसे कि अनोखे "हैंडल" मान (जिन्हें नामांकित स्थिरांक के साथ प्रतिस्थापित किया जाना चाहिए), लेकिन यह भी "प्रायोगिक यूरोपीय स्पैरो की तरह वायुयान की गति से प्रति पखवाड़े में" अनियंत्रित स्थिरांक हो सकता है, जहाँ संख्यात्मक मान बिना टिप्पणियों या सहायक संदर्भ के प्लग किया जाता है।


0

मैं निश्चित रूप से हां / ना कहने के लिए उद्यम नहीं करूंगा, लेकिन यहां कुछ सवाल हैं जो आपको खुद से पूछना चाहिए कि यह ठीक है या नहीं।

  1. यदि संख्याओं का कोई मतलब नहीं है, तो वे पहले स्थान पर क्यों हैं? क्या उन्हें किसी और चीज़ से बदला जा सकता है? क्या आप वैल्यू असेसरीज के बजाय मेथड कॉल और फ्लो के आधार पर वेरिफिकेशन कर सकते हैं? मॉकिटो की verify()विधि की तरह कुछ पर विचार करें जो यह जांचता है कि क्या कोई निश्चित विधि कॉल वास्तव में एक मूल्य का दावा करने के बजाय वस्तुओं को नकली करने के लिए किया गया था या नहीं।

  2. संख्या तो ऐसा कुछ मतलब है, तो वे चर कि उचित नाम कर रहे हैं करने के लिए आवंटित किया जाना चाहिए।

  3. संख्या 2को लिखना TWOकुछ संदर्भों में सहायक हो सकता है, और अन्य संदर्भों में इतना नहीं।

    • उदाहरण के लिए: assertEquals(TWO, half_of(FOUR))कोड पढ़ने वाले व्यक्ति के लिए समझ में आता है। यह तुरंत स्पष्ट है कि आप क्या परीक्षण कर रहे हैं।
    • यदि फिर भी अपने परीक्षण है assertEquals(numCustomersInBank(BANK_1), TWO), तो यह नहीं है कि खास मतलब। क्यों करता है BANK_1दो ग्राहकों को शामिल? हम किस लिए परीक्षण कर रहे हैं?
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.