Database
 sql >> Baza danych >  >> RDS >> Database

Uproszczenie testowania jednostkowego Główna procedura składowana, która również nazywa się procedurą użytkową

Ten artykuł zawiera opis testowania jednostki bazy danych procedury składowanej, która zawiera w sobie procedurę narzędziową.

W tym artykule omówię scenariusz testowania jednostkowego bazy danych, w którym główna procedura składowana zależy od procedury narzędziowej, a główna procedura musi zostać przetestowana jednostkowo, aby upewnić się, że wymagania są spełnione. Kluczem jest upewnienie się, że test jednostkowy może być napisany tylko dla pojedynczej jednostki kodu, co oznacza, że ​​potrzebujemy jednego testu jednostkowego dla procedury głównej i innego testu jednostkowego dla procedury użytkowej.

Testowanie jednostkowe pojedynczej procedury składowanej jest łatwiejsze w porównaniu z testowaniem jednostkowym procedury, która wywołuje procedurę narzędziową w swoim kodzie.

Bardzo ważne jest zrozumienie scenariusza procedury narzędziowej i tego, dlaczego różni się ona od testowania jednostkowego normalnej procedury składowanej.

Scenariusz:Procedura narzędziowa w ramach procedury głównej

W celu zrozumienia scenariusza procedury użytkowej zacznijmy od definicji i przykładu procedury użytkowej:

Co to jest procedura narzędziowa

Procedura narzędziowa to na ogół niewielka procedura używana przez główne procedury do wykonania określonego zadania, takiego jak uzyskanie czegoś dla procedury głównej lub dodanie czegoś do procedury głównej.

Inną definicją procedury narzędziowej jest mała procedura składowana napisana do celów konserwacyjnych, która może obejmować tabele systemowe lub widoki, które mogą być wywoływane przez dowolną liczbę procedur lub nawet bezpośrednio.

Przykłady procedury użytkowej

Pomyśl o scenariuszu klient-zamówienie-produkt, w którym klient składa zamówienie na konkretny produkt. Jeśli utworzymy główną procedurę, aby uzyskać wszystkie zamówienia złożone przez konkretnego klienta, wówczas procedura użyteczności może nam pomóc w zrozumieniu, czy każde zamówienie zostało złożone przez klienta w dzień powszedni czy w weekend.
W ten sposób można napisać procedurę małej użyteczności, aby zwrócić „dzień tygodnia” lub „weekend” na podstawie daty zamówienia produktu przez klienta.

Innym przykładem mogą być procedury składowane w systemie, takie jak „sp_server_info” w głównej bazie danych, które dostarczają informacji o wersji zainstalowanej SQL Server:

EXEC sys.sp_server_info

Dlaczego procedura testowania jednostek jest inna

Jak wspomniano wcześniej, testowanie jednostkowe procedury użytkowej, która jest wywoływana wewnątrz głównej procedury, jest nieco skomplikowane niż testowanie jednostkowe prostej procedury składowanej.

Biorąc pod uwagę wspomniany powyżej przykład zamówienia klienta, musimy napisać test jednostkowy, aby sprawdzić, czy procedura użyteczności działa poprawnie, a także należy napisać test jednostkowy, aby sprawdzić, czy główna procedura, która wywołuje procedurę użyteczności, również działa poprawnie, a także spełnia wymagania biznesowe.

Jest to zilustrowane następująco:

Izolowanie od wyzwania użyteczności/procedury głównej

Głównym wyzwaniem przy pisaniu testów jednostkowych dla procedury, która zawiera procedurę narzędziową, jest upewnienie się, że nie powinniśmy martwić się o działanie procedury użytkowej podczas pisania testu jednostkowego dla procedury głównej i to samo dotyczy procedury narzędziowej . Jest to trudne zadanie, o którym należy pamiętać podczas pisania testów jednostkowych dla takiego scenariusza.
Odizolowanie się od narzędzia lub procedury głównej jest koniecznością, w zależności od tego, która procedura jest testowana. Musimy pamiętać o następujących rzeczach w kontekście izolowania podczas testów jednostkowych:

  1. Izolowanie od procedury narzędziowej podczas testowania jednostki głównej procedury.
  2. Izolowanie od głównej procedury podczas procedury narzędziowej testowania jednostek.

Pamiętaj, że ten artykuł koncentruje się na testowaniu jednostki głównej procedury poprzez oddzielenie jej od procedury użytkowej.

Tworzenie głównej procedury i jej procedury użytkowej

Aby napisać test jednostkowy dla scenariusza, w którym procedura narzędzia jest używana przez procedurę główną, najpierw musimy spełnić następujące wymagania wstępne:

  1. Przykładowa baza danych
  2. Wymagania biznesowe

Konfiguracja przykładowej bazy danych (SQLBookShop)

Tworzymy prostą dwutabelową przykładową bazę danych o nazwie „SQLBookShop”, która zawiera rekordy wszystkich uporządkowanych książek, jak pokazano poniżej:

Utwórz przykładową bazę danych SQLBookShop w następujący sposób:

-- (1) Create SQLBookShop database
  CREATE DATABASE SQLBookShop;
  GO

Utwórz i wypełnij obiekty bazy danych (tabele) w następujący sposób:

USE SQLBookShop;

-- (2) Drop book and book order tables if they already exist
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES T WHERE T.TABLE_NAME='BookOrder') DROP TABLE dbo.BookOrder
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES T WHERE T.TABLE_NAME='Book') DROP TABLE dbo.Book
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES T WHERE T.TABLE_TYPE='View' AND t.TABLE_NAME='OrderedBooks') DROP VIEW dbo.OrderedBooks
  

-- (3) Create book table 
  CREATE TABLE Book
    (BookId INT PRIMARY KEY IDENTITY(1,1),
    Title VARCHAR(50),
    Stock INT,
    Price DECIMAL(10,2),
    Notes VARCHAR(200)
    )

-- (4) Create book order table
CREATE TABLE dbo.BookOrder
  (OrderId INT PRIMARY KEY IDENTITY(1,1),
  OrderDate DATETIME2,
  BookId INT,
  Quantity INT,
  TotalPrice DECIMAL(10,2)
  )

-- (5) Adding foreign keys for author and article category
ALTER TABLE dbo.BookOrder ADD CONSTRAINT FK_Book_BookId FOREIGN KEY (BookId) REFERENCES Book (BookId) 
  

-- (6) Populaing book table
INSERT INTO dbo.Book (Title, Stock, Price, Notes)
   VALUES
  
  ('Mastering T-SQL in 30 Days', 10, 200, ''),
  ('SQL Database Reporting Fundamentals', 5, 100, ''),
  ('Common SQL Mistakes by Developers',15,100,''),
  ('Optimising SQL Queries',20,200,''),
  ('Database Development and Testing Tips',30,50,''),
  ('Test-Driven Database Development (TDDD)',20,200,'')


-- (7) Populating book order table

  INSERT INTO dbo.BookOrder (OrderDate, BookId, Quantity, TotalPrice)
    VALUES
   ('2018-01-01', 1, 2, 400),
   ('2018-01-02', 2, 2, 200),
   ('2018-01-03', 3, 2, 200),
     ('2018-02-04', 1, 2, 400),
     ('2018-02-05', 1, 3, 600),
     ('2018-02-06', 4, 3, 600),
     ('2018-03-07', 5, 2, 100),
     ('2018-03-08', 6, 2, 400),
     ('2018-04-10', 5, 2, 100),
     ('2018-04-11', 6, 3, 600);
  GO


-- (8) Creating database view to see all the books ordered by customers
CREATE VIEW dbo.OrderedBooks
  AS
  SELECT bo.OrderId
        ,bo.OrderDate
        ,b.Title
        ,bo.Quantity
        ,bo.TotalPrice
        FROM BookOrder bo INNER JOIN Book b ON bo.BookId = b.BookId

Szybkie sprawdzenie – przykładowa baza danych

Wykonaj szybkie sprawdzenie bazy danych, uruchamiając widok Książki zamówione za pomocą następującego kodu:

USE SQLBookShop

-- Run OrderedBooks view
SELECT
  ob.OrderID
 ,ob.OrderDate
 ,ob.Title AS BookTitle
 ,ob.Quantity
 ,ob.TotalPrice
FROM dbo.OrderedBooks ob

Pamiętaj, że używam dbForge Studio dla SQL Server, więc wygląd danych wyjściowych może się różnić, jeśli uruchomisz ten sam kod w SSMS (SQL Server Management Studio). Jednak nie ma różnicy między skryptami a ich wynikami.

Wymaganie biznesowe, aby zobaczyć najnowsze zamówienie z dodatkowymi informacjami

Do zespołu programistów zostało wysłane wymaganie biznesowe, które stwierdza, że ​​„użytkownik końcowy chce wiedzieć o ostatnim zamówieniu złożonym na konkretną książkę wraz z informacją, czy zamówienie zostało złożone w dzień powszedni, czy w weekend”

Słowo o TDDD

W tym artykule nie podążamy ściśle za tworzeniem baz danych sterowanych testami (TDDD), ale zdecydowanie zalecam korzystanie z rozwoju baz danych sterowanego testami (TDDD) do tworzenia procedur głównych i narzędziowych, które rozpoczynają się od stworzenia testu jednostkowego, aby sprawdzić, czy istnieje obiekt, który na początku kończy się niepowodzeniem, po czym następuje utworzenie obiektu i ponowne uruchomienie testu jednostkowego, który musi przejść.
Aby uzyskać szczegółowy opis, zapoznaj się z pierwszą częścią tego artykułu.

Procedura identyfikacji narzędzia

Widząc wymagania biznesowe, jedno jest pewne, że potrzebujemy procedury narzędziowej, która może nam powiedzieć, czy dana data jest dniem tygodnia, czy weekendem.

Procedura tworzenia narzędzia (GetDayType)

Utwórz procedurę narzędzia i nazwij ją „GetDayType” w następujący sposób:

-- Creating utility procedure to check whether the date passed to it is a weekday or weekend
CREATE PROCEDURE dbo.uspGetDayType 
  @OrderDate DATETIME2,@DayType CHAR(7) OUT
AS
BEGIN
  SET NOCOUNT ON
  IF (SELECT
        DATENAME(WEEKDAY, @OrderDate))
    = 'Saturday'
    OR (SELECT
        DATENAME(WEEKDAY, @OrderDate))
    = 'Sunday'
    SELECT @DayType= 'Weekend'
  ELSE
    SELECT @DayType = 'Weekday'
  SET NOCOUNT OFF
END
GO

Szybkie sprawdzenie – procedura narzędziowa

Napisz następujące wiersze kodu, aby szybko sprawdzić procedurę narzędzia:

-- Quick check utility procedure
declare @DayType varchar(10)
EXEC uspGetDayType '20181001',@DayType output
select @DayType AS [Type of Day]

Tworzenie głównej procedury (GetLatestOrderByBookId)

Utwórz główną procedurę, aby zobaczyć ostatnie zamówienie złożone dla konkretnej książki, a także czy zamówienie zostało złożone w dzień powszedni czy w weekend i nazwij ją „GetLatestOrderByBookId”, która zawiera wywołanie procedury narzędzia w następujący sposób:

-- Creating stored procedure to get most recent order based on bookid and also whether order was placed on weekend or weekday
CREATE PROCEDURE dbo.uspGetLatestOrderByBookId @BookId INT
AS
BEGIN
  -- Declare variables to store values
  DECLARE @OrderId INT
         ,@Book VARCHAR(50)
         ,@OrderDate DATETIME2
         ,@Quantity INT
         ,@TotalPrice DECIMAL(10, 2)
         ,@DayType VARCHAR(10)

  -- Get most recent order for a particular book and initialise variables
  SELECT TOP 1
    @OrderId = bo.OrderId
   ,@Book = b.Title
   ,@OrderDate = bo.OrderDate
   ,@Quantity = bo.Quantity
   ,@TotalPrice = bo.TotalPrice
  FROM BookOrder bo
  INNER JOIN Book b
    ON bo.BookId = b.BookId
  WHERE bo.BookId = @BookId
  ORDER BY OrderDate DESC

  -- Call utility procedure to get type of day for the above selected most recent order
  EXEC uspGetDayType @OrderDate
                    ,@DayType OUTPUT

  -- Show most recent order for a particular book along with the information whether order was placed on weekday or weekend
  SELECT
    @OrderId AS OrderId
   ,@OrderDate AS OrderDate
   ,@Book AS Book
   ,@Quantity AS Quantity
   ,@TotalPrice AS TotalPrice
   ,@DayType AS DayType
END
GO

Szybkie sprawdzenie – procedura główna

Uruchom następujący kod, aby sprawdzić, czy procedura działa poprawnie, czy nie:

-- Get latest order for the bookid=6
EXEC uspGetLatestOrderByBookId @BookId = 6

Procedura główna testowania jednostki Procedura wywoływania narzędzia

Kluczem jest tutaj zrozumienie różnicy między testowaniem jednostkowym głównej procedury a procedurą użytkową.

Obecnie koncentrujemy się na testowaniu jednostkowym głównej procedury, co oznacza, że ​​procedura narzędziowa musi być bezpiecznie odizolowana od tego testu jednostkowego.

Korzystanie z procedury szpiegowskiej

Aby upewnić się, że test jednostki głównej procedury pozostaje skupiony na testowaniu funkcjonalności procedury głównej, musimy użyć procedury szpiegowskiej dostarczonej przez tSQLt, która będzie działać jako skrót (zastępczy) dla procedury użytkowej.

Według tsqlt.org pamiętaj, że jeśli szpiegujesz procedurę, w rzeczywistości nie testujesz tej procedury jednostkowo, a raczej ułatwiasz testowanie jednostkowe innej procedury związanej z procedurą, którą szpiegujesz.

Na przykład, w naszym przypadku, jeśli chcemy przetestować główną procedurę jednostkową, musimy zakpić procedurę użytkową za pomocą procedury szpiegowskiej, która ułatwi nam testowanie jednostkowe głównej procedury.

Tworzenie testu jednostkowego dla procedury głównej Procedura narzędzia szpiegującego

Utwórz test jednostkowy bazy danych, aby sprawdzić, czy główna procedura działa poprawnie.

Ten artykuł działa dla dbForge Studio dla SQL Server (lub tylko dbForge Unit Test) i SSMS (SQL Server Management Studio) . Należy jednak pamiętać, że podczas korzystania z SSMS (SQL Server Management Studio) zakładam, że już zainstalowałeś tSQLt Framework i jesteś gotowy do pisania testów jednostkowych.

Aby utworzyć pierwszy test jednostkowy bazy danych, kliknij prawym przyciskiem myszy bazę danych SQLBookShop. W menu skrótów kliknij Test jednostkowy, a następnie Dodaj nowy test w następujący sposób:

Wpisz kod testu jednostkowego:

CREATE PROCEDURE GetLatestOrder.[test to check uspGetLatestOrderByBookId outputs correct data]
AS
BEGIN
  --Assemble
  
  -- Mock order Book and BookOrder table
  EXEC tSQLt.FakeTable @TableName='dbo.Book'
  EXEC tSQLt.FakeTable @TableName='dbo.BookOrder'
  
  -- Adding mock data to book table
  INSERT INTO dbo.Book (BookId,Title, Stock, Price, Notes)
  VALUES (1,'Basics of T-SQL Programming', 10, 100, ''),
    (2,'Advanced T-SQL Programming', 10, 200, '')

  -- Adding mock data to bookorder table
  INSERT INTO dbo.BookOrder (OrderId,OrderDate, BookId, Quantity, TotalPrice)
  VALUES (1,'2018-01-01', 1, 2, 200),
    (2,'2018-05-01', 1, 2, 200),
    (3,'2018-07-01', 2, 2, 400)
    
  -- Creating expected table
  CREATE TABLE GetLatestOrder.Expected (
    OrderId INT
   ,OrderDate DATETIME2
   ,Book VARCHAR(50)
   ,Quantity INT
   ,TotalPrice DECIMAL(10, 2)
   ,DayType VARCHAR(10)
  )

   -- Creating actual table
   CREATE TABLE GetLatestOrder.Actual (
    OrderId INT
   ,OrderDate DATETIME2
   ,Book VARCHAR(50)
   ,Quantity INT
   ,TotalPrice DECIMAL(10, 2)
   ,DayType VARCHAR(10)
  )
  
  -- Creating uspGetDayType spy procedure to isolate main procedure from it so that main procedure can be unit tested
  EXEC tSQLt.SpyProcedure @ProcedureName = 'dbo.uspGetDayType',@CommandToExecute = 'set @DayType = ''Weekday'' '
  
  -- Inserting expected values to the expected table
  INSERT INTO GetLatestOrder.Expected (OrderId, OrderDate, Book, Quantity, TotalPrice, DayType)
  VALUES (2,'2018-05-01', 'Basics of T-SQL Programming', 2, 200,'Weekday');


  --Act
 INSERT INTO GetLatestOrder.Actual
 EXEC uspGetLatestOrderByBookId @BookId = 1 -- Calling the main procedure

  --Assert 
  --Compare expected results with actual table results
  EXEC tSQLt.AssertEqualsTable @Expected = N'GetLatestOrder.Expected', -- nvarchar(max)
    @Actual = N'GetLatestOrder.Actual' -- nvarchar(max)
  
END;
GO

Wykonywanie testu jednostkowego dla procedury głównej

Uruchom test jednostkowy:

Gratulacje, pomyślnie przetestowałeś procedurę składowaną, izolując ją od jej procedury użytkowej po użyciu procedury szpiegowskiej.

Aby uzyskać więcej informacji na temat testów jednostkowych, zapoznaj się z następującymi częściami mojego poprzedniego artykułu o tworzeniu baz danych sterowanych testami (TDDD):

  • Skok, aby rozpocząć tworzenie baz danych oparte na testach (TDDD) – część 1
  • Skok, aby rozpocząć tworzenie baz danych oparte na testach (TDDD) – część 2
  • Skok, aby rozpocząć tworzenie baz danych oparte na testach (TDDD) – część 3

Rzeczy do zrobienia

Możesz teraz tworzyć testy jednostkowe bazy danych dla nieco złożonych scenariuszy, w których procedury składowane wywołują procedury narzędziowe.

  1. Spróbuj zmienić procedurę szpiegowską @CommandToExecute argument (wartość) jako @CommandToExecute =‘set @DayType =”Nic” ‘i zobacz, że test teraz się nie powiedzie
  2. Spróbuj spełnić wymagania biznesowe opisane w tym artykule, korzystając z programowania baz danych opartego na testach (TDDD)
  3. Spróbuj spełnić inne wymagania biznesowe, aby zobaczyć najnowsze zamówienie złożone przez dowolnego klienta za pomocą programowania sterowanego testami (TDDD) obejmującego tę samą procedurę narzędziową
  4. Spróbuj utworzyć test jednostkowy dla procedury użytkowej, izolując procedurę główną
  5. Proszę, spróbuj stworzyć test jednostkowy dla procedury, która wywołuje dwie procedury narzędziowe

Przydatne narzędzie:

dbForge Unit Test – intuicyjny i wygodny GUI do wdrażania zautomatyzowanych testów jednostkowych w SQL Server Management Studio.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak drogie są niejawne konwersje po stronie kolumny?

  2. Schemat płatka śniegu

  3. Jak napisać instrukcję CASE w SQL?

  4. SCD typu 2

  5. Metody automatyzacji Azure