NHibernate-এর সাথে Unit Testing করা সাধারণত একটু চ্যালেঞ্জিং হতে পারে কারণ NHibernate একটি ORM (Object-Relational Mapping) টুল এবং এর মধ্যে ডেটাবেসের সাথে সরাসরি যোগাযোগ ঘটে। তবে, সঠিক কৌশল ব্যবহার করলে আপনি সহজেই Unit Testing করতে পারবেন। এই লেখাটিতে NHibernate-এ Unit Testing এর জন্য কিছু জনপ্রিয় পদ্ধতি এবং টেকনিকগুলি আলোচনা করা হবে।
NHibernate এবং Unit Testing এর গুরুত্ব
Unit Testing মূলত একটি সফটওয়্যার ডেভেলপমেন্ট প্রক্রিয়া যা নিশ্চিত করে যে আপনার কোডের প্রতিটি অংশ সঠিকভাবে কাজ করছে। NHibernate ব্যবহার করার সময়, আমাদের টেস্টে ডেটাবেস অপারেশন, সেশন ম্যানেজমেন্ট এবং ট্রানজেকশন প্রক্রিয়াগুলি অন্তর্ভুক্ত করতে হয়। সঠিকভাবে Unit Testing করলে আপনি:
- ডেটাবেস ডিপেন্ডেন্সি কমাতে পারেন
- কোডের ভুল দ্রুত শনাক্ত করতে পারেন
- ইন্টিগ্রেশন টেস্টিং ও রিগ্রেশন টেস্টিং সহজতর হয়
Unit Testing এর জন্য Mocking Framework ব্যবহার
NHibernate সেশন এবং ডেটাবেস সম্পর্কিত অংশগুলি টেস্ট করার জন্য, আপনাকে Mocking Framework ব্যবহার করতে হবে। সাধারণত Moq বা NSubstitute এর মতো ফ্রেমওয়ার্কগুলো ব্যবহার করা হয়, যা সঠিকভাবে সেশন এবং ট্রানজেকশন তৈরি ও পরিচালনা করতে সাহায্য করে।
Moq ব্যবহার করে Unit Testing উদাহরণ
ধরা যাক আমাদের EmployeeService ক্লাসটি আছে, যেটি Employee এর ডেটাবেস অপারেশনগুলি পরিচালনা করে। আমরা Moq ব্যবহার করে এর উপর টেস্ট তৈরি করব।
using Moq;
using NHibernate;
using NUnit.Framework;
[TestFixture]
public class EmployeeServiceTests
{
private Mock<ISession> mockSession;
private Mock<ITransaction> mockTransaction;
private EmployeeService employeeService;
[SetUp]
public void SetUp()
{
mockSession = new Mock<ISession>();
mockTransaction = new Mock<ITransaction>();
// Mocking NHibernate Session and Transaction
mockSession.Setup(s => s.BeginTransaction()).Returns(mockTransaction.Object);
employeeService = new EmployeeService(mockSession.Object);
}
[Test]
public void Test_SaveEmployee_CallsCorrectMethods()
{
var employee = new Employee { Id = 1, Name = "John Doe", Salary = 50000 };
// Act
employeeService.SaveEmployee(employee);
// Assert
mockSession.Verify(s => s.Save(employee), Times.Once);
mockTransaction.Verify(t => t.Commit(), Times.Once);
}
[TearDown]
public void TearDown()
{
mockSession = null;
mockTransaction = null;
}
}
এখানে:
- Mock ব্যবহার করে NHibernate সেশনকে মক করা হয়েছে।
- mockSession.Setup() এর মাধ্যমে ট্রানজেকশন শুরু করার মক ফাংশন তৈরি করা হয়েছে।
- Verify() মেথড ব্যবহার করে নিশ্চিত করা হয়েছে যে
Save()মেথড এবংCommit()ট্রানজেকশন এক্সিকিউট হয়েছে।
Database মকিং (In-memory Database)
অন্য একটি উপায় হচ্ছে In-memory Database ব্যবহার করা, যেখানে কোনো প্রকৃত ডেটাবেস সার্ভার ছাড়াই আপনি NHibernate এর সাথে টেস্ট করতে পারবেন। SQLite বা H2 Database এই কাজের জন্য বেশ জনপ্রিয়। এইভাবে আপনি ডেটাবেসের সাথে ইনটিগ্রেশন টেস্ট করতে পারেন, তবে এটি সম্পূর্ণ ইউনিট টেস্ট না হয়ে Integration Test হিসেবে কাজ করবে।
SQLite Database দিয়ে Unit Testing
SQLite একটি হালকা ডেটাবেস যা আপনি ইন-মেমরি মোডে ব্যবহার করতে পারেন:
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
public class NHibernateHelper
{
public static ISessionFactory SessionFactory { get; private set; }
static NHibernateHelper()
{
SessionFactory = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory().ShowSql()) // In-memory database setup
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<EmployeeMap>())
.BuildSessionFactory();
// Create the database schema
new SchemaExport(SessionFactory).Create(false, true);
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
এখানে:
- SQLiteConfiguration.Standard.InMemory() দিয়ে ইন-মেমরি ডেটাবেস তৈরি করা হচ্ছে।
- SchemaExport ব্যবহার করে স্কিমা (টেবিল) তৈরি করা হচ্ছে।
এটি ইন-মেমরি ডেটাবেসের উপর NHibernate সেশন পরিচালনা করবে এবং টেস্টটি বাস্তব ডেটাবেসে না চলে সঞ্চালিত হবে।
NHibernate ট্রানজেকশন ম্যানেজমেন্ট এবং Unit Testing
NHibernate ট্রানজেকশন টেস্টিং করার সময়, আপনাকে সঠিকভাবে ট্রানজেকশন ম্যানেজমেন্ট করতে হবে। টেস্টে ডেটাবেসের সাথে কাজ করা হলে, প্রতিটি ট্রানজেকশনের শেষে ডেটা কমিট বা রোলব্যাক করা উচিত, যাতে টেস্টগুলি একে অপরের উপর প্রভাব ফেলতে না পারে।
ট্রানজেকশন ম্যানেজমেন্টের জন্য Unit Testing
using Moq;
using NHibernate;
using NUnit.Framework;
[TestFixture]
public class TransactionTest
{
private Mock<ISession> mockSession;
private Mock<ITransaction> mockTransaction;
[SetUp]
public void SetUp()
{
mockSession = new Mock<ISession>();
mockTransaction = new Mock<ITransaction>();
mockSession.Setup(s => s.BeginTransaction()).Returns(mockTransaction.Object);
}
[Test]
public void Test_TransactionCommit()
{
var employee = new Employee { Id = 1, Name = "Jane Doe", Salary = 60000 };
var employeeService = new EmployeeService(mockSession.Object);
employeeService.SaveEmployee(employee); // Service method that starts transaction and commits
mockTransaction.Verify(t => t.Commit(), Times.Once); // Verify commit happened
}
[TearDown]
public void TearDown()
{
mockSession = null;
mockTransaction = null;
}
}
এখানে:
- mockTransaction.Verify(t => t.Commit()) ব্যবহার করে নিশ্চিত করা হয়েছে যে ট্রানজেকশন কমিট হয়েছে।
Best Practices for Unit Testing with NHibernate
- Test Isolation: প্রতিটি টেস্টের জন্য আলাদা ডেটাবেস বা সেশন তৈরি করুন, যাতে এক টেস্টের পরিবর্তন অন্য টেস্টকে প্রভাবিত না করে।
- Transaction Rollback: প্রতিটি টেস্ট শেষে ট্রানজেকশন রোলব্যাক করুন, যাতে ডেটাবেসের অবস্থান অপরিবর্তিত থাকে।
- Mocking External Dependencies: যদি কোনো ডেটাবেস অপারেশন ছাড়া কোডের কার্যক্রম টেস্ট করতে হয়, তাহলে external dependencies (যেমন NHibernate সেশন) মক করতে হবে।
সারসংক্ষেপ
NHibernate এবং Unit Testing একত্রিত করার জন্য, Mocking Framework ব্যবহার করে NHibernate সেশন এবং ট্রানজেকশন মক করা যেতে পারে। এছাড়া, In-memory Database ব্যবহার করে আপনি বাস্তব ডেটাবেসের সাথে কাজ না করেও টেস্ট চালাতে পারেন। NHibernate-এর লগিক এবং ট্রানজেকশন ম্যানেজমেন্ট সঠিকভাবে টেস্ট করলে আপনি একটি স্থিতিশীল এবং কার্যকর অ্যাপ্লিকেশন তৈরি করতে সক্ষম হবেন।
Unit testing হল একটি গুরুত্বপূর্ণ টেস্টিং কৌশল, যা কোডের বিভিন্ন অংশ বা মডিউল স্বাধীনভাবে পরীক্ষা করতে সাহায্য করে। In-memory databases যেমন SQLite ব্যবহার করে ইউনিট টেস্টিং করার মাধ্যমে আপনি ডেটাবেস ইন্টারঅ্যাকশনকে দ্রুত এবং আরও কার্যকরভাবে পরীক্ষা করতে পারেন, কারণ এখানে ফাইল সিস্টেমে কোনো ডেটাবেস ফাইল তৈরি হয় না এবং টেস্টের শেষে ডেটাবেসের ডেটা মুছে যায়।
SQLite একটি লাইটওয়েট relational database management system (RDBMS), যা in-memory মোডে চালানো যেতে পারে। এই মোডে ডেটাবেসটি মেমরি (RAM) তে তৈরি হয় এবং টেস্ট সম্পন্ন হওয়ার পর তা মুছে যায়। NHibernate বা অন্য ORM টুলগুলির সাথে এই ধরনের ডাটাবেস ব্যবহার করলে, আপনি অল্প সময়ে টেস্টগুলো রান করতে পারেন এবং ডেটাবেস রিলেটেড টেস্টিং আরও সঠিকভাবে সম্পন্ন করতে পারেন।
In-Memory SQLite ব্যবহার করে Unit Test লেখার প্রক্রিয়া
এখানে, আমরা NHibernate ব্যবহার করে SQLite In-Memory Database ব্যবহার করে Unit Test লিখার উদাহরণ দেখব।
1. SQLite In-Memory Database কনফিগার করা
প্রথমে, আপনাকে SQLite এর জন্য NHibernate কনফিগারেশন সেট আপ করতে হবে। SQLite ইন-মেমরি ডেটাবেসের জন্য কনফিগারেশন করতে, hibernate.cfg.xml ফাইলটি বা কনফিগারেশন কোডে কিছু পরিবর্তন করতে হবে।
NHibernate Configuration কোড
var cfg = new Configuration();
cfg.Configure(); // Hibernate.cfg.xml কনফিগারেশন লোড করা
cfg.SetProperty("hibernate.dialect", "NHibernate.Dialect.SQLiteDialect");
cfg.SetProperty("hibernate.connection.driver_class", "NHibernate.Driver.SQLite20Driver");
cfg.SetProperty("hibernate.connection.provider", "NHibernate.Cfg.Environment.ConnectionProvider");
cfg.SetProperty("hibernate.connection.connection_string", "Data Source=:memory:;Version=3;New=True;");
cfg.SetProperty("hibernate.hbm2ddl.auto", "update"); // Schema আপডেট করার জন্য
var sessionFactory = cfg.BuildSessionFactory();
এখানে:
hibernate.connection.connection_stringপ্রপার্টি'Data Source=:memory:'দ্বারা SQLite ইন-মেমরি ডেটাবেস কনফিগার করা হয়েছে।hibernate.hbm2ddl.autoপ্রপার্টি'update'দিলে NHibernate স্বয়ংক্রিয়ভাবে ডেটাবেসের স্কিমা আপডেট করবে।
2. Unit Test Framework কনফিগারেশন
Unit Testing এর জন্য আমরা সাধারণত xUnit, NUnit বা MSTest ব্যবহার করতে পারি। এখানে xUnit ব্যবহার করে Unit Test কনফিগার করব।
xUnit Test Class
public class EmployeeTests : IDisposable
{
private readonly ISessionFactory sessionFactory;
private ISession session;
private ITransaction transaction;
public EmployeeTests()
{
// NHibernate Configuration
var cfg = new Configuration();
cfg.Configure(); // Hibernate.cfg.xml ফাইলের কনফিগারেশন লোড
cfg.SetProperty("hibernate.dialect", "NHibernate.Dialect.SQLiteDialect");
cfg.SetProperty("hibernate.connection.driver_class", "NHibernate.Driver.SQLite20Driver");
cfg.SetProperty("hibernate.connection.connection_string", "Data Source=:memory:;Version=3;New=True;");
cfg.SetProperty("hibernate.hbm2ddl.auto", "update");
// SessionFactory তৈরি করা
sessionFactory = cfg.BuildSessionFactory();
// সেশন শুরু করা
session = sessionFactory.OpenSession();
transaction = session.BeginTransaction();
// ডেটাবেস স্কিমা আপডেট করা
var employeeMapping = new EmployeeMapping();
new SchemaExport(cfg).Create(true, true);
}
[Fact]
public void Should_Insert_Employee()
{
var employee = new Employee { Name = "John Doe", Position = "Developer", HireDate = DateTime.Now };
// ডেটাবেসে ইনসার্ট করা
session.Save(employee);
// কমিট করা
transaction.Commit();
// পুনরায় সেশন থেকে রিটার্ন করা
var fetchedEmployee = session.Get<Employee>(employee.Id);
// Assertion
Assert.NotNull(fetchedEmployee);
Assert.Equal(employee.Name, fetchedEmployee.Name);
}
public void Dispose()
{
// টেস্টের পর ট্রানজেকশন বন্ধ করা এবং সেশন নিষ্ক্রিয় করা
transaction?.Dispose();
session?.Dispose();
sessionFactory?.Dispose();
}
}
এখানে:
EmployeeTestsক্লাসটি xUnit টেস্ট ক্লাস হিসেবে তৈরি করা হয়েছে, এবং এতেIDisposableইন্টারফেস ব্যবহার করা হয়েছে সেশন এবং ট্রানজেকশন পরিষ্কার করার জন্য।Should_Insert_Employeeটেস্ট মেথডে একটিEmployeeঅবজেক্ট তৈরি করা হয়েছে এবং সেটা ডেটাবেসে ইনসার্ট করা হয়েছে।SchemaExportক্লাস ব্যবহার করে ইন-মেমরি ডেটাবেসে স্কিমা তৈরি করা হয়েছে।
3. Employee Entity এবং Mapping ফাইল তৈরি করা
আপনার Employee ক্লাস এবং এর ম্যাপিং (NHibernate Mapping) তৈরি করতে হবে।
Employee Entity Class
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Position { get; set; }
public virtual DateTime HireDate { get; set; }
}
Employee Mapping Class
public class EmployeeMapping : ClassMapping<Employee>
{
public EmployeeMapping()
{
Table("Employees");
Id(x => x.Id, m => m.Generator(Generators.Identity));
Property(x => x.Name);
Property(x => x.Position);
Property(x => x.HireDate);
}
}
এখানে:
Employeeক্লাসের মধ্যে প্রয়োজনীয় প্রপার্টি ডিফাইন করা হয়েছে।EmployeeMappingক্লাসটি NHibernate ম্যাপিং কনফিগারেশন হিসেবে ব্যবহৃত হচ্ছে।
4. Unit Test এর Execution এবং পারফরম্যান্স বিশ্লেষণ
এখন, আপনি Unit Test চালিয়ে দেখতে পারেন যে ইন-মেমরি SQLite ডেটাবেসে Employee সঠিকভাবে ইনসার্ট এবং ফেচ হচ্ছে কিনা। SQLite ইন-মেমরি ডেটাবেসের সাহায্যে আপনার টেস্ট রান হবে দ্রুত, এবং প্রতিবার টেস্ট চলাকালীন নতুন ডেটাবেস তৈরি হবে, যা একটি পরিষ্কার পরিবেশ নিশ্চিত করবে।
উপসংহার
SQLite ইন-মেমরি ডেটাবেস ব্যবহার করে NHibernate এর সাথে Unit Testing করা খুবই কার্যকরী এবং দ্রুত। আপনি একাধিক টেস্ট ক্যাস তৈরি করতে পারেন এবং কোনও স্থায়ী ডেটাবেসের প্রয়োজন ছাড়াই ডেটাবেস ইন্টারঅ্যাকশন পরীক্ষা করতে পারেন। In-memory ডেটাবেস ব্যবহারের মাধ্যমে টেস্টিং আরও পরিষ্কার এবং দক্ষ হয়, কারণ এটি সমস্ত ডেটাবেস অপারেশন মেমরিতে পরিচালনা করে।
NHibernate-এ টেস্টিং করার সময়, বিশেষ করে ইউনিট টেস্ট (Unit Testing) করার সময়, NHibernate Session এবং Repository Pattern এর জন্য mocking করা খুবই গুরুত্বপূর্ণ। এই পদ্ধতিটি আপনাকে ডেটাবেস-নির্ভর কোডের টেস্টিং করতে সাহায্য করে, যাতে আপনি টেস্ট কেস চালানোর সময় ডেটাবেসে কোনো পরিবর্তন না ঘটান। Mocking এর মাধ্যমে আপনি NHibernate Session এবং Repository ক্লাসের কার্যকারিতা নকল (simulate) করতে পারেন।
এখানে, NHibernate Session এবং Repository Pattern এর জন্য mocking করার কিছু পদ্ধতি দেখানো হলো।
1. Repository Pattern in NHibernate
Repository Pattern একটি সফটওয়্যার ডিজাইন প্যাটার্ন যা ডোমেইন অবজেক্টদের সাথে ডেটাবেস ইন্টারঅ্যাকশন আবস্ট্রাক্ট (abstract) করে। Repository Pattern ব্যবহার করলে কোডে Business Logic এবং Data Access Logic আলাদা রাখা যায়, যার ফলে কোড সহজে রক্ষণাবেক্ষণযোগ্য এবং টেস্ট করা যায়।
1.1 Repository Interface and Implementation:
public interface IEmployeeRepository
{
Employee GetById(int id);
void Save(Employee employee);
void Delete(Employee employee);
IList<Employee> GetAll();
}
public class EmployeeRepository : IEmployeeRepository
{
private readonly ISession _session;
public EmployeeRepository(ISession session)
{
_session = session;
}
public Employee GetById(int id)
{
return _session.Get<Employee>(id);
}
public void Save(Employee employee)
{
using (ITransaction transaction = _session.BeginTransaction())
{
_session.SaveOrUpdate(employee);
transaction.Commit();
}
}
public void Delete(Employee employee)
{
using (ITransaction transaction = _session.BeginTransaction())
{
_session.Delete(employee);
transaction.Commit();
}
}
public IList<Employee> GetAll()
{
return _session.Query<Employee>().ToList();
}
}
এখানে, EmployeeRepository একটি বাস্তব ক্লাস, যা NHibernate Session ব্যবহার করে ডেটাবেসের সাথে ইন্টারঅ্যাক্ট করে।
2. Mocking NHibernate Session
Mocking মূলত Test Doubles তৈরির একটি পদ্ধতি, যার মাধ্যমে আপনি এমন অবজেক্ট তৈরি করেন যেগুলো আসল অবজেক্টের কার্যকারিতা নকল (simulate) করে। NHibernate Session mocking এর জন্য, সাধারণত আমরা Moq বা অন্য কোনো mocking লাইব্রেরি ব্যবহার করি।
2.1 Moq লাইব্রেরি দিয়ে NHibernate Session Mocking:
Moq একটি জনপ্রিয় mocking লাইব্রেরি যা C#-এ টেস্টিং এর জন্য ব্যবহৃত হয়। এখানে আমরা দেখবো কিভাবে ISession এবং ITransaction কে mock করা যায়।
using Moq;
using NHibernate;
using NUnit.Framework;
[TestFixture]
public class EmployeeRepositoryTests
{
private Mock<ISession> _mockSession;
private Mock<ITransaction> _mockTransaction;
private IEmployeeRepository _employeeRepository;
[SetUp]
public void Setup()
{
_mockSession = new Mock<ISession>();
_mockTransaction = new Mock<ITransaction>();
// Mocking the Get method of ISession
_mockSession.Setup(s => s.Get<Employee>(It.IsAny<int>())).Returns(new Employee { Id = 1, Name = "John Doe" });
// Mocking transaction to ensure commit works
_mockSession.Setup(s => s.BeginTransaction()).Returns(_mockTransaction.Object);
_employeeRepository = new EmployeeRepository(_mockSession.Object);
}
[Test]
public void GetById_ShouldReturnEmployee_WhenEmployeeExists()
{
var employee = _employeeRepository.GetById(1);
Assert.IsNotNull(employee);
Assert.AreEqual("John Doe", employee.Name);
}
[Test]
public void Save_ShouldCommitTransaction_WhenSavingEmployee()
{
var employee = new Employee { Id = 2, Name = "Jane Doe" };
_employeeRepository.Save(employee);
_mockSession.Verify(s => s.SaveOrUpdate(It.IsAny<Employee>()), Times.Once);
_mockTransaction.Verify(t => t.Commit(), Times.Once);
}
}
এখানে:
- Moq লাইব্রেরি ব্যবহার করে আমরা
ISessionএবংITransactionএর মক অবজেক্ট তৈরি করেছি। Setupমেথডের মাধ্যমেGetমেথডটি একটিEmployeeঅবজেক্ট রিটার্ন করার জন্য কনফিগার করেছি।Saveমেথডের জন্য একটি টেস্ট তৈরি করেছি যেখানে আমরা চেক করেছি যেSaveOrUpdateএবংCommitমেথডগুলো ঠিকমতো কল হয়েছে।
3. Mocking NHibernate Session and Repository Using In-Memory Database
এছাড়া, আপনি In-Memory Database ব্যবহার করে বাস্তব ডেটাবেস ছাড়া NHibernate-এর কার্যকারিতা টেস্ট করতে পারেন। এটি আপনার টেস্টগুলোকে ডেটাবেস থেকে বিচ্ছিন্ন রাখে এবং দ্রুত টেস্ট চালানোর সুবিধা দেয়। যেমন, SQLite বা H2 ইন-মেমরি ডেটাবেস ব্যবহার করা যেতে পারে।
3.1 In-Memory Database Configuration (Example with SQLite):
var configuration = new Configuration();
configuration.Configure(); // NHibernate config from hibernate.cfg.xml
configuration.AddAssembly(Assembly.GetExecutingAssembly()); // Add mappings
// Use SQLite In-Memory DB
configuration.SetProperty(NHibernate.Cfg.Environment.ConnectionString, "Data Source=:memory:;Version=3;New=True;");
configuration.SetProperty(NHibernate.Cfg.Environment.Dialect, "NHibernate.Dialect.SQLiteDialect");
var sessionFactory = configuration.BuildSessionFactory();
using (var session = sessionFactory.OpenSession())
{
var repository = new EmployeeRepository(session);
// Your test logic here
}
এখানে, আমরা SQLite ব্যবহার করে ইন-মেমরি ডেটাবেস সেটআপ করেছি এবং NHibernate-এর কার্যকারিতা টেস্ট করছি।
4. Conclusion
Mocking NHibernate Session এবং Repository Pattern ব্যবহার করে টেস্টিং করার পদ্ধতি অনেক সুবিধাজনক। এতে আপনি ডেটাবেস ইন্টারঅ্যাকশন ছাড়াই Business Logic টেস্ট করতে পারেন এবং ডেটাবেসে কোনো পরিবর্তন না করেই আপনার কোডের কার্যকারিতা যাচাই করতে পারবেন। Moq লাইব্রেরি ব্যবহার করে আপনি সহজেই ISession এবং ITransaction মক করতে পারেন, এবং ইন-মেমরি ডেটাবেস ব্যবহার করে বাস্তব ডেটাবেস ছাড়া টেস্ট চালাতে পারেন।
Integration Testing হল একটি সফটওয়্যার টেস্টিং কৌশল, যার মাধ্যমে বিভিন্ন সিস্টেম বা মডিউল একত্রে কাজ করছে কিনা তা পরীক্ষা করা হয়। এটি সাধারণত ইউনিট টেস্টিংয়ের পরে করা হয় এবং এর লক্ষ্য হচ্ছে সিস্টেমের বিভিন্ন কম্পোনেন্টের মধ্যে ইন্টারঅ্যাকশন এবং ডেটা প্রবাহ সঠিকভাবে কাজ করছে কিনা তা যাচাই করা।
NHibernate-এ Integration Testing প্রধানত ডেটাবেসের সাথে কাজ করে, যেখানে আপনার লক্ষ্য থাকবে একটি সঠিক পরিবেশে (ডাটাবেস, সেশন ফ্যাক্টরি ইত্যাদি) কোডের সঠিক কার্যকারিতা যাচাই করা।
Integration Testing কী?
Integration Testing এমন একটি প্রক্রিয়া, যেখানে একাধিক সিস্টেম বা মডিউলকে একত্রে পরীক্ষা করা হয়। এখানে প্রতিটি মডিউল এককভাবে টেস্ট করা হয় না, বরং তাদের ইন্টিগ্রেশন বা একসাথে কাজ করার ক্ষমতা যাচাই করা হয়।
NHibernate ব্যবহার করার সময়, Integration Testing সাধারণত Session এবং Transaction এর সাথে কাজ করার সময় ডেটাবেসের ইন্টিগ্রেশন পরীক্ষা করা হয়।
Integration Testing এর মূল লক্ষ্য
- Multiple Components Interaction: একাধিক কম্পোনেন্ট যেমন, ডেটাবেস, সেশন, ট্যাবল, এবং সার্ভিসের ইন্টিগ্রেশন পরীক্ষিত হয়।
- Data Flow Validation: সঠিকভাবে ডেটা প্রবাহ এবং সঠিক ডেটাবেস অপারেশন (যেমন, ইনসার্ট, আপডেট, ডিলিট) সম্পন্ন হচ্ছে কিনা তা নিশ্চিত করা।
- Transaction Management: একাধিক ডেটাবেস ট্রানজেকশন এবং তাদের কম্প্লিট বা রোলব্যাক সঠিকভাবে পরিচালনা হচ্ছে কিনা তাও পরীক্ষা করা হয়।
Integration Testing এর পদ্ধতি
NHibernate-এ Integration Testing সাধারণত Unit of Work প্যাটার্ন এবং Transaction Management এর সাথে সংযুক্ত থাকে। নিচে কিছু গুরুত্বপূর্ণ পদ্ধতি আলোচনা করা হলো যা ব্যবহার করে NHibernate অ্যাপ্লিকেশনের ইন্টিগ্রেশন টেস্টিং করা যায়।
1. Test with In-memory Database
NHibernate এর Integration Testing করার সবচেয়ে সহজ উপায় হলো In-memory Database ব্যবহার করা। এতে ডেটাবেস তৈরি করতে কোনো প্রকার ফাইল বা পরিসর সংরক্ষণ করতে হয় না, এবং এটি দ্রুত টেস্টিং করার সুযোগ দেয়।
একটি ইন-মেমরি ডেটাবেস কনফিগার করার জন্য SQLite ব্যবহার করা যেতে পারে।
In-memory Database Integration Test Example:
public class EmployeeIntegrationTest
{
private ISessionFactory sessionFactory;
[SetUp]
public void Setup()
{
// In-memory SQLite database setup
var cfg = new Configuration();
cfg.Configure(); // Hibernate configuration file
cfg.SetProperty("hibernate.dialect", "NHibernate.Dialect.SQLiteDialect");
cfg.SetProperty("hibernate.connection.driver_class", "NHibernate.Driver.SQLite20Driver");
cfg.SetProperty("hibernate.connection.connection_string", "DataSource=:memory:;Version=3;New=True;");
sessionFactory = cfg.BuildSessionFactory();
}
[Test]
public void TestEmployeeInsertion()
{
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
// Create a new employee
var employee = new Employee { Name = "John Doe", Age = 30 };
session.Save(employee);
transaction.Commit();
}
// Verify the employee was inserted
using (var session = sessionFactory.OpenSession())
{
var employee = session.Get<Employee>(1);
Assert.AreEqual("John Doe", employee.Name);
Assert.AreEqual(30, employee.Age);
}
}
[TearDown]
public void TearDown()
{
sessionFactory.Close();
}
}
এখানে একটি ইন-মেমরি SQLite ডেটাবেস ব্যবহার করে ইন্টিগ্রেশন টেস্ট তৈরি করা হয়েছে। SetUp মেথডে ডেটাবেস কনফিগারেশন এবং TestEmployeeInsertion মেথডে ডেটাবেসে Employee অবজেক্ট ইনসার্ট করা হচ্ছে।
2. Test with Real Database
প্রকৃত ডেটাবেসের সাথে Integration Testing করার জন্য আপনার ডেটাবেস কনফিগারেশন এবং সংযোগ সরাসরি বাস্তব পরিবেশে চালাতে হবে। এই ধরনের টেস্টিং সাধারণত ডেটাবেসে রিয়েল টাইম অপারেশন পরীক্ষা করতে ব্যবহৃত হয়।
Real Database Integration Test Example:
[Test]
public void TestRealDatabaseIntegration()
{
// Use a real database connection string
var connectionString = "Server=localhost;Database=testdb;User Id=myuser;Password=mypassword;";
var cfg = new Configuration();
cfg.Configure();
cfg.SetProperty("hibernate.connection.connection_string", connectionString);
sessionFactory = cfg.BuildSessionFactory();
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
// Create a new employee
var employee = new Employee { Name = "Jane Doe", Age = 25 };
session.Save(employee);
transaction.Commit();
}
// Verify the employee was inserted into the real database
using (var session = sessionFactory.OpenSession())
{
var employee = session.Get<Employee>(1);
Assert.AreEqual("Jane Doe", employee.Name);
Assert.AreEqual(25, employee.Age);
}
}
এখানে, real database (যেমন, SQL Server, MySQL) ব্যবহার করা হয়েছে যেখানে ডেটাবেসের লাইফটাইমে Employee টেবিলে ইনসার্ট অপারেশন পরীক্ষা করা হচ্ছে।
3. Test Transactions with Rollback
Transaction Rollback নিশ্চিত করার জন্য ইন্টিগ্রেশন টেস্টিংয়ে একটি গুরুত্বপূর্ণ কৌশল হল RollBack পদ্ধতি ব্যবহার করা। এটি নিশ্চিত করে যে টেস্ট শেষে ডেটাবেসে কোনো পরিবর্তন থাকবে না এবং ডেটাবেস সঠিক অবস্থায় ফিরে যাবে।
[Test]
public void TestEmployeeTransactionRollback()
{
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var employee = new Employee { Name = "Temporary Employee", Age = 29 };
session.Save(employee);
// Manually rollback the transaction
transaction.Rollback();
}
// Verify that the employee was not saved to the database
using (var session = sessionFactory.OpenSession())
{
var employee = session.Get<Employee>(1);
Assert.IsNull(employee); // Employee should not exist
}
}
এখানে, টেস্টের পরে Rollback ব্যবহার করা হয়েছে যাতে টেস্টের শেষে ডেটাবেসে কোনো পরিবর্তন না থাকে।
4. Test with Mocking Frameworks
একটি Mocking Framework (যেমন, Moq বা NSubstitute) ব্যবহার করে, আপনি বাস্তব ডেটাবেস বা সেশন ফ্যাক্টরি ব্যবহারের পরিবর্তে মক অবজেক্ট ব্যবহার করে Integration Testing করতে পারেন। এতে ডেটাবেসের উপর কোন আসল অপারেশন না করেও কোডের লজিক টেস্ট করা সম্ভব হয়।
সারাংশ
Integration Testing গুরুত্বপূর্ণ একটি অংশ যেটি আপনাকে কোডের বিভিন্ন অংশ একত্রে কাজ করছে কিনা তা যাচাই করতে সহায়তা করে। NHibernate-এ ইনটিগ্রেশন টেস্টিংয়ের সময়, ইন-মেমরি ডেটাবেস ব্যবহার, রিয়েল ডেটাবেসের সাথে টেস্টিং, ট্রানজেকশন রোলব্যাক ইত্যাদি কৌশল ব্যবহার করা যেতে পারে। এগুলি নিশ্চিত করে যে ডেটাবেস অপারেশনগুলো সঠিকভাবে কাজ করছে এবং কোনো ধরনের পরিবর্তন অবাঞ্ছিতভাবে ডেটাবেসে প্রভাব ফেলছে না।
Test Driven Development (TDD) হল একটি সফটওয়্যার ডেভেলপমেন্ট পদ্ধতি যেখানে কোড লেখার আগে প্রথমে টেস্ট কেস লেখা হয়। TDD এর মূল ধারণা হল কোড লেখার পূর্বে টেস্ট কেস লিখে, পরে সেই টেস্টের ভিত্তিতে কোড তৈরি করা। NHibernate ব্যবহার করার সময়, TDD একটি গুরুত্বপূর্ণ কৌশল হতে পারে যাতে আপনার ডেটাবেস লেয়ারটি (ORM) সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করা যায়।
TDD এর তিনটি মূল ধাপ:
- Red: প্রথমে একটি টেস্ট লিখুন যা আপনার বর্তমান কোডের জন্য ফেল করবে। এটি একটি নতুন ফিচারের জন্য টেস্ট কেস হতে পারে।
- Green: এখন কোড লিখুন যা টেস্টটি পাস করতে সাহায্য করবে।
- Refactor: কোডটি রিফ্যাক্টর করুন, তবে টেস্টগুলি যেন সবসময় পাস করতে থাকে, তা নিশ্চিত করুন।
NHibernate এবং TDD এর মধ্যে সম্পর্ক
NHibernate এর সাথে TDD ব্যবহার করার সময়, আপনাকে যে বিষয়গুলো মনে রাখতে হবে তা হলো:
- Mocking: NHibernate এর Session অবজেক্টকে মক করা। এটি গুরুত্বপূর্ণ, কারণ আপনি ডেটাবেসে কোন পরিবর্তন করতে চান না, তবে টেস্টের মাধ্যমে সেগুলিকে যাচাই করতে চান।
- Integration Tests: TDD-তে সাধারণত ইউনিট টেস্ট এবং ইন্টিগ্রেশন টেস্ট থাকে। NHibernate এর সাথে ইন্টিগ্রেশন টেস্টে প্রকৃত ডেটাবেসের উপর কাজ করতে হয়, তবে এটি সঠিকভাবে কনফিগার করা উচিত যাতে ডেটাবেসে কোনও অবাঞ্ছিত পরিবর্তন না হয়।
- In-Memory Database: টেস্টিং এর জন্য একটি ইন-মেমরি ডেটাবেস ব্যবহার করা যেতে পারে, যেমন SQLite, যাতে আপনি টেস্ট চলাকালীন কোনও প্রকৃত ডেটাবেসকে প্রভাবিত না করেন।
NHibernate এবং TDD এর জন্য টেস্ট কেস লেখা
এখানে আমরা একটি Employee ক্লাসের জন্য TDD এবং NHibernate ব্যবহার করে একটি সাধারণ টেস্ট কেস লিখে দেখব।
1. Employee ক্লাস তৈরি করা
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual decimal Salary { get; set; }
}
2. Test Setup - NHibernate কনফিগারেশন
TDD এর জন্য আমাদের প্রথমে NHibernate কনফিগারেশন সঠিকভাবে সেট করতে হবে, যাতে টেস্ট চলাকালীন ডেটাবেস সঠিকভাবে কাজ করে।
public class NHibernateHelper
{
private static ISessionFactory sessionFactory;
public static ISessionFactory SessionFactory
{
get
{
if (sessionFactory == null)
{
sessionFactory = new Configuration()
.Configure() // hibernate.cfg.xml থেকে কনফিগারেশন লোড করে
.BuildSessionFactory();
}
return sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
3. Test Class তৈরি করা
এখন আমরা একটি সাধারণ unit test লিখব যেখানে Employee ক্লাসের একটি ইনস্ট্যান্স ডাটাবেসে ইনসার্ট করে তা টেস্ট করা হবে। আমরা NUnit এবং NHibernate ব্যবহার করে টেস্ট করব। এখানে in-memory database ব্যবহার করা হবে যাতে টেস্টের জন্য কোন প্রকৃত ডেটাবেসে পরিবর্তন না হয়।
using NUnit.Framework;
using NHibernate;
using System;
[TestFixture]
public class EmployeeTests
{
private ISession session;
[SetUp]
public void Setup()
{
session = NHibernateHelper.OpenSession();
}
[TearDown]
public void TearDown()
{
if (session.IsOpen)
{
session.Close();
}
}
[Test]
public void TestEmployeeInsertion()
{
// Arrange
var employee = new Employee { Name = "John Doe", Salary = 50000 };
// Act
using (var transaction = session.BeginTransaction())
{
session.Save(employee);
transaction.Commit();
}
// Assert
using (var transaction = session.BeginTransaction())
{
var insertedEmployee = session.Get<Employee>(employee.Id);
Assert.IsNotNull(insertedEmployee);
Assert.AreEqual("John Doe", insertedEmployee.Name);
Assert.AreEqual(50000, insertedEmployee.Salary);
}
}
}
এখানে:
- Setup মেথডে আমরা একটি নতুন NHibernate সেশন তৈরি করছি।
- TearDown মেথডে আমরা সেশনটি বন্ধ করে দিচ্ছি।
- TestEmployeeInsertion টেস্ট কেসে, একটি Employee অবজেক্ট তৈরি করে তা ডেটাবেসে ইনসার্ট করা হচ্ছে, তারপর আমরা যাচাই করছি যে ডেটাবেসে সঠিকভাবে ইনসার্ট হয়েছে কিনা।
Mocking NHibernate এর Session
TDD এর একটি গুরুত্বপূর্ণ অংশ হল মকিং। সাধারণত, যখন আপনি ইউটিলিটি ক্লাস বা ডেটাবেস সম্পর্কিত কোড টেস্ট করেন, তখন ডেটাবেসের সাথে সরাসরি যোগাযোগ করার পরিবর্তে মক অবজেক্ট ব্যবহার করা হয়। NHibernate এর ISession এবং ITransaction ইন্টারফেসগুলি মক করা যেতে পারে। এর জন্য আপনি Moq বা NSubstitute মত লাইব্রেরি ব্যবহার করতে পারেন।
using Moq;
using NHibernate;
using NUnit.Framework;
[TestFixture]
public class EmployeeServiceTests
{
private Mock<ISession> mockSession;
private Mock<ITransaction> mockTransaction;
[SetUp]
public void Setup()
{
mockSession = new Mock<ISession>();
mockTransaction = new Mock<ITransaction>();
}
[Test]
public void TestEmployeeInsertionWithMocking()
{
// Arrange
var employeeService = new EmployeeService(mockSession.Object);
var employee = new Employee { Name = "Jane Doe", Salary = 60000 };
mockSession.Setup(s => s.BeginTransaction()).Returns(mockTransaction.Object);
// Act
employeeService.SaveEmployee(employee);
// Assert
mockSession.Verify(s => s.Save(It.IsAny<Employee>()), Times.Once);
mockTransaction.Verify(t => t.Commit(), Times.Once);
}
}
এখানে:
- Mock এবং Mock ব্যবহার করে NHibernate এর সেশন এবং ট্রানজেকশন মক করা হয়েছে।
- Verify মেথড দিয়ে নিশ্চিত করা হয়েছে যে
Saveমেথড এবংCommitট্রানজেকশন একবার করে কল করা হয়েছে।
ইন-মেমরি ডেটাবেস ব্যবহার
TDD এর মধ্যে in-memory database ব্যবহার করা অত্যন্ত উপকারী, কারণ এটি দ্রুত টেস্টিং প্রদান করে এবং ডেটাবেসে কোনো স্থায়ী পরিবর্তন করতে হয় না। আপনি NHibernate এর সাথে SQLite বা H2 ব্যবহার করতে পারেন ইন-মেমরি ডেটাবেস হিসেবে।
<hibernate-configuration>
<session-factory>
<!-- Use SQLite In-Memory Database -->
<property name="hibernate.dialect">NHibernate.Dialect.SQLiteDialect</property>
<property name="hibernate.connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
<property name="hibernate.connection.connection_string">Data Source=:memory:;Version=3;New=True;</property>
<property name="hibernate.hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>
এখানে:
- SQLite ইন-মেমরি ডেটাবেস ব্যবহৃত হচ্ছে, যা টেস্টের সময় কার্যকরী হবে এবং টেস্ট শেষে ডেটাবেসটি মুছে যাবে।
সারাংশ
TDD এবং NHibernate ব্যবহার করে আপনি:
- কোড লেখার আগে টেস্ট কেস তৈরি করবেন।
- ডেটাবেস লেয়ারটি সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করবেন।
- Mocking এবং In-memory databases ব্যবহার করে ডেটাবেস অপারেশনগুলো টেস্ট করবেন, যাতে ডেটাবেসে কোনো পরিবর্তন না আসে।
এভাবে TDD প্রক্রিয়াটি আপনাকে NHibernate ব্যবহারের সময় একটি শক্তিশালী, পরীক্ষিত এবং দৃঢ় কোড বেস তৈরিতে সাহায্য করবে।
Read more