V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huzhikuizainali
V2EX  ›  编程

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

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

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

    为了防止程序 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   ·   实用小工具   ·   1225 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 1531ms · UTC 23:03 · PVG 07:03 · LAX 15:03 · JFK 18:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.