3

除非设置要测试的代码,否则您不能测试代码是否被普遍接受?

一段假设的代码:

public void QueueOrder(SalesOrder order)
{
   if (order.Date < DateTime.Now-20)
      throw new Exception("Order is too old to be processed");
   ...  
}

有些人会考虑将其重构为:

protected DateTime MinOrderAge;
{
   return DateTime.Now-20;
}

public void QueueOrder(SalesOrder order)
{
   if (order.Date < MinOrderAge)
      throw new Exception("Order is too old to be processed");
   ...
}

注意:你可以想出更复杂的解决方案;涉及IClock接口和工厂。它不影响我的问题。

更改上述代码的问题是代码已更改。代码已更改,而客户并未要求更改。任何改变都需要召开会议和电话会议。所以我处于不测试任何东西更容易的地步。

如果我不愿意/不能做出改变:这会让我无法进行测试吗?

注意:上面的伪代码可能看起来像 C#,但这只是为了它的可读性。问题与语言无关。

注意:假设的代码片段、问题、重构需求和重构是假设的。如果您对我的不满意,您可以插入自己的假设代码示例。

注意:以上假设代码是假设的。与任何代码的任何关系,无论是活的还是死的,纯属巧合。

注意:代码是假设的,但任何答案都不是。这个问题不是主观的:因为我相信有一个答案。


更新:当然,这里的问题是我不能保证上面示例中的更改不会破坏任何东西。当然,我将一段代码重构为一个单独的方法,并且代码在逻辑上是相同的。

但我不能保证添加新的受保护方法不会偏移对象的虚拟方法表,如果这个类在 DLL 中,那么我刚刚引入了访问冲突。

4

7 回答 7

4

答案是肯定的,需要更改一些代码才能使其可测试。

但是可能有很多代码可以在无需更改的情况下进行测试。我会先专注于为这些东西编写测试,然后在其他客户需求给你机会以可测试的方式重构它时为其余的东西编写测试。

于 2010-10-27T13:37:43.297 回答
1

代码可以从一开始就编写成可测试的。如果一开始就没有考虑到可测试性,你仍然可以测试它,你可能会遇到一些困难。

在您的假设代码中,您可以通过创建一个日期远在过去的 SalesOrder 来测试原始代码,或者您可以模拟 DateTime.Now。正如您所展示的那样重构代码对于测试来说更好,但这并不是绝对必要的。

于 2010-10-27T13:36:50.747 回答
1

如果您的代码不是为测试而设计的,那么测试它会更加困难。在您的示例中,您必须覆盖 DateTime.Now 方法,这可能不是一件容易的事。

我您认为向您的代码添加测试几乎没有什么价值,或者不允许更改现有代码,那么您不应该这样做。

但是,如果您相信 TDD,那么您应该编写带有测试的新代码。

于 2010-10-27T13:40:55.037 回答
1

您可以使用 Mock 对象框架对原始示例进行单元测试。在这种情况下,我会多次模拟 SalesOrder 对象,每次配置不同的 Date 值,然后进行测试。这避免了更改任何已发布的代码,并允许您验证有问题的算法,即订单日期不是过去太久。

鉴于您正在处理的依赖关系以及您可以使用的语言功能,为了更好地全面了解可能发生的事情,我建议使用旧代码有效工作

于 2010-10-27T17:01:41.383 回答
0

这在一些动态语言中很容易实现。例如,即使 SUT(被测系统)将其用作隐式依赖项,我也可以在 import/using 语句中挂钩并用存根替换实际依赖项。或者我可以重新定义那些符号(类、方法、函数等)。我不是说这是要走的路。东西应该重构,但写一些特性测试更容易。

于 2010-10-27T13:38:16.290 回答
0

这种代码的问题总是,它正在创建并依赖于许多静态类、框架类型等......

为所有这些对象“注入”假货的一个非常好的解决方案是 Typemock Isolator(它是商业的,但值得每一分钱)。所以是的,您当然可以测试遗留代码,这些代码是在没有考虑可测试性的情况下编写的。我已经用 Typemock 完成了一个大项目,并且取得了非常好的结果。

除了 Typemock,您可以使用免费的 MS Moles 框架,它的功能基本相同。只是它有一个非常不直观的 API,并且更难学习和使用。

HTH。
托马斯

于 2010-10-27T13:43:16.723 回答
0

Mockito + PowerMock 用于 Mockito。

您将能够测试几乎所有内容,而无需大幅更改您的代码。但是需要一些二传手来注入模拟。

于 2010-10-29T15:54:40.787 回答