为什么要通过程序来测试程序? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huzhikuizainali
V2EX    编程

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

  •  
  •   huzhikuizainali 2023-10-03 20:22:38 +08:00 1486 次点击
    这是一个创建于 737 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    Sketch
        1
    Sketch  
       2023-10-03 20:36:56 +08:00 via iPhone
    用 1 道简单但不严谨的数学题,或许能回答题主的第 1 个疑问。
    Q: 工程师小陈在写完每段生产代码后都会写完备的单元测试覆盖代码。假设小陈写代码犯错的概率是 50%,正确的代码会产生正确的结果,错误的代码会产生错误的结果,请问每段生产代码出现错误的概率为多少?
    huzhikuizainali
        2
    huzhikuizainali  
    OP
       2023-10-03 21:47:42 +08:00
    @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
        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 产生出一个永远通过的单元测试结果,那。。。我也不知道是什么鬼了
    zhuisui
        4
    zhuisui  
       2023-10-03 22:14:31 +08:00
    简单一句话,单元测试本身可以说并不是和业务逻辑一个级别的程序,因为不需要用到程序的分支、循环等复杂的控制逻辑,输入用硬编码,调用和输出比较用预设的方法,整个过程都是顺序的。
    huzhikuizainali
        5
    huzhikuizainali  
    OP
       2023-10-03 22:31:43 +08:00
    @zhuisui 不知道我的理解对不对。单元测试主要检测 1+1 是否等于 2 的问题。也就是业务逻辑是否正确。 所以如果把单元测试要检测的问题看过集合 X 。那么 X 是 bug 这个集合的子集。bug 是包罗万象的。 比如你输入 章+1 这个可能会引起程序崩溃,但是这个问题不属于单元测试检测的问题。可以这么认为么?
    Sketch
        6
    Sketch  
       2023-10-03 23:01:07 +08:00 via iPhone
    @zhuisui

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

    确切的说,你提到的这里的 2 个失败场合都可以被单元测试捕获,所以生产错误的概率还是 25%,错误的概率还是下降了。
    当然,我也提到这个问题是不够严谨的,只是为了说明单元测试还是有它的价值。
    lujjjh
        7
    lujjjh  
       2023-10-03 23:14:35 +08:00
    真实情况是程序 A 通常需要长期维护,如果每次修改代码之后都人工回归一遍,效率很低而且更容易出错,而程序员最擅长的就是把这种需要重复做的琐事自动化。另外,单元测试的代码基本就是断言函数不同输入下的输出,所以很难写出 BUG 。写测试的时间倒是可能跟写程序 A 的追平,但是如果把程序 A 之后维护的时间都算进去,那么写测试的时间就可以忽略不计了。
    kaneg
        8
    kaneg  
       2023-10-04 09:50:33 +08:00 via iPhone
    虽然都是程序,但二者的复杂度是不同的,一般来说单元测试不会比实际的业务复杂。所以用自动化来测试就像四两拨千斤,是以小搏大。
    zhuisui
        9
    zhuisui  
       2023-10-04 12:41:26 +08:00
    @huzhikuizainali 可以这么认为。引起业务逻辑出错的 bug 是无限的,但是业务逻辑提供的功能是有限的,所以单元测试也总是测试有限的场景。
    zhuisui
        10
    zhuisui  
       2023-10-04 12:47:30 +08:00
    @Sketch
    我这里的“失败”,指的是单元测试对业务逻辑的测试结果,而不是单元测试是否能成功达成目的。
    其中第 2 、4 列对应的是单元测试成功检测出错误的业务逻辑的情况。
    第 1 、4 列都是单元测试失败,但对应的业务逻辑不一定错误。
    deorth
        11
    deorth  
       2023-10-06 23:32:55 +08:00 via Android
    如果业务代码改动了,只要调用的接口没改动,那单测不需要重写
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1105 人在线   最高记录 6679   span class="snow">     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 23:20 PVG 07:20 LAX 16:20 JFK 19:20
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86