わざわざ SQL DB 立てたくなかったので LocalDB 使えるか調べたメモ
こんなのを見つけたので出来そうな感じでしたが、
Database Integration Tests in Visual Studio Team Services and Cake Build | Trailmax Tech
で教えてくれたので特に何もせず接続文字列だけ LocalDB にして動かす形にしてます。
VSTS の Hosted VSTS2017 agent で動かすので、LocalDB は既定のインスタンス(MSSQLLocalDB)で問題無しですね。*1
ちなみにバージョンは 2018/05/07 時点で SQL Server 2016 SP1 でした。
Database の作成や初期データは、ビルド実行前に *.bacpac で投入する方法にしてます。
※個別のテスト用のデータは、テスト毎に投入しますが不変なデータも毎回入れるのは面倒なので事前に用意する形です。
bacpac は、ざっくりいうと スキーマとデータをパッケージングしたファイルです。
Data-tier Applications | Microsoft Docs
これがあれば、SQL DB / SQL Server にデータベース(スキーマとデータ)丸ごとインポートすることが出来ます。
bacpac のインポートは、PowerShell でさくっと出来ます。
このスクリプトを VSTS のビルド定義 PowerShell から呼び出すだけ。
$dir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)
Add-Type -Path "$dir\Microsoft.SqlServer.Dac.dll"
$srv = New-Object Microsoft.SqlServer.Dac.DacServices "Data Source=(localdb)\MSSQLLocalDB;Pooling=False"
$package = [Microsoft.SqlServer.Dac.BacPackage]::Load("$dir\Sample.bacpac")
$srv.ImportBacpac($package, "Sample")
気を付ける点は、Microsoft.SqlServer.Dac.dll 読むのには、依存関係にある dll も読み込める場所に配置しとく必要がある位ですかね。
今回は、
NuGet Gallery | Microsoft.SqlServer.DacFx.x64 140.3881.1
を使いましたが、Microsoft.SqlServer.Dac.dll を含む6つの dll を *.ps1 と同じ場所に置いてます。
接続文字列は 環境変数 にあればそこから取る形にしてます。*2
VSTS で実行する時は、ビルド定義で接続文字列埋め込む形です。
using System;
using System.Data.SqlClient;
using Xunit;
using Dapper;
using Xunit.Abstractions;
public class UnitTest1 {
[Fact]
public void Test1() {
var connstr = Environment.GetEnvironmentVariable("VSTS_CONNSTR")
?? @"普段使う接続文字列";
using (var conn = new SqlConnection(connstr)) {
Assert.Equal("Test", conn.ExecuteScalar<string>(
@"select Name from Table1 where Id = 1"));
}
}
}
VSTS の ビルドで 環境変数の設定はこちらを参考に。
Build variables | Microsoft Docs
指定する接続文字列はこんな感じで。
Server=(localdb)\MSSQLLocalDB;Initial Catalog=Sample;Pooling=false