Test-Driven Development (TDD) হল একটি ডেভেলপমেন্ট পদ্ধতি যেখানে কোড বাস্তবায়নের আগে টেস্ট লেখা হয়। ডেভেলপার প্রথমে একটি ব্যর্থ টেস্টের আকারে প্রত্যাশিত আচরণ প্রণয়ন করে, তারপর এটি পাস করার জন্য ন্যূনতম কোড লেখে এবং এর পরে ফলাফল রিফ্যাক্টর করে। Martin Fowler (2023)-এর মতে, TDD কোনো টেস্টিং কৌশল নয় — এটি একটি ডিজাইন কৌশল যা আর্কিটেকচারকে শৃঙ্খলাবদ্ধ করে এবং কোড লেখার পর্যায়ে ত্রুটির সংখ্যা হ্রাস করে।
মূল পয়েন্ট
Test-Driven Development হল একটি সফটওয়্যার ডেভেলপমেন্ট অনুশীলন যেখানে স্বয়ংক্রিয় টেস্ট প্রোডাকশন কোড লেখা নির্ধারণ করে। ঐতিহ্যগত পদ্ধতির বিপরীতে যেখানে কোড লেখা হয় এবং তারপর পরীক্ষা করা হয়, TDD ক্রমটি উল্টে দেয়: প্রথমে টেস্ট লেখা হয়, তারপর কোড যা সেই টেস্ট পাস করে।
TDD-এর প্রতিষ্ঠাতা Kent Beck বলে বিবেচিত হন, যিনি 1990-এর দশকের শেষের দিকে Extreme Programming (XP) পদ্ধতির অংশ হিসাবে এই অনুশীলনটি প্রণয়ন করেছিলেন। “Test-Driven Development: By Example” (2002) বইয়ে, বেক TDD-এর পাঁচটি নিয়ম বর্ণনা করেছেন যা আদর্শ হয়ে উঠেছে: প্রোডাকশন কোডের আগে টেস্ট লিখুন, টেস্ট পাস করার জন্য ঠিক ততটুকু কোড লিখুন এবং প্রতিটি চক্রের পরে রিফ্যাক্টর করুন।
প্রথম নীতি — টেস্ট ইন্টারফেস নির্ধারণ করে. ডেভেলপারকে চিন্তা করতে বাধ্য করা হয় যে কম্পোনেন্ট কীভাবে ব্যবহার করা হবে, তা বাস্তবায়নের আগে। এটি শুরু থেকেই একটি পরিষ্কার API গঠন করে।
দ্বিতীয় নীতি — ন্যূনতম বাস্তবায়ন. যখন টেস্ট লেখা হয়, ডেভেলপার ঠিক ততটুকু প্রোডাকশন কোড লেখে যতটুকু এটি পাস করার জন্য প্রয়োজন — একটি লাইনও বেশি নয়। এটি অকাল বিমূর্ততা এবং অত্যধিক জটিলতা প্রতিরোধ করে, যাকে Martin Fowler Speculative Generality বলে।
TDD এবং “পরে” টেস্টিংয়ের মধ্যে মূল পার্থক্য — ক্রমের শৃঙ্খলা। TDD-তে, টেস্ট শুধু কোড যাচাই করে না — এটি তার গঠন নির্দেশ করে। Microsoft Research (Nagappan et al., 2008) গবেষণা অনুসারে, TDD প্রয়োগকারী দলগুলি ঐতিহ্যগত পদ্ধতি ব্যবহারকারী দলগুলির তুলনায় 40–90% কম ত্রুটির ঘনত্ব প্রদর্শন করে।
Red-Green-Refactor চক্রটি একটি তিন-পদক্ষেপের ক্রম যা প্রতিটি নতুন টেস্টের জন্য পুনরাবৃত্তি হয়। Red: একটি টেস্ট লিখুন যা পাস করে না। Green: টেস্ট পাস করার জন্য ন্যূনতম কোড লিখুন। Refactor: আচরণ পরিবর্তন না করে কোড উন্নত করুন।
ডেভেলপার একটি টেস্ট লেখে যা এখনও বাস্তবায়িত হয়নি এমন কার্যকারিতা পরীক্ষা করে। এই পর্যায়ে, টেস্টটিকে ব্যর্থ হতে হবে — এটি নিশ্চিত করে যে টেস্ট সত্যিই কিছু যাচাই করছে। Android ডেভেলপমেন্ট পরিবেশে, JUnit 5 ফ্রেমওয়ার্ক ব্যর্থ টেস্টের জন্য লাল সূচক দেখায়, যা এই পর্যায়ের নাম দিয়েছে।
class CalculatorTest {
fun testAddition() {
val result = Calculator().add(2, 3)
Assertions.assertEquals(5, result)
}
}
এই পর্যায়ে, টেস্ট পাস করার জন্য যথেষ্ট ন্যূনতম প্রোডাকশন কোড লেখা হয়। কোনো অতিরিক্ত নয় — শুধু সবুজ সূচকের জন্য যা প্রয়োজন। যদি বাস্তবায়ন একটি ধ্রুবক হতে পারে, তবে এটি ধ্রুবক হোক। রিফ্যাক্টরিং পরবর্তী ধাপে হবে যখন নতুন টেস্ট আসবে।
class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}
}
সবুজ টেস্ট রিফ্যাক্টরিং-এর জন্য বীমা। ডেভেলপার বাস্তবায়ন পুনরায় লিখতে পারে, কর্মক্ষমতা অপ্টিমাইজ করতে পারে বা পঠনযোগ্যতা উন্নত করতে পারে, এই আস্থার সাথে যে টেস্ট অবিলম্বে প্রত্যাশিত আচরণ থেকে কোনো বিচ্যুতি সনাক্ত করবে। Android মোবাইল ডেভেলপমেন্টে, এই পর্যায়টি সাধারণ ইন্টারফেস বের করা এবং কোড পুনরাবৃত্তি কমানোর জন্য বিশেষভাবে গুরুত্বপূর্ণ।
মোবাইল প্রকল্পে TDD প্রয়োগ করলে পরিমাপযোগ্য সুবিধা পাওয়া যায়, যা একাডেমিক গবেষণা এবং শীর্ষস্থানীয় ডেভেলপমেন্ট স্টুডিওর অনুশীলন উভয় দ্বারা নিশ্চিত।
চারটি শিল্প প্রকল্পে IBM গবেষণা (Bhat & Nagappan, 2006) দেখিয়েছে যে TDD ব্যবহারকারী দলগুলি ঐতিহ্যগত পদ্ধতিতে কাজ করা অনুরূপ দলগুলির তুলনায় 40% কম ত্রুটি তৈরি করে। মোবাইল ডেভেলপমেন্টের জন্য, যেখানে Google Play-তে প্রকাশের পরে বাগ ফিক্সের খরচ কোড লেখার পর্যায়ের তুলনায় উল্লেখযোগ্যভাবে বেশি, এই মেট্রিকটি গুরুত্বপূর্ণ।
TDD-এর সাথে লেখা টেস্টগুলি API-এর জীবন্ত ডকুমেন্টেশন হিসাবে কাজ করে। প্রকল্পে যোগদানকারী ডেভেলপার টেস্ট পড়ে বুঝতে পারে কীভাবে প্রতিটি কম্পোনেন্ট ব্যবহার করা উচিত। এটি উচ্চ টিম টার্নওভার পরিস্থিতিতে বিশেষভাবে মূল্যবান — মোবাইল স্টুডিওর একটি সাধারণ চ্যালেঞ্জ।
90% ছাড়িয়ে যাওয়া কোড কভারেজ ডেভেলপারদের কিছু ভাঙার ভয় ছাড়াই রিফ্যাক্টর করতে দেয়। Google তার “Software Engineering at Google” (2020) বইয়ে টেস্ট কভারেজকে লক্ষ লক্ষ লাইনের কোডের প্রকল্পে কোড বেস পরিষ্কার রাখার মূল কারণ বলে।
মোবাইল ডেভেলপমেন্টে TDD ইকোসিস্টেমে ইউনিট টেস্টিং, মকিং এবং UI কম্পোনেন্ট যাচাইয়ের জন্য টুল অন্তর্ভুক্ত — Android এবং iOS উভয়ের জন্য।
| টুল | প্ল্যাটফর্ম | উদ্দেশ্য |
|---|---|---|
| JUnit 5 | Android (Kotlin/Java) | ইউনিট টেস্টের জন্য মৌলিক ফ্রেমওয়ার্ক |
| Mockito | Android | মক অবজেক্ট তৈরি এবং কল যাচাইকরণ |
| MockK | Android (Kotlin) | Kotlin-first সিনট্যাক্স এবং coroutine সমর্থন সহ মকিং |
| Turbine | Android | Kotlin Flow এবং রিঅ্যাকটিভ স্ট্রিম টেস্টিং |
| XCTest | iOS (Swift) | স্ট্যান্ডার্ড টেস্টিং ফ্রেমওয়ার্ক |
Kotlin-এ Android প্রকল্পের জন্য, স্ট্যান্ডার্ড স্ট্যাকের মধ্যে JUnit 5 + MockK অন্তর্ভুক্ত। MockK, Mockito-র চেয়ে ভালো কারণ এটি অতিরিক্ত সেটআপ ছাড়াই Kotlin-এর প্রথম-শ্রেণির বৈশিষ্ট্য — sealed class, coroutine এবং suspend ফাংশন — সমর্থন করে।
iOS ডেভেলপমেন্টে, TDD XCTest-এর মাধ্যমে প্রয়োগ করা হয় — Apple-এর বিল্ট-ইন ফ্রেমওয়ার্ক যা assertions, টেস্ট ক্লাস এবং Xcode Server বা GitHub Actions-এর মাধ্যমে CI/CD ইন্টিগ্রেশন প্রদান করে। iOS-এ মকিংয়ের জন্য Cuckoo এবং OHHTTPStubs লাইব্রেরি ব্যবহার করা হয়।
Android-এর জন্য Kotlin-এ TDD-এর একটি বাস্তব পরিস্থিতি দেখি — একটি ইউজার রিপজিটরি টেস্টিং। প্রথমে আমরা টেস্ট লিখি, তারপর বাস্তবায়ন যা সেই টেস্ট পাস করে।
class UserRepositoryTest {
private val api = mockk<UserApi>()
private val dao = mockk<UserDao>()
private val repo = UserRepository(api, dao)
fun `when api returns user then cache and emit`() = runTest {
val user = User(1, "Alice")
coEvery { api.getUser(1) } returns user
every { dao.insert(user) } returns Unit
val result = repo.getUser(1)
assertEquals(user, result)
verify { dao.insert(user) }
}
}
class UserRepository(
private val api: UserApi,
private val dao: UserDao
) {
suspend fun getUser(id: Int): User {
val user = api.getUser(id)
dao.insert(user)
return user
}
}
প্রথম টেস্ট পাস করার পরে, আমরা দ্বিতীয়টি যোগ করি — নেটওয়ার্ক ত্রুটির সময় আচরণ পরীক্ষা করি। এখন টেস্ট নির্ধারণ করে যে API ব্যর্থ হলে, রিপজিটরির ক্যাশ থেকে ডেটা ফেরত দেওয়া উচিত।
fun `when api fails then return cached user`() = runTest {
val cached = User(1, "Cached Alice")
coEvery { api.getUser(1) } throws IOException()
every { dao.getById(1) } returns cached
val result = repo.getUser(1)
assertEquals(cached, result)
}
TDD-তে রূপান্তর সাধারণ ভুলের সাথে জড়িত যা পদ্ধতির সমস্ত সুবিধা বাতিল করতে পারে। এই ফাঁদগুলি বোঝা দলগুলিকে অনুশীলন আরও কার্যকরভাবে প্রয়োগ করতে সহায়তা করে।
প্রথম এবং সবচেয়ে সাধারণ অ্যান্টি-প্যাটার্ন — একটি টেস্টে অত্যধিক কার্যকারিতা পরীক্ষা করা। টেস্টটি ঠিক একটি দাবি যাচাই করা উচিত। যদি টেস্ট ব্যর্থ হয়, ডেভেলপারের জানা উচিত অতিরিক্ত ডিবাগিং ছাড়াই ঠিক কী ভেঙেছে।
দ্বিতীয় ভুল — এমন একটি টেস্ট লেখা যা শুরু থেকেই পাস করে। যদি টেস্টটি অন্তত একবার লাল না হয়, তবে আস্থা নেই যে এটি সত্যিই কিছু যাচাই করছে। নিয়ম: কখনও এমন টেস্টকে বিশ্বাস করবেন না যা আপনি ব্যর্থ হতে দেখেননি।
তৃতীয় সাধারণ ভুল — সবুজ পর্যায়ে থেমে যাওয়া। রিফ্যাক্টরিং ঐচ্ছিক নয় বরং চক্রের একটি বাধ্যতামূলক পদক্ষেপ। এটি ছাড়া, কোড বেস ক্ষয়প্রাপ্ত হয়, টেস্ট ভঙ্গুর হয়ে যায় এবং TDD-এর সুবিধা হারিয়ে যায়।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
TDD প্রথম এবং সর্বাগ্রে একটি ডিজাইন কৌশল, টেস্টিং কৌশল নয়। TDD-তে টেস্টগুলি স্পেসিফিকেশনের ভূমিকা পালন করে: তারা বাস্তবায়নের আগে কম্পোনেন্ট API নির্ধারণ করে। Kent Beck নিজে TDD-কে “ডিজাইনের শৃঙ্খলা বলেন, টেস্টিংয়ের নয়।”
Microsoft Research গবেষণা অনুসারে, TDD অভ্যাসে পরিণত হতে দলগুলির 3 থেকে 6 মাস অবিচ্ছিন্ন অনুশীলন প্রয়োজন। প্রথম 2–3 সপ্তাহে উত্পাদনশীলতা 15–30% কমে যায়, কিন্তু অভিযোজনের পরে এটি ডিবাগিং সময় হ্রাসের কারণে মূল স্তরে ফিরে আসে বা অতিক্রম করে।
হ্যাঁ, কিন্তু সীমাবদ্ধতা সহ। UI লজিকের (ViewModel, State) জন্য, TDD সরাসরি প্রযোজ্য। ভিজ্যুয়াল কম্পোনেন্টের (Compose UI, SwiftUI Views) জন্য, স্ন্যাপশট টেস্টিং TDD-কে পরিপূরক করে কিন্তু প্রতিস্থাপন করে না। ব্যবসায়িক যুক্তি এবং উপস্থাপনা আলাদা করার পরামর্শ দেওয়া হয়।
লিগ্যাসি কোডের জন্য, “ক্যারেক্টারাইজেশন টেস্ট”-এর কৌশল সুপারিশ করা হয় — যেখানে বিদ্যমান আচরণের উপর টেস্ট লেখা হয় এবং তারপর কোড রিফ্যাক্টর করা হয়। এই পদ্ধতিটি Michael Feathers-এর “Working Effectively with Legacy Code” (2004) বইয়ে বর্ণিত হয়েছে এবং TDD ধীরে ধীরে প্রয়োগ করতে দেয়।
TDD এবং Clean Architecture একে অপরকে শক্তিশালী করে। পরিষ্কার আর্কিটেকচারের স্তরগুলির মধ্যে স্পষ্ট সীমানা প্রয়োজন, এবং TDD ডেভেলপারকে টেস্টের মাধ্যমে সেই সীমানা ডিজাইন করতে বাধ্য করে। Domain স্তর mock-নির্ভরতা সহ বিচ্ছিন্নভাবে পরীক্ষা করা হয়, data স্তর — ইন্টিগ্রেশন টেস্টের মাধ্যমে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন