यूनिट टेस्टिंग सॉफ्टवेयर सत्यापन की एक विधि है जिसमें सिस्टम के बाकी हिस्सों से अलग करके कोड के अलग-अलग मॉड्यूल या फ़ंक्शन की सटीकता की जाँच की जाती है। 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) का उपयोग करें। सभी आधुनिक फ्रेमवर्क पैरामीटराइज़्ड टेस्ट, अंतर्निहित assertions और समानांतर निष्पादन का समर्थन करते हैं।
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 एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें