5

GETUTCDATE() 関数を数回使用するストアド プロシージャがあります。これは非常に特殊な事業部門の sproc であるため、ここで表示することはあまり意味がありません。そうは言っても、sproc が呼び出されるのはその年だけであることを知っておくと役立つかもしれません。これは、私がやっていることの複雑さを示すものではありませんが、私が話していることを説明するのに役立つはずの不自然な例です:

CREATE PROCEDURE dbo.GenerateRequestListForCurrentYear AS BEGIN
  SELECT RequestId, StartDate, EndDate FROM Requests
  WHERE YEAR(EndDate) = YEAR(GETUTCDATE());
END;

私のテストは次のようになります。

CREATE PROCEDURE testClass.[test Requests are generated for the current year] AS BEGIN
  -- arrange
  EXEC tSQLt.FakeTable 'dbo.Requests';
  INSERT INTO dbo.Requests (RequestId, StartDate, EndDate) VALUES
    (1, '2/1/14', '2/10/14'), (2, '2/1/13', '2/10/13');

  SELECT TOP (0) * INTO #Expected FROM dbo.Requests;
  SELECT TOP (0) * INTO #Actual FROM dbo.Requests;
  INSERT INTO #Expected VALUES
    (1, '2/1/14', '2/10/14');

  -- act
  INSERT INTO #Actual
  EXEC dbo.GenerateRequestListForCurrentYear;

  -- assert
  EXEC tSQLt.AssertEqualsTable #Expected, #Actual;
END;

いくつかのオプションがあります。

  1. 日付/時刻をパラメーターとして渡します (NULL の場合は値を GETUTCDATE() に設定します)。
  2. GETUTCDATE() への呼び出しを独自の関数に置き換えて、tSQLt を使用して偽造できる日付/時刻を返します
  3. ?

これらはどちらも、少し臭いと思われるテストにのみ必要なオプションのようです。プライマリ アプリケーションからの呼び出し方法に関して、この sproc をパラメーター化する必要はありません。

独自の依存関係を持つ SQL の組み込み関数との依存関係に関連するため、tSQLt テストでそれらの呼び出しを偽造する方法はありますか? tSQLt を使用してテストで指定した日付を返すために GETUTCDATE() への呼び出しを偽造するより良い方法はありますか、それともこれらが私の唯一のオプションですか?

4

4 に答える 4

4

どちらのアプローチも使用できます。Andrew のように、私は過去に両方を使用しました。

ただし、私は通常、可能な限りオプション 1 (パラメーターを渡す) を好みます。実行をより繰り返し可能にするという追加の利点があります。言い換えれば、私は任意の日付を渡すことができ、それはしばしばサポートに役立ち、新しい機能の追加をより簡単にしました。これは、SQL 以外の言語でも役立つと思います。個々の複雑なコードの結果を、いつ実行されたかに依存するのではなく、受け取ったパラメーターとシステム内のデータに依存するようにする効果があります。つまり、現在の時刻をパラメーターとして渡すことのテストを超えた利点があり、ためらいを和らげる可能性があります。(テストをサポートするために設計上の決定を下すことに何の問題もないと私は信じていることに注意してください。これは製品の重要な部分です)。

オプション 2 も機能し、システム関数をラップする独自の関数を作成するだけです。ただし、これはパフォーマンスに影響を与える可能性があるため、十分にテストする必要があることに注意してください。関数がクエリに関係している場合、SQL Server は必ずしも親切ではありません。パフォーマンスの問題が想定されるため、クエリでスカラー関数を使用しないというアドバイスは好きではありません。パフォーマンスのペナルティがない場合もあれば、パフォーマンスの違いが問題にならない場合もあるためです。ただし、関数をラップする場合は、その可能性に注意する必要があります。

于 2014-04-11T02:53:03.807 に答える
2

テストでテスト データを生成し、テストが常に現在の年の信頼できるデータを取得するようにします (つまり、相対的な日付を使用します)。そうすれば、データは常に期待される結果を返します。

もちろん、GETUTCDATE() の呼び出しは依存関係にありますが、実際には、ほとんどのシステム関数から分離するのは困難 (または不可能) です。使用される日付機能をテストすることがより重要だと思います。

あなたの例を使用するには:

CREATE PROCEDURE testClass.[test Requests are generated for the current year] AS BEGIN
  -- arrange
  EXEC tSQLt.FakeTable 'dbo.Requests';
  INSERT INTO dbo.Requests (RequestId, StartDate, EndDate) --Calculate working example in current year
    SELECT 1,'2/1/'+convert(nvarchar(4),year(GETUTCDATE())),'2/10/'+convert(nvarchar(4),year(GETUTCDATE()))
  INSERT INTO dbo.Requests (RequestId, StartDate, EndDate) --Calculate previous year example
    SELECT 2,'2/1/'+convert(nvarchar(4),year(dateadd(year,-1,GETUTCDATE()))),'2/10/'+convert(nvarchar(4),year(dateadd(year,-1,GETUTCDATE())))

  SELECT TOP (0) * INTO #Expected FROM dbo.Requests;
  SELECT TOP (0) * INTO #Actual FROM dbo.Requests;
  INSERT INTO #Expected 
    SELECT 1,'2/1/'+convert(nvarchar(4),year(GETUTCDATE())),'2/10/'+convert(nvarchar(4),year(GETUTCDATE()));
  -- act
  INSERT INTO #Actual
  EXEC dbo.GenerateRequestListForCurrentYear;

  -- assert
  EXEC tSQLt.AssertEqualsTable #Expected, #Actual;
END;

テストをコーディングするのは少し手間がかかり、将来のテストの期待について考える必要がありますが、テスト対象のコードに干渉することなくコーディングできるため、私はこのアプローチを好みます。テストが今後も機能することを知っておいてください。

于 2014-04-10T20:35:10.247 に答える