Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.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
C# 有人能解释一下吗;假装成功,直到成功。”;测试驱动开发中的方法?_C#_.net_Unit Testing_Tdd_Nunit - Fatal编程技术网

C# 有人能解释一下吗;假装成功,直到成功。”;测试驱动开发中的方法?

C# 有人能解释一下吗;假装成功,直到成功。”;测试驱动开发中的方法?,c#,.net,unit-testing,tdd,nunit,C#,.net,Unit Testing,Tdd,Nunit,我有一个问题,当你采取“伪造它直到你成功”的TDD方法时,我无法理解代码的演变 好的,您伪造了它,假设您返回了一个常量,因此中断的测试在开始时是绿色的。然后重新分解代码。然后你运行同样的测试,很明显,它会通过,因为你伪造了它 但是,如果考试通过了,你怎么能相信呢,尤其是当你知道你是伪造的时候 如何用真实代码重构来重构伪造的测试,使其仍然可靠 谢谢您首先创建了一个单元测试来测试不存在的新功能 现在,您对一个不存在的方法进行了单元测试。然后创建一个什么都不做的方法,单元测试就会编译,当然会失败 然后

我有一个问题,当你采取“伪造它直到你成功”的TDD方法时,我无法理解代码的演变

好的,您伪造了它,假设您返回了一个常量,因此中断的测试在开始时是绿色的。然后重新分解代码。然后你运行同样的测试,很明显,它会通过,因为你伪造了它

但是,如果考试通过了,你怎么能相信呢,尤其是当你知道你是伪造的时候

如何用真实代码重构来重构伪造的测试,使其仍然可靠


谢谢

您首先创建了一个单元测试来测试不存在的新功能

现在,您对一个不存在的方法进行了单元测试。然后创建一个什么都不做的方法,单元测试就会编译,当然会失败

然后继续构建方法、底层功能等,直到单元测试成功

这是(某种)测试驱动的开发

您应该能够相信这一点的原因是,您应该进行单元测试,以便它能够实际测试您的功能。当然,如果它只是返回一个常量,而你只是对它进行测试,那么你就有问题了。但是,您的单元测试还没有完成


单元测试(理论上)应该测试每一行。如果你已经做到了,这应该可以了。

简单的回答是:写更多的测试

如果该方法返回一个常量(当它应该计算某些内容时),只需添加一个具有不同结果的条件测试。那么,假设你有以下几点:

@Test
public void testLength()
{
    final int result = objectUnderTest.myLength("hello");
    assertEquals(5, result);
}
myLength
被实现为
return 5
,然后您编写了一个类似的(附加)测试,但通过了
“foobar”
,并断言输出为6


当您编写测试时,您应该尽量对实现怀恨在心,并尝试编写一些暴露其缺点的东西。当你在编写代码时,我认为你应该非常放任,只需做很少的事情就可以使那些讨厌的测试变成绿色。

这可能是指使用模拟/存根/赝品的做法,你的被测系统/类与之合作

在这个场景中,您“伪造”了协作者,而不是您正在测试的东西,因为您没有该协作者接口的实现


因此,你假装它,直到你“成功”,这意味着你在一个具体的类中实现它。

假装它,直到你写下最简单的东西来通过你当前的测试。通常,当您为一个新特性编写了一个测试用例时,最简单的方法就是返回一个常量。当简单的东西满足你的测试时,那是因为你(还)没有足够的测试。因此,请编写另一个测试,正如@andrzejdoyle所说。现在,您正在开发的功能需要一些逻辑。也许这次最简单的事情就是编写非常基本的if-else逻辑来处理两个测试用例。你知道你在假装,所以你知道你还没做完。当编写实际代码来解决问题变得比扩展伪代码以覆盖另一个测试用例更简单时,您就是这么做的。您已经有足够的测试用例来确保您正确地编写了它。

在TDD中,所有需求都表示为测试。如果你伪造了一些东西,并且所有的测试都通过了,你的要求就满足了。如果这没有给您预期的行为,那么您没有将所有需求表示为测试


如果你继续在这一点上伪造东西,你最终会注意到最简单的解决办法是实际解决问题。

当你重构代码时,你正在从返回一个常量值切换到返回一个以派生/计算的变量表示的表达式

假设测试在第一次编写时是正确的,那么它对于新重构的实现仍然有效,并且不必重构


理解伪造它背后的动机很重要:这类似于先编写断言,除了生产代码。它让您进入绿色,让您能够在通过测试的同时,以最简单的方式将假表达式转换为有效表达式。当实施不明显时,首先要尝试,在您放弃并切换到三角测量之前。

FWIW如果您采用此策略,我强烈建议您使用开发人员生产力工具,如Jetbrains Resharper,因为它将大大加快您的能力。从方法返回的单个常量从技术上讲是使测试成功的最简单方法。然而,对于任何方法,您都很可能会有多个确证测试,并且需要一个常数才能全部通过。单元测试不应该测试每一行。具有故障条件的方法将仅针对该条件进行测试,并针对每个附加成功/故障条件进行附加测试。因此,即使在理论上,很少有测试会测试每一行。我所说的“每一行”是指代码覆盖率。我知道你的意思,但我认为所有这些术语都是相对的,因为100%的代码覆盖率在技术上意味着每一行。当然,不可能检查代码中是否存在每一行代码,但是您正在测试您希望存在的代码是否存在。将“test”更改为“tests”:@PietervanGinkel代码覆盖率有多种度量标准,您指的是语句覆盖率。100%的代码覆盖率并不意味着每一行。这个答案是对TDD的一种描述,但它并没有触及TDD中使用的“在你成功之前假装成功”策略。这听起来是一个合理的答案。不仅您可能没有实现collaborator,在测试环境中使用它甚至可能有害。想一想与re互动