कोड कवरेज के चार सामान्य टाइप

जानें कि कोड कवरेज क्या होता है और इसे मेज़र करने के चार सामान्य तरीके खोजें.

क्या आपने "कोड कवरेज" वाक्यांश सुना है? इस पोस्ट में, हम जानेंगे कि टेस्ट में कौनसा कोड कवरेज होता है और उसे मेज़र करने के चार सामान्य तरीके क्या हैं.

कोड कवरेज क्या है?

कोड कवरेज एक ऐसी मेट्रिक है जो आपके टेस्ट किए गए सोर्स कोड का प्रतिशत मापती है. इससे आपको उन मामलों का पता लगाने में मदद मिलती है जहां सही जांच नहीं की जा सकती.

अक्सर, इन मेट्रिक को रिकॉर्ड करने की प्रोसेस कुछ इस तरह दिखती है:

फ़ाइल % स्टेटमेंट % ब्रांच % फ़ंक्शन % लाइन छिपी हुई लाइनें
file.js 90% 100% 90% 80% 89,256
coffee.js 55.55% 80% 50% 62.5% 10 से 11, 18

नई सुविधाएं और टेस्ट जोड़ने पर, कोड कवरेज का प्रतिशत बढ़ता है. इससे आपको इस बात पर भरोसा हो सकता है कि आपके ऐप्लिकेशन को पूरी तरह से टेस्ट कर लिया गया है. हालांकि, खोजने के लिए बहुत कुछ है.

कोड कवरेज के चार सामान्य टाइप

कोड कवरेज को इकट्ठा करने और उसका हिसाब लगाने के चार सामान्य तरीके हैं: फ़ंक्शन, लाइन, ब्रांच, और स्टेटमेंट कवरेज.

टेक्स्ट कवरेज के चार टाइप.

यह देखने के लिए कि हर तरह का कोड कवरेज अपने प्रतिशत का हिसाब कैसे लगाता है, कॉफ़ी में इस्तेमाल होने वाली चीज़ों का हिसाब लगाने के लिए, नीचे दिए गए कोड के उदाहरण पर विचार करें:

/* coffee.js */

export function calcCoffeeIngredient(coffeeName, cup = 1) {
  let espresso, water;

  if (coffeeName === 'espresso') {
    espresso = 30 * cup;
    return { espresso };
  }

  if (coffeeName === 'americano') {
    espresso = 30 * cup; water = 70 * cup;
    return { espresso, water };
  }

  return {};
}

export function isValidCoffee(name) {
  return ['espresso', 'americano', 'mocha'].includes(name);
}

calcCoffeeIngredient फ़ंक्शन की पुष्टि करने वाले टेस्ट:

/* coffee.test.js */

import { describe, expect, assert, it } from 'vitest';
import { calcCoffeeIngredient } from '../src/coffee-incomplete';

describe('Coffee', () => {
  it('should have espresso', () => {
    const result = calcCoffeeIngredient('espresso', 2);
    expect(result).to.deep.equal({ espresso: 60 });
  });

  it('should have nothing', () => {
    const result = calcCoffeeIngredient('unknown');
    expect(result).to.deep.equal({});
  });
});

इस लाइव डेमो पर, कोड और टेस्ट चलाए जा सकते हैं या डेटा स्टोर करने की जगह देखी जा सकती है.

फ़ंक्शन कवरेज

कोड कवरेज: 50%

/* coffee.js */

export function calcCoffeeIngredient(coffeeName, cup = 1) {
  // ...
}

function isValidCoffee(name) {
  // ...
}

फ़ंक्शन कवरेज एक आसान मेट्रिक है. यह आपके कोड में मौजूद उन फ़ंक्शन का प्रतिशत कैप्चर करता है जिन्हें आपके टेस्ट कॉल करते हैं.

कोड के उदाहरण में, दो फ़ंक्शन हैं: calcCoffeeIngredient और isValidCoffee. टेस्ट में सिर्फ़ calcCoffeeIngredient फ़ंक्शन को कॉल किया जाता है, इसलिए फ़ंक्शन कवरेज 50% है.

लाइन का कवरेज

कोड कवरेज: 62.5%

/* coffee.js */

export function calcCoffeeIngredient(coffeeName, cup = 1) {
  let espresso, water;

  if (coffeeName === 'espresso') {
    espresso = 30 * cup;
    return { espresso };
  }

  if (coffeeName === 'americano') {
    espresso = 30 * cup; water = 70 * cup;
    return { espresso, water };
  }

  return {};
}

export function isValidCoffee(name) {
  return ['espresso', 'americano', 'mocha'].includes(name);
}

लाइन कवरेज, उन एक्ज़ीक्यूटेबल कोड लाइनों का प्रतिशत मापता है जिन्हें आपके टेस्ट सुइट ने एक्ज़ीक्यूट किया है. अगर कोड की कोई लाइन लागू नहीं हुई है, तो इसका मतलब है कि कोड के कुछ हिस्से की जांच नहीं हुई है.

कोड के उदाहरण में, एक्ज़ीक्यूटेबल कोड की आठ लाइनें हैं (लाल और हरे रंग से हाइलाइट की गई है) लेकिन टेस्ट, americano शर्त (दो लाइन) और isValidCoffee फ़ंक्शन (एक लाइन) को लागू नहीं करते हैं. इससे लाइन कवरेज 62.5% होता है.

ध्यान दें कि लाइन कवरेज में, function isValidCoffee(name) और let espresso, water; जैसे एलान वाले स्टेटमेंट शामिल नहीं हैं. ऐसा इसलिए है, क्योंकि इन्हें एक्ज़ीक्यूट नहीं किया जा सकता.

शाखा की कवरेज

कोड कवरेज: 80%

/* coffee.js */

export function calcCoffeeIngredient(coffeeName, cup = 1) {
  // ...

  if (coffeeName === 'espresso') {
    // ...
    return { espresso };
  }

  if (coffeeName === 'americano') {
    // ...
    return { espresso, water };
  }

  return {};
}
…

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

कोड के उदाहरण में पांच ब्रांच दी गई हैं:

  1. सिर्फ़ coffeeName चेक का निशान. से calcCoffeeIngredient को कॉल किया जा रहा है
  2. coffeeName और cup चेक का निशान. के साथ calcCoffeeIngredient को कॉल किया जा रहा है
  3. कॉफ़ी, एस्प्रेसो चेक का निशान. है
  4. कॉफ़ी अमेरिकानो X का निशान. है
  5. अन्य कॉफ़ी चेक का निशान.

इन टेस्ट में, Coffee is Americano शर्त को छोड़कर सभी ब्रांच शामिल होती हैं. इसलिए, ब्रांच की कवरेज 80% है.

स्टेटमेंट कवरेज

कोड कवरेज: 55.55%

/* coffee.js */

export function calcCoffeeIngredient(coffeeName, cup = 1) {
  let espresso, water;

  if (coffeeName === 'espresso') {
    espresso = 30 * cup;
    return { espresso };
  }

  if (coffeeName === 'americano') {
    espresso = 30 * cup; water = 70 * cup;
    return { espresso, water };
  }

  return {};
}

export function isValidCoffee(name) {
  return ['espresso', 'americano', 'mocha'].includes(name);
}

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

कोड के उदाहरण में, एक्ज़ीक्यूटेबल कोड की आठ लाइनें हैं, लेकिन नौ स्टेटमेंट हैं. क्या आपको दो स्टेटमेंट वाली लाइन दिख सकती है?

अपने जवाब की जांच करें

यह लाइन है: espresso = 30 * cup; water = 70 * cup;

इन टेस्ट में नौ स्टेटमेंट में से सिर्फ़ पांच स्टेटमेंट शामिल हैं. इस वजह से, स्टेटमेंट कवरेज 55.55% है.

अगर आप हमेशा एक लाइन में एक स्टेटमेंट लिखते हैं, तो लाइन का कवरेज, आपके स्टेटमेंट कवरेज के बराबर होगा.

आपको किस तरह का कोड कवरेज चुनना चाहिए?

ज़्यादातर कोड कवरेज टूल में, ये चार तरह के सामान्य कोड कवरेज शामिल होते हैं. कोड कवरेज की कौनसी मेट्रिक को प्राथमिकता देनी है, यह प्रोजेक्ट की ज़रूरी शर्तों, डेवलपमेंट के तरीकों, और टेस्टिंग के लक्ष्यों पर निर्भर करता है.

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

हाई स्टेटमेंट कवरेज हासिल करने के बाद, ब्रांच कवरेज और फ़ंक्शन कवरेज पर जाएं.

क्या टेस्ट कवरेज और कोड कवरेज एक जैसे हैं?

नहीं. टेस्ट कवरेज और कोड कवरेज को लेकर अक्सर भ्रम की स्थिति होती है, लेकिन ये दोनों अलग-अलग होते हैं:

  • टेस्ट कवरेज: ऐक्वालिटेटिव मेट्रिक से पता चलता है कि टेस्ट सुइट, सॉफ़्टवेयर की सुविधाओं को कितनी अच्छी तरह से कवर करता है. इससे यह पता लगाने में मदद मिलती है कि कितना खतरा है.
  • कोड कवरेज: यह आंकड़ों वाली मेट्रिक है, जो जांच के दौरान चलाए गए कोड का अनुपात मापती है. इससे पता चलता है कि जांच में कितने कोड शामिल किए जाते हैं.

यहां इसका आसान सा उदाहरण दिया गया है: वेब ऐप्लिकेशन को एक घर के तौर पर मानें.

  • जांच के कवरेज से पता चलता है कि टेस्ट घर के कमरों को कितनी अच्छी तरह से कवर करते हैं.
  • कोड कवरेज से पता चलता है कि टेस्ट कितने हाउस से गुज़रे हैं.

100% कोड कवरेज का मतलब यह नहीं है कि कोई गड़बड़ी नहीं होगी

टेस्टिंग के दौरान, अच्छे कोड कवरेज हासिल करना ज़रूर चाहिए, लेकिन 100% कोड कवरेज इस बात की गारंटी नहीं देता कि आपके कोड में कोई गड़बड़ी या कमी है.

100% कोड कवरेज पाने का आसान तरीका

नीचे दी गई जांच करें:

/* coffee.test.js */

// ...
describe('Warning: Do not do this', () => {
  it('is meaningless', () => { 
    calcCoffeeIngredient('espresso', 2);
    calcCoffeeIngredient('americano');
    calcCoffeeIngredient('unknown');
    isValidCoffee('mocha');
    expect(true).toBe(true); // not meaningful assertion
  });
});

यह टेस्ट, 100% फ़ंक्शन, लाइन, ब्रांच, और स्टेटमेंट कवरेज हासिल करता है. हालांकि, इसका कोई मतलब नहीं है, क्योंकि यह असल में कोड की जांच नहीं करता है. expect(true).toBe(true) दावा हमेशा पास होगा, भले ही कोड सही तरीके से काम कर रहा हो या नहीं.

एक खराब मेट्रिक, बिना किसी मेट्रिक से ज़्यादा खराब होती है

एक खराब मेट्रिक आपको सुरक्षा के बारे में गलत जानकारी दे सकती है. यह किसी मेट्रिक के न होने से भी बुरा है. उदाहरण के लिए, अगर आपके पास ऐसा टेस्ट सुइट है जो 100% कोड कवरेज पा लेता है, लेकिन सभी टेस्ट काम के नहीं हैं, तो आपको सुरक्षा का झूठा एहसास हो सकता है कि आपके कोड की अच्छी तरह से जांच की जा चुकी है. अगर आपने गलती से ऐप्लिकेशन कोड का कोई हिस्सा मिटा दिया है या उसे तोड़ दिया है, तो भी जांच पास हो जाएंगी. हालांकि, ऐप्लिकेशन सही तरीके से काम नहीं करता है.

ऐसी स्थिति से बचने के लिए:

  • जांच की समीक्षा करें. टेस्ट लिखें और उनकी समीक्षा करें, ताकि यह पक्का किया जा सके कि वे काम के हैं या नहीं. साथ ही, अलग-अलग स्थितियों में कोड की जांच करें.
  • कोड कवरेज का इस्तेमाल दिशा-निर्देश के तौर पर करें. इसे जांच के असर या कोड की क्वालिटी को मापने के लिए इस्तेमाल न करें.

अलग-अलग तरह की टेस्टिंग में कोड कवरेज का इस्तेमाल करना

आइए विस्तार से जानते हैं कि तीन सामान्य तरह की जांच की मदद से, कोड कवरेज का इस्तेमाल कैसे किया जा सकता है:

  • यूनिट टेस्ट. कोड कवरेज इकट्ठा करने के लिए, ये टेस्ट टाइप सबसे अच्छे होते हैं, क्योंकि इन्हें कई छोटी स्थितियों और जांच के पाथ को कवर करने के लिए डिज़ाइन किया गया है.
  • इंटिग्रेशन की जांच. इनसे, इंटिग्रेशन की जांच के लिए कोड कवरेज इकट्ठा करने में मदद मिल सकती है. हालांकि, इनका इस्तेमाल सावधानी से करें. इस मामले में, सोर्स कोड के बड़े हिस्से के कवरेज का आकलन किया जाता है. इससे यह पता लगाने में मुश्किल हो सकती है कि कौनसे टेस्ट, कोड के किन हिस्सों को असल में कवर करते हैं. इसके बावजूद, इंटिग्रेशन टेस्ट के कोड कवरेज की गिनती करना, ऐसे लेगसी सिस्टम के लिए काम का हो सकता है जिनमें अलग-अलग यूनिट नहीं होती.
  • एंड-टू-एंड (E2E) टेस्ट. इन टेस्ट के पेचीदा होने की वजह से E2E टेस्ट के लिए कोड कवरेज को मापना, मुश्किल और चुनौती भरा काम है. कोड कवरेज का इस्तेमाल करने के बजाय, ज़रूरी कवरेज का इस्तेमाल करना बेहतर तरीका हो सकता है. ऐसा इसलिए, क्योंकि E2E टेस्ट का फ़ोकस, सोर्स कोड पर नहीं, बल्कि आपके टेस्ट की ज़रूरी शर्तों को पूरा करने पर होता है.

नतीजा

जांच के असर को मेज़र करने के लिए, कोड कवरेज फ़ायदेमंद मेट्रिक हो सकता है. इससे आपको अपने ऐप्लिकेशन की क्वालिटी बेहतर बनाने में मदद मिल सकती है. इसके लिए, यह पक्का करना ज़रूरी है कि आपके कोड में मौजूद अहम लॉजिक की अच्छी तरह से जांच की गई हो.

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

100% कोड कवरेज का लक्ष्य तय करना नहीं है. इसके बजाय, आपको कोड कवरेज के साथ-साथ पूरे टेस्ट प्लान का इस्तेमाल करना चाहिए. इसमें, टेस्टिंग के कई तरीकों को शामिल किया जाना चाहिए. इनमें यूनिट टेस्ट, इंटिग्रेशन टेस्ट, एंड-टू-एंड टेस्ट, और मैन्युअल टेस्ट शामिल हैं.

पूरे कोड के उदाहरण और अच्छे कोड कवरेज वाले टेस्ट देखें. इस लाइव डेमो में, कोड और टेस्ट चलाए जा सकते हैं.

/* coffee.js - a complete example */

export function calcCoffeeIngredient(coffeeName, cup = 1) {
  if (!isValidCoffee(coffeeName)) return {};

  let espresso, water;

  if (coffeeName === 'espresso') {
    espresso = 30 * cup;
    return { espresso };
  }

  if (coffeeName === 'americano') {
    espresso = 30 * cup; water = 70 * cup;
    return { espresso, water };
  }

  throw new Error (`${coffeeName} not found`);
}

function isValidCoffee(name) {
  return ['espresso', 'americano', 'mocha'].includes(name);
}
/* coffee.test.js - a complete test suite */

import { describe, expect, it } from 'vitest';
import { calcCoffeeIngredient } from '../src/coffee-complete';

describe('Coffee', () => {
  it('should have espresso', () => {
    const result = calcCoffeeIngredient('espresso', 2);
    expect(result).to.deep.equal({ espresso: 60 });
  });

  it('should have americano', () => {
    const result = calcCoffeeIngredient('americano');
    expect(result.espresso).to.equal(30);
    expect(result.water).to.equal(70);
  });

  it('should throw error', () => {
    const func = () => calcCoffeeIngredient('mocha');
    expect(func).toThrowError(new Error('mocha not found'));
  });

  it('should have nothing', () => {
    const result = calcCoffeeIngredient('unknown')
    expect(result).to.deep.equal({});
  });
});