刚学编程,没参加过实际项目协同工作。有一个关于单元测试的疑问。
为了防止程序 A 出 bug 要测试,我自己写完一段代码也要看输出是不是符合预期。问题是我写代码 A 就要找 bug ,然后我再写测试代码 B ,A 和 B 都可能出 bug 。出 bug 的机会提高一倍。写代码的时间提高一倍(不是严格的一倍)。所以为什么要写个测试程序 B 来对目标程序 A 进行测试呢?从成本收益的角度来看划算么? 可否从实际工作的角度解答一下这个疑问?
1
Sketch 2023-10-03 20:36:56 +08:00 via iPhone
用 1 道简单但不严谨的数学题,或许能回答题主的第 1 个疑问。
Q: 工程师小陈在写完每段生产代码后都会写完备的单元测试覆盖代码。假设小陈写代码犯错的概率是 50%,正确的代码会产生正确的结果,错误的代码会产生错误的结果,请问每段生产代码出现错误的概率为多少? |
2
huzhikuizainali OP @Sketch 两段代码同时出错的概率是 0.25 。但是只有一段代码出错的概率是 0.25+0.25=0.5 。所以出 bug 的总概率变成 0.25+0.5=0.75 。不出 bug 的概率从原来一段代码的 0.5 变成了 1-0.75=0.25 。
. |
3
zhuisui 2023-10-03 22:06:34 +08:00
> 两段代码同时出错的概率是 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 产生出一个永远通过的单元测试结果,那。。。我也不知道是什么鬼了 |
4
zhuisui 2023-10-03 22:14:31 +08:00
简单一句话,单元测试本身可以说并不是和业务逻辑一个级别的程序,因为不需要用到程序的分支、循环等复杂的控制逻辑,输入用硬编码,调用和输出比较用预设的方法,整个过程都是顺序的。
|
5
huzhikuizainali OP @zhuisui 不知道我的理解对不对。单元测试主要检测 1+1 是否等于 2 的问题。也就是业务逻辑是否正确。 所以如果把单元测试要检测的问题看过集合 X 。那么 X 是 bug 这个集合的子集。bug 是包罗万象的。 比如你输入 章+1 这个可能会引起程序崩溃,但是这个问题不属于单元测试检测的问题。可以这么认为么?
|
6
Sketch 2023-10-03 23:01:07 +08:00 via iPhone
@zhuisui
“业务逻辑 正确 正确 错误 错误 单元测试 错误 正确 错误 正确 测试结果 失败 成功 成功 失败” 确切的说,你提到的这里的 2 个失败场合都可以被单元测试捕获,所以生产错误的概率还是 25%,错误的概率还是下降了。 当然,我也提到这个问题是不够严谨的,只是为了说明单元测试还是有它的价值。 |
7
lujjjh 2023-10-03 23:14:35 +08:00
真实情况是程序 A 通常需要长期维护,如果每次修改代码之后都人工回归一遍,效率很低而且更容易出错,而程序员最擅长的就是把这种需要重复做的琐事自动化。另外,单元测试的代码基本就是断言函数不同输入下的输出,所以很难写出 BUG 。写测试的时间倒是可能跟写程序 A 的追平,但是如果把程序 A 之后维护的时间都算进去,那么写测试的时间就可以忽略不计了。
|
8
kaneg 2023-10-04 09:50:33 +08:00 via iPhone
虽然都是程序,但二者的复杂度是不同的,一般来说单元测试不会比实际的业务复杂。所以用自动化来测试就像四两拨千斤,是以小搏大。
|
9
zhuisui 2023-10-04 12:41:26 +08:00
@huzhikuizainali 可以这么认为。引起业务逻辑出错的 bug 是无限的,但是业务逻辑提供的功能是有限的,所以单元测试也总是测试有限的场景。
|
10
zhuisui 2023-10-04 12:47:30 +08:00
@Sketch
我这里的“失败”,指的是单元测试对业务逻辑的测试结果,而不是单元测试是否能成功达成目的。 其中第 2 、4 列对应的是单元测试成功检测出错误的业务逻辑的情况。 第 1 、4 列都是单元测试失败,但对应的业务逻辑不一定错误。 |
11
deorth 2023-10-06 23:32:55 +08:00 via Android
如果业务代码改动了,只要调用的接口没改动,那单测不需要重写
|