2008-09-29 20 views
20

Al igual que muchas empresas que requieren todo el acceso a través de procedimientos almacenados, parece que tenemos una gran cantidad de lógica de negocios bloqueada en sprocs. Estas cosas son simplemente difíciles de probar, y algunas de ellas se han vuelto absurdas. ¿Alguien por ahí tiene un conjunto de mejores prácticas que pueden hacer que sea un poco más fácil probar estas cosas con confianza?¿Cuál es la mejor manera de probar un procedimiento almacenado?

Actualmente mantenemos unas 30 bases de datos "Problemáticas" con las que nos encontramos. Esto no siempre está especialmente bien documentado y seguro que no está automatizado.

Respuesta

2

No estoy seguro de si esto es lo que está buscando, pero ya que está usando SQL Server: he encontrado que LINQ es una gran prueba de herramienta procs almacenados. Puede simplemente arrastrar los procedimientos almacenados en un diagrama DBML y luego llamarlos como métodos en su contexto de datos. Mejora la configuración de conexiones ADO, etc. para un arnés de prueba. Si configura un proyecto de prueba en Visual Studio, por ejemplo, puede simplemente probar sus procedimientos como métodos en otro objeto. Si tus programas almacenados devuelven conjuntos de resultados, creo que LINQ los traducirá en variables anónimas a las que deberías poder acceder a través de IEnumerable o IQueryable (alguien pls verifica esto). Pero si solo devuelve códigos de retorno, esta debería ser una manera rápida y bastante sencilla.

+0

Lectores: Tenga en cuenta que esto se refiere a LINQ to SQL. –

2

Noté que su publicación fue etiquetada como SqlServer. Si ese es el caso, entonces debería mirar Team Edition para Database Professionals que es parte de Visual Studio. He aquí algunos artículos:

El último es En realidad, la plataforma DB cruzada, mientras que DBPro es únicamente SQL Server por el momento.

1

Parece una política terrible. Tal vez pueda escribir un procedimiento almacenado que ejecute SQL y comience a hacer la transición del código para ejecutarlo allí.

En cualquier caso, probaría llamar a los procedimientos almacenados a través de un marco de automatización tradicional. Como puerta de enlace entre la aplicación y los datos, estos deben manejarse como pruebas de integración, en lugar de pruebas de unidades puras. Sin embargo, puede usar un marco de prueba de unidad basado en xUnit para conducirlos. Siempre que sus pruebas tengan acceso para ejecutar SQL en la base de datos, quizás a través del método que mencioné anteriormente, debería poder afirmar que se realizaron los cambios correctos.

Un desafío es que usted indica que se están volviendo largos. Recomendaría dividirlos en subrutinas y hacerlos lo más pequeños posible. Hace que sea más fácil de probar y más fácil de mantener.

+0

La política existe porque en un momento todos los SQL se crearon y se ejecutaron en el nivel medio y en algún momento en el front-end. Al igual que muchos lugares, las personas llevan la corrección a extremos a veces. Tienes razón en que los sprocs son demasiado largos, para hacer una buena refactorización, aunque necesito pruebas. –

3

Teníamos una capa de acceso a datos muy delgada que básicamente fachalaba los procedimientos almacenados para que parecieran métodos C#. Nuestro conjunto de pruebas NUnit tenía SetUp/TearDown para crear/deshacer una transacción y probar los métodos que llamaban a DAL. Nada lujoso, y resultó ser más fácil de mantener que TSQLUnit test-suite.

1

Aquí es mi baja tecnología, el método de polvo rápido de entradas ejemplo que acabamos de mantener convenientemente situado en el DDL


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

Funciona aún mejor para las UDF ya que no hay cambio de estado que preocuparse. Evidentemente, yo no recomendaría esto en lugar de un marco de pruebas, pero si me quedo con esta simple disciplina segundo cálculo de costos de

Afirmar que mi sproc manejable de tamaño pasa al menos un simple "prueba de unidad"

Antes de ejecutar CREATE PROCEDURE, encuentro que cometo menos errores (probablemente debido a la disciplina más que a la prueba en sí).

1

Un método que he usado es escribir una prueba de unidad 'temporal' para refactorizar un procedimiento almacenado en particular. Guarde los datos de un conjunto de consultas de una base de datos y guárdelos en algún lugar donde pueda obtener una prueba unitaria.

Luego, refactorice su stock de proc. Los datos devueltos deben ser iguales y se pueden comparar directamente con los datos guardados, de forma automática o manual.

Una alternativa es ejecutar los dos procedimientos almacenados en paralelo y comparar los conjuntos de resultados.

Esto funciona especialmente bien para los procedimientos almacenados de solo selección, pero las actualizaciones, las inserciones & son más complejas.

He utilizado este método para llevar el código a un estado en el que sea más susceptible a las pruebas unitarias, o más simple, o ambos.

Cuestiones relacionadas