UnitTesting返回复杂数据集的类

LaB*_*cca 5 delphi refactoring unit-testing legacy-code

经过几个月的挫折和在先前开发人员的巫毒娃娃中插入针头所花费的时间后,我决定尝试重构遗留代码.

我已经订购了Micheal Feather的书,我正在进行Fowler的重构,我用DUnit做了一些示例项目.

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

我工作的代码几乎100%都包含在UI中的业务逻辑,而且所有都是过程式编程(除了少数例外).应用程序开始快速而肮脏,并继续这样.

现在为我的所有应用程序编写测试都是毫无意义的任务,但我想尝试对需要重构的东西进行单元测试.

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

因此,为了避免大规模的复制和粘贴操作,我需要新的类.

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

由于重构发生在小步骤并且需要测试以更好地重构我对如何继续进行有点困惑.

我不清楚以下几点:

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

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

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

Ken*_*ran 2

您的最终目标是将 UI、数据存储和业务逻辑分离到不同的层中。

使用自动测试框架测试 UI 非常困难。您最终会希望将尽可能多的业务逻辑与 UI 分离。这可以使用各种模型/视图/* 模式之一来完成。我更喜欢 MVP 被动视图,它试图使 UI 只不过是一个界面。如果您使用数据集 MVP 监督控制器可能更适合。

数据存储需要有自己的测试套件,但这些测试与单元测试不同(尽管您可以使用相同的单元测试框架),并且通常数量较少。您可以摆脱这种情况,因为大部分繁重的工作是由第三方数据组件和 dbms(在您的情况下为 T*Dataset)完成的。这些是集成测试。基本上确保您的代码与供应商的代码兼容。如果您在数据库中定义了任何存储过程,则也需要。它们比单元测试慢得多,并且不需要经常运行。

业务逻辑是您最想测试的。每个计算、循环或分支都应该至少有一个测试(越多越好)。在遗留代码中,此逻辑通常直接接触 UI 和数据库,并在单个函数中执行多项操作。在这里,Extract Method是你的朋友。提取方法的好地方是:

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
Run Code Online (Sandbox Code Playgroud)

当您遇到这些撤离点之一时

  1. 决定您希望新方法的方法签名是什么样子:方法名称、参数、返回值。
  2. 编写一个测试来调用它并检查预期结果。
  3. 提取方法。

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

Delphi 内置的提取方法不提供任何调整签名的方法,因此如果这是您自己的选择,您将不得不在提取后解决它。您还需要公开新方法,以便您的测试可以访问它。有些人不愿公开私有实用程序方法,但在这个早期阶段你别无选择。一旦您取得了足够的进展,您将开始看到您提取的一些实用方法属于它们自己的类(在这种情况下,无论如何它们都必须是公共的),而其他方法可以设为私有/受保护并间接测试通过测试依赖于它们的方法。

随着测试套件的增长,您将希望在每次更改后运行它们,以确保最新的更改不会破坏其他地方的内容。

这个主题太大了,无法在答案中完全涵盖。当这本书到达时,您会发现您的绝大多数问题都得到了解决。