এই সম্পূর্ণ গাইডের মাধ্যমে রিঅ্যাক্ট টেস্টিং লাইব্রেরি (RTL) আয়ত্ত করুন। সেরা অনুশীলন এবং বাস্তব উদাহরণসহ আপনার রিঅ্যাক্ট অ্যাপ্লিকেশনের জন্য কার্যকর, রক্ষণাবেক্ষণযোগ্য এবং ব্যবহারকারী-কেন্দ্রিক পরীক্ষা লিখতে শিখুন।
রিঅ্যাক্ট টেস্টিং লাইব্রেরি: একটি বিস্তারিত গাইড
আজকের দ্রুতগতির ওয়েব ডেভেলপমেন্টের জগতে, আপনার রিঅ্যাক্ট অ্যাপ্লিকেশনগুলির গুণমান এবং নির্ভরযোগ্যতা নিশ্চিত করা অপরিহার্য। রিঅ্যাক্ট টেস্টিং লাইব্রেরি (RTL) ব্যবহারকারীর দৃষ্টিকোণ থেকে পরীক্ষা লেখার জন্য একটি জনপ্রিয় এবং কার্যকর সমাধান হিসেবে আবির্ভূত হয়েছে। এই গাইডটি RTL-এর একটি সম্পূর্ণ চিত্র তুলে ধরে, মৌলিক ধারণা থেকে শুরু করে উন্নত কৌশল পর্যন্ত সবকিছু কভার করে, যা আপনাকে শক্তিশালী এবং রক্ষণাবেক্ষণযোগ্য রিঅ্যাক্ট অ্যাপ্লিকেশন তৈরি করতে সক্ষম করবে।
কেন রিঅ্যাক্ট টেস্টিং লাইব্রেরি বেছে নেবেন?
প্রচলিত টেস্টিং পদ্ধতিগুলো প্রায়শই ইমপ্লিমেন্টেশন ডিটেইলসের উপর নির্ভর করে, যা সামান্য কোড পরিবর্তনেই টেস্টগুলোকে ভঙ্গুর করে তোলে। আরটিএল, অন্যদিকে, আপনাকে আপনার কম্পোনেন্টগুলোকে এমনভাবে পরীক্ষা করতে উৎসাহিত করে যেভাবে একজন ব্যবহারকারী সেগুলোর সাথে ইন্টারঅ্যাক্ট করবে, অর্থাৎ ব্যবহারকারী যা দেখে এবং অনুভব করে তার উপর ফোকাস করে। এই পদ্ধতির বেশ কিছু মূল সুবিধা রয়েছে:
- ব্যবহারকারী-কেন্দ্রিক টেস্টিং: RTL ব্যবহারকারীর দৃষ্টিকোণ প্রতিফলিত করে এমন পরীক্ষা লিখতে উৎসাহিত করে, যা নিশ্চিত করে যে আপনার অ্যাপ্লিকেশনটি শেষ-ব্যবহারকারীর দৃষ্টিকোণ থেকে প্রত্যাশিতভাবে কাজ করে।
- টেস্টের ভঙ্গুরতা হ্রাস: ইমপ্লিমেন্টেশন ডিটেইলস পরীক্ষা করা এড়িয়ে চলার মাধ্যমে, কোড রিফ্যাক্টর করার সময় RTL টেস্টগুলো ভেঙে যাওয়ার সম্ভাবনা কম থাকে, যা আরও রক্ষণাবেক্ষণযোগ্য এবং শক্তিশালী টেস্টের দিকে পরিচালিত করে।
- উন্নত কোড ডিজাইন: RTL আপনাকে এমন কম্পোনেন্ট লিখতে উৎসাহিত করে যা অ্যাক্সেসিবল এবং ব্যবহার করা সহজ, যা সামগ্রিকভাবে আরও ভালো কোড ডিজাইনের দিকে পরিচালিত করে।
- অ্যাক্সেসিবিলিটির উপর ফোকাস: RTL আপনার কম্পোনেন্টগুলোর অ্যাক্সেসিবিলিটি পরীক্ষা করা সহজ করে তোলে, যা নিশ্চিত করে যে আপনার অ্যাপ্লিকেশনটি সকলের জন্য ব্যবহারযোগ্য।
- সরলীকৃত টেস্টিং প্রক্রিয়া: RTL একটি সহজ এবং স্বজ্ঞাত API প্রদান করে, যা টেস্ট লেখা এবং রক্ষণাবেক্ষণ করা সহজ করে তোলে।
আপনার টেস্টিং এনভায়রনমেন্ট সেট আপ করা
আপনি RTL ব্যবহার শুরু করার আগে, আপনাকে আপনার টেস্টিং এনভায়রনমেন্ট সেট আপ করতে হবে। এর জন্য সাধারণত প্রয়োজনীয় ডিপেন্ডেন্সি ইনস্টল করা এবং আপনার টেস্টিং ফ্রেমওয়ার্ক কনফিগার করা জড়িত।
পূর্বশর্ত
- Node.js এবং npm (অথবা yarn): আপনার সিস্টেমে Node.js এবং npm (অথবা yarn) ইনস্টল করা আছে কিনা তা নিশ্চিত করুন। আপনি অফিসিয়াল Node.js ওয়েবসাইট থেকে এগুলো ডাউনলোড করতে পারেন।
- রিঅ্যাক্ট প্রজেক্ট: আপনার একটি বিদ্যমান রিঅ্যাক্ট প্রজেক্ট থাকা উচিত অথবা ক্রিয়েট রিঅ্যাক্ট অ্যাপ বা অনুরূপ টুল ব্যবহার করে একটি নতুন প্রজেক্ট তৈরি করুন।
ইনস্টলেশন
npm বা yarn ব্যবহার করে নিম্নলিখিত প্যাকেজগুলো ইনস্টল করুন:
npm install --save-dev @testing-library/react @testing-library/jest-dom jest babel-jest @babel/preset-env @babel/preset-react
অথবা, yarn ব্যবহার করে:
yarn add --dev @testing-library/react @testing-library/jest-dom jest babel-jest @babel/preset-env @babel/preset-react
প্যাকেজগুলোর ব্যাখ্যা:
- @testing-library/react: রিঅ্যাক্ট কম্পোনেন্ট পরীক্ষা করার জন্য মূল লাইব্রেরি।
- @testing-library/jest-dom: DOM নোড সম্পর্কে অ্যাসার্ট করার জন্য কাস্টম জেস্ট ম্যাচার সরবরাহ করে।
- Jest: একটি জনপ্রিয় জাভাস্ক্রিপ্ট টেস্টিং ফ্রেমওয়ার্ক।
- babel-jest: একটি জেস্ট ট্রান্সফরমার যা আপনার কোড কম্পাইল করতে Babel ব্যবহার করে।
- @babel/preset-env: একটি Babel প্রিসেট যা আপনার টার্গেট এনভায়রনমেন্ট সমর্থন করার জন্য প্রয়োজনীয় Babel প্লাগইন এবং প্রিসেট নির্ধারণ করে।
- @babel/preset-react: রিঅ্যাক্টের জন্য একটি Babel প্রিসেট।
কনফিগারেশন
আপনার প্রজেক্টের রুটে নিম্নলিখিত বিষয়বস্তু সহ একটি `babel.config.js` ফাইল তৈরি করুন:
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
};
একটি টেস্ট স্ক্রিপ্ট অন্তর্ভুক্ত করার জন্য আপনার `package.json` ফাইল আপডেট করুন:
{
"scripts": {
"test": "jest"
}
}
জেস্ট কনফিগার করার জন্য আপনার প্রজেক্টের রুটে একটি `jest.config.js` ফাইল তৈরি করুন। একটি ন্যূনতম কনফিগারেশন এইরকম হতে পারে:
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['/src/setupTests.js'],
};
নিম্নলিখিত বিষয়বস্তু সহ একটি `src/setupTests.js` ফাইল তৈরি করুন। এটি নিশ্চিত করে যে জেস্ট DOM ম্যাচারগুলো আপনার সমস্ত টেস্টে উপলব্ধ থাকবে:
import '@testing-library/jest-dom/extend-expect';
আপনার প্রথম টেস্ট লেখা
আসুন একটি সহজ উদাহরণ দিয়ে শুরু করা যাক। ধরুন আপনার একটি রিঅ্যাক্ট কম্পোনেন্ট আছে যা একটি অভিবাদন বার্তা প্রদর্শন করে:
// src/components/Greeting.js
import React from 'react';
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
export default Greeting;
এখন, আসুন এই কম্পোনেন্টের জন্য একটি টেস্ট লিখি:
// src/components/Greeting.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';
test('একটি অভিবাদন বার্তা রেন্ডার করে', () => {
render(<Greeting name="World" />);
const greetingElement = screen.getByText(/Hello, World!/i);
expect(greetingElement).toBeInTheDocument();
});
ব্যাখ্যা:
- `render`: এই ফাংশনটি কম্পোনেন্টকে DOM-এ রেন্ডার করে।
- `screen`: এই অবজেক্টটি DOM কোয়েরি করার জন্য বিভিন্ন মেথড সরবরাহ করে।
- `getByText`: এই মেথডটি টেক্সট কন্টেন্ট দ্বারা একটি এলিমেন্ট খুঁজে বের করে। `/i` ফ্ল্যাগটি সার্চকে কেস-ইনসেনসিটিভ করে তোলে।
- `expect`: এই ফাংশনটি কম্পোনেন্টের আচরণ সম্পর্কে অ্যাসারশন তৈরি করতে ব্যবহৃত হয়।
- `toBeInTheDocument`: এই ম্যাচারটি অ্যাসার্ট করে যে এলিমেন্টটি DOM-এ উপস্থিত আছে।
টেস্ট চালানোর জন্য, আপনার টার্মিনালে নিম্নলিখিত কমান্ডটি চালান:
npm test
যদি সবকিছু সঠিকভাবে কনফিগার করা থাকে, তাহলে টেস্টটি পাস করা উচিত।
সাধারণ RTL কোয়েরি
RTL DOM-এ এলিমেন্ট খোঁজার জন্য বিভিন্ন কোয়েরি মেথড সরবরাহ করে। এই কোয়েরিগুলো ডিজাইন করা হয়েছে ব্যবহারকারীরা কীভাবে আপনার অ্যাপ্লিকেশনের সাথে ইন্টারঅ্যাক্ট করে তা অনুকরণ করার জন্য।
`getByRole`
এই কোয়েরিটি একটি এলিমেন্টকে তার ARIA role দ্বারা খুঁজে বের করে। যখনই সম্ভব `getByRole` ব্যবহার করা একটি ভাল অভ্যাস, কারণ এটি অ্যাক্সেসিবিলিটি উন্নত করে এবং নিশ্চিত করে যে আপনার টেস্টগুলো অন্তর্নিহিত DOM কাঠামোর পরিবর্তনেও স্থিতিশীল থাকে।
<button role="button">Click me</button>
const buttonElement = screen.getByRole('button');
expect(buttonElement).toBeInTheDocument();
`getByLabelText`
এই কোয়েরিটি একটি এলিমেন্টকে তার সংশ্লিষ্ট লেবেলের টেক্সট দ্বারা খুঁজে বের করে। এটি ফর্ম এলিমেন্ট পরীক্ষা করার জন্য দরকারী।
<label htmlFor="name">Name:</label>
<input type="text" id="name" />
const nameInputElement = screen.getByLabelText('Name:');
expect(nameInputElement).toBeInTheDocument();
`getByPlaceholderText`
এই কোয়েরিটি একটি এলিমেন্টকে তার placeholder টেক্সট দ্বারা খুঁজে বের করে।
<input type="text" placeholder="Enter your email" />
const emailInputElement = screen.getByPlaceholderText('Enter your email');
expect(emailInputElement).toBeInTheDocument();
`getByAltText`
এই কোয়েরিটি একটি ইমেজ এলিমেন্টকে তার alt টেক্সট দ্বারা খুঁজে বের করে। অ্যাক্সেসিবিলিটি নিশ্চিত করার জন্য সমস্ত ইমেজের জন্য অর্থপূর্ণ alt টেক্সট প্রদান করা গুরুত্বপূর্ণ।
<img src="logo.png" alt="Company Logo" />
const logoImageElement = screen.getByAltText('Company Logo');
expect(logoImageElement).toBeInTheDocument();
`getByTitle`
এই কোয়েরিটি একটি এলিমেন্টকে তার title অ্যাট্রিবিউট দ্বারা খুঁজে বের করে।
<span title="Close">X</span>
const closeElement = screen.getByTitle('Close');
expect(closeElement).toBeInTheDocument();
`getByDisplayValue`
এই কোয়েরিটি একটি এলিমেন্টকে তার display value দ্বারা খুঁজে বের করে। এটি আগে থেকে পূরণ করা মান সহ ফর্ম ইনপুট পরীক্ষা করার জন্য দরকারী।
<input type="text" value="Initial Value" />
const inputElement = screen.getByDisplayValue('Initial Value');
expect(inputElement).toBeInTheDocument();
`getAllBy*` কোয়েরি
`getBy*` কোয়েরি ছাড়াও, RTL `getAllBy*` কোয়েরিও সরবরাহ করে, যা মিলে যাওয়া এলিমেন্টগুলির একটি অ্যারে রিটার্ন করে। যখন আপনাকে অ্যাসার্ট করতে হয় যে একই বৈশিষ্ট্যের একাধিক এলিমেন্ট DOM-এ উপস্থিত আছে তখন এগুলি দরকারী।
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
const listItems = screen.getAllByRole('listitem');
expect(listItems).toHaveLength(3);
`queryBy*` কোয়েরি
`queryBy*` কোয়েরিগুলো `getBy*` কোয়েরিগুলোর মতোই, কিন্তু যদি কোনো মিলে যাওয়া এলিমেন্ট না পাওয়া যায় তবে এরা একটি ত্রুটি নিক্ষেপ করার পরিবর্তে `null` রিটার্ন করে। যখন আপনি অ্যাসার্ট করতে চান যে একটি এলিমেন্ট DOM-এ উপস্থিত *নেই* তখন এটি দরকারী।
const missingElement = screen.queryByText('Non-existent text');
expect(missingElement).toBeNull();
`findBy*` কোয়েরি
`findBy*` কোয়েরিগুলো `getBy*` কোয়েরিগুলোর অ্যাসিঙ্ক্রোনাস সংস্করণ। তারা একটি Promise রিটার্ন করে যা মিলে যাওয়া এলিমেন্টটি পাওয়া গেলে সমাধান হয়। এগুলি অ্যাসিঙ্ক্রোনাস অপারেশন পরীক্ষা করার জন্য দরকারী, যেমন একটি API থেকে ডেটা আনা।
// একটি অ্যাসিঙ্ক্রোনাস ডেটা ফেচ সিমুলেট করা হচ্ছে
const fetchData = () => new Promise(resolve => {
setTimeout(() => resolve('Data Loaded!'), 1000);
});
function MyComponent() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetchData().then(setData);
}, []);
return <div>{data}</div>;
}
test('অ্যাসিঙ্ক্রোনাসভাবে ডেটা লোড করে', async () => {
render(<MyComponent />);
const dataElement = await screen.findByText('Data Loaded!');
expect(dataElement).toBeInTheDocument();
});
ব্যবহারকারীর ইন্টারঅ্যাকশন সিমুলেট করা
RTL ব্যবহারকারীর ইন্টারঅ্যাকশন সিমুলেট করার জন্য `fireEvent` এবং `userEvent` API সরবরাহ করে, যেমন বোতামে ক্লিক করা, ইনপুট ফিল্ডে টাইপ করা এবং ফর্ম জমা দেওয়া।
`fireEvent`
`fireEvent` আপনাকে প্রোগ্রাম্যাটিকভাবে DOM ইভেন্ট ট্রিগার করতে দেয়। এটি একটি নিম্ন-স্তরের API যা আপনাকে ফায়ার করা ইভেন্টগুলির উপর সূক্ষ্ম-নিয়ন্ত্রণ দেয়।
<button onClick={() => alert('Button clicked!')}>Click me</button>
import { fireEvent } from '@testing-library/react';
test('একটি বোতাম ক্লিক সিমুলেট করে', () => {
const alertMock = jest.spyOn(window, 'alert').mockImplementation(() => {});
render(<button onClick={() => alert('Button clicked!')}>Click me</button>);
const buttonElement = screen.getByRole('button');
fireEvent.click(buttonElement);
expect(alertMock).toHaveBeenCalledTimes(1);
alertMock.mockRestore();
});
`userEvent`
`userEvent` একটি উচ্চ-স্তরের API যা ব্যবহারকারীর ইন্টারঅ্যাকশনকে আরও বাস্তবসম্মতভাবে সিমুলেট করে। এটি ফোকাস ম্যানেজমেন্ট এবং ইভেন্ট অর্ডারিংয়ের মতো বিবরণ পরিচালনা করে, যা আপনার টেস্টগুলোকে আরও শক্তিশালী এবং কম ভঙ্গুর করে তোলে।
<input type="text" onChange={e => console.log(e.target.value)} />
import userEvent from '@testing-library/user-event';
test('একটি ইনপুট ফিল্ডে টাইপ করা সিমুলেট করে', () => {
const inputElement = screen.getByRole('textbox');
userEvent.type(inputElement, 'Hello, world!');
expect(inputElement).toHaveValue('Hello, world!');
});
অ্যাসিঙ্ক্রোনাস কোড টেস্টিং
অনেক রিঅ্যাক্ট অ্যাপ্লিকেশন অ্যাসিঙ্ক্রোনাস অপারেশন জড়িত, যেমন একটি API থেকে ডেটা আনা। RTL অ্যাসিঙ্ক্রোনাস কোড পরীক্ষা করার জন্য বেশ কিছু সরঞ্জাম সরবরাহ করে।
`waitFor`
`waitFor` আপনাকে একটি অ্যাসারশন করার আগে একটি শর্ত সত্য হওয়ার জন্য অপেক্ষা করতে দেয়। এটি অ্যাসিঙ্ক্রোনাস অপারেশন পরীক্ষা করার জন্য দরকারী যা সম্পূর্ণ হতে কিছু সময় নেয়।
function MyComponent() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
setTimeout(() => {
setData('Data loaded!');
}, 1000);
}, []);
return <div>{data}</div>;
}
import { waitFor } from '@testing-library/react';
test('ডেটা লোড হওয়ার জন্য অপেক্ষা করে', async () => {
render(<MyComponent />);
await waitFor(() => screen.getByText('Data loaded!'));
const dataElement = screen.getByText('Data loaded!');
expect(dataElement).toBeInTheDocument();
});
`findBy*` কোয়েরি
যেমন আগে উল্লেখ করা হয়েছে, `findBy*` কোয়েরিগুলো অ্যাসিঙ্ক্রোনাস এবং একটি Promise রিটার্ন করে যা মিলে যাওয়া এলিমেন্টটি পাওয়া গেলে সমাধান হয়। এগুলি অ্যাসিঙ্ক্রোনাস অপারেশন পরীক্ষা করার জন্য দরকারী যা DOM-এ পরিবর্তনের কারণ হয়।
হুক টেস্টিং
রিঅ্যাক্ট হুক হলো পুনঃব্যবহারযোগ্য ফাংশন যা স্টেটফুল লজিককে এনক্যাপসুলেট করে। RTL কাস্টম হুকগুলোকে বিচ্ছিন্নভাবে পরীক্ষা করার জন্য `@testing-library/react-hooks` থেকে `renderHook` ইউটিলিটি প্রদান করে (যা v17 থেকে `@testing-library/react`-এর পক্ষে অবচয়িত হয়েছে)।
// src/hooks/useCounter.js
import { useState } from 'react';
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => {
setCount(prevCount => prevCount + 1);
};
const decrement = () => {
setCount(prevCount => prevCount - 1);
};
return { count, increment, decrement };
}
export default useCounter;
// src/hooks/useCounter.test.js
import { renderHook, act } from '@testing-library/react';
import useCounter from './useCounter';
test('কাউন্টার বৃদ্ধি করে', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
ব্যাখ্যা:
- `renderHook`: এই ফাংশনটি হুক রেন্ডার করে এবং হুকের ফলাফল সহ একটি অবজেক্ট রিটার্ন করে।
- `act`: এই ফাংশনটি স্টেট আপডেটের কারণ হওয়া যেকোনো কোডকে মোড়ানোর জন্য ব্যবহৃত হয়। এটি নিশ্চিত করে যে রিঅ্যাক্ট সঠিকভাবে আপডেটগুলো ব্যাচ এবং প্রসেস করতে পারে।
উন্নত টেস্টিং কৌশল
আপনি RTL-এর মূল বিষয়গুলো আয়ত্ত করার পরে, আপনি আপনার টেস্টের গুণমান এবং রক্ষণাবেক্ষণযোগ্যতা উন্নত করতে আরও উন্নত টেস্টিং কৌশলগুলো অন্বেষণ করতে পারেন।
মডিউল মক করা
কখনও কখনও, আপনার কম্পোনেন্টগুলোকে বিচ্ছিন্ন করতে এবং পরীক্ষার সময় তাদের আচরণ নিয়ন্ত্রণ করতে আপনাকে বাহ্যিক মডিউল বা ডিপেন্ডেন্সি মক করতে হতে পারে। জেস্ট এই উদ্দেশ্যে একটি শক্তিশালী মকিং API সরবরাহ করে।
// src/api/dataService.js
export const fetchData = async () => {
const response = await fetch('/api/data');
const data = await response.json();
return data;
};
// src/components/MyComponent.js
import React, { useState, useEffect } from 'react';
import { fetchData } from '../api/dataService';
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetchData().then(setData);
}, []);
return <div>{data}</div>;
}
// src/components/MyComponent.test.js
import { render, screen, waitFor } from '@testing-library/react';
import MyComponent from './MyComponent';
import * as dataService from '../api/dataService';
jest.mock('../api/dataService');
test('API থেকে ডেটা ফেচ করে', async () => {
dataService.fetchData.mockResolvedValue({ message: 'Mocked data!' });
render(<MyComponent />);
await waitFor(() => screen.getByText('Mocked data!'));
expect(screen.getByText('Mocked data!')).toBeInTheDocument();
expect(dataService.fetchData).toHaveBeenCalledTimes(1);
});
ব্যাখ্যা:
- `jest.mock('../api/dataService')`: এই লাইনটি `dataService` মডিউলটিকে মক করে।
- `dataService.fetchData.mockResolvedValue({ message: 'Mocked data!' })`: এই লাইনটি মক করা `fetchData` ফাংশনটিকে কনফিগার করে যাতে এটি নির্দিষ্ট ডেটা সহ একটি সমাধানকৃত Promise রিটার্ন করে।
- `expect(dataService.fetchData).toHaveBeenCalledTimes(1)`: এই লাইনটি অ্যাসার্ট করে যে মক করা `fetchData` ফাংশনটি একবার কল করা হয়েছিল।
কনটেক্সট প্রোভাইডার
যদি আপনার কম্পোনেন্ট একটি কনটেক্সট প্রোভাইডারের উপর নির্ভর করে, তাহলে পরীক্ষার সময় আপনাকে আপনার কম্পোনেন্টকে সেই প্রোভাইডারে মোড়াতে হবে। এটি নিশ্চিত করে যে কম্পোনেন্টটির কনটেক্সট মানগুলিতে অ্যাক্সেস রয়েছে।
// src/contexts/ThemeContext.js
import React, { createContext, useState } from 'react';
export const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// src/components/MyComponent.js
import React, { useContext } from 'react';
import { ThemeContext } from '../contexts/ThemeContext';
function MyComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div style={{ backgroundColor: theme === 'light' ? '#fff' : '#000', color: theme === 'light' ? '#000' : '#fff' }}>
<p>Current theme: {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
// src/components/MyComponent.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
import { ThemeProvider } from '../contexts/ThemeContext';
test('থিম টগল করে', () => {
render(
<ThemeProvider>
<MyComponent />
</ThemeProvider>
);
const themeParagraph = screen.getByText(/Current theme: light/i);
const toggleButton = screen.getByRole('button', { name: /Toggle Theme/i });
expect(themeParagraph).toBeInTheDocument();
fireEvent.click(toggleButton);
expect(screen.getByText(/Current theme: dark/i)).toBeInTheDocument();
});
ব্যাখ্যা:
- আমরা পরীক্ষার সময় প্রয়োজনীয় কনটেক্সট সরবরাহ করতে `MyComponent`-কে `ThemeProvider`-এ মোড়াই।
রাউটারের সাথে টেস্টিং
রিঅ্যাক্ট রাউটার ব্যবহার করে এমন কম্পোনেন্ট পরীক্ষা করার সময়, আপনাকে একটি মক রাউটার কনটেক্সট সরবরাহ করতে হবে। আপনি `react-router-dom` থেকে `MemoryRouter` কম্পোনেন্ট ব্যবহার করে এটি অর্জন করতে পারেন।
// src/components/MyComponent.js
import React from 'react';
import { Link } from 'react-router-dom';
function MyComponent() {
return (
<div>
<Link to="/about">Go to About Page</Link>
</div>
);
}
// src/components/MyComponent.test.js
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import MyComponent from './MyComponent';
test('সম্পর্কে পেজের একটি লিঙ্ক রেন্ডার করে', () => {
render(
<MemoryRouter>
<MyComponent />
</MemoryRouter>
);
const linkElement = screen.getByRole('link', { name: /Go to About Page/i });
expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute('href', '/about');
});
ব্যাখ্যা:
- আমরা একটি মক রাউটার কনটেক্সট সরবরাহ করতে `MyComponent`-কে `MemoryRouter`-এ মোড়াই।
- আমরা অ্যাসার্ট করি যে লিঙ্ক এলিমেন্টটির সঠিক `href` অ্যাট্রিবিউট রয়েছে।
কার্যকর টেস্ট লেখার জন্য সেরা অনুশীলন
RTL দিয়ে টেস্ট লেখার সময় অনুসরণ করার জন্য এখানে কিছু সেরা অনুশীলন রয়েছে:
- ব্যবহারকারীর ইন্টারঅ্যাকশনের উপর ফোকাস করুন: ব্যবহারকারীরা কীভাবে আপনার অ্যাপ্লিকেশনের সাথে ইন্টারঅ্যাক্ট করে তা সিমুলেট করে এমন টেস্ট লিখুন।
- ইমপ্লিমেন্টেশন ডিটেইলস পরীক্ষা করা এড়িয়ে চলুন: আপনার কম্পোনেন্টের অভ্যন্তরীণ কার্যকারিতা পরীক্ষা করবেন না। পরিবর্তে, পর্যবেক্ষণযোগ্য আচরণের উপর ফোকাস করুন।
- পরিষ্কার এবং সংক্ষিপ্ত টেস্ট লিখুন: আপনার টেস্টগুলো বোঝা এবং রক্ষণাবেক্ষণ করা সহজ করুন।
- অর্থপূর্ণ টেস্টের নাম ব্যবহার করুন: এমন টেস্টের নাম বেছে নিন যা পরীক্ষিত আচরণকে সঠিকভাবে বর্ণনা করে।
- টেস্টগুলোকে বিচ্ছিন্ন রাখুন: টেস্টগুলোর মধ্যে নির্ভরতা এড়িয়ে চলুন। প্রতিটি টেস্ট স্বাধীন এবং স্বয়ংসম্পূর্ণ হওয়া উচিত।
- এজ কেস পরীক্ষা করুন: শুধু 'হ্যাপি পাথ' পরীক্ষা করবেন না। এজ কেস এবং ত্রুটির শর্তগুলোও পরীক্ষা করা নিশ্চিত করুন।
- কোড লেখার আগে টেস্ট লিখুন: আপনার কোড লেখার আগে টেস্ট লিখতে টেস্ট-ড্রিভেন ডেভেলপমেন্ট (TDD) ব্যবহার করার কথা বিবেচনা করুন।
- "AAA" প্যাটার্ন অনুসরণ করুন: অ্যারেঞ্জ, অ্যাক্ট, অ্যাসার্ট। এই প্যাটার্নটি আপনার টেস্টগুলোকে কাঠামোবদ্ধ করতে এবং আরও পঠনযোগ্য করতে সহায়তা করে।
- আপনার টেস্টগুলো দ্রুত রাখুন: ধীরগতির টেস্ট ডেভেলপারদের ঘন ঘন সেগুলো চালানো থেকে নিরুৎসাহিত করতে পারে। নেটওয়ার্ক অনুরোধ মক করে এবং DOM ম্যানিপুলেশনের পরিমাণ কমিয়ে আপনার টেস্টগুলোর গতি অপ্টিমাইজ করুন।
- বর্ণনামূলক ত্রুটির বার্তা ব্যবহার করুন: যখন অ্যাসারশন ব্যর্থ হয়, তখন ত্রুটির বার্তাগুলোতে ব্যর্থতার কারণ দ্রুত সনাক্ত করার জন্য যথেষ্ট তথ্য সরবরাহ করা উচিত।
উপসংহার
রিঅ্যাক্ট টেস্টিং লাইব্রেরি আপনার রিঅ্যাক্ট অ্যাপ্লিকেশনগুলির জন্য কার্যকর, রক্ষণাবেক্ষণযোগ্য এবং ব্যবহারকারী-কেন্দ্রিক পরীক্ষা লেখার জন্য একটি শক্তিশালী টুল। এই গাইডে বর্ণিত নীতি এবং কৌশলগুলো অনুসরণ করে, আপনি শক্তিশালী এবং নির্ভরযোগ্য অ্যাপ্লিকেশন তৈরি করতে পারেন যা আপনার ব্যবহারকারীদের চাহিদা পূরণ করে। ব্যবহারকারীর দৃষ্টিকোণ থেকে পরীক্ষা করার উপর ফোকাস করতে, ইমপ্লিমেন্টেশন ডিটেইলস পরীক্ষা করা এড়াতে এবং পরিষ্কার ও সংক্ষিপ্ত টেস্ট লিখতে মনে রাখবেন। RTL গ্রহণ করে এবং সেরা অনুশীলনগুলো অবলম্বন করে, আপনি আপনার অবস্থান বা আপনার বিশ্বব্যাপী দর্শকদের নির্দিষ্ট প্রয়োজনীয়তা নির্বিশেষে আপনার রিঅ্যাক্ট প্রজেক্টগুলোর গুণমান এবং রক্ষণাবেক্ষণযোগ্যতা উল্লেখযোগ্যভাবে উন্নত করতে পারেন।