因此,每当我尝试学习测试驱动的开发时,总会有一些困扰我的地方,我想,对于单元测试和测试驱动的开发过程应该如何“完成”,我肯定缺少一些基本的东西。
好吧,假设你有一个简单的类,叫做计算器。假设您有一个尝试用测试“驱动”的方法。该方法称为"Add“。它应该取两个数字,然后给出这两个数字的和。
假设测试看起来是这样的:
[TestMethod]
public void AddingTwoAndThreeEquals5()
{
var myCalulator = new Calculator();
var result = myCalulator.Add(2, 3);
Assert.AreEqual(5, result);
}
作为一个测试是有意义的,对吧?
假设这是我的实现选择:
public int Add(int a, int b)
{
return 5;
}
这个很管用。考试会通过的。嘿,实现就像实现一样简单--没有任何冗余。你怎么能重构呢?你是“绿色”的,很好走!:)
但这显然是一个可怕的实现选择!它将几乎立即在生产中失败(试想一下用例中的"2“和"2”是“相加”以得到“5”--这个想法!喘气)!如果测试驱动开发只是专注于让测试尽快通过,那么有什么可以防止您像这样“玩”测试呢?当然,这并不是代码测试驱动开发应该产生的质量,但是在哪里可以预期代码会被修正为更“灵活”,因为它显然需要在生产中更好地发挥作用?
难道只需要有足够的测试,让他们在做这样的事情时,立即通过是不可能的吗?这是在签入之前应该与对等方进行代码评审的那类事情吗?开发人员是否只是理性地知道,即使在技术上使测试通过,也不可能通过生产,也就是说,开发人员是否只是用常识来知道什么是和不符合过程的精神,即使他们在技术上让测试进入“绿色”?
这显然是一个极端的例子,因为没有人可能签入这样的代码。但是,测试驱动开发应该如何防止这样的“驱动”代码呢?这是一个概念上的绊脚石,当我承诺学习测试驱动的开发时,我觉得这只是一些基本的东西,我不知道测试驱动开发是什么,也不应该为我们“做”什么。
非常感谢你通过我的问题来支持我!
干杯!:)
发布于 2021-09-21 04:53:29
这个很管用。考试会通过的。嘿,实现就像实现一样简单--没有任何冗余。
啊-但那不是真的,你在这里确实有复制,你需要看到它。
public int Add(int a, int b)
{
return 5;
}
变成了
public int Add(int a, int b)
{
return 2 + 3;
}
变成了
public int Add(int a, int b)
{
assert a == 2;
assert b == 3;
return a + b;
}
现在,复制被删除了,您可以继续进行下一个测试。
实际上,Beck使用“重构”的方式与Fowler的定义有些不同。在Beck的例子中,如果一个更改使测试通过,它就算作一个重构,尽管示例中的行为--您不是--测试--但是可能会发生变化。
因此,我们希望Beck跳过最后一个示例,直接转到:
public int Add(int a, int b)
{
return a + b;
}
我得到的是工作代码,而不是测试代码,所以我的哲学是尽可能少地进行测试,以达到一定程度的自信-- 肯特·贝克,2008年。
现在,今天的情况比这要复杂一些。粗略时间线: Kent (Re)在开始编写极限编程(XP)时介绍了测试第一编程。“示例测试驱动的开发”在几年后出版,当时的想法(a)已经传播,(b)有若干不同的口译员,有自己的解释、目标、议程等。
我们有很多不同的想法,比如“最简单的东西”和“你不会需要它”,这些想法在同一个社区中很常见,人们尝试将它们应用到TDD的测试和重构中。有时候口号翻译得很好,有时.没那么多?
测试驱动的开发应该如何防止这样的“驱动”代码呢?
因此,首先要认识到的是,“驱动”在这里是纯粹的营销垃圾。曾经有一段时间,人们相信设计是从测试中得到的--但这并没有真正奏效,而回想起来,有一些非常清晰的信息表明,这是行不通的。迈克尔-弗斯称这一时期为听着,妈,没有手的时代。
在有些情况下,测试的实现会提示您的设计中存在问题(过多的无关设置是一个常见的例子)。但是结构不变测试根本不能“驱动”一个结构--所有的“重构”都是可逆的。
这些测试所能做的是,如果您为改进设计而进行的小代码更改会更改您所测量的任何行为,则会提醒您。如果是这样,您可以立即评估和补救矛盾(通常通过恢复引入错误的小更改)并继续前进。
(与“测试第一”方法相比,在输入整个设计之前,测试将失败。同样的测试可能仍然失败,现在你必须去挖掘你引入的错误。缩短反馈回路是TDD的主要思想。)
现在,从头上看,一个更好的测试是有两个随机生成的整数,Add的结果是添加第一个和第二个整数的结果。突然,测试变得更加健壮了。
测试驱动开发/测试驱动设计是一种设计实践,而不是测试实践。防止来自地狱的企业开发者的渎职不是TDD的目标。
发布于 2021-09-23 17:45:04
在驾驶设计时,作弊实际上是相当常见的事情(“通过测试,犯下任何必要的罪行”)。它适用于2和3,甚至与几乎无限数量的其他数字组合。欺骗可以通过消除VoiceOfUnreason显示的复制(5在您的测试和生产代码中复制,用a+b替换它来删除此复制)或“三角剖分”(编写更多期望不同结果的测试)来解决。TDD并不是“人为的愚蠢”,甚至不是恶意的。
发布于 2021-10-24 15:20:49
这里的复制在测试和生产代码中。注意以下两行
Assert.AreEqual(5, result);
return 5;
要删除这种重复,您需要考虑使代码更通用。正如@EricSchaefer正确地提到的,要使代码更通用,您需要遵循三角剖分技术。
https://stackoverflow.com/questions/69262392
复制相似问题