Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 可以对非';t最初设计要测试,而不更改任何代码?_Unit Testing_Language Agnostic_Regression - Fatal编程技术网

Unit testing 可以对非';t最初设计要测试,而不更改任何代码?

Unit testing 可以对非';t最初设计要测试,而不更改任何代码?,unit-testing,language-agnostic,regression,Unit Testing,Language Agnostic,Regression,除非代码设置为要测试,否则您不能测试代码,这是否已被普遍接受 假设的代码位: public void QueueOrder(SalesOrder order) { if (order.Date < DateTime.Now-20) throw new Exception("Order is too old to be processed"); ... } public void QueueOrder(销售订单) { if(order.Date

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

假设的代码位:

public void QueueOrder(SalesOrder order)
{
   if (order.Date < DateTime.Now-20)
      throw new Exception("Order is too old to be processed");
   ...  
}
public void QueueOrder(销售订单)
{
if(order.Date
有些人会考虑将其重构为:

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");
   ...
}
受保护的日期时间最小值;
{
return DateTime.Now-20;
}
公共无效队列订单(销售订单订单)
{
如果(订单日期<最小订单日期)
抛出新异常(“订单太旧,无法处理”);
...
}
注意:你可以想出更复杂的解决方案;涉及
IClock
接口和工厂。这不影响我的问题

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

如果我不愿意/无法进行更改:是否会导致我无法执行测试

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

注意:假设的代码片段、问题、重构需求和重构都是假设的。如果你不喜欢我的话,你可以插入你自己假设的代码样本

注:上述假设代码为假设代码。与任何代码的任何关系,无论是生的还是死的,都纯粹是巧合

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


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


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

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


在假设的代码中,您可以通过创建日期远在过去的SalesOrder来测试原始代码,也可以模拟DateTime.Now。按照您所展示的方式重构代码对于测试来说更好,但这不是绝对必要的。

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


但是可能有很多代码可以在不必修改的情况下进行测试。我将首先集中精力为这些东西编写测试,然后在其他客户需求给您机会以可测试的方式对其进行重构时为其余的东西编写测试。

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

如果您的代码不是为测试而设计的,那么测试它就更难了。在您的示例中,您必须重写DateTime.Now方法,这可能不是一件容易的任务

如果您认为在代码中添加测试没有什么价值,或者不允许更改现有代码,那么您不应该这样做


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

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

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

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

HTH.

Thomas

您可以使用模拟对象框架对原始示例进行单元测试。在本例中,我将多次模拟SalesOrder对象,每次配置不同的日期值,然后进行测试。这避免了更改任何附带的代码,并允许您验证有问题的算法,即订单日期不太远


为了更好地全面了解您正在处理的依赖关系以及您可以使用的语言特性,我建议您这样做

Mockito+PowerMock用于Mockito


您将能够测试几乎所有内容,而无需大幅更改代码。但是需要一些setter来注入mock。

您可以对任何代码进行单元测试。有些课程比其他课程更难测试。例如,servlet类比POJO更难进行单元测试,因为servlet类比POJO依赖更多的基础设施,而重构正是我们开始遇到麻烦的地方(@Ian-这被称为“技术债务”。如果你试图向客户解释这个概念,但他们不买,那么他们将不得不处理稳步增加的维护和更改请求成本,以及稳步降低的稳定性和性能。