আমি আপনার “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) লিস্ট রিটার্ন করে কিনা (Using Assert.Empty).
  • Unit Test 2 (Add Few Countries): GetAllCountries_AddFewCountries নামে টেস্ট লেখা, যেখানে লুপ চালিয়ে কিছু Country অ্যাড করা হয় এবং চেক করা হয় যে অ্যাড করা Country-গুলো GetAllCountries মেথড থেকে ফিরে আসা লিস্টে আছে কিনা (Using Assert.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" }
];