撰寫單元測試並非一定需要,我從不為了寫單元測試而寫,
但有些情況撰寫單元測試確實有必要,例如複雜權限判斷的核心SP,
因開發人員菜鳥A改了某個user function,導致權限判斷核心SP結果不如預期,
如有多寫一份測試案例來驗證已經知道的結果,上線前先跑過所有測試案例,有時如同救命仙丹。
開發團隊中,人員素質絕對有高有低,有資深有資淺,在這樣環境中,
針對容易出錯的功能撰寫單元測試我覺得有其必要性,
這篇我來介紹如何在SQL Server實現TDD,針對SP、Function、DML…等。
Red-gate推出SQL Test可輕易整合至SSMS,讓在SQL Server中撰寫單元測試很容易,
但我這裡要介紹另一套open source的tSQLt framework。
下載tSQLt並設定環境
1.SQL SERVER啟用CLR
Exec sp_configure 'clr enabled', 1;
RECONFIGURE;
2.資料庫啟用TRUSTWORTHY
alter database RicoTDD set trustworthy on
3.執行tSQLt.class.sql
執行完成後,你可以看到資料庫下多了tSQLt Schema、SP、table、function..等。
到這裡tSQLt環境已經設定完成了,下面我簡單來撰寫單元測試。
User Defined Function
create function UF_AddAmusementTax
(
@amt money
)
returns money
as
begin
return @amt+ (@amt * .09);
end
該function很簡單,計算票價加娛樂稅後返回總金額。
開始撰寫測試案例(我已經知道該function預期結果並了解domain邏輯)
新增test class
exec tSQLt.NewTestClass 'TesRicoTDD'; --新增test class
go
新增test case
if object_id('TesRicoTDD.Test_UF_AddAmusementTax', 'P') is not null
drop proc TesRicoTDD.Test_UF_AddAmusementTax;
go
create proc TesRicoTDD.Test_UF_AddAmusementTax
as
begin
declare @total MONEY
select @total = dbo.UF_AddAmusementTax(30);
exec tSQLt.AssertEquals 32.7, @total; --透過tSQLt.AssertEquals驗證娛樂稅計算結果是否如預期正確
end;
go
exec tSQLt.Run 'TesRicoTDD.Test_UF_AddAmusementTax'; --執行測試
現在我更改錯誤測試案例,看看tSQLt會出現什麼結果
if object_id('TesRicoTDD.Test_UF_AddAmusementTax', 'P') is not null
drop proc TesRicoTDD.Test_UF_AddAmusementTax;
go
create proc TesRicoTDD.Test_UF_AddAmusementTax
as
begin
declare @total MONEY
select @total = dbo.UF_AddAmusementTax(30);
exec tSQLt.AssertEquals 81.7, @total; --透過tSQLt.AssertEquals驗證娛樂稅計算結果是否如預期正確,這裡我輸入錯誤81.7
end;
go
exec tSQLt.Run 'TesRicoTDD.Test_UF_AddAmusementTax'; --執行測試
你現在還覺得在SQL SERVER撰寫單元測試很麻煩嗎?還遙不可及嗎?
後面我還會介紹如何實現TDD for SP、DML、DDL…等。
參考
Getting Started with Test Driven Design in SQL Server
Database unit testing, are we all doing it wrong?
Ten Things I Wish I'd Known When I Started Using tSQLt and SQL Test