TsqlUnit是一种用来测试Transact-Sql的框架,属于xUnit家族的一员。TSQLUnit是开源项目,可以从LGPL(http://www.opensource.org/licenses/lgpl-license.php)得到许可,也就是说他可以在任何项目中使用,甚至商业程序。想知道如何使用请看”快速入门”。
TSQLUnit由Henrik Ekelund开发。
投稿
请通过开源项目跟踪系统提交错误报告和请求。如果你有兴趣成为一名开发人员,请把你的SoureForge unixName给Henrik Ekelund。如果你改进了相应的过程也请立即把代码发给我们。
快速入门:
下边简单介绍使用TSQLUnit编写和组织测试代码的步骤。
为什么?
我猜测大多数T-SQL开发者是在SQL查询分析器里使用Print语句和一些临时的测试来测试存储过程的。其中一些也用T-SQL调试器检查变量值,分析结果时需要人的判断。他们也是特别的,测试不容易被重复。利用TSQLUnit或者任何其他xUnit框架做测试,不会有这样的缺点。我相信这是几个使用自动化测试的优势。
1.可以不断重复。很多好的自动化测试可以让你有勇气提高代码质量,而不用担心任何中断。提高代码质量经常叫做“重构“
2.测试代码也可以起到文档的作用。他们解释你写的存储过程期待发生出现结果。
3.在写存储过程之前写测试代码可以让你仔细思考将要用到的接口,可以改进设计。
自动化测试是极限编程方法学的基石之一,极限编程试图解决很多传统软件开发中的问题。你可以在http://www.xprogramming.org或者http://www.extremeprogramming.org中获得更多的相关信息。
怎样做?
当测试的时候,下边是你需要做的:
1.创建一个名字前缀为ut加下划线的存储过程,比如ut_testSometing。
2.编写测试代码,测试失败时要调用tsu_failure。
3.执行tsu_runTests,运行你编写的测试代码然后显示测试结果。
下边是个简单的例子,假设你想测试功能为格式化句子开头的第一个单词为大写的,名为capitalize的存储过程。
Create Procedure ut_testCapitalize AS
Begin
Declare @outStr VARCHAR(500)
Exec Capitalize ‘a String’, @outStr OUT
If (ASCII(Left(@outStr, 1)) <> ASCII(‘A’)) or @outStr IS NULL
EXEC tsu_failure ‘Capitalize should make the first character uppercase’
End
除上边测试用例外,建议你写更多的测试capitalize过程的用例。你可以测试当输入null的时候,传入不止一个句子的时候等等很多情况。当你创建很多相似的测试用例,他们经常用同样的代码处理表格和其他输入数据时,你应该建立一个Fixture。
TestSuites
存储过程tsu_runTests缺省运行所有的测试用例。当测试用例变得很多的时候,你希望对相似的用例进行分组,因此他归类更加明显。在面向对象的的xUnit框架中都实现了相同的TestSuit类来维护测试用例。在TSQLUnit中你可以通过给测试类前面加上相同的前缀的的方法来对测试类分组。
假设你有三个测试用例,ut_CapitalizeOneSentence,ut_CapitalizeWithNull和ut_testCalcSalesForAllCustomers。由于前两个相关联,你想把它们放在一个独立的测试组中,以便可以把它从需要长时间运行的第三个用例中独立出来。把前两个测试用例重命名为ut_capitalizeTests_oneSentence与ut_capitalizeTests_withNull,这时就有了一个名为capitalizeTests的测试组。如果你想运行组中所有的测试用例,就执行tsu_runTests 'capitalizeTests'命令。
许多测试都需要准备相当多的后台数据。这个后台被称为 test fixture。Fixture可以在相似的测试用例中共享。这样能够使测试代码简洁清晰。在TSQLUnit中,通过创建一个名为“setup”的特殊的存储过程为测试组添加一个Fixture。测试组中的每个用例执行前都会执行setup这个存储过程。Setup与测试是在一个事务中执行的,执行完后事务回滚,因此你不需要关心测试执行顺序。不用担心前面的测试执行改变了Fixture的值。
创建一个名为ut_capitalizeTests_setup的存储过程为capitalizeTests组增加一个Fixture。
可以通过创建名为teardown的存储过程来明确地清除一些不会自动析构的对象。在这个例子里应当叫做ut_capitalizeTests_teardown。说明Teardown过程有用的一个例子是,如果在setup过程中创建了一个文件,测试执行结束后,因为事务回滚,文件不会被删除,所以必须在teardown过程中手工删除。
这里给出一个比较长的例子说明如何使用setup存储过程。我们想测试Northwind数据库中SalesByCategory这个过程分别在有折扣与无折扣的情况下能否正确的计算出销售额。需要两个测试用例。SalesByCategory中的查询使用了四个表的数据。我们可以用一个fixture来代替需要用到的数据。下面给出过程的伪代码,完整的代码在http://tsqlunit.sourceforge.net/tsqlunit_cookbook_fixture_example.htm。
CREATE PROCEDURE ut_salesbycategory_setup AS
BEGIN
-- 1. Remove foreign key constraints related to for the tables Categories, Products and Orders.
-- This makes it easier to clear the tables and insert testdata.
-- 2. Delete all existing data for the tables Categories, Products and Orders.
-- 3. Insert one row of test data for each table
END
CREATE PROCEDURE ut_salesbycategory_noDiscount AS
BEGIN
-- 1. Create a variable @ok that will hold the result of the test.
-- 2. Clear all data from the table [Order Details].
-- Insert a new row in [Order Details] with UnitPrice=100 and Quantity=10
-- 3. Execute SalesByCategory
-- 4. If the returned TotalPurchase is 1000 (UnitPrice*Quantity), set @ok to 1
-- 5. If @ok is zero, Execute tsu_failure
END
CREATE PROCEDURE ut_salesbycategory_discount AS
BEGIN
-- Do exactly as ut_salesbycategory_noDiscount, but add a discount of 30 percent
-- to the row in [Order Details]. Test that SalesByCategory is 700 (70 percent of 1000).
END
一些建议:
每个测试过程只测试一个特性。
进行比较操作的时候要特别注意表达式为空的情况。上面Ut_salebycategory_noDiscount过程中的@ok变量的Pattern解决了这方面的一些问题。在所有的用例中它都返回失败信息,除非用例执行正确。
当测试用例数量越来越多时重构它们。保证自己理解他们做了什么。
当写测试代码很困难时,说明你应该修改接口的设计了,或者重构系统。
不要在已上线的产品环境中运行测试。即使TSQLUnit能够回滚所有在测试过程中的修改,你仍不能够保证会发生什么。在无法摆脱bug的世界里,需要小心对待这些问题。如果你感觉有危险,那么在运行测试前应该做个备份,或者最好在数据库的复本上运行测试。
版权声明:51testing软件测试网及相关内容提供者拥有51testing.com内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像。51testing软件测试网欢迎与业内同行进行有益的合作和交流,如果有任何有关内容方面的合作事宜,请联系我们。