sql >> Database >  >> RDS >> Database

Vereenvoudiging van het testen van eenheden Belangrijkste opgeslagen procedure die ook een hulpprogramma-procedure aanroept

Dit artikel geeft een overzicht van de database-eenheid die een opgeslagen procedure test die een hulpprogrammaprocedure bevat.

In dit artikel ga ik een scenario voor het testen van een database-eenheid bespreken wanneer een opgeslagen hoofdprocedure afhankelijk is van een hulpprogrammaprocedure en de hoofdprocedure moet worden getest om er zeker van te zijn dat aan de vereisten wordt voldaan. De sleutel is om ervoor te zorgen dat een eenheidstest alleen kan worden geschreven voor een enkele code-eenheid, wat betekent dat we één eenheidstest nodig hebben voor de hoofdprocedure en een andere eenheidstest voor de hulpprogrammaprocedure.

Het testen van een enkele opgeslagen procedure is eenvoudiger in vergelijking met het testen van een procedure die een hulpprogrammaprocedure in de code aanroept.

Het is erg belangrijk om het scenario van de hulpprogrammaprocedure te begrijpen en waarom het anders is dan het testen van eenheden bij een normale opgeslagen procedure.

Scenario:hulpprogrammaprocedure binnen hoofdprocedure

Laten we, om het scenario voor de hulpprogrammaprocedure te begrijpen, beginnen met de definitie en het voorbeeld van de hulpprogrammaprocedure:

Wat is een hulpprogrammaprocedure

Een hulpprogrammaprocedure is over het algemeen een kleine procedure die door de hoofdprocedure(s) wordt gebruikt om een ​​specifieke taak uit te voeren, zoals het verkrijgen van iets voor de hoofdprocedure of het toevoegen van iets aan de hoofdprocedure.

Een andere definitie van hulpprogrammaprocedure is een kleine opgeslagen procedure die is geschreven voor onderhoudsdoeleinden en waarbij systeemtabellen of views kunnen worden gebruikt die door een aantal procedures of zelfs rechtstreeks kunnen worden aangeroepen.

Voorbeelden van hulpprogrammaprocedure

Denk aan een klant-bestelling-productscenario waarbij een klant een bestelling plaatst voor een bepaald product. Als we de hoofdprocedure maken om ons alle bestellingen te bezorgen die door een bepaalde klant zijn geplaatst, kan een hulpprogrammaprocedure worden gebruikt om ons te helpen begrijpen of elke bestelling door de klant op weekdagen of in het weekend is geplaatst.
Op deze manier wordt een kleine hulpprogramma-procedure kan worden geschreven om "Weekdag" of "Weekend" te retourneren op basis van de datum waarop het product door de klant is besteld.

Een ander voorbeeld zijn door het systeem opgeslagen procedures zoals "sp_server_info" in de hoofddatabase die informatie over de geïnstalleerde versie van SQL Server geeft:

EXEC sys.sp_server_info

Waarom de procedure voor het testen van eenheden anders is

Zoals eerder besproken, is het testen van een hulpprogramma een procedure die in de hoofdprocedure wordt aangeroepen enigszins gecompliceerd dan het testen van een eenvoudige opgeslagen procedure.

Gezien het hierboven genoemde voorbeeld van een klantorder-product, moeten we een eenheidstest schrijven om te controleren of de hulpprogrammaprocedure goed werkt en er moet ook een eenheidstest worden geschreven om te controleren of de hoofdprocedure die de hulpprogrammaprocedure aanroept ook goed functioneert en voldoet aan de zakelijke vereisten.

Dit wordt als volgt geïllustreerd:

Isoleren van utiliteits-/hoofdprocedure-uitdaging

De belangrijkste uitdaging bij het schrijven van een eenheidstest voor de procedure die een hulpprogrammaprocedure omvat, is ervoor te zorgen dat we ons geen zorgen hoeven te maken over het functioneren van de hulpprogrammaprocedure bij het schrijven van een eenheidstest voor de hoofdprocedure en hetzelfde geldt voor de hulpprogrammaprocedure . Dit is een uitdagende taak die in gedachten moet worden gehouden bij het schrijven van unit-tests voor een dergelijk scenario.
Isoleren van het hulpprogramma of de hoofdprocedure is een must, afhankelijk van welke procedure wordt getest. We moeten de volgende dingen in gedachten houden in de context van isoleren tijdens het testen van eenheden:

  1. Isoleren van de hulpprogrammaprocedure bij het testen van de hoofdprocedure.
  2. Isoleren van de hoofdprocedure bij het testen van de hulpprogrammaprocedure.

Houd er rekening mee dat dit artikel is gericht op het testen van de hoofdprocedure door deze te isoleren van de hulpprogrammaprocedure.

Hoofdprocedure en de bijbehorende hulpprogrammaprocedure maken

Om een ​​eenheidstest te schrijven voor een scenario waarin de hulpprogrammaprocedure wordt gebruikt door de hoofdprocedure, moeten we eerst aan de volgende vereisten voldoen:

  1. Voorbeelddatabase
  2. Zakelijke vereiste(n)

Voorbeelddatabase instellen (SQLBookShop)

We creëren een eenvoudige voorbeelddatabase met twee tabellen, genaamd "SQLBookShop", die de records van alle bestelde boeken bevat, zoals hieronder weergegeven:

Maak als volgt een SQLBookShop-voorbeelddatabase:

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

Maak en vul database-objecten (tabellen) als volgt:

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

Snelle controle – voorbeelddatabase

Voer een snelle databasecontrole uit door de weergave OrderedBooks uit te voeren met de volgende code:

USE SQLBookShop

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

Houd er rekening mee dat ik dbForge Studio voor SQL Server gebruik, dus het uiterlijk van de uitvoer kan verschillen als u dezelfde code uitvoert in SSMS (SQL Server Management Studio). Er is echter geen verschil tussen scripts en hun resultaten.

Zakelijke vereiste om de laatste bestelling met aanvullende informatie te zien

Er is een zakelijke eis naar het ontwikkelteam gestuurd waarin staat:"De eindgebruiker wil weten wat de meest recente bestelling voor een bepaald boek is, samen met de informatie of de bestelling op een weekdag of in het weekend is geplaatst"

Een woordje over TDDD

We volgen in dit artikel niet strikt test-gedreven database-ontwikkeling (TDDD), maar ik raad ten zeerste aan om test-gedreven database-ontwikkeling (TDDD) te gebruiken om zowel hoofd- als hulpprogramma-procedures te creëren, die begint met het maken van een eenheidstest om te controleren of er een object bestaat dat mislukt eerst, gevolgd door het maken van het object en het opnieuw uitvoeren van de eenheidstest die moet slagen.
Raadpleeg het eerste deel van dit artikel voor een gedetailleerde uitleg.

Hulpprogramma identificeren

Als we de zakelijke vereisten zien, is één ding zeker dat we een hulpprogramma nodig hebben dat ons kan vertellen of een bepaalde datum een ​​weekdag of een weekend is.

Procedure voor hulpprogramma's maken (GetDayType)

Maak een hulpprogramma-procedure en noem deze als volgt "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

Snelle controle – hulpprogrammaprocedure

Schrijf de volgende regels code om snel de hulpprogrammaprocedure te controleren:

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

Hoofdprocedure maken (GetLatestOrderByBookId)

Maak de hoofdprocedure om de meest recente bestelling voor een bepaald boek te zien en ook of de bestelling op een weekdag of in het weekend is geplaatst en noem deze "GetLatestOrderByBookId", die de oproep voor de hulpprogrammaprocedure als volgt bevat:

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

Snelle controle – hoofdprocedure

Voer de volgende code uit om te zien of de procedure goed werkt of niet:

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

Hoofdprocedure voor het testen van een eenheid Aanroepen van de hulpprogrammaprocedure

De sleutel hier is om het verschil te begrijpen tussen het testen van de hoofdprocedure en de hulpprogrammaprocedure.

We zijn momenteel gefocust op het testen van eenheden van de hoofdprocedure, dus dit betekent dat de hulpprogrammaprocedure op elegante wijze moet worden geïsoleerd van deze eenheidstest.

Gebruik van spionageprocedure

Om ervoor te zorgen dat de test van de hoofdprocedure-eenheid gericht blijft op het testen van de functionaliteit van de hoofdprocedure, moeten we de spionageprocedure gebruiken die wordt geleverd door tSQLt, die gaat fungeren als een stub (plaatsaanduiding) voor de hulpprogrammaprocedure.

Volgens tsqlt.org, onthoud alsjeblieft dat als je een procedure bespioneert, je die procedure niet echt unit test, maar dat je het gemakkelijker maakt voor de andere procedure die verband houdt met de procedure die je bespioneert om een ​​unit te testen.

In ons geval, als we bijvoorbeeld de hoofdprocedure willen testen, moeten we de hulpprogrammaprocedure bespotten door het gebruik van een spionageprocedure, wat het voor ons gemakkelijker zal maken om de hoofdprocedure te testen.

Eenheidstest maken voor de hoofdprocedure Spionhulpprogrammaprocedure

Maak een database-eenheidstest om te controleren of de hoofdprocedure correct functioneert.

Dit artikel werkt voor dbForge Studio voor SQL Server (of alleen dbForge Unit Test) en SSMS (SQL Server Management Studio) . Houd er echter rekening mee dat wanneer ik SSMS (SQL Server Management Studio) gebruik, ik aanneem dat u tSQLt Framework al hebt geïnstalleerd en klaar bent om de unit-tests te schrijven.

Om de eerste database-eenheidstest te maken, klikt u met de rechtermuisknop op de SQLBookShop-database. Klik in het snelmenu op Eenheidstest en vervolgens op Nieuwe test toevoegen als volgt:

Schrijf de eenheidstestcode:

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

Eenheidstest uitvoeren voor hoofdprocedure

Voer de eenheidstest uit:

Gefeliciteerd, je hebt met succes een opgeslagen procedure getest door het te isoleren van de hulpprogramma-procedure na het gebruik van de spionageprocedure.

Voor meer informatie over unit testing kunt u de volgende delen van mijn vorige artikel over test-driven database development (TDDD) doornemen:

  • Spring om te beginnen met testgestuurde databaseontwikkeling (TDDD) – deel 1
  • Spring om te beginnen met testgestuurde databaseontwikkeling (TDDD) – deel 2
  • Spring om te beginnen met testgestuurde databaseontwikkeling (TDDD) – deel 3

Dingen om te doen

U kunt nu database-eenheidtests maken voor enigszins complexe scenario's waarin opgeslagen procedures hulpprogrammaprocedures aanroepen.

  1. Probeer de spionageprocedure @CommandToExecute-argument (waarde) te wijzigen als @CommandToExecute ='set @DayType =”Nothing” ' en zie dat de test nu gaat mislukken
  2. Probeer te voldoen aan de zakelijke vereisten in dit artikel door testgestuurde databaseontwikkeling (TDDD) te gebruiken
  3. Probeer te voldoen aan een andere zakelijke vereiste om de meest recente bestelling te zien die door een klant is geplaatst met behulp van testgestuurde ontwikkeling (TDDD) met dezelfde hulpprogrammaprocedure
  4. Probeer een eenheidstest te maken voor de hulpprogrammaprocedure door de hoofdprocedure te isoleren
  5. Probeer uzelf eens een eenheidstest te maken voor een procedure die twee hulpprogramma-procedures aanroept

Handig hulpmiddel:

dbForge Unit Test – een intuïtieve en handige GUI voor het implementeren van geautomatiseerde unit-testing in SQL Server Management Studio.


  1. 3 manieren om de taakstappen van een SQL Server Agent-taak (T-SQL) te krijgen

  2. Hoe de LTRIM()-functie werkt in MySQL

  3. Tabel en kolom ophalen die een reeks bezitten

  4. Het transactielogboek voor de database is vol