ইউনিট টেস্টিং হল সফটওয়্যার যাচাইকরণের একটি পদ্ধতি যেখানে সিস্টেমের বাকি অংশ থেকে আলাদা করে কোডের পৃথক মডিউল বা ফাংশনের সঠিকতা পরীক্ষা করা হয়। Martin Fowler, 2026-এর মতে, ইউনিট টেস্টগুলি CI/CD এবং রিফ্যাক্টরিংয়ের ভিত্তি, যা কোডের কার্যকারিতা সম্পর্কে দ্রুত প্রতিক্রিয়া প্রদান করে। মডিউল টেস্টিং ডেভেলপমেন্টের প্রাথমিক পর্যায়ে ত্রুটি সনাক্ত করতে সাহায্য করে, যা সংশোধনের খরচ কয়েকগুণ কমিয়ে দেয়।
মূল বিষয়
ইউনিট টেস্টিং হল সোর্স কোডের পৃথক ইউনিট — ফাংশন, মেথড, ক্লাস — প্রোগ্রামের বাকি অংশ থেকে আলাদা করে যাচাই করার প্রক্রিয়া। প্রতিটি টেস্ট মডিউলের একটি নির্দিষ্ট ব্যবহারের পরিস্থিতি চালায় এবং ফলাফল প্রত্যাশিত সাথে মেলে কিনা তা পরীক্ষা করে। ইউনিট টেস্টগুলি প্রধান কোডের মতো একই প্রোগ্রামিং ভাষায় লেখা হয় এবং ডেভেলপমেন্ট এনভায়রনমেন্ট বা CI/CD পাইপলাইনে স্বয়ংক্রিয়ভাবে চলে। ইন্টিগ্রেশন টেস্টের বিপরীতে, ইউনিট টেস্টগুলি বাস্তব ডেটাবেস, ফাইল সিস্টেম বা নেটওয়ার্ক পরিষেবার সাথে যোগাযোগ করে না।
প্রধান লক্ষ্য হল পরিবর্তনের পরে কোডের সঠিকতা সম্পর্কে দ্রুত প্রতিক্রিয়া। যদি একজন ডেভেলপার কোনো মেথড রিফ্যাক্টর করে, ইউনিট টেস্টের সেট নিশ্চিত করে যে আচরণ ভাঙেনি। Google Testing Blog (2025) অনুসারে, 60% এর বেশি ইউনিট টেস্ট কভারেজযুক্ত প্রকল্পগুলিতে প্রোডাকশন ঘটনা 2.5 গুণ কম হয়। অতিরিক্ত সুবিধা: কোড ডকুমেন্টেশন (টেস্টগুলি দেখায় কীভাবে API ব্যবহার করতে হয়), রিফ্যাক্টরিং সহজীকরণ (আচরণ বজায় রেখে বাস্তবায়ন পরিবর্তন করা যায়), এবং দ্রুত রিগ্রেশন ডায়াগনস্টিকস।
প্রতিটি স্বয়ংক্রিয় টেস্ট ইউনিট টেস্ট নয়। মানদণ্ড: একটি একক মডিউল (ক্লাস বা ফাংশন) পরীক্ষা করা হয়, বাহ্যিক নির্ভরতাগুলি মক বা স্টাব দিয়ে প্রতিস্থাপিত হয়, টেস্ট মিলিসেকেন্ডে চলে এবং সার্ভার বা ডেটাবেস শুরু করার প্রয়োজন হয় না। বাস্তব ডেটাবেসে অ্যাক্সেস করা টেস্ট হল ইন্টিগ্রেশন টেস্ট। ব্রাউজার খোলা টেস্ট হল E2E টেস্ট। টেস্টের প্রকারের মধ্যে সীমানা বোঝা টেস্ট পিরামিডে সঠিকভাবে প্রচেষ্টা বিতরণের জন্য গুরুত্বপূর্ণ।
গুণগত ইউনিট টেস্টগুলি Robert C. Martin দ্বারা প্রণীত FIRST নীতিগুলি অনুসরণ করে। প্রতিটি টেস্ট Fast (দ্রুত — মিলিসেকেন্ড), Isolated (বিচ্ছিন্ন — অন্যান্য টেস্টের উপর নির্ভরশীল নয়), Repeatable (পুনরাবৃত্তিযোগ্য — যেকোনো মেশিনে একই ফলাফল), Self-validating (স্ব-বৈধতা — ফলাফল "পাস" বা "ফেল", ম্যানুয়াল চেক ছাড়া), এবং Timely (সময়োপযোগী — কোডের আগে বা সাথে লেখা) হওয়া উচিত। যেকোনো নীতি লঙ্ঘন টেস্টের মান কমিয়ে দেয়।
ইউনিট টেস্ট লেখার জন্য একটি স্ট্যান্ডার্ড টেমপ্লেট। Arrange — ডেটা এবং নির্ভরতা প্রস্তুত করা: অবজেক্ট তৈরি, মক কনফিগার, ইনপুট প্যারামিটার সেট করা। Act — পরীক্ষিত ক্রিয়া সম্পাদন: মেথড বা ফাংশন কল করা। Assert — ফলাফল যাচাই: প্রকৃত মানের সাথে প্রত্যাশিত মানের তুলনা। তিনটি ব্লকে বিভাজন টেস্টকে পড়ার যোগ্য এবং বোধগম্য করে তোলে। যদি Assert ব্লকের জটিল যুক্তির প্রয়োজন হয়, টেস্টটি সম্ভবত একবারে অনেক বেশি পরীক্ষা করছে।
// Kotlin-এ JUnit 5 সহ AAA প্যাটার্ন ব্যবহার করে ইউনিট টেস্টের উদাহরণ
class CalculatorTest {
private lateinit var calculator: Calculator
@BeforeEach
fun setUp() {
// ARRANGE — পরীক্ষার অবজেক্ট তৈরি করুন
calculator = Calculator()
}
@Test
fun addition_shouldReturnCorrectSum() {
// ACT — ক্রিয়া সম্পাদন করুন
val result = calculator.add(2, 3)
// ASSERT — ফলাফল যাচাই করুন
Assertions.assertEquals(5, result)
}
}
টেস্টের নামটি বর্ণনা করা উচিত কী পরীক্ষা করা হচ্ছে এবং কী ফলাফল প্রত্যাশিত। বিন্যাস: [methodName]_[scenario]_[expectedResult]। উদাহরণ: calculateTotal_whenDiscountApplied_shouldReturnDiscountedTotal। একটি ভাল টেস্টের নাম মন্তব্য প্রতিস্থাপন করে এবং ব্যর্থ হলে সাথে সাথে নির্দেশ করে কোন কার্যকারিতা ভেঙেছে। test1, checkSomething বা verify এর মতো নাম এড়িয়ে চলুন — তারা কোনো তথ্য বহন করে না এবং রোগ নির্ণয় জটিল করে তোলে।
পরীক্ষিত মডিউলকে বাহ্যিক নির্ভরতা থেকে আলাদা করতে টেস্ট ডাবল (test doubles) ব্যবহার করা হয়। প্রধান প্রকার: মক (mocks) — যাচাই করে যে একটি নির্দিষ্ট মেথড প্রত্যাশিত প্যারামিটার দিয়ে কল করা হয়েছিল; স্টাব (stubs) — মেথড কল করার সময় পূর্বনির্ধারিত মান ফেরত দেয়; ফেক (fakes) — বাস্তব উপাদানের সরলীকৃত বাস্তবায়ন (যেমন, ডেটাবেসের সাথে কাজ করা UserRepository-এর পরিবর্তে InMemoryUserRepository)। পছন্দ নির্ভর করে কী যাচাই করতে হবে: অবস্থা (স্টাব) বা মিথস্ক্রিয়া (মক)।
| ডাবল | কী যাচাই করে | উদাহরণ |
|---|---|---|
| মক | সঠিক প্যারামিটার সহ মেথড কল | userRepository.save(user) ঠিক 1 বার কল হয়েছিল |
| স্টাব | ফেরতের মান | repository.findById(1) User(id=1, name="Test") ফেরত দেয় |
| ফেক | সরলীকৃত বাস্তবায়নের মাধ্যমে যুক্তি | DB-এর পরিবর্তে HashMap সহ InMemoryMapUserRepository |
| স্পাই | বাস্তব অবজেক্টের আংশিক মকিং | spy(repo).when(findById).thenReturn(user) |
Mockito হল Java এবং Kotlin-এর জন্য সবচেয়ে জনপ্রিয় মকিং ফ্রেমওয়ার্ক। এটি mock() এর মাধ্যমে মক তৈরি, when().thenReturn() এর মাধ্যমে ফেরতের মান কনফিগার এবং verify() এর মাধ্যমে কল যাচাই করতে দেয়। Mockito (5.x) এর আধুনিক সংস্করণ স্ট্যাটিক মক (mockStatic) এবং BDDMockito (given-willReturn) এর মাধ্যমে সরলীকৃত সিনট্যাক্স সমর্থন করে। একটি গুরুত্বপূর্ণ নিয়ম: যা আপনার নয় তা মক করবেন না — ভ্যালু অবজেক্ট এবং স্ট্যান্ডার্ড লাইব্রেরির জন্য মক তৈরি করবেন না।
// Kotlin-এ Mockito সহ ইউনিট টেস্টের উদাহরণ
class OrderServiceTest {
@Mock
private lateinit var paymentGateway: PaymentGateway
@Mock
private lateinit var userRepository: UserRepository
private lateinit var orderService: OrderService
@BeforeEach
fun init() {
MockitoAnnotations.openMocks(this)
orderService = OrderService(paymentGateway, userRepository)
}
@Test
fun processOrder_whenPaymentFails_shouldThrowException() {
// given
val user = User(id = 1, balance = 100.0)
val order = Order(amount = 200.0)
Mockito.`when`(paymentGateway.charge(any())).thenReturn(false)
Mockito.`when`(userRepository.findById(1)).thenReturn(user)
// when & then
assert Throws<PaymentException> {
orderService.processOrder(user.id, order)
}
// verify
Mockito.verify(paymentGateway).charge(any())
}
}
TDD (Test-Driven Development) হল একটি পদ্ধতি যেখানে কোড বাস্তবায়নের আগে টেস্ট লেখা হয়। "লাল-সবুজ-রিফ্যাক্টর" চক্র: একটি টেস্ট লিখুন যা ব্যর্থ হয় (লাল), টেস্ট পাস করার জন্য ন্যূনতম কোড লিখুন (সবুজ), আচরণ পরিবর্তন না করে কোড উন্নত করুন (রিফ্যাক্টর)। TDD নিশ্চিত করে যে সমস্ত কোড টেস্ট দ্বারা আচ্ছাদিত (বাস্তবায়িত কার্যকারিতার জন্য কভারেজ = 100%) এবং কোড পরীক্ষাযোগ্য — যদি কোড পরীক্ষা করা কঠিন হয়, তাহলে আর্কিটেকচারের উন্নতি প্রয়োজন।
IBM (2006-2026, অনুদৈর্ঘ্য গবেষণা)-এর গবেষণা অনুসারে, TDD ব্যবহারকারী দলগুলিতে কোডের পরে টেস্ট লেখা দলগুলির তুলনায় প্রোডাকশনে 40-80% কম ত্রুটি থাকে। TDD আর্কিটেকচারও উন্নত করে: ডেভেলপার বাস্তবায়নের আগে API ডিজাইন সম্পর্কে চিন্তা করতে বাধ্য হয়, যা লুজ কাপলিং এবং হাই কোহেশন-এর দিকে নিয়ে যায়। একটি অতিরিক্ত প্রভাব হল জীবন্ত ডকুমেন্টেশন: টেস্টগুলি মডিউল আচরণের স্পেসিফিকেশন হিসাবে কাজ করে, যা সর্বদা আপ-টু-ডেট থাকে।
TDD সবসময় সর্বোত্তম নয়। UI উপাদানগুলি আলাদাভাবে পরীক্ষা করা কঠিন — তাদের জন্য স্ন্যাপশট টেস্ট বা ভিজ্যুয়াল রিগ্রেশন টেস্টিং (Percy, Chromatic) বেশি কার্যকর। প্রোটোটাইপিং এবং গবেষণা (স্পাইক সলিউশন) টেস্টের প্রয়োজন হয় না। টেস্ট ছাড়া লিগ্যাসি কোড TDD-এর মাধ্যমে কভার করা কঠিন — এখানে প্রথমে ক্যারেক্টারাইজেশন টেস্ট (রিফ্যাক্টরিংয়ের আগে বর্তমান আচরণ ক্যাপচার করে এমন টেস্ট) প্রয়োজন। এই ক্ষেত্রে, TDD সম্পূর্ণরূপে পরিত্যাগ করা হয় না বরং অভিযোজিত হয় — পুরো লিগ্যাসি কোডের জন্য নয়, পরিবর্তিত কার্যকারিতার জন্য টেস্ট লেখা হয়।
মোবাইল ডেভেলপমেন্টের নিজস্ব বিশেষত্ব রয়েছে: বিজনেস লজিক প্রায়শই UI কোডের (Activity, ViewController, ViewModel) সাথে মিশ্রিত হয়, যা ইউনিট টেস্টিংকে জটিল করে তোলে। সর্বোত্তম অনুশীলন হল পাতলা ভিউ, মোটা ViewModels: সমস্ত যুক্তি UI উপাদান থেকে আলাদা ক্লাসে (UseCase, Repository, ViewModel) বের করে আনুন যা এমুলেটর ছাড়াই সহজে পরীক্ষা করা যায়। Android এবং iOS-এর নেটিভ ইউনিট টেস্টিং ফ্রেমওয়ার্ক রয়েছে যা ডিভাইস চালু না করেই JVM/Native-তে চলে।
Android ইউনিট টেস্টগুলি এমুলেটর ছাড়াই স্থানীয় JVM-তে চলে, যা নির্বাহের গতি প্রদান করে — একটি সাধারণ টেস্ট 100ms-এর কম সময় নেয়। JUnit 5 প্রধান রানার। ViewModel টেস্টের জন্য, করুটিন পরীক্ষার জন্য kotlinx-coroutines-test এবং StateFlow পরীক্ষার জন্য Turbine ব্যবহার করুন। Robolectric শ্যাডো ক্লাস লোড করে এমুলেটর ছাড়াই Android-নির্ভর উপাদান (Context, Resources) পরীক্ষা করতে দেয়। Compose টেস্টের জন্য, Compose UI Test ব্যবহার করুন — কিন্তু এগুলি UI টেস্ট, ইউনিট টেস্ট নয়।
iOS ইউনিট টেস্টগুলি Swift-এ XCTest (Xcode-এ নির্মিত) দিয়ে লেখা হয়। Quick + Nimble হল আরও পঠনযোগ্য টেস্টের (describe/context/it) জন্য BDD ফ্রেমওয়ার্ক। মকিংয়ের জন্য, Cuckoo (মক জেনারেশন) বা SwiftyMocky ব্যবহার করুন। Swift প্রোটোকল এবং ডিপেন্ডেন্সি ইনজেকশন সমর্থন করে, যা নির্ভরতা প্রতিস্থাপন সহজ করে তোলে। মূল বিষয়: iOS ইউনিট টেস্টগুলি বাস্তব ডিভাইসে নয়, macOS সিমুলেটরে চলে। হার্ডওয়্যার বৈশিষ্ট্য (ক্যামেরা, ব্লুটুথ) প্রয়োজন এমন টেস্টগুলি ইন্টিগ্রেশন টেস্ট।
Flutter ইউনিট টেস্টগুলি flutter_test প্যাকেজ ব্যবহার করে এবং এমুলেটর ছাড়াই Dart VM-তে চলে। মকিংয়ের জন্য, কোড জেনারেশন (build_runner) সহ mockito প্যাকেজ ব্যবহার করুন। উইজেট টেস্ট (একই প্যাকেজে) পৃথক উইজেট পরীক্ষা করে কিন্তু রেন্ডারিং প্রয়োজন এবং ধীরে চলে — শুধুমাত্র UI যুক্তি যাচাইয়ের জন্য ব্যবহার করুন। খাঁটি Dart যুক্তি (মডেল, রিপোজিটরি, ব্লক) flutter_test ইম্পোর্ট না করেই নিয়মিত Dart টেস্ট হিসাবে পরীক্ষা করা হয়।
// Flutter-এ mockito সহ ইউনিট টেস্টের উদাহরণ
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
@GenerateMocks([ApiClient])
import 'user_repository_test.mocks.dart';
void main() {
late MockApiClient mockApi;
late UserRepository repository;
setUp(() {
mockApi = MockApiClient();
repository = UserRepository(mockApi);
});
test('fetchUser returns user when API succeeds', () async {
// Arrange
final expectedUser = User(id: 1, name: 'Test');
when(mockApi.getUser(1))
.thenAnswer((_) async => expectedUser);
// Act
final result = await repository.fetchUser(1);
// Assert
expect(result, expectedUser);
verify(mockApi.getUser(1)).called(1);
});
}
কার্যকর ইউনিট টেস্টিংয়ের জন্য শৃঙ্খলা প্রয়োজন। প্রধান নিয়ম: আচরণ পরীক্ষা করুন, বাস্তবায়ন নয়। টেস্টের জানা উচিত নয় কীভাবে মডিউলটি অভ্যন্তরীণভাবে বাস্তবায়িত হয়েছে (কোন প্রাইভেট মেথড কল করা হয়, কোন ক্রমে)। যদি টেস্ট বাস্তবায়নের সাথে আবদ্ধ থাকে, তবে এটি প্রতিটি রিফ্যাক্টরিংয়ে ভেঙে যায় এবং মান হারায়। টেস্ট চুক্তি যাচাই করে: ইনপুট X-এ, আউটপুট Y হওয়া উচিত। ব্যতিক্রম হল গুরুত্বপূর্ণ কর্মক্ষমতা সহ অ্যালগরিদমের জন্য টেস্ট, যেখানে কলের ক্রম গুরুত্বপূর্ণ।
100% কভারেজ একটি অপ্রাপ্য এবং অপ্রয়োজনীয় লক্ষ্য। Google Testing Blog (2025) অনুসারে, ইউনিট টেস্টের জন্য সর্বোত্তম কভারেজ স্তর হল কোডের 70-80% লাইন। 100% কভারেজ প্রায়শই গেটার, সেটার এবং কনস্ট্রাক্টর পরীক্ষা করে অর্জিত হয়, যা কোনো মান যোগ করে না। গুরুত্বপূর্ণ বিজনেস লজিক-এ ফোকাস করুন: জটিল গণনা, বৈধতা, ত্রুটি হ্যান্ডলিং, এজ কেস। পরিমাপের জন্য JaCoCo (Java), Coverage.py (Python), Istanbul (JS) ব্যবহার করুন এবং CI-তে একটি থ্রেশহোল্ড সেট করুন — 60% এর নিচে কভারেজে বিল্ড ব্যর্থতা।
ইউনিট টেস্ট যেকোনো CI/CD পাইপলাইনের প্রথম স্তর। এগুলি বিল্ড এবং ডিপ্লয়মেন্টের আগে, রিপোজিটরিতে প্রতিটি পুশে চলে। ইউনিট টেস্ট স্যুটের গড় রানটাইম 5 মিনিটের বেশি হওয়া উচিত নয় — বেশি হলে, টেস্টগুলি "দ্রুত" থাকে না এবং ডেভেলপাররা সেগুলি লোকালি চালানো বন্ধ করে দেয়। টেস্টগুলিকে দ্রুত (ইউনিট) এবং ধীর (ইন্টিগ্রেশন) এ ভাগ করুন এবং পাইপলাইনের বিভিন্ন ধাপে চালান। গতির জন্য সমান্তরাল নির্বাহ এবং ফেল-ফাস্ট ব্যবহার করুন।
সচরাচর জিজ্ঞাস্য
ইউনিট টেস্ট বাহ্যিক নির্ভরতাগুলি মক দিয়ে প্রতিস্থাপন করে একটি মডিউলকে বিচ্ছিন্নভাবে যাচাই করে। ইন্টিগ্রেশন টেস্ট একাধিক বাস্তব উপাদানের (DB, API, ফাইল সিস্টেম) মধ্যে মিথস্ক্রিয়া যাচাই করে। ইউনিট টেস্ট মিলিসেকেন্ডে চলে, ইন্টিগ্রেশন টেস্ট সেকেন্ডে। টেস্ট পিরামিডে, ইউনিট টেস্ট 70% গঠন করে।
নির্বাচন প্ল্যাটফর্মের উপর নির্ভর করে: Java/Kotlin-এর জন্য JUnit 5, iOS/Swift-এর জন্য XCTest, Python-এর জন্য pytest, JavaScript/TypeScript-এর জন্য Jest/Vitest, Flutter-এর জন্য flutter_test। মকিংয়ের জন্য, Mockito (Java), Cuckoo (iOS), unittest.mock (Python) বা vitest.mock (JS) ব্যবহার করুন। সমস্ত আধুনিক ফ্রেমওয়ার্ক প্যারামিটারাইজড টেস্ট, বিল্ট-ইন অ্যাসারশন এবং সমান্তরাল নির্বাহ সমর্থন করে।
Fast — টেস্ট মিলিসেকেন্ডে চলে। Isolated — অন্যান্য টেস্ট বা বাহ্যিক সিস্টেমের উপর নির্ভর করে না। Repeatable — যেকোনো মেশিনে একই ফলাফল দেয়। Self-validating — স্বয়ংক্রিয়ভাবে ফলাফল যাচাই করে। Timely — কোডের আগে বা সাথে লেখা হয়। একটি নীতি লঙ্ঘন করলেও টেস্টিং কার্যকারিতা হ্রাস পায়।
হ্যাঁ, অবশ্যই। ViewModel-এ বিজনেস লজিক থাকে — ইভেন্ট হ্যান্ডলিং, ডেটা ট্রান্সফর্মেশন, স্টেট ম্যানেজমেন্ট। Android-এ, করুটিনের জন্য kotlinx-coroutines-test এবং StateFlow পরীক্ষার জন্য Turbine ব্যবহার করুন। iOS-এ, ViewModel-এ Combine Publishers বা async/await পরীক্ষা করুন। ViewModel টেস্টগুলি এমুলেটর ছাড়াই JVM/macOS-এ চলমান বিশুদ্ধ ইউনিট টেস্ট।
ইউনিট টেস্টে নেটওয়ার্ক রিকোয়েস্ট নির্বাহিত হয় না — সেগুলি HTTP ক্লায়েন্ট মক দিয়ে প্রতিস্থাপিত হয়। Android-এ, MockWebServer (OkHttp) ব্যবহার করুন — এটি একটি স্থানীয় HTTP সার্ভার চালায়, যা মকের চেয়ে উত্তম কারণ এটি বাস্তব নেটওয়ার্ক মিথস্ক্রিয়া পুনরুৎপাদন করে। MockWebServer বাস্তবতা না হারিয়ে বিচ্ছিন্নতা প্রদান করে। iOS-এর জন্য — প্রতিক্রিয়া আটকাতে এবং প্রতিস্থাপন করতে OHHTTPStubs বা URLProtocol ব্যবহার করুন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন