আমি Gemini, আপনার Simple Coding Tutor। আজকের সেশনে আপনাকে স্বাগতম!
Outline অনুযায়ী আমরা এখন Section 24-এর একদম শেষ পর্যায়ে আছি এবং আমাদের বর্তমান টপিক হলো Clean Architecture-এ Tests (Lecture 329) কনফিগার করা। আগের লেকচারগুলোতে আমরা Core, Infrastructure এবং UI লেয়ার তৈরি করেছি। আজ আমরা আমাদের পুরনো প্রজেক্টের Unit Tests এবং Integration Tests-গুলোকে এই নতুন আর্কিটেকচারে মাইগ্রেট করব। চলুন শুরু করা যাক!
📝 Lecture Summary
ভবিষ্যতে দ্রুত রিভিশন দেওয়ার জন্য পুরো লেকচারের মূল বিষয়গুলো নিচে দেওয়া হলো:
- Test Projects Setup:
testsফোল্ডারে তিনটি আলাদা XUnit Test Project তৈরি করা হয়েছে:ServiceTests,ControllerTestsএবংIntegrationTests। - Code Migration: পুরনো মনোলিথিক প্রজেক্ট থেকে সংশ্লিষ্ট Test ফাইলগুলো কপি করে নতুন প্রজেক্টগুলোতে পেস্ট করা হয়েছে।
- Accessing Program Class: Integration Test-এর জন্য UI প্রজেক্টের
.csprojফাইলেInternalsVisibleToকনফিগার করা হয়েছে, যাতে Test প্রজেক্ট UI-এরProgramক্লাস অ্যাক্সেস করতে পারে। - NuGet Packages: টেস্টিংয়ের জন্য
Moq,AutoFixture, এবংFluentAssertionsপ্যাকেজগুলো ইন্সটল করা হয়েছে। Integration Test-এর জন্য অতিরিক্ত কিছু প্যাকেজ (Mvc.Testing,InMemory,HtmlAgilityPack) যুক্ত করা হয়েছে। - Project References: Test প্রজেক্টগুলো থেকে Core এবং UI প্রজেক্টের প্রয়োজনীয় রেফারেন্স অ্যাড করা হয়েছে।
- Successful Execution: কোনো লজিক্যাল কোড পরিবর্তন ছাড়াই সবগুলো টেস্ট রান করানো হয়েছে এবং তা সফলভাবে পাস করেছে।
🔍 Comprehensive Breakdown
1. Why Separate Test Projects? (Priority: 9/10)
Why: পুরনো প্রজেক্টে আমাদের একটিমাত্র Test প্রজেক্ট ছিল যেখানে সব ধরনের টেস্ট রাখা হতো। কিন্তু Clean Architecture-এ Separation of Concerns খুব গুরুত্বপূর্ণ। তাই Service (Core), Controller (UI) এবং Integration-এর জন্য আলাদা আলাদা Test প্রজেক্ট তৈরি করা হয়েছে। এতে প্রোজেক্ট ম্যানেজ করা সহজ হয় এবং কোন লেয়ারে সমস্যা হচ্ছে তা দ্রুত বের করা যায়।
2. Creating the Test Projects (Priority: 8/10)
tests Solution ফোল্ডারের ভেতরে তিনটি নতুন xUnit Test Project তৈরি করা হয়েছে:
ContactsManager.ServiceTestsContactsManager.ControllerTestsContactsManager.IntegrationTests
(Visual Studio Code Shortcut): টার্মিনালে নিচের কমান্ডগুলো দিয়ে সহজেই এই প্রজেক্টগুলো তৈরি করা যায়:
dotnet new xunit -n ContactsManager.ServiceTests
dotnet new xunit -n ContactsManager.ControllerTests
dotnet new xunit -n ContactsManager.IntegrationTests
প্রজেক্ট তৈরির পর ডিফল্টভাবে তৈরি হওয়া UnitTest1.cs ফাইলগুলো ডিলিট করে দেওয়া হয়েছে।
3. Migrating Test Files (Priority: 8/10)
পুরনো প্রজেক্ট থেকে ফাইলগুলো নতুন প্রজেক্টে আনা হয়েছে:
- ServiceTests:
CountriesServiceTest.csএবংPersonsServiceTest.csকপি করা হয়েছে। - ControllerTests:
PersonsControllerTest.csকপি করা হয়েছে। - IntegrationTests:
CustomWebApplicationFactory.csএবংPersonsControllerIntegrationTest.csকপি করা হয়েছে।
4. The InternalsVisibleTo Configuration (Priority: 10/10)
Why: Integration Test রান করার জন্য আমাদের CustomWebApplicationFactory ব্যবহার করতে হয়, যা UI প্রজেক্টের Program ক্লাসকে কল করে ইন-মেমোরি সার্ভার তৈরি করে। কিন্তু Program ক্লাসটি সাধারণত Internal বা private থাকে। তাই UI প্রজেক্টকে বলে দিতে হয় যেন সে তার Internal ক্লাসগুলো IntegrationTests প্রজেক্টকে অ্যাক্সেস করতে দেয়।
- Action: UI প্রজেক্টে ডাবল ক্লিক করে এর
.csprojফাইলে<InternalsVisibleTo>প্রপার্টি যুক্ত করা হয়েছে। (এর ইমপ্লিমেন্টেশন নিচে দেওয়া হলো)।
5. Installing NuGet Packages (Priority: 10/10)
সঠিকভাবে Test রান করার জন্য নির্দিষ্ট প্রজেক্টে প্যাকেজ ইন্সটল করা হয়েছে:
-
All Test Projects (Service, Controller, Integration):
-
FluentAssertions(সহজে Assertions লেখার জন্য) -
AutoFixture(অটোমেটিক ডামি ডাটা জেনারেট করার জন্য) -
Moq(ডিপেন্ডেন্সি বা রিপোজিটরি মক করার জন্য) -
Only in IntegrationTests:
-
Microsoft.AspNetCore.Mvc.Testing(Integration Test-এর মূল প্যাকেজ) -
Microsoft.EntityFrameworkCore.InMemory(টেস্টিংয়ের সময় আসল ডাটাবেসের বদলে RAM-এ ডাটাবেস তৈরির জন্য) -
Fizzler.Systems.HtmlAgilityPack(HTML Response বডি পার্স এবং চেক করার জন্য)
6. Adding Project References (Priority: 10/10)
Why: Test প্রজেক্টগুলো নিজে থেকে কিছু চেনে না। তাদের বলে দিতে হয় তারা কোন প্রজেক্টকে টেস্ট করবে।
- ServiceTests: এটি
Coreপ্রজেক্টকে টেস্ট করবে, তাইCore-এর রেফারেন্স অ্যাড করা হয়েছে। - ControllerTests: এটি Controller-কে টেস্ট করবে যা
UIপ্রজেক্টে আছে, তাইUI-এর রেফারেন্স অ্যাড করা হয়েছে। - IntegrationTests: এটি পুরো অ্যাপ্লিকেশন ফ্লো টেস্ট করবে, তাই এখানেও
UI-এর রেফারেন্স অ্যাড করা হয়েছে।
7. Fixing Errors and Running Tests (Priority: 7/10)
সব কনফিগারেশন শেষে সলিউশন বিল্ড করলে কিছু ছোট এরর আসে। যেমন: CountriesServiceTest-এ Microsoft.EntityFrameworkCore namespace-টি অপ্রয়োজনীয়ভাবে যুক্ত ছিল, যা রিমুভ করা হয়েছে। এরপর Test Explorer থেকে Run All ক্লিক করলে দেখা যায় আগের আর্কিটেকচারের সব লজিক Clean Architecture-এও নিখুঁতভাবে কাজ করছে!
💻 Code Implementation
1. Exposing Program Class via .csproj (UI Project):
লেকচারে দেখানো পদ্ধতিতে UI প্রজেক্টের ContactsManager.UI.csproj ফাইলে নিচের কোডটি যুক্ত করতে হয়:
<ItemGroup>
<InternalsVisibleTo Include="ContactsManager.IntegrationTests" />
</ItemGroup>
🌟 Best Practices & .NET 10 Updates
- Test Naming Convention: Test মেথডের নাম সবসময় বর্ণনামূলক হওয়া উচিত। Best practice হলো
MethodName_StateUnderTest_ExpectedBehaviorপ্যাটার্ন ফলো করা (যেমন:AddPerson_NullRequest_ReturnsArgumentNullException)। - Keep Mocking Simple: শুধু ততটুকুই মক (Mock) করুন, যতটুকু আপনার টেস্ট পাস করার জন্য প্রয়োজন। ওভার-মকিং টেস্টকে জটিল করে তোলে।
.NET 10 Update (Smarter way for Program.cs access):
.NET 6/7 থেকে শুরু করে .NET 10 পর্যন্ত Top-level statements-এর কারণে Program.cs এ কোনো ক্লাস ডিক্লেয়ারেশন থাকে না। লেকচারে দেখানো .csproj-এ InternalsVisibleTo ব্যবহার করা একটু ঝামেলার। এর চেয়ে Smarter Update হলো, সরাসরি আপনার UI প্রজেক্টের Program.cs ফাইলের একদম নিচে এই এক লাইন কোড যুক্ত করে দেওয়া:
// Program.cs (At the very bottom)
// ... app.Run();
public partial class Program { } // Integration test-কে এই ক্লাসটি অ্যাক্সেস করার সুযোগ দেয়
এই এক লাইন কোড লিখলে আপনাকে আর .csproj ফাইল এডিট করতে হবে না, এবং Integration Test খুব সহজেই Program ক্লাসকে চিনে নিবে!