2012-06-27 3 views
6

Esiste un modo per creare semplici test unitari per query SQL in SSMS? Sono abbastanza nuovo per T-SQL & SSMS, ma mi piacerebbe provare a portare alcune delle mie vecchie abitudini TDD in questa arena, se possibile.Test di unità in SQL Server Management Studio

Quindi, ad esempio, quando scrivo DDL per creare funzioni complesse e cosa no, mi piacerebbe avere un modo per includere un test di unità che (in caso di errore) potrebbe effettivamente far sì che il pannello di output visualizzi un messaggio di errore al momento dell'esecuzione. (. Questo sarebbe analogo a "rompere il costruire" in un ambiente di programmazione normale)

Attualmente, quando scrivo una funzione che è sintatticamente corretto, poi ha colpito F5 per eseguirlo, il messaggio di output è:

Command(s) completed successfully. 

Quello che sto cercando è un semplice trucco SQL per simulare i casi di test di luce rossa/verde di base. Quindi scriverei una serie di test-statement che passerebbero solo se la mia funzione definita dall'utente funzionasse come previsto. In caso contrario, un messaggio di errore verrà visualizzato, come ad esempio:

Msg 207, Level 16, State 1, Line 2 
Invalid statement. 

che mi permettesse di passare immediatamente alla prova fallire e vedere che cosa ho fatto di sbagliato.

Non mi aspetto che ci sia qualcosa di "built-in" per questo, ma c'è un modo in cui posso "fingere"?

Aggiornamento: Ho appena appreso che puoi throw exceptions in SS2012, che sono sicuro che avrei potuto usare per questo scopo, ma purtroppo mi sono bloccato con SS2008 per ora. C'è qualcosa di paragonabile in SS2008?

+0

Aggiornamento: mi sono appena imbattuto in questa utile scrittura: ["Introduzione a Test Driven Design in SQL Server"] (http://www.sqlmag.com/print/sql-server/test-driven-design-sql -server-142881) – kmote

risposta

6

Questi sono i 2 quadri Posso consigliare

T.S.T.

http://tst.codeplex.com/

Testing codice SQL Server con TST

http://www.infoq.com/articles/tst-sql-server

tSQLt

http://tsqlt.org/

test SQL (corridore per tSQLt)

http://www.red-gate.com/products/sql-development/sql-test/

Update 1

Leggendo la tua risposta forse si trova la seguente discarica utile.

TRY CATCH è stato introdotto con SQL Server 2005 (e per questo motivo non si dovrebbe mai guardare a qualcosa di più vecchio del 2005). È possibile (ri) generare un'eccezione utilizzando una stored procedure menzionata nel mio dump, incluso il numero di riga. In SQL Server 2012 (finalmente!) Hanno introdotto il lancio mentre si menziona la creazione di Tsql in un linguaggio solido dopo 14 anni.

Quindi, ecco la mia discarica, ho bisogno di ripulirlo un giorno così è più copia incolla amichevole.

SET XACT_ABORT ON 
SET CONCAT_NULL_YIELDS_NULL OFF 

DECLARE @message varchar (max) 
DECLARE @who varchar (255) 
set @who = OBJECT_NAME(@@PROCID) -- name of the currently executing sproc 

BEGIN TRY 

-- ====================================================================================== 
SET @message = 'HELLO' 
EXEC Log @who, @message 

     .... 

-- ====================================================================================== 
SET @message = 'GOODBYE' 
EXEC Log @who, @message 

END TRY 

BEGIN CATCH 


     -- ====================================================================================== 
--If an error generated in a TRY block causes the state of the current transaction to be invalidated, the transaction is classified as an uncommittable transaction. 
--An error that ordinarily ends a transaction outside a TRY block causes a transaction to enter an uncommittable state when the error occurs inside a TRY block. 
-- http://msdn.microsoft.com/en-us/library/ms175976.aspx 
     if XACT_STATE() = -1 rollback; 

    -- ====================================================================================== 
SET @message = 'Rolling Back transaction if present' 
EXEC Log @who, @message 

    -- Its important to rollback the transaction at the very start of the catch. 
-- Otherwise the records that are written to the log will also be roll backed. 

IF @@TRANCOUNT > 0 
BEGIN 
ROLLBACK TRAN 
END 

-- ====================================================================================== 
SET @message = 'Error Occured ' 
set @message = @message + ' ERROR_NUMBER() : ' + cast(ERROR_NUMBER() as varchar(max)) 
set @message = @message + ' ERROR_SEVERITY() : ' + cast(ERROR_SEVERITY() as varchar(max)) 
set @message = @message + ' ERROR_STATE() : ' + cast(ERROR_STATE() as varchar(max)) 
set @message = @message + ' ERROR_PROCEDURE() : ' +cast(ERROR_PROCEDURE() as varchar(max)) 
set @message = @message + ' ERROR_LINE() : ' + cast(ERROR_LINE() as varchar(max)) 
set @message = @message + ' ERROR_MESSAGE() : ' + cast(ERROR_MESSAGE() as varchar(max)) 

EXEC Log @who, @message 

    exec usp_RethrowError 


END CATCH 


Error logging sproc and table 

CREATE PROCEDURE [dbo].[Log] 
(
@who varchar(255), 
@message varchar(max) 
) 
AS 

SET XACT_ABORT ON 
SET CONCAT_NULL_YIELDS_NULL OFF 

INSERT INTO [ApplicationLog] 
(
[Date], 
[Level], 
[Logger], 
[Host], 
[Message] 
) 
VALUES 
(
getDate(), 
'INFO', 
@who, 
'dummy', 
@message 
) 

CREATE TABLE [dbo].[ApplicationLog] (
[Id]   [int] IDENTITY(1, 1) NOT NULL, 
[Date]   [datetime] NOT NULL, 
[Thread]  [varchar](255) NULL, 
[Level]   [varchar](50) NOT NULL, 
[Logger]  [varchar](255) NOT NULL, 
[Host]   [varchar](50) NOT NULL, 
[Message]  [varchar](max) NOT NULL, 
[Exception]  [varchar](max) NULL 
) 


Rethrow an exception 

ALTER PROCEDURE [dbo].[usp_RethrowError] 
-- BOL contains a good example of that, there is a stored procedure called usp_RethrowError 

AS -- Return if there is no error information to retrieve. 

SET XACT_ABORT ON 
SET CONCAT_NULL_YIELDS_NULL OFF 

IF ERROR_NUMBER() IS NULL 
    RETURN ; 

DECLARE @ErrorMessage NVARCHAR(4000), 
    @ErrorNumber INT, 
    @ErrorSeverity INT, 
    @ErrorState INT, 
    @ErrorLine INT, 
    @ErrorProcedure NVARCHAR(200) ; 

    -- Assign variables to error-handling functions that 
    -- capture information for RAISERROR. 
SELECT @ErrorNumber = ERROR_NUMBER(), @ErrorSeverity = ERROR_SEVERITY(), 
     @ErrorState = ERROR_STATE(), @ErrorLine = ERROR_LINE(), 
     @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ; 

    -- Building the message string that will contain original 
    -- error information. 
SELECT @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 
     'Message: ' + ERROR_MESSAGE() ; 

    -- Raise an error: msg_str parameter of RAISERROR will contain 
    -- the original error information. 
RAISERROR (@ErrorMessage, @ErrorSeverity, 1, @ErrorNumber, -- parameter: original error number. 
    @ErrorSeverity, -- parameter: original error severity. 
    @ErrorState, -- parameter: original error state. 
    @ErrorProcedure, -- parameter: original error procedure name. 
    @ErrorLine-- parameter: original error line number. 
     ) ; 
+0

Quando ho posto questa domanda per la prima volta, stavo solo cercando alcuni "one liners" che potrebbero portare a termine il mio compito dichiarato, piuttosto che i framework completi. Ma questi suggerimenti sono fantastici - dovrò esplorarli. Grazie! – kmote

+0

Sono uno sviluppatore C# e quasi sempre faccio la mia logica in quella lingua, così posso testare l'unità. Ma quando si lavora con 100 milioni di righe di transazione sql può fare la differenza tra un'ora di elaborazione o 12. È bene che queste strutture esistano anche se fino ad ora mi sono basato sul mio mini framework fino ad ora. Ho giocato con i precedenti 2 e loro hanno finito il lavoro. – buckley

+0

Grazie per l'aggiornamento, che mi ha portato alla descrizione originale di "usp_RethrowError" in [BOL] (http://msdn.microsoft.com/en-us/library/ms179296 (v = sql.105) .aspx). Roba molto interessante! Non sono esattamente sicuro di come potrei usarlo nella mia situazione attuale, ma posso vedere che potrebbe essere estremamente utile in futuro. – kmote

0

Beh, ho trovato una possibile soluzione alla mia domanda: RAISERROR. Questa "opere" in una certa misura (almeno nel modo in cui mi è stato invisioning), permettendomi di costruire test di base come:

IF dbo.myTestedFunction(@parm) != @myExpectedResult 
    RAISERROR('>> Unit Test FAILED! -- %d, 11, 0, @parm) 

E 'eccentrico, ma fa visualizzazione di un messaggio di errore che posso cliccare su saltare alla linea di codice incriminata (che, nel mio caso, è il Test unitario fallito) - anche se con qualche informazione fasulla sulla prima riga.

+0

Ho aggiornato la mia risposta se hai bisogno di (ri) gettare sql> 2005 e vuoi accedere al numero di riga che originariamente causava l'eccezione (in questo caso C# jargon) – buckley