2012-06-27 39 views
6

¿Existe alguna manera de crear pruebas unitarias simples para consultas SQL en SSMS? Soy bastante nuevo en T-SQL & SSMS, pero me gustaría tratar de llevar algunos de mis viejos hábitos TDD a este ámbito, si es posible.Pruebas unitarias en SQL Server Management Studio

Entonces, por ejemplo, cuando escribo el DDL para crear funciones complejas y lo que no, me gustaría tener alguna forma de incluir una prueba unitaria que (en caso de falla) haría que el panel de salida mostrara un mensaje de error en la ejecución. (. Esto sería análogo a "romper la acumulación" en un entorno de programación normal)

En la actualidad, cuando escribo una función que es sintácticamente correcta, después haga clic en F5 para ejecutarlo, el mensaje de salida es:

Command(s) completed successfully. 

Lo que estoy buscando es un simple truco SQL para simular casos de prueba básicos de luz roja/luz verde. Así que escribiría una serie de declaraciones de prueba que pasarían solo si mi función definida por el usuario funciona según lo previsto. De lo contrario, se mostrará un mensaje de error, tales como:

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

lo que permitiría que salte inmediatamente a la prueba falla y veo lo que hice mal.

No espero que haya nada "incorporado" para esto, pero ¿hay alguna forma de que pueda "fingirlo"?

Actualización: acabo de aprender que pueda throw exceptions en SS2012, que estoy seguro de que podría utilizar para este propósito, pero por desgracia estoy atascado con SS2008 por ahora. ¿Hay algo comparable en SS2008?

+0

Actualización: Acabo de encontrar este artículo útil: ["Introducción al diseño impulsado por prueba en SQL Server"] (http://www.sqlmag.com/print/sql-server/test-driven-design-sql -server-142881) – kmote

Respuesta

6

Estos son los 2 marcos puedo recomendar

T.S.T.

http://tst.codeplex.com/

probar código SQL Server con TST

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

tSQLt

http://tsqlt.org/

SQL de prueba (corredor de tSQLt)

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

Actualización 1

La lectura de su respuesta tal vez a encontrar el siguiente volcado útil.

TRY CATCH se introdujo con SQL Server 2005 (y por esta razón uno nunca debe mirar algo más antiguo que 2005). Puede (re) lanzar una excepción utilizando un procedimiento almacenado mencionado en mi volcado, incluido el número de línea. En SQL Server 2012 ellos (¡finalmente!) Introdujeron throw, como mencionas, haciendo de Tsql un lenguaje robusto después de 14 años.

Así que aquí está mi volcado, necesito limpiarlo algún día, así que es más fácil copiar y pegar.

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

Cuando le pregunté por primera vez, solo buscaba algunos "diseños únicos" que pudieran cumplir mi tarea declarada, en lugar de marcos completos. Pero estas sugerencias son geniales, tendré que explorarlas. ¡Gracias! – kmote

+0

Soy desarrollador de C# y casi siempre hago mi lógica en ese idioma para que pueda probar la unidad. Pero cuando se trabaja con 100 millones de filas, transact sql puede marcar la diferencia entre una hora de procesamiento o 12. Es bueno que estos frameworks existan, aunque hoy debo confiar en mi propio mini framework hasta ahora. Sin embargo, jugué con los 2 anteriores y ellos hacen el trabajo. – buckley

+0

Gracias por la actualización, que me llevó a la descripción original de 'usp_RethrowError' en [BOL] (http://msdn.microsoft.com/en-us/library/ms179296 (v = sql.105) .aspx). Cosas muy interesantes! No estoy exactamente seguro de cómo podría usarlo en mi situación actual, pero puedo ver que podría ser extremadamente útil en el futuro. – kmote

0

Bueno, he encontrado una posible solución a mi propia pregunta: RAISERROR. Este "obras" en cierta medida (al menos en la forma en que estaba invisioning), lo que permite que construya pruebas básicas como:

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

Es peculiar, pero hace pantalla un mensaje de error que puedo hacer clic en saltar a la línea ofensiva del código (que, en mi caso, es la prueba unitaria fallida), aunque con alguna información falsa en la primera línea.

+0

Actualicé mi respuesta si necesita (re) lanzar en sql> 2005 y desea acceder al número de línea que originalmente causó la excepción (la jerga C# aquí) – buckley

Cuestiones relacionadas