Unit Tests should be repeatable. Having a database with default data is not avoidable in 100% of tests. Therefore, you need a way to have a database on your CI server. But this database needs to be up-to-date with schema and reference data changes after check-in.
EF Code First provides a simple way to drop your existing database and create a new one from scratch. I create an MSBuild script to manage just about everything developers needs to do with the project.
- Build code
- Drop the database
- Recreate the database
- Run unit tests
- Generate coverage reports
Recreating the database is easy. The first step is to drop the database. SqlCMD.exe comes in handy here. Here’s my MSBuild target to drop the PracticeTime database.
<Target Name="DropDatabase"> <Message Text="====== Drop Database =====" /> <Exec Command='sqlcmd.exe -S (local) -E -Q "drop database [PracticeTime.Web]"' IgnoreExitCode="True" /> </Target>
Now, it’s just a matter of creating the database. The EntityFramework package comes with a tools directory which contains a command-line migrate program: migrate.exe. This needs to be copied to the same dll location containing your Migrations folder. Then, it’s called with your migrations assembly and its config file. My entire CreateDatabase target looks like this:
<Target Name="CreateDatabase"> <Message Text="================= Creating Database"></Message> <CallTarget Targets="DropDatabase" /> <Copy SourceFiles="..\packages\EntityFramework.6.0.2\tools\migrate.exe" DestinationFolder="..\src\Web\PracticeTime.Web.DataAccess\bin\" ></Copy> <Exec WorkingDirectory="..\src\Web\PracticeTime.Web.DataAccess\bin\" Command='migrate PracticeTime.Web.DataAccess.dll /startUpConfigurationFile=PracticeTime.Web.DataAccess.dll.config' /> </Target>
Each time a developer runs the build using MSBuild, they get a fresh database based on their entity models. It’s very slick.
NOTE : For projects which don’t use EF Code First, I maintain all the database scripts in source. I have a CreateDatabase program that recreates the database from those files. The thinking is the same, only the tooling is different.
- Unit Tests runs should be repeatable
- Developers should be able to create a fresh database quickly
- Default data should be available
- Use MSBuild tasks for automation