#sql-server
Вопрос:
Как и во многих компаниях, которым требуется, чтобы весь доступ осуществлялся через хранимые процедуры, у нас, похоже, много бизнес-логики заперто в sprocs. Эти вещи просто трудно проверить, и некоторые из них уже давно стали глупыми. Есть ли у кого-нибудь набор лучших практик, которые могут немного облегчить уверенное тестирование этих вещей?
В настоящее время мы поддерживаем около 30 «проблемных» баз данных, с которыми мы сталкиваемся. Это не всегда особенно хорошо документировано и, безусловно, не автоматизировано.
Ответ №1:
Коллега клянется платформой тестирования TSQLUnit. Возможно, стоит обратить внимание на ваши потребности.
Ответ №2:
У нас был очень тонкий уровень доступа к данным, который в основном состоял из хранимых процедур, похожих на методы C#. Затем наш набор тестов NUnit был настроен/демонтирован для создания/отката транзакции и методов тестирования, которые вызывались в DAL. Ничего особенного, и оказалось, что его проще поддерживать, чем набор тестов TSQLUnit.
Комментарии:
1. Этот метод выглядит простым в настройке, но запускаете ли вы sprocs последовательно? Это может вызвать некоторые проблемы с их параллельным запуском.
Ответ №3:
Не уверен, что это то, что вы ищете, но поскольку вы используете SQL Server: я обнаружил, что LINQ-отличный инструмент для тестирования хранимых процессов. Вы можете просто перетащить хранимые процедуры на диаграмму DBML, а затем вызвать их в качестве методов в своем datacontext. Лучше, чем настройка соединений ADO и т. Д. Для тестовой проводки. Например, если вы настроили тестовый проект в Visual Studio, вы можете просто протестировать свои процедуры, такие как методы, на другом объекте. Если ваши сохраненные процедуры возвращают результирующие наборы, я думаю, что LINQ переведет это в анонимные переменные, к которым вы сможете получить доступ через IEnumerable или IQueryable (кто-нибудь, пожалуйста, проверьте это). Но если вы возвращаете только коды возврата, это должен быть быстрый и довольно простой способ.
Комментарии:
1. Читатели: Обратите внимание, что это относится к LINQ to SQL.
Ответ №4:
Я заметил, что ваш пост был помечен как SQLServer. Если это так, то вам следует ознакомиться с выпуском Team для специалистов по базам данных, который является частью Visual Studio. Вот несколько статей:
- Учебник, который я написал о создании хранимых процессов с помощью DBPro
- статья в журнале MSDN, которая более подробно
- DbFit, платформа, которая интегрируется с FIT и Fitnesse для функционального тестирования баз данных
Последний на самом деле является кросс-БД платформой, в то время как DBPro на данный момент является исключительно SQL Server.
Комментарии:
1. ссылка на
MSDN magazine article
это по состоянию на июнь 2021 года.
Ответ №5:
Один из методов, который я использовал, — это написать «временный» модульный тест для рефакторинга определенной хранимой процедуры. Вы сохраняете данные из набора запросов из базы данных и сохраняете их там, где модульный тест может их получить.
Затем произведите рефакторинг вашего программного обеспечения. Возвращаемые данные должны быть одинаковыми и могут быть сопоставлены непосредственно с сохраненными данными автоматически или вручную.
Альтернативой является параллельный запуск двух хранимых процедур и сравнение наборов результатов.
Это особенно хорошо работает для хранимых процедур только для выбора, но обновления, вставки и удаления являются более сложными.
Я использовал этот метод, чтобы привести код в состояние, когда он более восприимчив к модульному тестированию, или проще, или и то, и другое.
Ответ №6:
Попробуйте TST. Вы можете скачать и установить его по адресу: http://tst.codeplex.com/
Ответ №7:
Это кажется ужасной политикой. Возможно, вы можете написать хранимую процедуру, которая выполняет SQL, и начать переводить свой код для выполнения там.
В любом случае, я бы проверил вызов хранимых процедур с помощью традиционной платформы автоматизации. Как шлюз между приложением и данными, они должны обрабатываться как интеграционные тесты, а не как чистые модульные тесты. Тем не менее, вы можете использовать платформу модульного тестирования на основе xUnit для их управления. Пока ваши тесты имеют доступ к запуску SQL в базе данных, возможно, с помощью метода, о котором я упоминал ранее, вы сможете утверждать, что были внесены правильные изменения.
Одна из проблем заключается в том, что вы указываете, что они становятся длительными. Я бы рекомендовал разбить их на подпрограммы и сделать их как можно меньше. Это облегчает тестирование и обслуживание.
Комментарии:
1. Политика существует, потому что в свое время весь SQL был построен и выполнен на среднем уровне, а иногда и на переднем. Как и во многих других местах, люди иногда доводят коррекцию до крайности. Вы правы в том, что вопросы становятся слишком длинными, чтобы сделать хороший рефакторинг, хотя мне нужны тесты.
Ответ №8:
Вот мой низкотехнологичный, быстрый способ просто хранить примеры входных данных, удобно расположенных в 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
--Отображение Доказательств Модульного Тестирования
/*
выбирать
@EmployeeID как EmployeeID
,@SuckupPoints как SuckupPoints
,@Метка времени как метка времени
*/
--==========================================================================
--После редактирования для низкотехнологичного, негосударственного изменения "модульного" вызова теста
--==========================================================================
--Примеры Входных данных
ОБЪЯВИТЕ @SuckupPloyId int
ОБЪЯВИТЕ @SuckupIdentityRecordId int
УСТАНОВИТЬ @SuckupPloyId = 3
/*
-- =============================================
-- Автор: 6еордж Джетсон
-- Дата создания: 01/02/3000
-- Описание: Подлизывается к боссу
-- =============================================
СОЗДАЙТЕ ПРОЦЕДУРУ [dbo].[uspBrownNoseMrSpacely]
@SuckupPloyId int
,@SuckupIdentityRecordId int ВЫВОД
КАК
НАЧАТЬ
*/
ОБЪЯВИТЬ @EmployeeID int
ОБЪЯВИТЬ @SuckupPoints int
ОБЪЯВИТЬ @DateTimeStamp дата и время
УСТАНОВИТЕ @EmployeeID = dbo.svfGetEmployeeId('6eorge Jetson')
УСТАНОВИТЕ @SuckupPoints = dbo.svfGetSuckupPoints(@SuckupPloyId)
УСТАНОВИТЕ @DateTimeStamp = getdate()
--Заявление об изменении состояния данных теперь закомментировано, чтобы предотвратить изменение состояния данных
-- ВСТАВИТЬ В [dbo].[tblSuckupPointsEarned]([EmployeeID], [SuckupPoints], [Метка времени] )
-- ЗНАЧЕНИЯ (@EmployeeID, @SuckupPoints, @Отметка времени)
УСТАНОВИТЕ @SuckupIdentityRecordId = @@Идентификатор
--КОНЕЦ-Нужно также прокомментировать вопрос "КОНЕЦ"
--Отображение Доказательств Модульного Тестирования
выбирать
@EmployeeID как EmployeeID
,@SuckupPoints как SuckupPoints
,@Метка времени как метка времени
Это работает еще лучше для udfs, так как нет необходимости беспокоиться об изменении состояния. Ясно, что я бы не рекомендовал это вместо системы тестирования, но если я буду придерживаться этой простой дисциплины, требующей затрат секунд, то
Утверждайте, что мой sproc управляемого размера проходит, по крайней мере, простой «модульный тест».
перед выполнением ПРОЦЕДУРЫ СОЗДАНИЯ я обнаружил, что совершаю меньше ошибок (вероятно, из-за большей дисциплины, чем сам тест).