2008-09-29 10 views
20

Wie viele Unternehmen, die alle Zugriffe über gespeicherte Prozeduren benötigen, scheint es, als hätten wir eine Menge Geschäftslogik in sprocs gespeichert. Diese Dinge sind einfach schwer zu testen, und einige von ihnen sind lange albern geworden. Hat jemand da draußen eine Reihe von Best Practices, die es ein wenig leichter machen können, diese Dinge selbstbewusst zu testen?Was ist der beste Weg, um eine gespeicherte Prozedur zu testen?

Gegenwärtig haben wir 30 oder so "Problem" -Datenbanken, gegen die wir laufen. Dies ist nicht immer besonders gut dokumentiert und es ist sicher nicht automatisiert.

Antwort

2

Nicht sicher, ob dies das ist, was Sie suchen, aber da Sie SQL Server verwenden: Ich habe festgestellt, LINQ ein großartiger Werkzeug Test gespeicherte Procs. Sie können die gespeicherten Prozeduren einfach in ein DBML-Diagramm ziehen und sie dann als Methoden auf Ihrem Datenkontext aufrufen. Beats Einrichten von ADO-Verbindungen usw. für ein Testkabel. Wenn Sie beispielsweise ein Testprojekt in Visual Studio einrichten, können Sie Ihre Prozeduren einfach wie Methoden für ein anderes Objekt testen. Wenn Ihre gespeicherten Prozeduren Ergebnismengen zurückgeben, denke ich, dass LINQ das in anonyme Variablen übersetzt, auf die Sie über IEnumerable oder IQueryable zugreifen können (jemand verifiziert dies). Wenn Sie jedoch nur Rückgabecodes senden, sollte dies schnell und einfach erfolgen.

+0

Leser: Beachten Sie, dass sich dies auf LINQ to SQL bezieht. –

2

Ich bemerkte, dass Ihr Beitrag als SqlServer getaggt wurde. Wenn dies der Fall ist, sollten Sie sich die Team Edition für Datenbankprofis ansehen, die Teil von Visual Studio ist. Hier einige Artikel:

Die letzte zu tun ist, tatsächlich Cross-DB-Plattform, während DBPro derzeit nur SQL Server ist.

1

Das scheint wie eine schreckliche Politik. Vielleicht können Sie eine gespeicherte Prozedur schreiben, die SQL ausführt und damit beginnt, den Code so umzuwandeln, dass er dort ausgeführt wird.

In jedem Fall würde ich testen, die gespeicherten Prozeduren über ein traditionelles Automatisierungsframework aufrufen. Als Gateway zwischen der Anwendung und den Daten sollten diese als Integrationstests und nicht als reine Komponententests behandelt werden. Sie können jedoch ein xUnit-basiertes Unit-Test-Framework verwenden, um diese zu steuern. Solange Ihre Tests Zugriff auf SQL für die Datenbank haben, vielleicht durch die oben erwähnte Methode, sollten Sie in der Lage sein zu bestätigen, dass die richtigen Änderungen vorgenommen wurden.

Eine Herausforderung besteht darin, dass Sie angeben, dass sie zu lang werden. Ich würde empfehlen, sie in Subroutinen zu zerlegen und so klein wie möglich zu machen. Es erleichtert das Testen und erleichtert die Wartung.

+0

Die Richtlinie existiert, weil auf einmal alle SQL in der mittleren Schicht und irgendwann im Frontend erstellt und ausgeführt wurde. Wie viele Orte nehmen Menschen manchmal die Korrektur zu Extremen. Sie haben Recht, dass die Sprocs zu lang werden, um ein gutes Refactoring durchzuführen, obwohl ich Tests brauche. –

3

Wir hatten eine sehr dünne Datenzugriffsschicht, die gespeicherte Prozeduren im Grunde wie C# -Methoden aussehen ließ. Unsere NUnit-Testsuite hatte dann SetUp/TearDown, um eine Transaktion und Testmethoden, die in DAL aufgerufen wurden, zu erstellen/zurückzusetzen. Nichts Besonderes und erwies sich als einfacher zu pflegen als TSQLUnit Testsuite.

1

Hier ist meine Low-Tech, schnelle Nummer Methode nur halten Beispiel Eingaben bequem in der DDL befindet


USE [SpacelySprockets] 

GO
/****** Object: StoredProcedure [dbo].[uspBrownNoseMrSpacely] Script Date: 02/03/3000 00:24:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--================================
--Stored Procedure DDL:
--================================ --Example Inputs
/*
DECLARE @SuckupPloyId int
DECLARE @SuckupIdentityRecordId int
SET @SuckupPloyId = 3
*/ -- =============================================
-- Author: 6eorge Jetson
-- Create date: 01/02/3000
-- Description: Sucks up to the boss
-- =============================================
CREATE PROCEDURE [dbo].[uspBrownNoseMrSpacely]
@SuckupPloyId int
,@SuckupIdentityRecordId int OUTPUT
AS
BEGIN DECLARE @EmployeeId int DECLARE @SuckupPoints int DECLARE @DateTimeStamp datetime SET @EmployeeId = dbo.svfGetEmployeeId('6eorge Jetson') SET @SuckupPoints = dbo.svfGetSuckupPoints(@SuckupPloyId) SET @DateTimeStamp = getdate() --Data state-changing statement in sproc INSERT INTO [dbo].[tblSuckupPointsEarned]([EmployeeId], [SuckupPoints], [DateTimeStamp]) VALUES (@EmployeeId, @SuckupPoints, @DateTimeStamp) SET @SuckupIdentityRecordId = @@Identity END
--Unit Test Evidence Display /* SELECT @EmployeeId as EmployeeId ,@SuckupPoints as SuckupPoints ,@DateTimeStamp as DateTimeStamp */ --========================================================================== --After editing for low-tech, non-state changing "unit-like" test invocation --========================================================================== --Example Inputs DECLARE @SuckupPloyId int DECLARE @SuckupIdentityRecordId int SET @SuckupPloyId = 3 /* -- ============================================= -- Author: 6eorge Jetson -- Create date: 01/02/3000 -- Description: Sucks up to the boss -- ============================================= CREATE PROCEDURE [dbo].[uspBrownNoseMrSpacely] @SuckupPloyId int ,@SuckupIdentityRecordId int OUTPUT AS BEGIN */ DECLARE @EmployeeId int DECLARE @SuckupPoints int DECLARE @DateTimeStamp datetime SET @EmployeeId = dbo.svfGetEmployeeId('6eorge Jetson') SET @SuckupPoints = dbo.svfGetSuckupPoints(@SuckupPloyId) SET @DateTimeStamp = getdate() --Data state-changing statement now commented out to prevent data state change -- INSERT INTO [dbo].[tblSuckupPointsEarned]([EmployeeId], [SuckupPoints], [DateTimeStamp]) -- VALUES (@EmployeeId, @SuckupPoints, @DateTimeStamp) SET @SuckupIdentityRecordId = @@Identity --END --Need to comment out the sproc "END" also --Unit Test Evidence Display SELECT @EmployeeId as EmployeeId ,@SuckupPoints as SuckupPoints ,@DateTimeStamp as DateTimeStamp

Es funktioniert sogar besser für udfs, da es keine Änderung des Zustandes ist zu befürchten. Offensichtlich , ich würde das nicht anstelle einem Test-Framework empfehlen, aber wenn ich auf diese einfachen Sekunden-Kalkulation Disziplin

Assert halte, dass meine managable großen sproc gehen zumindest einen einfachen „Unit-Test“

vor dem Ausführen von CREATE PROCEDURE, finde ich, dass ich weniger Fehler mache (wahrscheinlich wegen Disziplin mehr als der Test selbst).

1

Eine Methode, die ich verwendet habe, besteht darin, einen 'temporären' Komponententest zum Refactoring einer bestimmten gespeicherten Prozedur zu schreiben. Sie speichern die Daten aus einer Reihe von Abfragen aus einer Datenbank und speichern sie dort, wo ein Komponententest sie abfragen kann.

Dann refaktorieren Sie Ihre Proc-Aktie. Die zurückgegebenen Daten sollten identisch sein und können direkt oder automatisch mit den gespeicherten Daten verglichen werden.

Eine Alternative besteht darin, die beiden gespeicherten Prozeduren parallel auszuführen und die Ergebnismengen zu vergleichen.

Dies funktioniert besonders gut für nur ausgewählte gespeicherte Prozeduren, aber Updates, Einfügungen & Löschungen sind komplexer.

Ich habe diese Methode verwendet, um den Code in einen Zustand zu bringen, in dem er anfälliger für Komponententests ist, oder einfacher, oder beides.

Verwandte Themen