为什么要通过程序来测试程序?

221 天前
 huzhikuizainali

刚学编程,没参加过实际项目协同工作。有一个关于单元测试的疑问。

为了防止程序 A 出 bug 要测试,我自己写完一段代码也要看输出是不是符合预期。问题是我写代码 A 就要找 bug ,然后我再写测试代码 B ,A 和 B 都可能出 bug 。出 bug 的机会提高一倍。写代码的时间提高一倍(不是严格的一倍)。所以为什么要写个测试程序 B 来对目标程序 A 进行测试呢?从成本收益的角度来看划算么? 可否从实际工作的角度解答一下这个疑问?

861 次点击
所在节点    编程
11 条回复
Sketch
221 天前
用 1 道简单但不严谨的数学题,或许能回答题主的第 1 个疑问。
Q: 工程师小陈在写完每段生产代码后都会写完备的单元测试覆盖代码。假设小陈写代码犯错的概率是 50%,正确的代码会产生正确的结果,错误的代码会产生错误的结果,请问每段生产代码出现错误的概率为多少?
huzhikuizainali
221 天前
@Sketch 两段代码同时出错的概率是 0.25 。但是只有一段代码出错的概率是 0.25+0.25=0.5 。所以出 bug 的总概率变成 0.25+0.5=0.75 。不出 bug 的概率从原来一段代码的 0.5 变成了 1-0.75=0.25 。
.
zhuisui
221 天前
> 两段代码同时出错的概率是 0.25 。但是只有一段代码出错的概率是 0.25+0.25=0.5 。所以出 bug 的总概率变成 0.25+0.5=0.75 。不出 bug 的概率从原来一段代码的 0.5 变成了 1-0.75=0.25 。

哈哈哈哈,神了!
从问题和这个回答看,显然是不知道单元测试的意义,是用来保证业务逻辑代码正确的。

但是上面这个提问不合适,因为正确的单元测试能测出问题,而错误的单元测试会掩盖问题,所以 50%的概率写出错误的单元测试时,会出现业务代码错误且单元测试错误而最终导致 bug 的情况。
做成表格就是
---------------------
业务逻辑 正确 正确 错误 错误
单元测试 错误 正确 错误 正确
测试结果 失败 成功 成功 失败
--------------------
测试结果概率还是 50%,和写代码正确的概率是一样的。显然这个简单的问题并不能解答疑问。

写单元测试的原则是,面向业务逻辑提供的功能/接口测试,而不针对/忽略实现。业务逻辑负责的是实现。所以在做这两部分工作时,不会有相同的逻辑。
至于你说两块代码出 bug ,那是另外一个问题,不是单元测试本身能避免的。单元测试本身已经足够简单了,因为就是制造输入和检查输出,极端情况下,这应该完全可以用字面量做到,如果这都能写出 bug 产生出一个永远通过的单元测试结果,那。。。我也不知道是什么鬼了
zhuisui
221 天前
简单一句话,单元测试本身可以说并不是和业务逻辑一个级别的程序,因为不需要用到程序的分支、循环等复杂的控制逻辑,输入用硬编码,调用和输出比较用预设的方法,整个过程都是顺序的。
huzhikuizainali
221 天前
@zhuisui 不知道我的理解对不对。单元测试主要检测 1+1 是否等于 2 的问题。也就是业务逻辑是否正确。 所以如果把单元测试要检测的问题看过集合 X 。那么 X 是 bug 这个集合的子集。bug 是包罗万象的。 比如你输入 章+1 这个可能会引起程序崩溃,但是这个问题不属于单元测试检测的问题。可以这么认为么?
Sketch
221 天前
@zhuisui

“业务逻辑 正确 正确 错误 错误
单元测试 错误 正确 错误 正确
测试结果 失败 成功 成功 失败”

确切的说,你提到的这里的 2 个失败场合都可以被单元测试捕获,所以生产错误的概率还是 25%,错误的概率还是下降了。
当然,我也提到这个问题是不够严谨的,只是为了说明单元测试还是有它的价值。
lujjjh
221 天前
真实情况是程序 A 通常需要长期维护,如果每次修改代码之后都人工回归一遍,效率很低而且更容易出错,而程序员最擅长的就是把这种需要重复做的琐事自动化。另外,单元测试的代码基本就是断言函数不同输入下的输出,所以很难写出 BUG 。写测试的时间倒是可能跟写程序 A 的追平,但是如果把程序 A 之后维护的时间都算进去,那么写测试的时间就可以忽略不计了。
kaneg
221 天前
虽然都是程序,但二者的复杂度是不同的,一般来说单元测试不会比实际的业务复杂。所以用自动化来测试就像四两拨千斤,是以小搏大。
zhuisui
221 天前
@huzhikuizainali 可以这么认为。引起业务逻辑出错的 bug 是无限的,但是业务逻辑提供的功能是有限的,所以单元测试也总是测试有限的场景。
zhuisui
221 天前
@Sketch
我这里的“失败”,指的是单元测试对业务逻辑的测试结果,而不是单元测试是否能成功达成目的。
其中第 2 、4 列对应的是单元测试成功检测出错误的业务逻辑的情况。
第 1 、4 列都是单元测试失败,但对应的业务逻辑不一定错误。
deorth
218 天前
如果业务代码改动了,只要调用的接口没改动,那单测不需要重写

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/978765

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX