好吧,直接进入第三步不是更容易,而且根本不做 BooksLimit() 单元测试吗?
是的...如果您不花时间编写测试,您将花费更少的时间编写测试。您的项目总体上可能需要更长的时间,因为您将花费大量时间进行调试,但也许这更容易向您的经理解释?如果是这样的话……找一份新工作!测试对于提高您对软件的信心至关重要。
当您拥有大量代码时,单元测试最有价值。使用几个类无需单元测试即可轻松调试简单的家庭作业。一旦你走出世界,并且在数百万行的代码库中工作 - 你将需要它。您根本无法单步调试您的调试器。你根本无法理解一切。您需要知道您所依赖的课程。您需要知道是否有人说“我只是要对行为做出这种改变......因为我需要它”,但他们忘记了还有 200 种其他用途取决于这种行为。单元测试有助于防止这种情况。
关于使维护更加困难:NO WAY! 我不能充分利用它。
如果你是唯一一个参与过你的项目的人,那么是的,你可能会这么想。但那是疯狂的谈话!尝试在没有单元测试的情况下加快 30k 行项目的速度。尝试在没有单元测试的情况下添加需要对代码进行重大更改的功能。没有信心你没有打破其他工程师的隐含假设。对于维护者(或现有项目的新开发者)来说,单元测试是关键。我依靠单元测试来记录文档、行为、假设、告诉我什么时候破坏了某些东西(我认为这些东西不相关)。有时,一个写得不好的 API 的测试写得不好,而且可能是一场噩梦,因为测试会占用你所有的时间。最终你会想要重构这段代码并修复它,但你的用户也会感谢你——因为它,你的 API 将更容易使用。
关于覆盖的说明:
对我来说,这不是 100% 的测试覆盖率。100% 的覆盖率并没有找到所有的错误,考虑一个有两个if
语句的函数:
// Will return a number less than or equal to 3
int Bar(bool cond1, bool cond2) {
int b;
if (cond1) {
b++;
} else {
b+=2;
}
if (cond2) {
b+=2;
} else {
b++;
}
}
现在考虑我编写一个测试来测试:
EXPECT_EQ(3, Bar(true, true));
EXPECT_EQ(3, Bar(false, false));
那是100%的覆盖率。这也是一个不符合约定的函数——Bar(false, true);
失败,因为它返回 4。所以“完全覆盖”不是最终目标。
老实说,我会跳过BooksLimit()
. 它返回一个常量,因此可能不值得花时间编写它们(并且应该在编写时对其进行测试DisplayBooks()
)。当有人决定(错误地)根据货架尺寸计算该限制时,我可能会感到难过,它不再满足我们的要求。我以前被“不值得测试”烧伤。去年我写了一些代码,我对我的同事说:“这个类主要是数据,不需要测试”。它有一个方法。它有一个错误。它开始生产了。它在半夜寻呼我们。我觉得很愚蠢。所以我写了测试。然后我对哪些代码构成“不值得测试”进行了长期而艰苦的思考。没有多少。
所以,是的,你可以跳过一些测试。100% 的测试覆盖率很棒,但这并不意味着你的软件是完美的。这一切都归结为面对变化的信心。
如果我把class A
,class B
和class C
放在一起,我发现有些东西不起作用,我想花时间调试这三个吗?不。我想知道,A
并且B
已经满足了他们的合同(通过单元测试),我的新代码class C
可能已经坏了。所以我对它进行了单元测试。如果我不进行单元测试,我怎么知道它坏了?通过单击一些按钮并尝试新代码?这很好,但还不够。一旦你的程序扩大规模,就不可能重新运行所有手动测试来检查一切是否正常。这就是为什么进行单元测试的人通常也会自动运行他们的测试。告诉我“通过”或“失败”,不要告诉我“输出是……”。
好的,去写一些更多的测试......