2010-10-19 50 views
5

在经历了数月的挫折之后,以及在以前的开发者的巫毒娃娃中插入针的时间之后,我决定最好尝试重构遗留代码。UnitTesting一个返回一个复杂数据集的类

我已经订购了Micheal Feather's book,我进入了Fowler's refactoring,我用DUnit做了一些示例项目。

所以,即使我不掌握这个主题,我觉得是时候采取行动,并将一些想法付诸实践。

我工作的代码中几乎有100%的商业逻辑被困在用户界面中,而且都是程序编程(有一些例外)。该应用程序开始如同快速&脏,并继续如此。

现在编写所有应用程序的测试对我而言是一个没有意义的任务,但我想尝试单元测试我需要重构的东西。

一个大的“TForm业务逻辑类”所做的一项复杂任务是读取数据库数据,进行一些计算并填充调度程序组件。我想删除阅读数据库数据和计算部分,并分配给一个新的类这个任务。当然,这是一种改进当前设计的方法,它不是从头开始的最佳方式,但我想这样做,因为这个新类返回的数据在其他方面也很有用,例如现在我有人要求发送调度程序数据的电子邮件通知。

所以为了避免大量的复制和粘贴操作,我需要新的类。

现在调度程序从一个巨大的数据集(大小和数量的字段)中填充,可能第一个重构步骤可能是从新类中获取数据集。但是,将来我最好使用一个新的类(比如TSchedulerData或其他一些不太需要调度器的名字)来管理数据,而不是有一个数据集,因为我可以有一个TSchedulerData对象。

由于重构发生在小步骤和测试需要更好地重构我有点困惑如何继续。

以下几点是我不明白:

1)如何测试一个复杂的数据集?我应该运行工作应用程序,将一个结果集保存到xml中,然后在使用包含该xml数据的TClientDataSet的地方编写测试?

2)我有多少要关心TSchedulerData?我的意思是我不是100%确定我会使用TSchedulerData,可能我会坚持使用数据集,无论如何,创建将在2周内丢弃的复杂测试对DUnitNewbee没有吸引力。无论如何,可能这是它的工作原理。我无法想象没有测试的情况下我会面对的错误数量。

最后说明:我知道有人认为从头开始重写是一个更好的选择,但这不是一个选项。 “该应用程序非常庞大,今天已售出,今天还需要新功能才能停止营业”。这就是我所知道的,无论如何,重构可以挽救我的生命并延长应用程序的生命。

回答

2

您的最终目标是将用户界面,数据存储和业务逻辑分为不同的层。

使用自动测试框架测试UI非常困难。您最终希望尽可能多地从UI中分离业务逻辑。这可以使用各种模型/视图/ *模式之一来完成。我更喜欢MVP被动视图,它试图使UI成为一个界面。如果您使用的是数据集MVP,则监督控制器可能更适合。数据存储需要有自己的一套测试,但是这些测试与单元测试不同(尽管你可以使用相同的单元测试框架),而且通常只有更少的测试。你可以逃避这一点,因为大部分繁重的工作都是由第三方数据组件和dbms(在你的情况下是T * Dataset)完成的。这些是集成测试。基本上确保你的代码与供应商的代码很好。如果您在数据库中定义了任何存储过程,也是需要的。它们比单元测试慢得多,不需要经常运行。

业务逻辑就是你最想测试的东西。每个计算,循环或分支应该至少有一个测试(更多是可取的)。在传统代码中,这种逻辑经常直接触及UI和数据库,并在一个函数中执行多项操作。这里提取方法是你的朋友。好的地方提取方法是:

for I:=0 to List.Count - 1 do 
begin 
    //HERE 
end; 

if /*HERE if its a complex condition*/ then 
begin 
    //HERE 
end 
else 
begin 
    //HERE 
end 

Answer := Var1/Var2 + Var1 * Var3; //HERE 

当你遇到这些提取点之一

  1. 决定你想要什么样的方法签名看起来像你的新方法:方法的名称,参数,返回值。
  2. 编写一个测试调用它并检查预期结果。
  3. 提取该方法。

如果一切顺利,您将拥有至少一次通过单元测试的新提取方法。

德尔福的内置提取方法不给你任何方式来调整签名,所以如果这是你自己的选择,你将不得不做出并在提取后修复它。您还需要公开新方法,以便您的测试可以访问它。有些人不愿意公开私人公用事业方法,但在这个早期阶段,你没有什么选择。一旦你取得了足够的进步,你就会开始看到你提取的一些实用方法属于他们自己的类(在这种情况下,他们必须公开),而其他的可以被私有/保护和间接测试通过测试依赖于它们的方法。

随着您的测试套件的增长,您需要在每次更改后运行它们,以确保您的最新更改没有在其他地方发生。

本主题太大而无法完全覆盖答案。你会发现你的问题绝大多数都是在这本书到达时才报道的。

2

我会说在接近婴儿的步骤接近它。步骤#1:应该总是在你的入侵区域进行一些测试。TForm - 回归测试又名安全网。在你的情况下,感觉应用程序正在做什么。从我读到的,它似乎是一个数据转换器。因此,花时间去了解所有输入数据和相应输出计划的组合(或者最重要的是,如果不可行)。把它们写成测试。确保所有测试都通过。

步骤#2:现在尝试你的重构。在回归网络的安全性下,将代码块移入内聚类等。

测试复杂的数据集 - 测试文件转储应该是最后的手段。但在这种情况下,它似乎是一个简单的选择开始。也许你可以用它自己的Equals()实现将它变成一流的域对象TSchedule。 推迟设计决策/更改,直到您在修改区域附近有一个可靠的回归测试套件。

+0

好的,谢谢。我所担心的是编写测试需要花费很多时间,因为数据很复杂。文件转储很复杂,所以这是我第一次真正的单元测试尝试,我担心会失去一周的时间,并以不成功的测试结束。无论如何,我没有其他地方可以开始,我的意思是,我需要改变这个代码,所以我应该从这里开始。 – LaBracca 2010-10-19 09:27:35

相关问题