tSQLt – testowanie procedur, sortowanie

W poprzednim wpisie pokazałem jak testować wiersze zwracane przez procedury.  Niestety nie brały one pod uwagę kolejności wierszy, co może wydawać się nienaturalne. Załóżmy, że mamy następującą procedurę, zwracającą artykuły posortowane po tytule:

CREATE PROCEDURE [dbo].[GetArticles]
AS
BEGIN

	SELECT * FROM dbo.Articles  ORDER BY title asc;
END

Następnie analogicznie do poprzedniego wpisu, piszemy test jednostkowy:

  --Assemble
  EXEC tSQLt.FakeTable 'dbo.Articles'

  INSERT INTO dbo.Articles (Title) VALUES('C'),('B'),('A')

  CREATE TABLE ActualValues
  (
  		Id INTEGER,
		Title nvarchar(10),
		Content nchar(500)
  )

    CREATE TABLE ExpectedValues
  (
		Title nvarchar(10)
  )
  
 INSERT INTO dbo.ExpectedValues ( Title) VALUES  ( 'A'),('B'),('C')

 INSERT INTO ActualValues EXEC dbo.GetArticles;
  
  --Assert
  EXEC tSQLt.AssertEqualsTable @Expected = N'ExpectedValues',  @Actual = N'ActualValues'

Wstrzykujemy do naszego “mocka” wiersze w kolejności “C,B,A” i sprawdzamy, że na wyjściu pojawią się one w kolejności rosnącej ponieważ w procedurze mamy order by Title Asc. Odpalamy test i wszystko wydaje się w porządku. Niestety jest to błędny wniosek. Spróbujmy zmienić test do następującej postaci:

  --Assemble
  EXEC tSQLt.FakeTable 'dbo.Articles'

  INSERT INTO dbo.Articles (Title) VALUES('C'),('B'),('A')

  CREATE TABLE ActualValues
  (
  		Id INTEGER,
		Title nvarchar(10),
		Content nchar(500)
  )

    CREATE TABLE ExpectedValues
  (
		Title nvarchar(10)
  )
  
 INSERT INTO dbo.ExpectedValues ( Title) VALUES  ('C'),('B'),('A')

 INSERT INTO ActualValues EXEC dbo.GetArticles;
  
  --Assert
  EXEC tSQLt.AssertEqualsTable @Expected = N'ExpectedValues',  @Actual = N'ActualValues'

Zmieniliśmy kolejność oczekiwanych artykułów na błędną. Po uruchomieniu testu, przekonamy się, że wciąż zakończy się on sukcesem, czego oczywiście nie spodziewaliśmy się!

Niestety kolejność nie jest sprawdzana, co jak się dłużej zastanowimy ma sens, ale na pierwszy rzut oka jest mylące.

Musimy stworzyć kolumnę, która będzie identyfikowała kolejność. Naturalnym wyborem jest zatem “identity”:

  --Assemble
  EXEC tSQLt.FakeTable 'dbo.Articles'

  INSERT INTO dbo.Articles (Title) VALUES('C'),('B'),('A')

  CREATE TABLE ActualValues
  (
  		Id INTEGER,
		Title nvarchar(10),
		Content nchar(500),
		OrderSequence INT IDENTITY(1,1)
  )

    CREATE TABLE ExpectedValues
  (
		OrderSequence INT IDENTITY(1,1),
		Title nvarchar(10)
  )
  
 INSERT INTO dbo.ExpectedValues ( Title) VALUES  ('C'),('B'),('A')

 INSERT INTO ActualValues EXEC dbo.GetArticles;
  
  --Assert
  EXEC tSQLt.AssertEqualsTable @Expected = N'ExpectedValues',  @Actual = N'ActualValues'

Proszę zauważyć, że dodaliśmy OrderSequence do ExpectedValues oraz ActualValues. Po odpaleniu testu, dostaniemy błąd, ponieważ kolejność nie zgadza się:
1

Jeśli zmienimy ExpectedValues z powrotem do sekwencji rosnącej (A,B,C), wtedy test oczywiście zakończy się sukcesem.

Jak zatem to działa? Identity jest zwiększane automatycznie w momencie dodawania danych. Zatem ExpectedValues będzie miał wartości (1,A),(2,B) oraz (3,B). Analogicznie sprawa wygląda z ActualValues. Wynik GetArticles jest dodawany do tabeli ActualValues, która z kolei zawiera pole identity – za każdym razem OrderSequence jest zwiększane. Innymi słowy, dane musza być dodawane w tej samej kolejności, zarówno do ActualValues jak i ExpectedValues.

Leave a Reply

Your email address will not be published.