Skip to content

Commit 694d4aa

Browse files
v2.0.0 (#3)
* Add SqlServerDatabaseComparer class to perform comparison between two databases. * Add new PosInformatique.UnitTests.Databases.SqlServer.Dac NuGet package which contains DAC package tools. * Add new SqlServer.CreateDatabaseAsync() extension method to create a database from a DbContext. * Reduce the Entity Framework / Sql Client NuGet library dependencies with lower version.
1 parent e347b09 commit 694d4aa

File tree

115 files changed

+5020
-885
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+5020
-885
lines changed

.editorconfig

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
[*]
1+
[*.csproj]
22
indent_style = space
3-
indent_size = 4
3+
indent_size = 2
44

55
[*.cs]
6+
indent_style = space
7+
indent_size = 4
68

79
# StyleCop
810

@@ -14,3 +16,11 @@ dotnet_diagnostic.SA1601.severity = none
1416

1517
# SA1602: Enumeration items should be documented
1618
dotnet_diagnostic.SA1602.severity = none
19+
20+
# Visual Studio
21+
22+
# IDE0130: Namespace does not match folder structure
23+
dotnet_diagnostic.IDE0130.severity = none
24+
25+
# IDE0290: Use primary constructor
26+
dotnet_diagnostic.IDE0290.severity = none

.github/workflows/github-actions-release.yml

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
type: string
88
description: The version of the library
99
required: true
10-
default: 1.0.0
10+
default: 2.0.0
1111
VersionSuffix:
1212
type: string
1313
description: The version suffix of the library (for example rc.1)
@@ -39,5 +39,12 @@ jobs:
3939
--property:VersionSuffix=${{ github.event.inputs.VersionSuffix }}
4040
"src/UnitTests.Databases.SqlServer.EntityFramework/UnitTests.Databases.SqlServer.EntityFramework.csproj"
4141

42+
- name: Build UnitTests.Databases.SqlServer.Dac
43+
run: dotnet pack
44+
--property:Configuration=Release
45+
--property:VersionPrefix=${{ github.event.inputs.VersionPrefix }}
46+
--property:VersionSuffix=${{ github.event.inputs.VersionSuffix }}
47+
"src/UnitTests.Databases.SqlServer.Dac/UnitTests.Databases.SqlServer.Dac.csproj"
48+
4249
- name: Publish the package to nuget.org
4350
run: dotnet nuget push "src/**/bin/Release/*.nupkg" --api-key "${{ secrets.NUGET_APIKEY }}" --source https://api.nuget.org/v3/index.json

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<RunAnalyzers Condition="'$(Configuration)' == 'Release'">false</RunAnalyzers>
2020

2121
<!-- Disable the StyleCop 'XML comment analysis is disabled due to project configuration' warning. -->
22-
<NoWarn>$(NoWarn);SA0001</NoWarn>
22+
<NoWarn>$(NoWarn);SA0001;NU1903</NoWarn>
2323

2424
<!-- By default prefix all the assemblies name with ChantierConnect -->
2525
<AssemblyName>PosInformatique.$(MSBuildProjectName)</AssemblyName>

Directory.Packages.props

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
</PropertyGroup>
55
<ItemGroup>
66
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
7-
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
8-
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
7+
<PackageVersion Include="FluentAssertions" Version="6.12.1" />
8+
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.0.1" />
9+
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
910
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
10-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
11-
<PackageVersion Include="Microsoft.SqlServer.DacFx" Version="162.3.566" />
12-
<PackageVersion Include="PosInformatique.UnitTests.Databases.SqlServer.EntityFramework" Version="0.9.11" />
11+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
12+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
13+
<PackageVersion Include="Microsoft.SqlServer.DacFx" Version="161.6374.0" />
1314
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
14-
<PackageVersion Include="xunit" Version="2.9.0" />
15+
<PackageVersion Include="xunit" Version="2.9.1" />
1516
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
1617
</ItemGroup>
1718
</Project>

PosInformatique.UnitTests.Databases.sln

+7
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ EndProject
5252
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{8500A9B6-CAA0-432C-BABB-DDC86CE08994}"
5353
ProjectSection(SolutionItems) = preProject
5454
docs\WriteUnitTests.md = docs\WriteUnitTests.md
55+
docs\WriteDatabaseMigrationUnitTest.md = docs\WriteDatabaseMigrationUnitTest.md
5556
EndProjectSection
5657
EndProject
58+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.Databases.SqlServer.Dac", "src\UnitTests.Databases.SqlServer.Dac\UnitTests.Databases.SqlServer.Dac.csproj", "{8BE60460-EBA5-43DE-B85D-C756E2988DC8}"
59+
EndProject
5760
Global
5861
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5962
Debug|Any CPU = Debug|Any CPU
@@ -94,6 +97,10 @@ Global
9497
{04A7AE8F-FE77-435B-9250-600388BB8065}.Debug|Any CPU.Build.0 = Debug|Any CPU
9598
{04A7AE8F-FE77-435B-9250-600388BB8065}.Release|Any CPU.ActiveCfg = Release|Any CPU
9699
{04A7AE8F-FE77-435B-9250-600388BB8065}.Release|Any CPU.Build.0 = Release|Any CPU
100+
{8BE60460-EBA5-43DE-B85D-C756E2988DC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
101+
{8BE60460-EBA5-43DE-B85D-C756E2988DC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
102+
{8BE60460-EBA5-43DE-B85D-C756E2988DC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
103+
{8BE60460-EBA5-43DE-B85D-C756E2988DC8}.Release|Any CPU.Build.0 = Release|Any CPU
97104
EndGlobalSection
98105
GlobalSection(SolutionProperties) = preSolution
99106
HideSolutionNode = FALSE

README.md

+65-11
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,39 @@
44
It simplifies writing and executing tests, helping ensure your database and data access code are reliable and bug-free.
55
It is ideal for developers who want to validate data access based on SQL Server code during their development.
66

7-
This set of tools supports unit testing of the data access layer based on SQL Server.
7+
This set of tools supports unit testing of the persistence layer based on SQL Server.
88
Any kind of data access framework can be used with these tools:
99
- Raw ADO .NET queries.
1010
- Entity Framework.
1111
- Dapper.
1212
- ...
1313

14+
You can also use this tools to create and run integration tests with the
15+
[Integration tests in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-8.0)
16+
approach.
17+
18+
Since the version 2.0.0 this tools provide a comparer to compare the schema of two SQL databases.
19+
1420
## The approach of these tools
1521

1622
The main approach of these tools is to perform unit tests without using mocking or in-memory alternatives for ADO .NET code or Entity Framework `DbContext`, instead using a real SQL Server database.
1723

24+
Also, these tools offer simple way to compare two SQL databases to test migration script (or Entity Framework migration) when upgrading a database.
25+
1826
### Why is this approach recommended?
1927

20-
- Around 30% to 40% of the code in applications is located in the Data Access layer or repository components. Because it is hard to unit test, developers often skip testing,
28+
- Around 30% to 40% of the code in applications is located in the persistence layer or repository components. Because it is hard to unit test, developers often skip testing,
2129
resulting in lower code coverage.
2230
- When using a mock or in-memory approach for a `DbContext`, you don't truly test the Entity Framework mapping to your database, especially additional SQL constraints like nullability, uniqueness, foreign key cascades, etc.
2331
You also miss technical behaviors like transactions, connection management, triggers, etc.
2432
- When inserting data, it is crucial to ensure that the data in the columns are stored correctly (null/not null values, enum values to numerical values, custom or JSON serialized data, etc.).
2533
- If you use Entity Framework, you can detect warnings/errors raised by the `DbContext` during the development.
2634
- You perform unit test cases, meaning you write simple tests to validate small features instead of writing complex integration tests.
35+
- When changing the schema of the database, it is important to test and have a *safeguard* to check that the migration script (or Entity Framework migration actions) will update the database to the expected schema.
2736

28-
## How to unit test a Data Access Layer
37+
## How to unit test a persistence layer
2938

30-
To perform unit tests of a Data Access Layer, the approach is straightforward using the Arrange/Act/Assert pattern:
39+
To perform unit tests of a persistence layer, the approach is straightforward using the Arrange/Act/Assert pattern:
3140

3241
Before each unit test (`TestMethod` or `Fact` methods):
3342

@@ -48,6 +57,34 @@ Before each unit test (`TestMethod` or `Fact` methods):
4857

4958
To write a unit test using this approach with the [PosInformatique.UnitTests.Databases](https://github.com/PosInformatique/PosInformatique.UnitTests.Databases) tools, see the [Write unit tests to test the Data Access Layer](./docs/WriteUnitTests.md) page.
5059

60+
## How to unit test database migration
61+
62+
To perform unit tests of a database migration, the approach is straightforward and required only a unit test which perform the following actions:
63+
64+
1. Create an empty database (*initial database*).
65+
66+
2. Create a secondary database with the targeted schema (*target database*).
67+
68+
There are two ways to do this:
69+
- Deploy a DACPAC file (built by a SQL Server Database project).
70+
- Or create a database from a `DbContext` using Entity Framework.
71+
72+
3. Execute your database *migration code* on the *initial database*.
73+
74+
Your database *migration code* can be:
75+
- A simple SQL script file.
76+
- An Entity Framework migration sets executed with the `MigrateAsync()` method.
77+
78+
4. Compare the two databases schemas (*initial* and *target*).
79+
80+
If the database *migration code* works, the *initial* and *target* must have the same schema.
81+
82+
> **NB**: The initial database is not necessarily empty. It can be at a specific schema version X if we want to test the migration from version X to Y.
83+
84+
This approach does not test the migration of the data within the database. We can modify this process to inject some data in the first step to test it,
85+
but writing the unit test can be time-consuming. By focusing on the schema migration of the database, you can verify at least 80-90% of your database
86+
migration code. It's better than nothing and very useful for detecting issues during development or in a CI process!
87+
5188
## What do the PosInformatique.UnitTests.Databases tools provide?
5289

5390
Using the previous approach, the [PosInformatique.UnitTests.Databases](https://github.com/PosInformatique/PosInformatique.UnitTests.Databases) libraries allow you to:
@@ -59,33 +96,36 @@ Using the previous approach, the [PosInformatique.UnitTests.Databases](https://g
5996

6097
- Offer helpers to easily query and retrieve data from SQL tables (for assertions).
6198

99+
- Contain a comparer tool to check schema differences between two databases.
100+
62101
## NuGet packages
63102

64103
The [PosInformatique.UnitTests.Databases](https://github.com/PosInformatique/PosInformatique.UnitTests.Databases) tools are provided in two NuGet packages:
65104

66105
- [PosInformatique.UnitTests.Databases.SqlServer](https://www.nuget.org/packages/PosInformatique.UnitTests.Databases.SqlServer) NuGet package which contains:
67-
- Tools to deploy a SQL Server database using a DACPAC file before each unit test.
68106
- Helpers to initialize SQL Server databases with sample data.
69107
- Helpers to easily query SQL Server databases.
108+
- Helpers to compare the schema of two SQL Server databases.
109+
110+
- [PosInformatique.UnitTests.Databases.SqlServer.Dac](https://www.nuget.org/packages/PosInformatique.UnitTests.Databases.SqlServer.Dac) NuGet package which contains:
111+
- Tools to deploy a SQL Server database using a DACPAC file before each unit test.
70112

71113
- [PosInformatique.UnitTests.Databases.SqlServer.EntityFramework](https://www.nuget.org/packages/PosInformatique.UnitTests.Databases.SqlServer.EntityFramework) NuGet package which contains:
72114
- Tools to deploy a SQL Server database using a DbContext.
73-
74-
This package uses and includes the previous [PosInformatique.UnitTests.Databases.SqlServer](https://www.nuget.org/packages/PosInformatique.UnitTests.Databases.SqlServer) NuGet package.
75115

76116
## Samples / Demo
77117

78118
A complete sample solution is available in this repository inside the [samples](./samples) folder.
79119

80120
The solution contains the following sample projects:
81121
- [DemoApp.Domain](./samples/DemoApp.Domain/DemoApp.Domain.csproj): Represents the domain of the application with a set of sample business entities.
82-
- [DemoApp.DataAccessLayer](./samples/DemoApp.DataAccessLayer/DemoApp.DataAccessLayer.csproj): Represents a Data Access Layer with a set of repositories to unit test.
122+
- [DemoApp.DataAccessLayer](./samples/DemoApp.DataAccessLayer/DemoApp.DataAccessLayer.csproj): Represents a persistence layer with a set of repositories to unit test.
83123
- [DemoApp.DataAccessLayer.Tests](./samples/DemoApp.DataAccessLayer.Tests/DemoApp.DataAccessLayer.Tests.csproj): Unit test project to test the [DemoApp.DataAccessLayer](./samples/DemoApp.DataAccessLayer/DemoApp.DataAccessLayer.csproj)
84124
project using the [PosInformatique.UnitTests.Databases.SqlServer.EntityFramework](https://www.nuget.org/packages/PosInformatique.UnitTests.Databases.SqlServer.EntityFramework) package.
85125

86-
## Writing unit tests for a Data Access Layer
126+
## Writing unit tests for a persistence layer
87127

88-
To write unit tests for a Data Access Layer, follow the [Write unit tests to test the Data Access Layer](./docs/WriteUnitTests.md) documentation page, which explains the different steps to perform
128+
To write unit tests for a persistence layer, follow the [Write unit tests to test the persistence layer](./docs/WriteUnitTests.md) documentation page, which explains the different steps to perform
89129
using the [PosInformatique.UnitTests.Databases.SqlServer.EntityFramework](https://www.nuget.org/packages/PosInformatique.UnitTests.Databases.SqlServer.EntityFramework) library:
90130

91131
- [Create the SQL Server instance](./docs/WriteUnitTests.md#create-the-sql-server-instance)
@@ -99,4 +139,18 @@ using the [PosInformatique.UnitTests.Databases.SqlServer.EntityFramework](https:
99139
- [Write the unit tests for methods that retrieve data](./docs/WriteUnitTests.md#write-the-unit-tests-for-methods-that-retrieve-data)
100140
- [Write the unit tests for methods that update the data](./docs/WriteUnitTests.md#write-the-unit-tests-for-methods-that-update-the-data)
101141
- [Execute the unit tests](./docs/WriteUnitTests.md#execute-the-unit-tests)
102-
- [Check the database state after a unit test has failed](./docs/WriteUnitTests.md#check-the-database-state-after-an-unit-test-has-been-failed)
142+
- [Check the database state after a unit test has failed](./docs/WriteUnitTests.md#check-the-database-state-after-an-unit-test-has-been-failed)
143+
144+
## Writing unit test to check database migration
145+
146+
To write an unit test to check the migration of database, follow the [Write unit tests to test database migration](./docs/WriteDatabaseMigrationUnitTest.md)
147+
documentation page.
148+
149+
For Entity Framework migration:
150+
- [Create the SQL Server instance](./docs/WriteUnitTests.md#create-the-sql-server-instance)
151+
- [Create the LocalDB instance](./docs/WriteUnitTests.md#create-the-localdb-instance)
152+
- [Entity Framework migration approach](./docs/WriteDatabaseMigrationUnitTest.md#entity-framework-migration-approach)
153+
- [Create the unit tests project](./docs/WriteDatabaseMigrationUnitTest.md#create-the-unit-tests-project)
154+
- [Add the NuGet packages](./docs/WriteDatabaseMigrationUnitTest.md#add-the-nuget-packages)
155+
- [Write unit test to check the migration of the database](./docs/WriteDatabaseMigrationUnitTest.md#write-unit-test-to-check-the-migration-of-the-database)
156+
- [Check the report details of the `SqlServerDatabaseComparer` tool](./docs/WriteDatabaseMigrationUnitTest.md#check-the-report-details-of-the-sqlserverdatabasecomparer-tool)

0 commit comments

Comments
 (0)