Database
 sql >> база данни >  >> RDS >> Database

Опростяване на модулното тестване на основната съхранена процедура, която също нарича процедура на помощна програма

Тази статия предоставя пояснение за тестване на единица база данни на съхранена процедура, която съдържа процедура за помощ в нея.

В тази статия ще обсъдя един сценарий за тестване на база данни, когато основната съхранена процедура зависи от процедура на помощна програма и основната процедура трябва да бъде тествана на модул, за да се уверим, че изискванията са изпълнени. Ключът е да се гарантира, че единичен тест може да бъде написан само за една единица код, което означава, че се нуждаем от един единичен тест за основната процедура и друг единичен тест за процедурата на помощната програма.

Модулното тестване на една съхранена процедура е по-лесно в сравнение с модулното тестване на процедура, която извиква процедура на помощна програма в кода си.

Много е важно да разберете сценария на процедурата за помощна програма и защо той е различен от тестването с модул на нормална съхранена процедура.

Сценарий:Полезна процедура в рамките на основната процедура

За да разберем сценария на полезна процедура, нека започнем с дефиницията и примера за процедурата за помощна програма:

Какво е процедура за помощна програма

Помощната процедура обикновено е малка процедура, която се използва от главната(ите) процедура(и) за извършване на някаква специфична задача, като например получаване на нещо за основната процедура или добавяне на нещо към основната процедура.

Друга дефиниция на процедура за помощ е малка съхранена процедура, написана за целите на поддръжката, която може да включва системни таблици или изгледи, които да бъдат извиквани от произволен брой процедури или дори директно.

Примери за полезни процедури

Помислете за сценарий клиент-поръчка-продукт, при който клиент прави поръчка за конкретен продукт. Ако създадем основната процедура, за да получим всички поръчки, направени от конкретен клиент, тогава може да се използва процедура за помощ, за да ни помогне да разберем дали всяка поръчка е била направена от клиента в делничен ден или уикенд.
По този начин а малка помощна процедура може да бъде написана, за да върне „Ден от седмицата“ или „Уикенд“ въз основа на датата, на която продуктът е поръчан от клиента.

Друг пример могат да бъдат системно съхранени процедури като “sp_server_info” в главната база данни, която дава информация за инсталираната версия на SQL Server:

EXEC sys.sp_server_info

Защо процедурата на помощната програма за тестване на модул е ​​различна

Както беше обсъдено по-рано, модулното тестване на помощна процедура, която се извиква в основната процедура, е леко сложна от тестването на модул на проста съхранена процедура.

Като се има предвид споменатият по-горе пример за продукт за поръчка на клиента, трябва да напишем единичен тест, за да проверим, че процедурата за помощ работи добре, а също така трябва да бъде написан единичен тест, за да проверим, че основната процедура, която извиква помощната процедура, също функционира правилно, както и отговаря бизнес изискването(ите).

Това е илюстрирано по следния начин:

Изолиране от предизвикателство за помощна програма/главна процедура

Основното предизвикателство при написването на единичен тест(и) за процедурата, която включва процедура за помощ, е да се уверим, че не трябва да се притесняваме за функционирането на процедурата за помощ, когато пишем единичен тест за основната процедура и същото важи и за процедурата за полезност . Това е предизвикателна задача, която трябва да се има предвид при писане на единични тестове за такъв сценарий.
Изолирането от помощната програма или основната процедура е задължително, в зависимост от това коя процедура се тества. Трябва да имаме предвид следните неща в контекста на изолирането по време на тестване на модули:

  1. Изолиране от процедурата за помощна програма, когато модулното тестване на основната процедура.
  2. Изолиране от основната процедура при помощна процедура за тестване на модул.

Моля, не забравяйте, че тази статия е фокусирана върху модулното тестване на основната процедура, като я изолира от нейната полезна процедура.

Създаване на основна процедура и нейната помощна процедура

За да напишем единичен тест за сценарий, при който помощната процедура се използва от основната процедура, първо трябва да имаме следните предпоставки:

  1. Примерна база данни
  2. Бизнес изискване/и

Настройте примерна база данни (SQLBookShop)

Създаваме проста примерна база данни с две таблици, наречена „SQLBookShop“, която съдържа записите на всички подредени книги, както е показано по-долу:

Създайте примерна база данни на SQLBookShop, както следва:

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

Създайте и попълнете обекти на база данни (таблици), както следва:

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

Бърза проверка – Примерна база данни

Направете бърза проверка на базата данни, като стартирате изгледа OrderedBooks, като използвате следния код:

USE SQLBookShop

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

Моля, имайте предвид, че използвам dbForge Studio за SQL Server, така че изходният вид може да се различава, ако стартирате същия код в SSMS (SQL Server Management Studio). Въпреки това, няма разлика между скриптовете и техните резултати.

Бизнес изискване да видите последната поръчка с допълнителна информация

На екипа на разработчиците е изпратено бизнес изискване, което гласи, че „Крайният потребител иска да знае за последната поръчка, направена за конкретна книга, заедно с информацията дали поръчката е направена в делничен ден или уикенд“

Една дума за TDDD

Ние не следваме стриктно разработване на база данни, управлявано от тестове (TDDD) в тази статия, но силно препоръчвам да използвате разработване на база данни, управлявано от тестове (TDDD), за създаване на основни и помощни процедури, което започва със създаване на единичен тест, за да провери дали съществува обект, който отначало се проваля, последвано от създаване на обекта и повторно изпълнение на единичния тест, който трябва да премине.
За подробен преглед, моля, вижте първата част на тази статия.

Идентифициране на помощна процедура

Виждайки бизнес изискването, едно нещо е сигурно, че имаме нужда от процедура за помощ, която може да ни каже дали определена дата е делничен ден или уикенд.

Създаване на помощна процедура (GetDayType)

Създайте процедура за помощна програма и я наречете „GetDayType“, както следва:

-- 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

Бърза проверка – Процедура за помощна програма

Напишете следните редове код, за да проверите бързо помощната процедура:

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

Създаване на основна процедура (GetLatestOrderByBookId)

Създайте основната процедура, за да видите най-новата поръчка, направена за конкретна книга, както и дали поръчката е направена в делничен ден или уикенд и я наречете „GetLatestOrderByBookId“, която съдържа извикването на процедурата за помощ, както следва:

-- 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

Бърза проверка – Основна процедура

Изпълнете следния код, за да видите дали процедурата работи добре или не:

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

Основна процедура за тестване на модули Извикване на процедура на помощна програма

Ключът тук е да се разбере разликата между тестването на модула на основната процедура и процедурата на помощната програма.

Понастоящем сме фокусирани върху модулното тестване на основната процедура, така че това означава, че помощната процедура трябва да бъде изящно изолирана от този модулен тест.

Използване на шпионска процедура

За да се уверим, че единичният тест на основната процедура остава фокусиран върху тестването на функционалността на основната процедура, трябва да използваме шпионска процедура, предоставена от tSQLt, която ще действа като заглушка (заместител) за помощната процедура.

Според tsqlt.org, моля, не забравяйте, че ако шпионирате процедура, вие всъщност не тествате тази процедура, а улеснявате другата процедура, свързана с процедурата, която шпионирате, да бъде тествана на модул.

Например, в нашия случай, ако искаме да тестваме модула на основната процедура, тогава трябва да се подиграем на процедурата за помощ, като използваме шпионска процедура, която ще ни улесни при единично тестване на основната процедура.

Създаване на единичен тест за главна процедура Процедура на помощната програма за шпиониране

Създайте един тест за база данни, за да проверите правилно функционирането на основната процедура.

Тази статия работи за dbForge Studio за SQL Server (или само за dbForge Unit Test) и SSMS (SQL Server Management Studio) . Въпреки това, моля, имайте предвид, че когато използвате SSMS (SQL Server Management Studio), предполагам, че вече сте инсталирали tSQLt Framework и сте готови да напишете модулните тестове.

За да създадете първия тест за единица база данни, щракнете с десния бутон върху базата данни SQLBookShop. В контекстното меню щракнете върху Единичен тест и след това Добавете нов тест, както следва:

Напишете кода на единичния тест:

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

Извършване на единичен тест за основна процедура

Изпълнете единичния тест:

Поздравления, успешно тествахте единично съхранена процедура, като я изолирате от нейната помощна процедура след използване на шпионска процедура.

За повече информация относно модулното тестване, моля, прегледайте следните части от предишната ми статия относно разработването на база данни, управлявана от тестове (TDDD):

  • Прескочете към стартиране на разработване на база данни, управлявано от тестове (TDDD) – част 1
  • Прескочете към стартиране на разработване на база данни, управлявано от тестове (TDDD) – част 2
  • Прескочете към стартиране на разработване на база данни, управлявано от тестове (TDDD) – част 3

Неща за правене

Вече можете да създавате единични тестове на база данни за малко сложни сценарии, при които съхранените процедури извикват помощни процедури.

  1. Моля, опитайте да промените шпионска процедура @CommandToExecute аргумент (стойност) като @CommandToExecute =‘set @DayType =”Nothing” ‘ и вижте, че тестът ще се провали сега
  2. Моля, опитайте да изпълните бизнес изискването в тази статия, като използвате разработване на база данни, управлявано от тестове (TDDD)
  3. Моля, опитайте се да изпълните друго бизнес изискване, за да видите най-новата поръчка, направена от който и да е клиент, използвайки тестово управлявана разработка (TDDD), включваща същата процедура за помощ
  4. Моля, опитайте да създадете единичен тест за помощна процедура, като изолирате главната процедура
  5. Моля, опитайте да създадете единичен тест за процедура, която извиква две помощни процедури

Полезен инструмент:

dbForge Unit Test – интуитивен и удобен GUI за внедряване на автоматизирано тестване на модули в 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. Грешки при свързване с база данни или удостоверяване с подвижен тип

  2. Присъединете се към нас в Лас Вегас за SQLintersection и спестете $100

  3. T-SQL вторник #67 :Ново архивиране и възстановяване на разширени събития

  4. Rethink Flask – прост списък със задачи, поддържан от Flask и RethinkDB

  5. T-SQL вторник #33:Трикове:Схема Switch-A-Roo