एम्बेडेड सी डेवलपर्स के लिए अच्छी इकाई परीक्षण उदाहरण [बंद]


20

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

मैं अच्छे उदाहरणों के लिए वेब पर खोज कर रहा हूं, लेकिन मैं ऐसा कोई भी संघर्ष करने के लिए संघर्ष कर रहा हूं जो विशेष रूप से हमारे विकास के क्षेत्र पर लागू हो। हमारे द्वारा लिखे गए लगभग सभी सॉफ्टवेयर छोटे-छोटे माइक्रोकंट्रोलर पर चलने वाले गहन-एम्बेडेड नियंत्रण प्रणाली हैं। बहुत सी कोड है जो इकाई परीक्षण के लिए आसानी से लागू होता है (जब तक आप 'नीचे' की परत से स्पष्ट रहें: तब तक आप पीसी पर इकाई परीक्षण के बारे में बात करेंगे) जब तक आप 'नीचे' की परत से स्पष्ट नहीं रहते हैं: सामान जो सीधे बात करता है माइक्रोकंट्रोलर बाह्य उपकरणों के लिए। हालाँकि, अधिकांश उदाहरण मैंने पाया है कि यह स्ट्रिंग-प्रोसेसिंग (उदाहरण के लिए उत्कृष्ट डाइव इन पायथन रोमन अंकों के उदाहरण) पर आधारित है और चूंकि हम शायद ही कभी स्ट्रिंग्स का उपयोग करते हैं, यह वास्तव में उपयुक्त नहीं है (केवल लाइब्रेरी फ़ंक्शन के बारे में जो हमारे कोड आमतौर पर उपयोग करते हैं। कर रहे हैं memcpy, memcmpऔर memset,strcat या नियमित अभिव्यक्ति काफी सही नहीं है)।

इसलिए, इस सवाल पर: क्या कोई ऐसे कार्यों के कुछ अच्छे उदाहरण पेश कर सकता है, जिनका उपयोग मैं एक जीवित सत्र में इकाई परीक्षण प्रदर्शित करने के लिए कर सकता हूं? मेरी (परिवर्तन के अधीन) राय में एक अच्छा जवाब शायद होगा:

  • एक फ़ंक्शन जो काफी सरल है कि कोई भी (यहां तक ​​कि जो केवल कभी-कभी कोड लिखते हैं) समझ सकते हैं;
  • एक फ़ंक्शन जो व्यर्थ नहीं दिखाई देता है (यानी समता या सीआरसी का काम करना संभवतः एक फ़ंक्शन से बेहतर है जो दो संख्याओं को एक साथ गुणा करता है और एक यादृच्छिक निरंतर जोड़ता है);
  • एक फ़ंक्शन जो लोगों के एक कमरे के सामने लिखने के लिए काफी कम है (मैं त्रुटियों को कम करने के लिए विम के कई क्लिपबोर्ड का लाभ उठा सकता हूं ...);
  • एक फ़ंक्शन जो संख्याओं, सरणियों, बिंदुओं या संरचनाओं को पैरामीटर के रूप में लेता है और स्ट्रिंग को संभालने के बजाय कुछ समान देता है;
  • एक फ़ंक्शन जिसमें एक साधारण त्रुटि होती है (जैसे कि >इसके बजाय >=) यह आसान है कि वह अभी भी ज्यादातर मामलों में काम करेगा लेकिन कुछ विशेष किनारे के मामले से टूट जाएगा: एक यूनिट टेस्ट के साथ पहचानना और ठीक करना आसान है।

कोई विचार?

यद्यपि यह संभवतः प्रासंगिक नहीं है, परीक्षण स्वयं संभवतः Google टेस्ट फ्रेमवर्क का उपयोग करके C ++ में लिखे जाएंगे: हमारे सभी हेडर में पहले से ही #ifdef __cplusplus extern "C" {उनके चारों ओर आवरण हैं; मैंने अब तक किए गए परीक्षणों के साथ अच्छा काम किया है।


TDD को प्रबंधन को बेचने के लिए एक प्रस्तुति के साथ आने के रूप में यहां "समस्या" लेते हुए, यह मुझे वांछित प्रारूप को यथोचित रूप से फिट करने के लिए लगता है। ओपी इस समस्या के मौजूदा समाधान के लिए अनुरोध करता दिख रहा है।
टेक्नोफाइल

जवाबों:


15

यहाँ एक साधारण फ़ंक्शन है जो लेन बाइट्स पर चेकसम उत्पन्न करने वाला है ।

int checksum(void *p, int len)
{
    int accum = 0;
    unsigned char* pp = (unsigned char*)p;
    int i;
    for (i = 0; i <= len; i++)
    {
        accum += *pp++;
    }
    return accum;
}

इसके पास एक फ़र्स्टपोस्ट बग है: बयान के लिए, परीक्षण होना चाहिए i < len

क्या मजेदार है, अगर आप इसे इस तरह से एक टेक्स्ट स्ट्रिंग पर लागू करते हैं ...

char *myString = "foo";
int testval = checksum(myString, strlen(myString));

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

यहाँ एक साधारण इकाई परीक्षण है जो इस बग को चिह्नित करेगा (अधिकांश समय ... :-)

void main()
{
    // Seed the random number generator
    srand(time(NULL));

    // Fill an array with junk bytes
    char buf[1024];
    int i;
    for (i = 0; i < 1024; i++)
    {
        buf[i] = (char)rand();
    }

    // Put the numbers 0-9 in the first ten bytes
    for (i = 0; i <= 9; i++)
    {
        buf[i] = i;
    }

    // Now, the unit test. The sum of 0 to 9 should
    // be 45. But if buf[10] isn't 0 - which it won't be,
    // 255/256 of the time - this will fail.
    int testval = checksum(buf, 10);
    if (testval == 45)
    {
        printf("Passed!\n");
    }
    else
    {
        printf("Failed! Expected 45, got %d\n", testval);
    }
}

बहुत अच्छा! यह सिर्फ उस तरह का जवाब है जिसकी मैं उम्मीद कर रहा था: धन्यवाद।
DrAl

जब आप उस बफ़र को बनाते हैं जो आपके पास पहले से ही स्मृति के उस हिस्से में बकवास है, तो क्या यादृच्छिक संख्याओं के साथ इसे शुरू करना आवश्यक है?
सांप सैंडर्स

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

एक इकाई परीक्षण में गैर-नियतात्मक व्यवहारों पर भरोसा करना एक बुरा विचार है। एक परतदार परीक्षण आपको जल्द या बाद में सिरदर्द देगा ...
11

2

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

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

कुछ और विचार:

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

क्या आपके पास एक साधारण त्रुटि के लिए कोई विशिष्ट सुझाव है जो यह दिखाएगा कि परीक्षण कैसे जीवन को आसान बनाता है?
DrAl

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