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:
- Isoleren van de hulpprogrammaprocedure bij het testen van de hoofdprocedure.
- 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:
- Voorbeelddatabase
- 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.
- Probeer de spionageprocedure @CommandToExecute-argument (waarde) te wijzigen als @CommandToExecute ='set @DayType =”Nothing” ' en zie dat de test nu gaat mislukken
- Probeer te voldoen aan de zakelijke vereisten in dit artikel door testgestuurde databaseontwikkeling (TDDD) te gebruiken
- 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
- Probeer een eenheidstest te maken voor de hulpprogrammaprocedure door de hoofdprocedure te isoleren
- 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.