Bắt đầu nhanh
Cài đặt
Phần tiêu đề “Cài đặt”Thêm base class cho test framework của bạn và một package cho mỗi engine bạn kiểm thử.
dotnet add package DbTest.MSTest # base class for MSTest (brings DbTest.Core)dotnet add package DbTest.MsSql # SQL Server enginedotnet add package DbTest.PostgreSql # PostgreSQL enginedotnet add package DbTest.MySql # MySQL enginedotnet add package DbTest.MsSql.Dacpac # deploy a .dacpac (SQL Server database projects)Riêng DbTest.Core cung cấp harness mà không gắn với test framework nào. DbTest.MSTest đã kéo nó theo.
Về công cụ dòng lệnh, xem CLI.
Yêu cầu
Phần tiêu đề “Yêu cầu”- Docker phải đang chạy. Harness khởi động container thật thông qua Testcontainers.
- .NET 8 trở lên. Các package có sẵn asset
net8.0vànet10.0. .NET 8 và 9 dùng assetnet8.0, .NET 10 trở lên dùng assetnet10.0.
1. Thêm schema
Phần tiêu đề “1. Thêm schema”Đặt các file SQL vào một thư mục riêng cho mỗi engine. Các schema dưới đây chỉ là ví dụ: DDL nào test của bạn cần cũng được.
CREATE TABLE dbo.customers ( id INT IDENTITY(1, 1) PRIMARY KEY, email NVARCHAR(256) NOT NULL, display_name NVARCHAR(256) NOT NULL);CREATE TABLE customers ( id SERIAL PRIMARY KEY, email TEXT NOT NULL, display_name TEXT NOT NULL);CREATE TABLE customers ( id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(256) NOT NULL, display_name VARCHAR(256) NOT NULL);Copy các file này vào cạnh test binary, để SchemaRoot tương đối được resolve đúng:
<None Include="Schema\**\*" CopyToOutputDirectory="PreserveNewest" />Xem schema để biết quy tắc sắp thứ tự, tách script và loại trừ file.
2. Viết test một lần
Phần tiêu đề “2. Viết test một lần”Kế thừa DbTestBase trong một abstract class. Harness là harness dùng chung cho engine đang được test.
public abstract class CustomerTests : DbTestBase{ [TestMethod] public async Task Inserted_Customer_Should_Be_Counted() { await Harness.CleanAsync(); await Harness.ExecuteAsync( "INSERT INTO customers (email, display_name) VALUES (@email, @name)", [new DbParameterValue("@email", "ada@example.test"), new DbParameterValue("@name", "Ada")]);
var count = await Harness.QueryScalarAsync<int>( "SELECT COUNT(*) FROM customers WHERE email = @email", [new DbParameterValue("@email", "ada@example.test")]);
Assert.AreEqual(1, count); }}Các namespace cần dùng là DbTest.Core.Engine và DbTest.MSTest, cộng thêm một namespace cho mỗi engine: DbTest.MsSql, DbTest.PostgreSql hoặc DbTest.MySql.
3. Thêm một class cho mỗi engine
Phần tiêu đề “3. Thêm một class cho mỗi engine”Mỗi class chỉ rõ engine và nơi đặt schema của nó. Chỉ thêm những engine bạn cần.
[TestClass]public sealed class MsSqlCustomerTests : CustomerTests{ protected override DbEngine CreateEngine() => new MsSqlEngine(); protected override string SchemaRoot => "Schema/mssql";}[TestClass]public sealed class PostgresCustomerTests : CustomerTests{ protected override DbEngine CreateEngine() => new PostgreSqlEngine(); protected override string SchemaRoot => "Schema/postgres";}[TestClass]public sealed class MySqlCustomerTests : CustomerTests{ protected override DbEngine CreateEngine() => new MySqlEngine(); protected override string SchemaRoot => "Schema/mysql";}CreateEngine() được gọi trước mỗi test, nhưng chỉ lần gọi đầu tiên trong một lần chạy mới khởi động container.
4. Cấu hình test project một lần
Phần tiêu đề “4. Cấu hình test project một lần”Các test dùng chung một container, nên chúng chạy lần lượt từng test, và container cần được xóa ngay khi lần chạy kết thúc.
// Once per test project: tests share a container, so they run one at a time, and the// containers are removed as soon as the run ends.[assembly: DoNotParallelize]
[TestClass]public static class TestRun{ [AssemblyCleanup] public static Task Cleanup() => DbTestRun.DisposeAllAsync();}DbTestRun nằm trong namespace DbTest.MSTest.
Nếu không gọi DisposeAllAsync(), resource reaper của Testcontainers sẽ xóa container khi test host thoát.
5. Chạy thử
Phần tiêu đề “5. Chạy thử”dotnet testTest đầu tiên của mỗi engine khởi động container và áp dụng schema. Các test sau trong cùng lần chạy dùng lại container đó.
Nếu Docker không chạy, test đầu tiên fail với lỗi thật và mọi test sau fail ngay với cùng lỗi đó, thay vì mỗi test tự chờ container của nó đến khi timeout.
Tiếp theo
Phần tiêu đề “Tiếp theo”- Engine: image, tài khoản đăng nhập và các tùy chọn container.
- Shape guard và dọn dữ liệu: những gì chạy quanh mỗi test.
- Xử lý sự cố.