टीडीडी और पूर्ण परीक्षण कवरेज जहां घातीय परीक्षण मामलों की आवश्यकता होती है


18

मैं अपने ग्राहक से बहुत विशिष्ट आवश्यकताओं के अनुसार खोज परिणामों की एक अनियंत्रित सूची को सॉर्ट करने में सहायता करने के लिए एक सूची तुलनित्र पर काम कर रहा हूं। आवश्यकता के क्रम में निम्नलिखित नियमों के साथ रैंक प्रासंगिक एल्गोरिथ्म के लिए आवश्यकताओं को बुलाती है:

  1. नाम पर सटीक मिलान
  2. नाम में खोज क्वेरी के सभी शब्द या परिणाम का एक पर्याय
  3. परिणाम के नाम या पर्यायवाची में खोज क्वेरी के कुछ शब्द (% अवरोही)
  4. विवरण में खोज क्वेरी के सभी शब्द
  5. विवरण में खोज क्वेरी के कुछ शब्द (% अवरोही)
  6. अंतिम संशोधित तिथि अवरोही

इस तुलनित्र के लिए प्राकृतिक डिजाइन का विकल्प 2 की शक्तियों के आधार पर स्कोर की गई रैंकिंग प्रतीत होता है। कम महत्वपूर्ण नियमों का योग कभी भी उच्च महत्व के नियम पर सकारात्मक मैच से अधिक नहीं हो सकता है। यह निम्नलिखित स्कोर द्वारा प्राप्त किया जाता है:

  1. 32
  2. 16
  3. 8 (% उतरने पर आधारित माध्यमिक टाई-ब्रेकर स्कोर)
  4. 4
  5. 2 (सेकेंडरी टाई-ब्रेकर स्कोर% के आधार पर)
  6. 1

TDD स्पिरिट में मैंने पहले अपनी यूनिट टेस्ट के साथ शुरुआत करने का फैसला किया। प्रत्येक अद्वितीय परिदृश्य के लिए एक परीक्षण का मामला होना न्यूनतम 63 अद्वितीय परीक्षण मामलों में होगा नियम 3 और 5 पर माध्यमिक टाई ब्रेकर तर्क के लिए अतिरिक्त परीक्षण मामलों पर विचार नहीं करना।

वास्तविक परीक्षण वास्तव में हालांकि कम होंगे। वास्तविक नियमों के आधार पर, कुछ नियम यह सुनिश्चित करते हैं कि निचले नियम हमेशा सत्य होंगे (उदाहरण के लिए। 'जब सभी खोज क्वेरी शब्द विवरण में दिखाई देते हैं' तो नियम 'कुछ खोज क्वेरी शब्द विवरण में प्रकट होते हैं' हमेशा सही होगा)। अभी भी इनमें से प्रत्येक परीक्षण के मामलों को लिखने के प्रयास का स्तर इसके लायक है? क्या यह परीक्षण का स्तर है जिसे आमतौर पर टीडीडी में 100% परीक्षण कवरेज के बारे में बात करने के लिए कहा जाता है? यदि नहीं, तो एक स्वीकार्य वैकल्पिक परीक्षण रणनीति क्या होगी?


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

जवाबों:


17

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

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

फिर, दूसरी आवश्यकता के साथ शुरू करें:

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

यहां पकड़ में आता है : जब आप आवश्यकता / श्रेणी संख्या "n" के लिए परीक्षण के मामले जोड़ते हैं, तो आपको केवल यह सुनिश्चित करने के लिए परीक्षण जोड़ना होगा कि "n-1" श्रेणी का स्कोर "n" श्रेणी के स्कोर से अधिक है । आपको श्रेणियों 1, ..., n-1 के हर दूसरे संयोजन के लिए कोई भी परीक्षण मामले नहीं जोड़ने होंगे, क्योंकि आपके द्वारा पहले लिखे गए परीक्षण यह सुनिश्चित करेंगे कि उस श्रेणी के स्कोर अभी भी सही क्रम में होंगे।

तो यह आपको कई परीक्षण मामले देगा जो आवश्यकताओं की संख्या के साथ लगभग रैखिक बढ़ता है, न कि तेजी से।


1
मुझे वास्तव में यह उत्तर पसंद है। यह TDD को ध्यान में रखते हुए इस समस्या से निपटने के लिए एक स्पष्ट और संक्षिप्त इकाई परीक्षण रणनीति देता है। आप इसे काफी बारीकी से तोड़ते हैं।
maple_shaft

@maple_shaft: धन्यवाद, और मुझे वास्तव में आपका सवाल पसंद है। मुझे यह जोड़ना पसंद है कि मुझे लगता है कि सभी परीक्षण मामलों को डिजाइन करने के आपके दृष्टिकोण से भी पहले, परीक्षणों के लिए समतुल्यता वर्गों के निर्माण की क्लासिक तकनीक घातीय वृद्धि को कम करने के लिए पर्याप्त हो सकती है (लेकिन मैंने अभी तक काम नहीं किया था)।
डॉक्टर ब्राउन

13

एक वर्ग लिखने पर विचार करें जो शर्तों की पूर्वनिर्धारित सूची से गुजरता है और प्रत्येक सफल जाँच के लिए एक वर्तमान स्कोर को 2 से गुणा करता है।

यह बहुत आसानी से परीक्षण किया जा सकता है, सिर्फ नकली परीक्षण के एक जोड़े का उपयोग करके।

फिर आप प्रत्येक स्थिति के लिए एक वर्ग लिख सकते हैं और प्रत्येक मामले के लिए केवल 2 परीक्षण हैं।

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

public class ScoreBuilder
{
    private ISingleScorableCondition[] _conditions;
    public ScoreBuilder (ISingleScorableCondition[] conditions)
    {
        _conditions = conditions;
    }

    public int GetScore(string toBeScored)
    {
        foreach (var condition in _conditions)
        {
            if (_conditions.Test(toBeScored))
            {
                // score this somehow
            }
        }
    }
}

public class ExactMatchOnNameCondition : ISingleScorableCondition
{
    private IDataSource _dataSource;
    public ExactMatchOnNameCondition(IDataSource dataSource)
    {
        _dataSource = dataSource;
    }

    public bool Test(string toBeTested)
    {
        return _dataSource.Contains(toBeTested);
    }
}

// etc

आप देखेंगे कि आपकी 2 ^ स्थितियां परीक्षण जल्दी से 4+ (2 * शर्तों) पर आ जाती हैं। 20 64 की तुलना में बहुत कम है। और यदि आप एक और बाद में जोड़ते हैं, तो आपको किसी भी मौजूदा वर्ग (खुले-बंद सिद्धांत) को बदलना नहीं है, इसलिए आपको 64 नए परीक्षण लिखने की ज़रूरत नहीं है, आपके पास बस है 2 नए परीक्षणों के साथ एक और वर्ग जोड़ने के लिए और अपने स्कोरब्युलेर वर्ग में इंजेक्ट करें।


दिलचस्प दृष्टिकोण। पूरे समय मेरे दिमाग ने कभी भी एक ओओपी दृष्टिकोण पर विचार नहीं किया क्योंकि मैं एक एकल तुलनित्र घटक के दिमाग में फंस गया था। मैं वास्तव में एल्गोरिथ्म सलाह की तलाश नहीं कर रहा था, लेकिन यह बहुत उपयोगी है।
maple_shaft

4
@maple_shaft: नहीं, लेकिन आप टीडीडी सलाह की तलाश कर रहे थे और इस तरह के एल्गोरिदम इस सवाल को दूर करने के लिए एकदम सही हैं कि क्या यह प्रयास के लायक है, बहुत हद तक प्रयास को कम करके। जटिलता कम करना TDD की कुंजी है।
pdr

+1, बढ़िया जवाब। हालांकि मैं इस तरह के एक परिष्कृत समाधान के बिना भी मानता हूं, परीक्षण के मामलों की संख्या तेजी से बढ़ने की जरूरत नहीं है (नीचे मेरा उत्तर देखें)।
डॉक्टर ब्राउन

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

4

अभी भी इनमें से प्रत्येक परीक्षण के मामलों को लिखने के प्रयास का स्तर इसके लायक है?

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

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

63 वां परीक्षण शायद इसके लायक नहीं होगा क्योंकि यह कुछ ऐसा है जिसे आप 99.99% विश्वास करते हैं जो आपके कोड या किसी अन्य परीक्षण के तर्क से आच्छादित है।

क्या यह परीक्षण का स्तर है जिसे आमतौर पर टीडीडी में 100% परीक्षण कवरेज के बारे में बात करने के लिए कहा जाता है?

मेरी समझ 100% कवरेज का मतलब है कि सभी कोड पथ का उपयोग किया जाता है। इसका मतलब यह नहीं है कि आप अपने नियमों के सभी संयोजन करते हैं, लेकिन आपके कोड के सभी अलग-अलग रास्ते नीचे जा सकते हैं (जैसा कि आप बताते हैं, कुछ संयोजन कोड में मौजूद नहीं हो सकते हैं)। लेकिन जब से आप TDD कर रहे हैं, तब तक के लिए रास्तों की जाँच करने के लिए कोई "कोड" नहीं है। प्रक्रिया का अक्षर कहता है कि सभी 63+ बनाते हैं।

व्यक्तिगत रूप से, मैं एक पाइप सपना होने के लिए 100% कवरेज पाता हूं। इसके अलावा, यह अप्रत्याशित है। इकाई परीक्षण आपके सेवा के लिए मौजूद हैं, इसके विपरीत नहीं। जैसा कि आप अधिक परीक्षण करते हैं, आपको लाभ पर कम रिटर्न मिलता है (संभावना है कि परीक्षण एक बग को रोकता है + विश्वास कि कोड सही है)। इस बात पर निर्भर करता है कि आपका कोड क्या परिभाषित करता है कि उस स्लाइडिंग पैमाने पर आप परीक्षण करना कहां रोकते हैं। यदि आपका कोड परमाणु रिएक्टर चला रहा है, तो शायद सभी 63+ परीक्षण इसके लायक हैं। यदि आपका कोड आपके संगीत संग्रह का आयोजन कर रहा है, तो आप शायद बहुत कम के साथ दूर हो सकते हैं।


"कवरेज" आम तौर पर कोड कवरेज (कोड की प्रत्येक पंक्ति निष्पादित होती है) या शाखा कवरेज को संदर्भित करता है (हर शाखा को किसी भी दिशा में कम से कम एक बार निष्पादित किया जाता है)। दोनों प्रकार के कवरेज के लिए 64 विभिन्न परीक्षण मामलों की आवश्यकता नहीं है। कम से कम, एक गंभीर कार्यान्वयन के साथ नहीं जिसमें 64 मामलों में से प्रत्येक के लिए व्यक्तिगत कोड भागों शामिल नहीं हैं। तो 100% कवरेज पूरी तरह से संभव है।
डॉक ब्राउन

@ डॉकब्रोर्न - निश्चित रूप से, इस मामले में - अन्य चीजों का परीक्षण करना कठिन / असंभव है; स्मृति अपवाद पथ से बाहर पर विचार करें। व्यवहार को लागू करने के लिए अज्ञानी के परीक्षण से अनभिज्ञ सभी 64 को 'पत्र' टीडीडी द्वारा आवश्यक नहीं किया जाएगा?
तेलस्टिन

ठीक है, मेरी टिप्पणी प्रश्न से संबंधित थी, और आपके उत्तर से यह आभास होता है कि ओपी के मामले में 100% कवरेज प्राप्त करना कठिन हो सकता है । मुझे शक है कि। और मैं आपसे सहमत हूं कि कोई ऐसे मामलों का निर्माण कर सकता है जहां 100% कवरेज हासिल करना कठिन है, लेकिन यह नहीं पूछा गया था।
डॉक ब्राउन

4

मेरा तर्क है कि यह TDD के लिए एक आदर्श मामला है।

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

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


1

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

इस विचार को ध्यान में रखते हुए, मैं संपूर्ण रूप से 2 या 3 एकीकरण शैली परीक्षणों के साथ आपके द्वारा पृथक किए गए 6 रैंकिंग कारकों का परीक्षण करूंगा, जो यह सुनिश्चित करते हैं कि आप अपने परिणामों को समग्र रैंकिंग मानों तक ले जा रहे हैं। उदाहरण के लिए, केस # 1, नाम पर सटीक मिलान, मेरे पास परीक्षण करने के लिए कम से कम दो यूनिट परीक्षण होंगे जब इसके सटीक और जब इसके नहीं होने की संभावना है और दो परिदृश्यों में अपेक्षित स्कोर वापस आएगा। यदि इसका मामला संवेदनशील है, तो "सटीक मिलान" बनाम "सटीक मिलान" और संभवतः अन्य इनपुट विविधताओं जैसे विराम चिह्न, अतिरिक्त स्थान आदि का परीक्षण करने का मामला भी अपेक्षित स्कोर देता है।

एक बार जब मैंने रैंकिंग स्कोर में योगदान देने वाले सभी व्यक्तिगत कारकों के माध्यम से काम किया है, तो मैं अनिवार्य रूप से इनको एकीकरण स्तर पर सही ढंग से काम करने के लिए मानता हूं और अपने संयुक्त कारकों को सही ढंग से अंतिम अपेक्षित रैंकिंग स्कोर में योगदान देने पर ध्यान केंद्रित करता हूं।

यह मानते हुए कि # 2 / # 3 और # 4 / # 5 को एक ही अंतर्निहित विधियों के लिए सामान्यीकृत किया जाता है, लेकिन विभिन्न क्षेत्रों को पास करते हुए, आपको केवल अंतर्निहित विधियों के लिए इकाई परीक्षणों का एक सेट लिखना होगा और विशिष्ट का परीक्षण करने के लिए सरल अतिरिक्त इकाई परीक्षण लिखना होगा। फ़ील्ड्स (शीर्षक, नाम, विवरण, आदि) और निर्दिष्ट फैक्टरिंग में स्कोरिंग, इसलिए यह आपके समग्र परीक्षण प्रयास के अतिरेक को कम करता है।

इस दृष्टिकोण के साथ, उपर्युक्त दृष्टिकोण शायद केस # 1 पर 3 या 4 यूनिट टेस्ट देगा, शायद कुछ / सभी डब्ल्यू / समानार्थी शब्द पर 10 चश्मा - प्लस 4 मामलों की सही स्कोरिंग पर # 2 - # 5 और 2 अंतिम तिथि के 3 स्पेक्स ने रैंकिंग का आदेश दिया, फिर 3 से 4 एकीकरण स्तर के परीक्षण जो सभी 6 मामलों को संयुक्त रूप से मापते हैं, (अभी तक अस्पष्ट किनारे के मामलों के बारे में भूल जाएं जब तक कि आप स्पष्ट रूप से अपने कोड में कोई समस्या नहीं देखते हैं, यह सुनिश्चित करने के लिए व्यायाम करने की आवश्यकता है उस स्थिति को संभाला जाता है) या यह सुनिश्चित किया जाता है कि बाद के संशोधनों द्वारा उल्लंघन / टूट जाए। कोड लिखा हुआ 100% व्यायाम करने के लिए लगभग 25 या तो स्पेक्स की पैदावार होती है (भले ही आप सीधे लिखे गए तरीकों में से 100% कॉल न करते हों)।


1

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

कहा जा रहा है, आपकी जैसी आवश्यकताओं के लिए, मैं हमेशा पूरी तरह से इकाई परीक्षण करता हूं, यहां तक ​​कि व्यक्तिगत परियोजनाओं पर भी, जहां कोई भी मुझे नहीं बना रहा है, क्योंकि ऐसे मामले हैं जब इकाई परीक्षण आपको समय और वृद्धि बचाता है। कुछ परीक्षण करने के लिए जितनी अधिक इकाई परीक्षण की आवश्यकता होगी, उतनी ही अधिक समय की इकाई परीक्षण बचेंगे।

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.