Ответ 1
Коллега клянется структурой тестирования TSQLUnit. Может быть стоит посмотреть на ваши потребности.
Как и многие компании, которым требуется весь доступ через хранимые процедуры, у нас, похоже, есть много бизнес-логики, запертой в sprocs. Эти вещи просто трудно проверить, а некоторые из них стали глупыми. Кто-нибудь есть набор лучших практик, которые могут сделать его немного легче уверенно проверить эти вещи?
В настоящее время мы поддерживаем 30 или около того проблемных баз данных, с которыми мы сталкиваемся. Это не всегда особенно хорошо документировано и, конечно же, не автоматизировано.
Коллега клянется структурой тестирования TSQLUnit. Может быть стоит посмотреть на ваши потребности.
У нас был очень тонкий уровень доступа к данным, который в основном закрывал хранимые процедуры, чтобы выглядеть как методы С#. В нашем тестовом наборе NUnit был создан SetUp/TearDown для создания/отката транзакций и методов тестирования, вызванных в DAL. Ничего необычного, и оказалось, что его легче поддерживать, чем тестовый набор TSQLUnit.
Не уверен, что это то, что вы ищете, но так как вы используете SQL Server: я нашел, что LINQ является отличным инструментом тестирования хранимых procs. Вы можете просто перетащить хранимые процедуры на диаграмму DBML, а затем вызвать их как методы в вашем datacontext. Удаляет настройки соединений ADO и т.д. Для тестового жгута. Если вы настроили тестовый проект в Visual Studio, например, вы можете просто протестировать свои процедуры, например методы на другом объекте. Если ваши сохраненные procs возвращают результирующие наборы, я думаю, что LINQ переведет это в анонимные переменные, которые вы сможете получить через IEnumerable или IQueryable (кто-то pls проверяет это). Но если вы возвращаете только коды возврата, это должно быть быстрым и довольно простым способом.
Я заметил, что ваше сообщение было помечено как SqlServer. В этом случае вы должны посмотреть Team Edition для специалистов по базам данных, который является частью Visual Studio. Вот несколько статей:
Последняя является фактически платформой кросс-DB, в то время как DBPro - это только SQL Server.
Один из методов, который я использовал, - это написать "временный" unit test для рефакторинга конкретной хранимой процедуры. Вы сохраняете данные из набора запросов из базы данных и сохраняете их где-нибудь, где может быть unit test.
Затем реорганизуйте свой инвентарь. Возвращенные данные должны быть одинаковыми и могут сравниваться непосредственно с сохраненными данными автоматически или вручную.
Альтернативой является одновременное выполнение двух хранимых процедур и сравнение наборов результатов.
Это особенно хорошо работает для хранимых процедур только для выбора, но обновления, вставки и удаления более сложны.
Я использовал этот метод, чтобы получить код в состоянии, где он более восприимчив к единичному тестированию, или более простому, или и тому и другому.
Попробуйте TST. Вы можете скачать и установить его из: http://tst.codeplex.com/
Это кажется ужасной политикой. Возможно, вы можете написать хранимую процедуру, которая выполняет SQL и начнет переходить к вашему коду.
В любом случае, я бы протестировал вызов хранимых процедур через традиционную систему автоматизации. В качестве шлюза между приложением и данными они должны обрабатываться как интеграционные тесты, а не чистые модульные тесты. Тем не менее, вы можете использовать инфраструктуру модульного тестирования на основе xUnit, чтобы управлять ими. Пока ваши тесты имеют доступ для запуска SQL к базе данных, возможно, с помощью метода, о котором я упоминал ранее, вы должны быть уверены, что были сделаны правильные изменения.
Одна проблема состоит в том, что вы указываете, что они становятся длинными. Я бы рекомендовал разбить их на подпрограммы и сделать их как можно меньше. Это упрощает тестирование и упрощает обслуживание.
Здесь мой низкотехнологичный, быстрый метод простого хранения примеров, удобно расположенных в 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
Он работает еще лучше для udfs, так как нет никаких изменений состояния, о которых можно беспокоиться. Понятно, что я бы не рекомендовал это вместо тестовой структуры, но если я придерживаюсь этой простой дисциплины в секундах
Подтвердите, что мой sproc с управляемым размером проходит как минимум простой "unit test"
до выполнения CREATE PROCEDURE, я нахожу, что я делаю меньше ошибок (скорее всего, из-за дисциплины больше, чем самого теста).