技术开发 频道

使用Visual Studio进行测试驱动开发

  让我们添加另外一个测试来检验折扣为0的另一个边界条件。在您的测试屏幕中,点击绿色的加号并且将新测试命名为NinetyNineNinetyNineOrderShouldHaveZeroDiscount。修改脚本,使它调用我们的存储过程,并且修改Test Condition以验证存储过程返回的折扣数值为0:

  设置完毕后重新运行测试,您应该会发现这次运行快了不少,而且两个测试都通过了:

 
 

  现在我们来为下一个折扣级别编写测试。价值在$100.00和$299.99之间的订单会获得2%的折扣。添加一个名为OneHundredDollarOrderShouldHaveTwoPercentDiscount的新测试。现在,我们所期望的数值应该为0.02:

  现在再重新运行测试:

  前两个测试通过了,但是第三个失败了,因为它期望0.02却获得了0.00。我们可以改变存储过程的逻辑使测试通过,但是因为我们已经在数据库中了,那么就建立一个表格来存储这些值吧。右键单击数据库项目并选择Add -> Table,使用如下的定义创建一个OrderDiscounts表:

  CREATE TABLE [dbo].[OrderDiscounts]
       ( low_range float NOT NULL, high_range float NOT NULL, discount_amount float NOT NULL);

  因为我们希望控制测试业务逻辑时所使用的表中的数据,所以我们会创建一段脚本,在运行所有测试之前向数据表中插入合适的数据。在OrderDiscountTests.cs文件中,选择测试对应的下拉列表中的Common Scripts选项:

  请注意下拉列表的旁边有两个选项——Test Initialize和Test Cleanup。我们目前只需要使用Test Initialize来建立数据库。请确认目前选择了Test Initialize并点击“Click here to create”链接,然后输入以下脚本:

  INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (0.00, 99.99, 0.00);
       INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (100.00, 299.99, 0.02);
      INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (300.00, 999.99, 0.04);
      INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (1000.00, 10000000.00, 0.07);

  重新运行测试时,我们会发现一定的延迟,因为目标数据库中正在创建我们的数据表,不过最后一个测试依旧无法通过。现在我们就来把它变为绿灯。现在我们修改一下存储过程,让它从我们刚添加的数据表中获取折扣数量:

  CREATE PROCEDURE [dbo].[sp_calculate_discount_for_order]
       @orderAmount money
       AS
      SELECT discount_amount from OrderDiscounts
      where @orderAmount between low_range and high_range
      RETURN 0;

  重新运行测试:

  变绿了!然而,我们的测试还不可靠。回到我们的某个测试,并为它添加一个条件,确保我们的存储过程只会返回一条记录:

  重新运行测试,它们都通过了吗?

  失败了!不过更奇怪的是失败的原因:

  9条记录?我们看看数据库中究竟发生了什么:


  哇塞,好像我们的测试数据插入太多遍了。这是个非常重要的教训——当我们在操作数据库时,可能会没有意识到数据会始终存在并影响测试。让我们回头修改一下测试脚本来解决这个问题:

  TRUNCATE TABLE OrderDiscounts;
       INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (0.00, 99.99, 0.00);
       INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (100.00, 299.99, 0.02);
       INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (300.00, 999.99, 0.04);
       INSERT INTO OrderDiscounts(low_range, high_range, discount_amount)VALUES (1000.00, 10000000.00, 0.07);

  现在再重新运行以下测试,于是……

  所有的测试都通过了!在我们完成剩余的测试用例之前,可能您还会希望了解一件事情。当订单的价值正好在上限或下限时工作完全正常,但是如果正处在某个级别的上限和下一级别的下限时又会怎么样呢?换句话说,如果某个订单的价值经计算为99.997会发生什么呢?在了解这个状况之前,我们先来设想一下如果这个情况真的出现时该怎么样。我们在OrderDiscoutTests文件里再添加一个名为NinetyNineNinetyNineNineShouldHaveZeroDiscount的测试。当然,您的业务可能会希望换种做法——超过$99.99的数值就被视作下一级别。执行我们的存储过程并添加一个新的Test Condition以确保返回0.00。

  exec sp_calculate_discount_for_order 99.999

  运行我们的测试,通过了吗?

  没有。如果您查看错误信息,就会发现错误的原因是因为没有返回任何记录。我们可以改变插入至表格中的数据,但是如果其他某个人犯了同样的错误呢?根据我们的业务逻辑,我们似乎只需要保留2位小数就可以了,而money类型显得过于精确了一些。那么我们来修改一下存储过程:

  CREATE PROCEDURE [dbo].[sp_calculate_discount_for_order]
      @orderAmount float
      AS
      SELECT discount_amount from OrderDiscounts
     where ROUND(@orderAmount, 2, 1) between low_range and high_range
      RETURN 0;

  重新运行测试:

  绿的彻头彻尾!是时候实现其他的测试用例了,不过这就留给读者作为练习来做吧。

  正如您所看到的,在Team Edition for Database Professionals中,熟悉驱动测试开发的开发人员能够继续使用“红灯——绿灯——重构”的开发方式来编写存储过程。对于那些不进行测试驱动开发的开发人员,也可以利用数据库的离线表现形式,以及单元测试功能来确保数据库内业务逻辑功能实现的正确性。

0
相关文章