আমি আপনার “Simple Coding Tutor”। চলুন, আজকের লেকচারটি সহজভাবে এবং বিস্তারিতভাবে বুঝে নেওয়া যাক।
📝 Lecture Summary (Quick Revision)
ভবিষ্যতে দ্রুত রিভিশন দেওয়ার জন্য সম্পূর্ণ লেকচারের মূল কাজগুলো নিচে লিস্ট আকারে দেওয়া হলো:
- Interface Update:
ICountriesServiceইন্টারফেসেGetAllCountriesনামের নতুন একটি মেথড ডিক্লেয়ার করা, যাList<CountryResponse>রিটার্ন করবে। - Service Implementation (Dummy):
CountriesServiceক্লাসে এই নতুন মেথডটি ইমপ্লিমেন্ট করা এবং আপাততNotImplementedExceptionথ্রো করে রাখা। - C# Regions: ইউনিট টেস্টগুলোকে গুছিয়ে রাখার জন্য
#regionএবং#endregionএর ব্যবহার শেখা। - Unit Test 1 (Empty List):
GetAllCountries_EmptyListনামে টেস্ট লেখা, যা চেক করে যে কোনো Country অ্যাড না করলেGetAllCountriesমেথডটি একটি এম্পটি (empty) লিস্ট রিটার্ন করে কিনা (UsingAssert.Empty). - Unit Test 2 (Add Few Countries):
GetAllCountries_AddFewCountriesনামে টেস্ট লেখা, যেখানে লুপ চালিয়ে কিছু Country অ্যাড করা হয় এবং চেক করা হয় যে অ্যাড করা Country-গুলোGetAllCountriesমেথড থেকে ফিরে আসা লিস্টে আছে কিনা (UsingAssert.Contains). - Updating Existing Test: আগের লেকচারে লেখা
AddCountry_ProperCountryDetailsটেস্টটিতে একটি নতুন Assertion যোগ করা, যাতে নিশ্চিত হওয়া যায় যে নতুন অ্যাড করা Country-টিGetAllCountriesলিস্টের ভেতর উপস্থিত আছে।
🧠 Comprehensive Breakdown
এই লেকচারে আমরা Test-Driven Development (TDD) এর নিয়ম অনুসরণ করে GetAllCountries মেথডটির লজিক লেখার আগে তার জন্য Unit Test তৈরি করেছি। চলুন প্রতিটি ধাপ বিস্তারিতভাবে বুঝে নিই।
১. Interface-এ মেথড অ্যাড করা এবং XML Comments (Priority: 6/10)
Concept: ক্লায়েন্ট যাতে Service-এর সবগুলো মেথড সম্পর্কে জানতে পারে, তাই প্রথমে ইন্টারফেসে মেথড ডিক্লেয়ার করতে হয়।
Why: আমরা ICountriesService ইন্টারফেসে List<CountryResponse> GetAllCountries() মেথডটি যোগ করেছি। এর সাথে XML Comment (///) যোগ করা হয়েছে, যাতে অন্য কোনো ডেভেলপার মেথডটির ওপর হোভার (hover) করলেই এর কাজ বুঝতে পারে (টুলটিপ হিসেবে দেখায়)।
// ICountriesService.cs
/// <summary>
/// Returns all countries
/// </summary>
/// <returns>All countries from the list as List of CountryResponse</returns>
List<CountryResponse> GetAllCountries();
২. Service ক্লাসে মেথডটির Dummy Implementation (Priority: 5/10)
Concept: ইন্টারফেসে নতুন মেথড যোগ করলে, যে ক্লাসটি ওই ইন্টারফেসকে ইমপ্লিমেন্ট করছে, সেখানেও মেথডটি লিখতে হবে।
Why: আমরা Visual Studio-এর Quick Action (বা Ctrl + .) ব্যবহার করে CountriesService ক্লাসে মেথডটি তৈরি করেছি। যেহেতু আমরা এর মূল লজিক আগামী লেকচারে লিখব, তাই আপাতত কম্পাইলারকে খুশি রাখার জন্য throw new NotImplementedException(); লিখে রাখা হয়েছে।
// CountriesService.cs
public List<CountryResponse> GetAllCountries()
{
throw new NotImplementedException();
}
৩. C# Regions ব্যবহার করে কোড অর্গানাইজ করা (Priority: 4/10)
Concept: ক্লাসের ভেতরে অনেক কোড হয়ে গেলে সেগুলো সহজে ম্যানেজ করার জন্য #region ব্যবহার করা হয়।
Why: এটি ব্যবহার করলে আপনি কোডের ব্লকগুলোকে collapse (মিনিমাইজ) বা expand (ম্যাক্সিমাইজ) করে রাখতে পারবেন। লেকচারার AddCountry এর সব টেস্ট একটি রিজিয়নে এবং GetAllCountries এর টেস্টগুলো অন্য রিজিয়নে রেখেছেন।
#region AddCountry
// AddCountry এর সব ইউনিট টেস্ট...
#endregion
#region GetAllCountries
// GetAllCountries এর ইউনিট টেস্টগুলো এখানে লিখবো...
#endregion
৪. Unit Test: Empty List Check (Priority: 9/10)
Concept: সিস্টেমের শুরুতে যখন কোনো Country অ্যাড করা হয়নি, তখন মেথডটি কল করলে একটি এম্পটি (ফাঁকা) লিস্ট আসার কথা।
Why: এটি চেক করার জন্য আমরা XUnit-এর Assert.Empty() মেথডটি ব্যবহার করেছি।
[Fact]
public void GetAllCountries_EmptyList()
{
// Act: সরাসরি মেথড কল করা হচ্ছে
List<CountryResponse> actual_country_response_list = _countriesService.GetAllCountries();
// Assert: লিস্টটি ফাঁকা কিনা চেক করা
Assert.Empty(actual_country_response_list);
}
(এই টেস্টটি রান করলে ফেল করবে, কারণ মেথডটি এখনও NotImplementedException থ্রো করছে।)
৫. Unit Test: Add Few Countries Check (Priority: 10/10)
Concept: সিস্টেমে কিছু Country অ্যাড করার পর, GetAllCountries মেথডটি কল করলে ঠিক ওই Country-গুলোই ফিরে আসা উচিত।
Why: এখানে আমরা একটি লিস্টে কিছু ডামি (dummy) CountryAddRequest বানিয়েছি। তারপর লুপ চালিয়ে সেগুলোকে AddCountry মেথডের মাধ্যমে সিস্টেমে অ্যাড করেছি এবং যা রেসপন্স পেয়েছি তা একটি লিস্টে (country_response_list_from_add_country) জমিয়েছি। এরপর GetAllCountries() কল করে নিশ্চিত হয়েছি যে আমাদের জমানো প্রতিটি Country রেসপন্সের ভেতরে উপস্থিত আছে (using Assert.Contains).
[Fact]
public void GetAllCountries_AddFewCountries()
{
// Arrange
List<CountryAddRequest> country_request_list = new List<CountryAddRequest>() {
new CountryAddRequest() { CountryName = "USA" },
new CountryAddRequest() { CountryName = "UK" }
};
List<CountryResponse> country_response_list_from_add_country = new List<CountryResponse>();
foreach (CountryAddRequest country_request in country_request_list)
{
// AddCountry মেথড কল করে রেসপন্স লিস্টে সেভ করা
country_response_list_from_add_country.Add(_countriesService.AddCountry(country_request));
}
// Act
List<CountryResponse> actual_country_response_list = _countriesService.GetAllCountries();
// Assert: চেক করা হচ্ছে যে অ্যাড করা প্রতিটি Country লিস্টে আছে কিনা
foreach (CountryResponse expected_country in country_response_list_from_add_country)
{
Assert.Contains(expected_country, actual_country_response_list);
}
}
৬. Update Previous Test Case (Priority: 8/10)
Concept: আগের লেকচারে লেখা AddCountry_ProperCountryDetails টেস্টটিতে একটি ছোট আপডেট করা হয়েছে।
Why: যখন একটি Country সফলভাবে অ্যাড হয়, তখন সেটি GetAllCountries এর লিস্টেও থাকা উচিত। এই ইন্টিগ্রেশন চেক করার জন্য ওই টেস্টের একদম শেষে GetAllCountries() কল করে Assert.Contains() দিয়ে চেক করা হয়েছে।
// আগের টেস্টের শেষের দিকের অংশ (Act & Assert)
CountryResponse country_response_from_add = _countriesService.AddCountry(country_request);
// New Code added in this lecture
List<CountryResponse> countries_from_GetAllCountries = _countriesService.GetAllCountries();
// Asserting if the newly added country exists in the list
Assert.Contains(country_response_from_add, countries_from_GetAllCountries);
🏆 Best Practices (for XUnit and TDD)
- Test Naming Convention: টেস্ট মেথডের নাম দেখে যেন বোঝা যায় এটি কী কাজ করছে। যেমন:
MethodName_StateUnderTest_ExpectedBehavior(e.g.,GetAllCountries_EmptyList_ReturnsEmptyCollection). - Arrange, Act, Assert (AAA Pattern): প্রতিটি ইউনিট টেস্টকে এই তিনটি ভাগে ভাগ করে লেখা উচিত। লেকচারেও এই প্যাটার্নটি ফলো করা হয়েছে।
- Target Single Behavior: একটি টেস্ট মেথডে একটি মাত্র স্পেসিফিক বিহেভিয়ার (behavior) টেস্ট করা উচিত।
- Use C# Collection Expressions (.NET 8+): .NET 8 বা তার ওপরের ভার্সনে লিস্ট তৈরি করার সময়
new List<Type>() { ... }এর বদলে[ ... ]ব্যবহার করা যায়, যা কোডকে আরও ক্লিন করে।
// Modern C# Collection initialization
List<CountryAddRequest> country_request_list = [
new() { CountryName = "USA" },
new() { CountryName = "UK" }
];