きよくらの備忘録

「三日坊主と呼ばせない!日記」改め。主にソフトウェア開発関連の話題。

Visual Studio 2022でデータベース単体テストのチェックサムがVS2019以前と変わってしまう

随分昔に下書きをしたまま忘れていた記事の第二弾です

Visual Studio 2019(以下、VS2019)以前で作成した データベースの単体テスト (SQL Server Data Tools, SSDT) の単体テストのうち、テスト条件に データチェックサム を利用したテストをVisual Studio 2022(以下、VS2022)で実行するとチェックサムが合わずテスト失敗(RED)になる事象を経験しました。

※前提として、VS2019以前のSSDT単体テストプロジェクトをVS2022で開くとテスト実行で例外が発生する場合があります。対処については以下のエントリを参照。

kiyokura.hateblo.jp

事象

例として、VS2019以前のVisual Studioで作成したデータベースプロジェクトに、以下のようなテーブル値関数 MyFunction があるとします。

CREATE FUNCTION [dbo].[MyFunction]
(
  @param1 int,
  @param2 int,
  @param3 int
)
RETURNS @returntable TABLE
(
  value1 int,
  value2 varchar(10)
)
AS
BEGIN
  INSERT @returntable SELECT @param1, 'AAA';
  INSERT @returntable SELECT @param2, 'BBB';
  INSERT @returntable SELECT @param3, 'CCC';

  RETURN
END

SSDTの単体テスト機能を使用してデータチェック条件に 'データチェックサム' を使用した単体テストを作成、通ることを確認します。

データチェックサムでテスト条件を作成してテストが通ることを確認

このプロジェクトをVS2022で開き、そのまま単体テストを実行すると結果は失敗(RED)となります。

何もしてないのにテストが通らなくなった

原因

直接的にはVS2022からVisual Studioが64bitになったために発生していますが、ポイントとしては以下を把握しておく必要があります。

  • チェックサム算出時、32bit プロセスで算出するか64bitプロセスで算出値するかで値が異なる
  • 単体テスト編集時のチェックサム計算がどちらのアーキテクチャで実行されるかはVisual Studioのアーキテクチャに依存する
    • VS2019 ... 32bit
    • VS2022 ... 64bit
  • 単体テスト実行時のチェックサム計算がどちらのアーキテクチャで実行されるかは、単体テストのDLLがどのようにビルドされるに依存する
    • CPU Any ... ホストされるVSのアーキテクチャに依存
    • x86 ... 32bit
    • x64 ... 64bit
  • データベース単体テストプロジェクトは既定ではCPU Anyでビルドされる

以上より、前述のテスト失敗する状況は、以下となっていることがわかります。

  • 単体テスト内に埋め込まれているチェックサム値 → 32bit
  • テスト実行時のチェックサム計算
    • VS2019でテスト実行 … 32bit
    • VS2022でテスト実行 … 64bit

つまりあらかじめ計算されてテストコードに期待値として埋め込まれているチェックサム(Expected)と、テスト実行時に計算されるチェックサム(Actual)に差異が発生するためにテスト失敗になる、というのが発生している事象ということです。

対処

対処方法としては、ざっくり二通りあるかなと思います。

  • 対処法1 : VS2022でチェックサムを計算しなおす
  • 対処法2 : 単体テストプロジェクトのビルド対象プラットホームを「x86」にする

正攻法なのは「対処法1」であるとは思いますが、取り急ぎ失敗にならないようにテストを通すだけと割り切って「対処法2」を選択するのもナシではないと思います。 ただし、今後テストメソッドの修正や新規にテストを追加する場合は問題が生じる点は認識しておく必要があります。期待値としてのチェックサムを事前に計算する際にはVS2022(以上)で作業する以上は64bitとして計算されてしまうからです。

既存の単体テストプロジェクトにおける対象メソッド数などにもよると思いますが、『とりあえずx86に変更して逃げるようにしつつ、別途64bitプロセスとして実行するテストプロジェクトを作成し既存で変更の必要があるテストはそちら側に移動していく』みたいな段階的な対処というのも一つの手ではあるかもしれません。