不動の鳥の勉強記録

時間があるときに勉強したことをメモします。

SQL Server用のテストフレームワークtSQLtのインストール

■はじめに

SQL Server上で動くモジュールの品質を高めるためのテストフレームワークにtSQLtというものがあると聞いたので勉強しました。
環境面での安定稼働は進めてきたので、今後はビジネスロジックにも手を伸ばして品質向上を進めていきたいと思っています。

■tSQLtとは

tSQLtはSQL Server用の単体テストフレームワークオープンソースです。下記サイトが公式サイトです。

tsqlt.org

SQL Server 2005 Service Pack 2エディション以降のすべてのエディションのSQL Serverとの互換性があるとのことです。SQL Server 2000を利用している人は…早く利用しなくする活動をしましょう…

■インストール方法

サイトからダウンロードしたzipファイルを解凍すると5つのファイルがあります。
それぞれ下記内容となっています。

  • Example.sql: サンプルのsqlファイルです。
  • Lincense.txt: ライセンス事項が記載されているファイルです。
  • ReleaseNotes.txt: リリースノートが記載されているファイルです。
  • SetClrEnabled.sql: tSQLtの実行で必要なclr enabledを有効にするクエリが記載されています。
  • tSQLt.class.sql: tSQLtの必要セットがインストールされるsqlファイルです。

まず、tSQLtを利用するには、SQL Server構成オプションのclr enabledが有効になっている必要があるため、必要に応じて、SetClrEnabled.sqlを実行します。SQL Server 2017ではclr strict securityというサーバ構成オプションも追加されており、SQL Server 2017の環境ではこのサーバ構成オプションを無効にする必要があります。

次にtSQLt.class.sqlを実行します。これでインストールは完了です。
初めて利用するので公式サイトに記載のQuick Startを実行してみます。

チュートリアル 1 FIX THE FAILING TEST

Quick Startに記載のチュートリアルに従い実行してみます。 ここでは、テスト用のDBを作成しテストケースの実行とバグフィクスを体験できます。

tsqlt.org

まずExample.sqlを実行します。このファイルを実行すると、tSQLt_ExampleというDBがインスタンス上に作成されます。このDB内にtSQLt.class.sqlの内容と同時にチュートリアル用の処理(スキーマがAcceleratorのオブジェクト)が作成されます。

tSQLtを実行してみます。

EXEC tSQLt.RunALL;

実行するとエラーメッセージが表示されます。

-- 抜粋
[AcceleratorTests].[test ready for experimentation if 2 particles] failed: Expected: <1> but was: <0>

内容はそのまま[AcceleratorTests].[test ready for experimentation if 2 particles]というストアドプロシージャで期待値と異なる値が返ってきたというものになります。
次に[AcceleratorTests].[test ready for experimentation if 2 particles]を見てみます。

ALTER PROCEDURE 
  AcceleratorTests.[test ready for experimentation if 2 particles]
AS
BEGIN
  --Assemble: Fake the Particle table to make sure 
  --          it is empty and has no constraints
  EXEC tSQLt.FakeTable 'Accelerator.Particle';
  INSERT INTO Accelerator.Particle (Id) VALUES (1);
  INSERT INTO Accelerator.Particle (Id) VALUES (2);
  
  DECLARE @Ready BIT;
  
  --Act: Call the IsExperimentReady function
  SELECT @Ready = Accelerator.IsExperimentReady();
  
  --Assert: Check that 1 is returned from IsExperimentReady
  EXEC tSQLt.AssertEquals 1, @Ready;
  
END;

中を見てみると、Accelerator.Particleテーブルに2行データを入れて、Accelerator.IsExperimentReady()という関数を実行しその結果が1と等しいか確認するテストケースです。Accelerator.IsExperimentReady関数を見てます。

CREATE FUNCTION Accelerator.IsExperimentReady()
RETURNS BIT
AS
BEGIN 
  DECLARE @NumParticles INT;
  
  SELECT @NumParticles = COUNT(1) FROM Accelerator.Particle;
  
  IF @NumParticles > 2
    RETURN 1;

  RETURN 0;
END;

この関数では、Accelerator.Particleの行数をカウントし、2を超える場合は1を返却し、2以下の場合は0を返すとなっています。テストケースを正とすると、この関数では2の場合に1を返却する想定となっており、「IF @NumParticles > 2」の判定式が誤りとわかります。そのためAcclerator.IsExperimentReady関数の判定式を 「IF @NumParticles >= 2」に修正を行います。

そして再度テストケースを実行してみます。

EXEC tSQLt.RunALL;

実行するとエラーメッセージの出力がなくなりました。

チュートリアル 2 WRITE YOUR OWN NEW TEST

こちらでは自分のテストケースを作成する方法が紹介されています。

まずテストクラスを作成します。

EXEC tSQLt.NewTestClass 'TryItOut';
GO

これを実行するとTryItOutという名前のテストクラスが作成されます。このテストクラス名をスキーマとし、テストケースを作成していきます。

必ず失敗が記録されるテストケースを1つ作ります。

CREATE PROCEDURE TryItOut.[test this causes a failure]
AS
BEGIN
    EXEC tSQLt.Fail 'This is what a failure looks like';
END;
GO

続いて成功のテストケースを1つ作成します。

CREATE PROCEDURE TryItOut.[test this one passes]
AS
BEGIN
    DECLARE @sum INT;
    SELECT @sum = 1 + 2;

    EXEC tSQLt.AssertEquals 3, @sum;
END

テストを実行してみます。

EXEC tSQLt.RunAll;
GO

実行結果は下記のようになります。

[TryItOut].[test this causes a failure] failed: This is what a failure looks like

+---------------------+
|Test Execution Sumary|
+---------------------+

|No|Test Case Name                         |Result |
+--+---------------------------------------+-------+
|1 |[TryItOut].[test this one passes]      |Success|
|2 |[TryItOut].[test this causes a failure]|Failure|
-----------------------------------------------------------------------------
Msg 50000, Level 16, State 10, Line 1
Test Case Summary: 2 test case(s) executed, 1 succeeded, 1 failed, 0 errored.
-----------------------------------------------------------------------------

TryItOutスキーマ配下のテスト用のストアドプロシージャが2つ実行されたことが確認できます。

最後にテストケースを削除します。

EXEC tSQLt.DropClass 'TryItOut';
GO

先ほど作成した2つのストアドプロシージャが削除されていることが確認できました。

■おわりに

まずはtSQLtを使うにはどうやったらいいかというところで、tSQLtのインストールとチュートリアルを記載しました。次回はtSQLtが用意している関数などを見ていきたいと思います。