क्या 'परख' की एक श्रृंखला की तुलना में इकाई परीक्षण लिखने का एक बेहतर तरीका है?


12

Qunit का उपयोग करके मेरी इकाई परीक्षण के लिए एक बुनियादी उदाहरण यहां दिया गया है:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>

<link rel="stylesheet" href="qunit/qunit-1.13.0.css">
<script src = "qunit/qunit-1.13.0.js"></script>
<script src = "../js/fuzzQuery.js"></script>

<script>

test("Fuzz Query Basics", function()
        {
            equal(fuzzQuery("name:(John Smith)"), "name:(John~ Smith~)");
            equal(fuzzQuery("name:Jon~0.1"), "name:Jon~0.1");
            equal(fuzzQuery("Jon"), "Jon~");
            //etc

        }
    );

</script>
</head>
<body>
    <div id="qunit"></div>
</body>
</html>

अब मैं सोच रहा था कि यह थोड़ा दोहराव है।

एक सरणी में सभी इनपुट / आउटपुट डाल सकते हैं, और इसके माध्यम से लूप कर सकते हैं।

test("Fuzz Query Basics", function()
        {
            var equals = [
                           ["name:(John Smith)", "name:(John~ Smith~)"],
                           ["name:Jon~0.1", "name:Jon~0.1"],
                           ["Jon", "Jon~"]
                           ];

            for (var i = 0; i<equals.length; i++)
                {
                    equal(fuzzQuery(equals[i][0]), equals[i][1]);               
                }

        }
    );

और यह ठीक काम करता है।

इस दूसरी विधि के लिए मैं जो एकल लाभ सोच सकता हूं, वह यह है कि यदि यह पता चला कि आप वास्तव में equalइसका उपयोग नहीं करना चाहते हैं तो एक स्थान पर उस बदलाव को करना आसान है।

पठनीयता के संदर्भ में, मुझे नहीं लगता कि यह किसी भी तरह से निर्णायक है, हालांकि मैं शायद दूसरा पसंद करता हूं।

इसे आगे बढ़ाते हुए, आप इनपुट / आउटपुट मामलों को एक अलग CSV फ़ाइल में डाल सकते हैं, जिससे इसे संशोधित करना आसान हो सकता है।

प्रश्न है - इस प्रकार के यूनिट परीक्षणों को लिखने के बारे में सामान्य धारणाएं क्या हैं?

क्या कोई कारण है जो आपको उन्हें सरणियों में नहीं रखना चाहिए?


क्या इनमें से कोई आपको बताएगा कि कौन सा मूल्य विफल हुआ?
जेएफओ

1
@ जेफ़ो - हाँ - क्वैनिट के साथ - यदि कोई परीक्षण विफल रहता है, तो आउटपुट अपेक्षित मूल्य और वास्तविक मूल्य दिखाएगा।
dwjohnston

जवाबों:


8

आपके रिफैक्ट किए गए परीक्षणों में एक गंध है: सशर्त टेस्ट लॉजिक

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

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

समाधान, हमेशा की तरह, अमूर्त के स्तर को ऊपर ले जाना है। एक परीक्षण ढांचे का उपयोग करें जो आपको पैराट्राइज्ड परीक्षण देता है , जैसे कि xUnit.NET या Contexts do (अस्वीकरण: मैंने Contexed लिखा है)। यह आपको अलग-अलग व्यवहारों के लिए परीक्षणों को अलग-अलग रखते हुए एक ही व्यवहार के लिए एक साथ एक ही व्यवहार के लिए त्रिकोणीय परीक्षण समूहित करने की अनुमति देता है।


अच्छा सवाल, वैसे
बेंजामिन हॉजसन

1
1) यदि आप अमूर्तता का स्तर बढ़ाते हैं, तो क्या आप उन्हीं विवरणों को नहीं छिपा रहे हैं जो आपने कहा था कि लूप के लिए अस्पष्ट है? 2) सुनिश्चित नहीं है कि यहाँ पर मानकीकृत परीक्षण लागू नहीं हैं। ऐसा लगता है कि यहां कहीं समानताएं हैं, लेकिन मैंने ओपी के समान बहुत सारी परिस्थितियां प्राप्त की हैं जहां मेरे पास 10-20 मूल्यों का डेटा सेट था और बस उन सभी को SUT के माध्यम से चलाना चाहता था। हां, प्रत्येक मूल्य अलग है और संभावित रूप से विभिन्न बॉडरीज का परीक्षण करता है, लेकिन लगता है कि वास्तव में हर एक मूल्य के लिए "आविष्कार" परीक्षण नाम एक ओवरकिल होगा। मुझे समान उपयोग करने में इष्टतम मान / कोड-आकार अनुपात मिला ...
DXM

... छोरों। जब तक परीक्षण में विफल रहता है, तब तक मुखर बिल्कुल विफल हो जाता है, डेवलपर ने समस्या को ठीक से इंगित करने के लिए पर्याप्त प्रतिक्रिया दी है।
DXM

@DXM 1) परीक्षण रूपरेखा परिमाणित परीक्षण कार्यक्षमता प्रदान करता है। हम टेस्ट फ्रेमवर्क पर भरोसा करते हैं इसलिए हम इसके लिए टेस्ट नहीं लिखते हैं। 2) पैरामीट्रिज्ड परीक्षण वास्तव में इस उद्देश्य के लिए हैं: आप हर बार बिल्कुल समान कदम उठा रहे हैं, लेकिन विभिन्न इनपुट / आउटपुट मानों के साथ। टेस्ट फ्रेमवर्क आपको एक ही टेस्ट विधि के माध्यम से अलग-अलग इनपुट चलाकर प्रत्येक के लिए नाम लिखने की आवश्यकता को बचाता है।
बेंजामिन हॉजसन

5

ऐसा लगता है कि आप वास्तव में एक डेटा ड्रिवेन यूनिट टेस्ट चाहते हैं। चूंकि आपने क्वनीट का उपयोग करते हुए उल्लेख किया है, मुझे एक प्लगइन मिला जो कि मानकीकृत परीक्षणों को सक्षम करता है:

https://github.com/AStepaniuk/qunit-parameterize

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

GitHub README के ​​लिए उदाहरण कोड:

QUnit
    .cases([
        { a : 2, b : 2, expectedSum : 4 },
        { a : 5, b : 5, expectedSum : 10 },
        { a : 40, b : 2, expectedSum : 42 }
    ])
    .test("Sum test", function(params) {
        var actualSum = sum(params.a, params.b);
        equal(actualSum, params.expectedSum);
    });

1
सहमत, यह डेटा-संचालित परीक्षण की तरह दिखता है। लेकिन ऐसा लगता है कि वह वही है जो पहले से ही अपने दूसरे कोड उदाहरण में है।
रॉबर्ट हार्वे

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

1

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

यह मुझे तुरंत बताने की अनुमति देता है कि कौन से परीक्षण / इनपुट विफल हो रहे हैं।


0

मुझे आपका दूसरा दृष्टिकोण पसंद है, लेकिन मैं 2 अंक जोड़ूंगा

  • परीक्षण किए गए डेटा को संग्रहीत करने के लिए सरणियों का उपयोग न करें, क्योंकि अनुक्रमित के साथ काम करना एक साफ तरीका नहीं है
  • forछोरों का उपयोग न करें

`

[
    {
        process: "name:(John Smith)",
        result: "name:(John~ Smith~)"
    },
    {
        process: "name:Jon~0.1", 
        result: "name:Jon~0.1"
    },
    {
        process: "Jon", 
        result: "Jon~"
    }
]
.forEach(function(data){

    var result = fuzzQuery(data.process);
    equal(result, data.result);
});

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

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