हिन्दी

अधिक विश्वसनीय और रखरखाव योग्य सॉफ्टवेयर बनाने के लिए उन्नत Jest टेस्टिंग पैटर्न में महारत हासिल करें। वैश्विक विकास टीमों के लिए मॉकिंग, स्नैपशॉट टेस्टिंग, कस्टम मैचर्स जैसी तकनीकों का अन्वेषण करें।

Jest: मजबूत सॉफ्टवेयर के लिए उन्नत टेस्टिंग पैटर्न

आज के तेजी से बदलते सॉफ्टवेयर डेवलपमेंट परिदृश्य में, आपके कोडबेस की विश्वसनीयता और स्थिरता सुनिश्चित करना सर्वोपरि है। जबकि Jest जावास्क्रिप्ट टेस्टिंग के लिए एक वास्तविक मानक बन गया है, बुनियादी यूनिट टेस्ट से आगे बढ़ना आपके एप्लिकेशन में एक नए स्तर का विश्वास दिलाता है। यह पोस्ट उन्नत Jest टेस्टिंग पैटर्न पर प्रकाश डालती है जो वैश्विक दर्शकों के डेवलपर्स के लिए मजबूत सॉफ्टवेयर बनाने के लिए आवश्यक हैं।

बुनियादी यूनिट टेस्ट से आगे क्यों जाएं?

बुनियादी यूनिट टेस्ट अलग-थलग व्यक्तिगत घटकों को सत्यापित करते हैं। हालांकि, वास्तविक दुनिया के एप्लिकेशन जटिल सिस्टम होते हैं जहां घटक इंटरैक्ट करते हैं। उन्नत टेस्टिंग पैटर्न इन जटिलताओं को संबोधित करते हैं जो हमें सक्षम बनाते हैं:

मॉकिंग और स्पाइज में महारत हासिल करना

टेस्ट के तहत यूनिट को अलग करने के लिए मॉकिंग महत्वपूर्ण है, इसकी निर्भरताओं को नियंत्रित विकल्पों के साथ बदलकर। Jest इसके लिए शक्तिशाली उपकरण प्रदान करता है:

jest.fn(): मॉक्स और स्पाइज की नींव

jest.fn() एक मॉक फंक्शन बनाता है। आप इसके कॉल्स, आर्ग्यूमेंट्स और रिटर्न वैल्यूज को ट्रैक कर सकते हैं। यह अधिक परिष्कृत मॉकिंग रणनीतियों के लिए बिल्डिंग ब्लॉक है।

उदाहरण: फंक्शन कॉल्स को ट्रैक करना

// component.js
export const fetchData = () => {
  // एक API कॉल का अनुकरण करता है
  return Promise.resolve({ data: 'some data' });
};

export const processData = async (fetcher) => {
  const result = await fetcher();
  return `Processed: ${result.data}`;
};

// component.test.js
import { processData } from './component';

test('should process data correctly', async () => {
  const mockFetcher = jest.fn().mockResolvedValue({ data: 'mocked data' });
  const result = await processData(mockFetcher);
  expect(result).toBe('Processed: mocked data');
  expect(mockFetcher).toHaveBeenCalledTimes(1);
  expect(mockFetcher).toHaveBeenCalledWith();
});

jest.spyOn(): बिना बदले निरीक्षण करना

jest.spyOn() आपको किसी मौजूदा ऑब्जेक्ट पर किसी मेथड के कॉल्स का निरीक्षण करने की अनुमति देता है, बिना आवश्यक रूप से इसके कार्यान्वयन को बदले। यदि आवश्यक हो तो आप कार्यान्वयन को मॉक भी कर सकते हैं।

उदाहरण: एक मॉड्यूल मेथड पर जासूसी करना

// logger.js
export const logInfo = (message) => {
  console.log(`INFO: ${message}`);
};

// service.js
import { logInfo } from './logger';

export const performTask = (taskName) => {
  logInfo(`Starting task: ${taskName}`);
  // ... टास्क लॉजिक ...
  logInfo(`Task ${taskName} completed.`);
};

// service.test.js
import { performTask } from './service';
import * as logger from './logger';

test('should log task start and completion', () => {
  const logSpy = jest.spyOn(logger, 'logInfo');

  performTask('backup');

  expect(logSpy).toHaveBeenCalledTimes(2);
  expect(logSpy).toHaveBeenCalledWith('Starting task: backup');
  expect(logSpy).toHaveBeenCalledWith('Task backup completed.');

  logSpy.mockRestore(); // मूल कार्यान्वयन को पुनर्स्थापित करना महत्वपूर्ण है
});

मॉड्यूल इम्पोर्ट्स को मॉक करना

Jest की मॉड्यूल मॉकिंग क्षमताएं व्यापक हैं। आप पूरे मॉड्यूल या विशिष्ट एक्सपोर्ट्स को मॉक कर सकते हैं।

उदाहरण: एक बाहरी एपीआई क्लाइंट को मॉक करना

// api.js
import axios from 'axios';

export const getUser = async (userId) => {
  const response = await axios.get(`/api/users/${userId}`);
  return response.data;
};

// user-service.js
import { getUser } from './api';

export const getUserFullName = async (userId) => {
  const user = await getUser(userId);
  return `${user.firstName} ${user.lastName}`;
};

// user-service.test.js
import { getUserFullName } from './user-service';
import * as api from './api';

// पूरे api मॉड्यूल को मॉक करें
jest.mock('./api');

test('should get full name using mocked API', async () => {
  // मॉक किए गए मॉड्यूल से विशिष्ट फ़ंक्शन को मॉक करें
  api.getUser.mockResolvedValue({ id: 1, firstName: 'Ada', lastName: 'Lovelace' });

  const fullName = await getUserFullName(1);

  expect(fullName).toBe('Ada Lovelace');
  expect(api.getUser).toHaveBeenCalledTimes(1);
  expect(api.getUser).toHaveBeenCalledWith(1);
});

ऑटो-मॉकिंग बनाम मैनुअल मॉकिंग

Jest स्वचालित रूप से Node.js मॉड्यूल को मॉक करता है। ES मॉड्यूल या कस्टम मॉड्यूल के लिए, आपको jest.mock() की आवश्यकता हो सकती है। अधिक नियंत्रण के लिए, आप __mocks__ डायरेक्टरी बना सकते हैं।

मॉक कार्यान्वयन

आप अपने मॉक्स के लिए कस्टम कार्यान्वयन प्रदान कर सकते हैं।

उदाहरण: एक कस्टम कार्यान्वयन के साथ मॉकिंग

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// calculator.js
import { add, subtract } from './math';

export const calculate = (operation, a, b) => {
  if (operation === 'add') {
    return add(a, b);
  } else if (operation === 'subtract') {
    return subtract(a, b);
  }
  return null;
};

// calculator.test.js
import { calculate } from './calculator';
import * as math from './math';

// पूरे math मॉड्यूल को मॉक करें
jest.mock('./math');

test('should perform addition using mocked math add', () => {
  // 'add' फ़ंक्शन के लिए एक मॉक कार्यान्वयन प्रदान करें
  math.add.mockImplementation((a, b) => a + b + 10); // परिणाम में 10 जोड़ें
  math.subtract.mockReturnValue(5); // subtract को भी मॉक करें

  const result = calculate('add', 5, 3);

  expect(math.add).toHaveBeenCalledWith(5, 3);
  expect(result).toBe(18); // 5 + 3 + 10

  const subResult = calculate('subtract', 10, 2);
  expect(math.subtract).toHaveBeenCalledWith(10, 2);
  expect(subResult).toBe(5);
});

स्नैपशॉट टेस्टिंग: यूआई और कॉन्फ़िगरेशन को संरक्षित करना

स्नैपशॉट टेस्ट आपके घटकों या कॉन्फ़िगरेशन के आउटपुट को कैप्चर करने के लिए एक शक्तिशाली सुविधा है। वे विशेष रूप से यूआई टेस्टिंग या जटिल डेटा संरचनाओं के सत्यापन के लिए उपयोगी हैं।

स्नैपशॉट टेस्टिंग कैसे काम करती है

पहली बार जब कोई स्नैपशॉट टेस्ट चलता है, तो Jest एक .snap फ़ाइल बनाता है जिसमें टेस्ट किए गए मान का एक क्रमबद्ध प्रतिनिधित्व होता है। बाद के रनों पर, Jest वर्तमान आउटपुट की तुलना संग्रहीत स्नैपशॉट से करता है। यदि वे भिन्न होते हैं, तो टेस्ट विफल हो जाता है, जो आपको अनपेक्षित परिवर्तनों के प्रति सचेत करता है। यह विभिन्न क्षेत्रों या लोकेल में यूआई घटकों में रिग्रेशन का पता लगाने के लिए अमूल्य है।

उदाहरण: एक रिएक्ट कंपोनेंट का स्नैपशॉट लेना

मान लीजिए कि आपके पास एक रिएक्ट कंपोनेंट है:

// UserProfile.js
import React from 'react';

const UserProfile = ({ name, email, isActive }) => (
  <div>
    <h2>{name}</h2>
    <p><strong>Email:</strong> {email}</p>
    <p><strong>Status:</strong> {isActive ? 'Active' : 'Inactive'}</p>
  </div>
);

export default UserProfile;

// UserProfile.test.js
import React from 'react';
import renderer from 'react-test-renderer'; // रिएक्ट कंपोनेंट स्नैपशॉट के लिए
import UserProfile from './UserProfile';

test('renders UserProfile correctly', () => {
  const user = {
    name: 'Jane Doe',
    email: 'jane.doe@example.com',
    isActive: true,
  };
  const component = renderer.create(
    <UserProfile {...user} />
  );
  const tree = component.toJSON();
  expect(tree).toMatchSnapshot();
});

test('renders inactive UserProfile correctly', () => {
  const user = {
    name: 'John Smith',
    email: 'john.smith@example.com',
    isActive: false,
  };
  const component = renderer.create(
    <UserProfile {...user} />
  );
  const tree = component.toJSON();
  expect(tree).toMatchSnapshot('inactive user profile'); // नामित स्नैपशॉट
});

टेस्ट चलाने के बाद, Jest एक UserProfile.test.js.snap फ़ाइल बनाएगा। जब आप कंपोनेंट को अपडेट करते हैं, तो आपको परिवर्तनों की समीक्षा करनी होगी और संभवतः Jest को --updateSnapshot या -u फ्लैग के साथ चलाकर स्नैपशॉट को अपडेट करना होगा।

स्नैपशॉट टेस्टिंग के लिए सर्वोत्तम अभ्यास

कस्टम मैचर्स: टेस्ट पठनीयता को बढ़ाना

Jest के अंतर्निहित मैचर्स व्यापक हैं, लेकिन कभी-कभी आपको ऐसी विशिष्ट स्थितियों का दावा करने की आवश्यकता होती है जो कवर नहीं की जाती हैं। कस्टम मैचर्स आपको अपनी खुद की अभिकथन तर्क बनाने की अनुमति देते हैं, जिससे आपके टेस्ट अधिक अभिव्यंजक और पठनीय हो जाते हैं।

कस्टम मैचर्स बनाना

आप Jest के expect ऑब्जेक्ट को अपने स्वयं के मैचर्स के साथ विस्तारित कर सकते हैं।

उदाहरण: एक वैध ईमेल प्रारूप की जाँच करना

आपकी Jest सेटअप फ़ाइल में (उदाहरण के लिए, jest.setup.js, जो jest.config.js में कॉन्फ़िगर किया गया है):

// jest.setup.js

expect.extend({
  toBeValidEmail(received) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const pass = emailRegex.test(received);

    if (pass) {
      return {
        message: () => `expected ${received} not to be a valid email`,
        pass: true,
      };
    } else {
      return {
        message: () => `expected ${received} to be a valid email`,
        pass: false,
      };
    }
  },
});

// In your jest.config.js
// module.exports = { setupFilesAfterEnv: ['/jest.setup.js'] };

आपकी टेस्ट फ़ाइल में:

// validation.test.js

test('should validate email formats', () => {
  expect('test@example.com').toBeValidEmail();
  expect('invalid-email').not.toBeValidEmail();
  expect('another.test@sub.domain.co.uk').toBeValidEmail();
});

कस्टम मैचर्स के लाभ

एसिंक्रोनस ऑपरेशंस का परीक्षण

जावास्क्रिप्ट भारी रूप से एसिंक्रोनस है। Jest प्रोमिसेस और async/await के परीक्षण के लिए उत्कृष्ट समर्थन प्रदान करता है।

async/await का उपयोग करना

यह एसिंक कोड का परीक्षण करने का आधुनिक और सबसे पठनीय तरीका है।

उदाहरण: एक एसिंक फ़ंक्शन का परीक्षण

// dataService.js
export const fetchUserData = async (userId) => {
  // एक देरी के बाद डेटा लाने का अनुकरण करें
  await new Promise(resolve => setTimeout(resolve, 50));
  if (userId === 1) {
    return { id: 1, name: 'Alice' };
  } else {
    throw new Error('User not found');
  }
};

// dataService.test.js
import { fetchUserData } from './dataService';

test('fetches user data correctly', async () => {
  const user = await fetchUserData(1);
  expect(user).toEqual({ id: 1, name: 'Alice' });
});

test('throws error for non-existent user', async () => {
  await expect(fetchUserData(2)).rejects.toThrow('User not found');
});

.resolves और .rejects का उपयोग करना

ये मैचर्स प्रोमिस रिज़ॉल्यूशन और रिजेक्शन के परीक्षण को सरल बनाते हैं।

उदाहरण: .resolves/.rejects का उपयोग करना

// dataService.test.js (continued)

test('fetches user data with .resolves', () => {
  return expect(fetchUserData(1)).resolves.toEqual({ id: 1, name: 'Alice' });
});

test('throws error for non-existent user with .rejects', () => {
  return expect(fetchUserData(2)).rejects.toThrow('User not found');
});

टाइमर्स को संभालना

उन फ़ंक्शंस के लिए जो setTimeout या setInterval का उपयोग करते हैं, Jest टाइमर नियंत्रण प्रदान करता है।

उदाहरण: टाइमर्स को नियंत्रित करना

// delayedGreeter.js
export const greetAfterDelay = (name, callback) => {
  setTimeout(() => {
    callback(`Hello, ${name}!`);
  }, 1000);
};

// delayedGreeter.test.js
import { greetAfterDelay } from './delayedGreeter';

jest.useFakeTimers(); // नकली टाइमर्स सक्षम करें

test('greets after delay', () => {
  const mockCallback = jest.fn();
  greetAfterDelay('World', mockCallback);

  // टाइमर्स को 1000ms आगे बढ़ाएं
  jest.advanceTimersByTime(1000);

  expect(mockCallback).toHaveBeenCalledTimes(1);
  expect(mockCallback).toHaveBeenCalledWith('Hello, World!');
});

// यदि कहीं और आवश्यक हो तो वास्तविक टाइमर्स को पुनर्स्थापित करें
jest.useRealTimers();

टेस्ट संगठन और संरचना

जैसे-जैसे आपका टेस्ट सुइट बढ़ता है, रखरखाव के लिए संगठन महत्वपूर्ण हो जाता है।

Describe ब्लॉक्स और It ब्लॉक्स

संबंधित टेस्टों को समूहित करने के लिए describe का और व्यक्तिगत टेस्ट मामलों के लिए it (या test) का उपयोग करें। यह संरचना एप्लिकेशन की मॉड्यूलरिटी को दर्शाती है।

उदाहरण: संरचित टेस्ट

describe('User Authentication Service', () => {
  let authService;

  beforeEach(() => {
    // प्रत्येक टेस्ट से पहले मॉक्स या सर्विस इंस्टेंस सेट करें
    authService = require('./authService');
    jest.spyOn(authService, 'login').mockImplementation(() => Promise.resolve({ token: 'fake_token' }));
  });

  afterEach(() => {
    // मॉक्स को साफ करें
    jest.restoreAllMocks();
  });

  describe('login functionality', () => {
    it('should successfully log in a user with valid credentials', async () => {
      const result = await authService.login('user@example.com', 'password123');
      expect(result.token).toBeDefined();
      // ... अधिक अभिकथन ...
    });

    it('should fail login with invalid credentials', async () => {
      jest.spyOn(authService, 'login').mockRejectedValue(new Error('Invalid credentials'));
      await expect(authService.login('user@example.com', 'wrong_password')).rejects.toThrow('Invalid credentials');
    });
  });

  describe('logout functionality', () => {
    it('should clear user session', async () => {
      // लॉगआउट लॉजिक का परीक्षण करें...
    });
  });
});

सेटअप और टियरडाउन हुक्स

ये हुक्स मॉक डेटा, डेटाबेस कनेक्शन स्थापित करने, या टेस्टों के बीच संसाधनों को साफ करने के लिए आवश्यक हैं।

वैश्विक दर्शकों के लिए परीक्षण

जब एक वैश्विक दर्शक के लिए एप्लिकेशन विकसित करते हैं, तो परीक्षण संबंधी विचार विस्तारित होते हैं:

अंतर्राष्ट्रीयकरण (i18n) और स्थानीयकरण (l10n)

सुनिश्चित करें कि आपका यूआई और संदेश विभिन्न भाषाओं और क्षेत्रीय प्रारूपों के लिए सही ढंग से अनुकूलित हों।

उदाहरण: स्थानीयकृत दिनांक स्वरूपण का परीक्षण

// dateUtils.js
export const formatLocalizedDate = (date, locale) => {
  return new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'numeric', day: 'numeric' }).format(date);
};

// dateUtils.test.js
import { formatLocalizedDate } from './dateUtils';

test('formats date correctly for US locale', () => {
  const date = new Date(2023, 10, 15); // 15 नवंबर, 2023
  expect(formatLocalizedDate(date, 'en-US')).toBe('11/15/2023');
});

test('formats date correctly for German locale', () => {
  const date = new Date(2023, 10, 15);
  expect(formatLocalizedDate(date, 'de-DE')).toBe('15.11.2023');
});

समय क्षेत्र जागरूकता

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

डेटा में सांस्कृतिक बारीकियां

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

उन्नत तकनीकें और रणनीतियाँ

टेस्ट-ड्रिवन डेवलपमेंट (TDD) और बिहेवियर-ड्रिवन डेवलपमेंट (BDD)

Jest TDD (रेड-ग्रीन-रिफैक्टर) और BDD (गिवेन-व्हेन-देन) पद्धतियों के साथ अच्छी तरह से संरेखित है। कार्यान्वयन कोड लिखने से पहले वांछित व्यवहार का वर्णन करने वाले टेस्ट लिखें। यह सुनिश्चित करता है कि कोड शुरू से ही परीक्षणशीलता को ध्यान में रखकर लिखा गया है।

Jest के साथ इंटीग्रेशन टेस्टिंग

जबकि Jest यूनिट टेस्ट में उत्कृष्टता प्राप्त करता है, इसका उपयोग इंटीग्रेशन टेस्ट के लिए भी किया जा सकता है। कम निर्भरताओं को मॉक करना या Jest के runInBand विकल्प जैसे उपकरणों का उपयोग करना मदद कर सकता है।

उदाहरण: एपीआई इंटरेक्शन का परीक्षण (सरलीकृत)

// apiService.js
import axios from 'axios';

const API_BASE_URL = 'https://api.example.com';

export const createProduct = async (productData) => {
  const response = await axios.post(`${API_BASE_URL}/products`, productData);
  return response.data;
};

// apiService.test.js (Integration test)
import axios from 'axios';
import { createProduct } from './apiService';

// नेटवर्क लेयर को नियंत्रित करने के लिए इंटीग्रेशन टेस्ट के लिए axios को मॉक करें
jest.mock('axios');

test('creates a product via API', async () => {
  const mockProduct = { id: 1, name: 'Gadget' };
  const responseData = { success: true, product: mockProduct };

  axios.post.mockResolvedValue({
    data: responseData,
    status: 201,
    headers: { 'content-type': 'application/json' },
  });

  const newProductData = { name: 'Gadget', price: 99.99 };
  const result = await createProduct(newProductData);

  expect(axios.post).toHaveBeenCalledWith(`${process.env.API_BASE_URL || 'https://api.example.com'}/products`, newProductData);
  expect(result).toEqual(responseData);
});

समानांतरता और कॉन्फ़िगरेशन

Jest निष्पादन को गति देने के लिए समानांतर में टेस्ट चला सकता है। इसे अपनी jest.config.js में कॉन्फ़िगर करें। उदाहरण के लिए, maxWorkers सेट करना समानांतर प्रक्रियाओं की संख्या को नियंत्रित करता है।

कवरेज रिपोर्ट्स

अपने कोडबेस के उन हिस्सों की पहचान करने के लिए Jest की अंतर्निहित कवरेज रिपोर्टिंग का उपयोग करें जिनका परीक्षण नहीं किया जा रहा है। विस्तृत रिपोर्ट बनाने के लिए --coverage के साथ टेस्ट चलाएं।

jest --coverage

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

निष्कर्ष

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

अपनी जावास्क्रिप्ट टेस्टिंग प्रथाओं को उन्नत करने के लिए आज ही इन उन्नत तकनीकों को अपने वर्कफ़्लो में शामिल करना शुरू करें।

Jest: मजबूत सॉफ्टवेयर के लिए उन्नत टेस्टिंग पैटर्न | MLOG