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

[讨论] 在业务系统中写了 e2e 测试,还需要写单元测试吗?

  •  
  •   PixelMage · 6 天前 · 611 次点击

    假设你现在实现了一个登录注册的系统

    你写 e2e 测试用例把你的所有的 http 接口的功能以及异常情况都测了一遍并通过

    这时候还需要写单元测试吗?

    如果用?为什么? 如果不用,那是否以后业务系统就只需要写 e2e 测试就好了?

    19 回复  |  直到 2020-01-16 18:48:09 +08:00
    lihongjie0209
        1
    lihongjie0209   6 天前   ♥ 1
    你测试了 HTTP 接口就不需要测试 StringUtil 了? 单元测试测试的具体的代码, HTTP 接口测试的是具体的业务
    index90
        2
    index90   6 天前   ♥ 1
    如果你能确保你的接口测试用例,能够覆盖代码中所有可能的条件分支,那当然是最好的了。
    然而现实问题是,编写有效的接口测试比编写有效的单元测试成本更高。
    我这边的做法是,开发编写单元测试,覆盖 99%的代码行。QA 做功能测试,优先覆盖开心路径,逐步补齐异常测试用例。这样兼顾开发效率和软件质量。
    lihongjie0209
        3
    lihongjie0209   6 天前
    @index90 #2 99%的单测覆盖率, 可以具体说一下吗
    kwrush
        4
    kwrush   5 天前   ♥ 1
    e2e 把所有分支和情况都 cover 了,那可比单元测试难度高多了,我觉得根本就不可能,何必自寻死路。
    PixelMage
        5
    PixelMage   5 天前
    @lihongjie0209 其实我想表达的意思是,如果所有的业务情况,以及业务能考虑到的异常情况都通过了测试。为什么还需要考虑代码的单测?毕竟 it works?
    这只是我片面的想法哈,因为我觉得既然 e2e 都写好了,业务都 OK 了,我又何必在乎具体的代码。
    还请多指教~
    PixelMage
        6
    PixelMage   5 天前
    @kwrush 可能是我写的系统的比较简单,最多也就十来张表,CRUD,所以都是直接写 E2E 不写单测,最近产生了这个疑惑——“为什么还要写单测”
    PixelMage
        7
    PixelMage   5 天前
    @index90 学习了,感谢回复。可能是我现在的系统比较简单的缘故,我直接写 E2E 更快~
    lolizeppelin
        8
    lolizeppelin   5 天前 via Android
    写单元测试的过程就是优化和重构代码的过程

    写接口测试做不到
    index90
        9
    index90   5 天前
    @lihongjie0209 #3
    1. 每开发一个特性,就从主干拉出特性分支
    2. 开发完并加上单元测试,就提 MR
    3. MR 触发流水线,跑单元测试,计算代码行覆盖率,不达标就不通过
    4. 流水线跑通过后,才能合并回主干

    PS:关于特性,这里不是产品特性,更多是研发角度的特性,例如加个函数,加一个类等。我们一般趋向于把产品特性切分成多个更细的开发特性,这样可以确保分支不会离开主干太久。
    PPS:关于单元测试的有效性,执行层面上,只有代码覆盖率这一个可量化指标,而单元测试有效性只能靠自觉了( assert 的编写其实很影响单元测试的有效性的),例如一旦被发现“作弊”,就会被开除。

    不知道这是不是你想问的……
    index90
        10
    index90   5 天前
    @lolizeppelin #8
    对,写久了单元测试,就会有这样的感觉:
    如果发现单元测试比较难写,就会考虑我的代码设计是不是有问题
    lihongjie0209
        11
    lihongjie0209   5 天前
    @index90 #9 感谢回复, 我比较好奇你们的 service 层和 dao 层是做单元测试的.
    index90
        12
    index90   5 天前
    @lihongjie0209 凡是人手写的代码都需要写单元测试,只要是个函数都可以写单元测试。实践过程里可能比较棘手的是如何 mock 了。刚开始的时候挺痛苦的,现在基本不会出现无法写单元测试的情况(除了要往老代码里加特性)。
    PixelMage
        13
    PixelMage   5 天前
    @index90 想请教一下
    在 e2e 测试覆盖了所有业务逻辑的情况下,
    出于对业务系统稳定性的考虑,而不是代码逻辑优化的考虑下,
    是否还有必要再写单测?
    index90
        14
    index90   5 天前   ♥ 1
    @PixelMage 你这句话从理论上说没错,但实际上,你要 e2e 测试覆盖所有业务逻辑几乎不可能。

    而且服务程序还要考虑 failure 的情况吧,例如下游服务无响应,响应超时,例如数据库连接失败,查询失败等情况。如果要在 e2e 测试中完成,你还要部署这样的环境出来,而用单元测试的话就可以轻松覆盖这些异常情况了。

    回到你的问题:
    “在 e2e 测试覆盖了所有业务逻辑的情况下,” ——业务逻辑覆盖是否有可量化指标,如何证明你覆盖了“所有”的业务逻辑呢?
    “出于对业务系统稳定性的考虑,而不是代码逻辑优化的考虑下,”——系统稳定并不只有业务逻辑,还有其他异常情况考虑
    “是否还有必要再写单测?”——单元测试只是一种软件质量保证的手段,而且经过多年的考验,看看那些著名的开源软件有没有写单元测试。如果你觉得你比那些牛人聪明,你有比单元测试更好的手段去保障软件质量,你可以选择你的方法。
    PixelMage
        15
    PixelMage   5 天前
    @index90 感谢你的回答,真的,我困扰了很久。

    确实如果你所说,我并没有考虑到下游没响应,数据库失败的情况,我只覆盖了业务的正常流和异常流。但我很好奇如何在单测里覆盖这些东西?不知道有没有 repo 可以参考一下(我是真的想学习一下,没有别的意思)

    “业务逻辑覆盖是否有可量化指标,如何证明你覆盖了“所有”的业务逻辑呢” ——也只能尽量,毕竟总有黑天鹅,尽量的意思就是 1. 梳理出所有可能的业务异常情况并测试到 2. 测试覆盖率

    “系统稳定并不只有业务逻辑,还有其他异常情况考虑”, “单元测试只是一种软件质量保证的手段,而且经过多年的考验
    ....你可以选择你的方法”——
    没错你说得对,但是在日常的业务系统开发中,而不是伟大软件开发中,经常会出现为了开发速度牺牲质量的 tradeoff,我其实很倾向于“只写 e2e 是一种比较划算的 tradeoff”。另:我问一个我在阿里写 java 的同事这个问题,他说:哪有时间写什么测试,直接丢给测试同学。所以我觉得这种现象是常见的。理想情况下,当然是都写最好,但是现实世界往往不尽如人意。

    再一次感谢你的回答~真的很认真,感谢。
    index90
        16
    index90   5 天前   ♥ 1
    @PixelMage 要找 repo 的话,可以上 github 上找,我看得比较多是 dgraph 和 k8s 的 repo (跟工作有关)。
    哦对了,我是 Gopher,Java 不是很熟,不过根据经验,标准库里面的例子就足够学了,我相信 Java 的标准库应该也有单元测试的。

    关于你最后一点“但是在日常的业务系统开发中,而不是伟大软件开发中,经常会出现为了开发速度牺牲质量的 tradeoff”,我想还是分享一下我的经历。(这里的质量,我理解的是程序是否有 bug,而不是代码优不优雅的问题)

    其实刚开始我们也是觉得写单元测试浪费时间,如果把开发活动框在从研发到打包这段过程的话,单元测试的确是影响了开发进度的。但是如果你把软件的发布,运营,bug 反馈,定位,修复,再发布这些环节考虑进来,你会崩溃掉的。

    “为了开发速度牺牲质量”,其实到了最后我们发现这是个伪命题来的,因为软件质量是第一位的。如果软件万一真的有 bug,即使不考虑业务损失,当这个 bug 出现的时候,你需要马上放下手上正在开发的特性,去排查定位,重建环境,代码修复,测试,打包,发布等,这一系列的工作牵扯到的不只是写出这个 bug 的那一位研发人员,而是牵扯到运维,测试等一系列人员。将人力成本,时间成本,沟通成本等考虑进来之后,其实整个团队的研发效能非常低的。

    当然,如果一个研发人员和一个测试人员合作无间,测试能够在出现 bug 的时候,就直接告诉研发人员是哪个模块甚至哪一行出问题了,这种分工也是没问题的,但是我没见过。语言沟通有效率本来就够低了,更何况现在研发和测试都不在一个办公室里,用 IM 发着文字沟通,又或者在看板上发评论来沟通 bug。

    “为了开发速度牺牲质量”这种观念很普遍,我猜是因为大部分研发人员都是个体在工作,容易把自己的职责框在写代码到代码提交之间。但当你开始关心整个研发团队的效能上时,你很容易发现问题。
    PixelMage
        17
    PixelMage   5 天前
    @index90

    对于“业务系统是否应该写测试”,我觉得我们都是一致的,不写测试带来的都是短期的时间收益,和长期的整体研发效能损失。所以对于“为了开发速度牺牲质量——不写测试”,我也是觉得不可取的。

    但是我更想知道的是“ [业务] 系统里只写 E2E 不写单元来达到时间和收益的最佳 tradeoff”是不是合适的?
    我举一个量化的例子
    我假设写 E2E 测试能 COVER 90%的业务 BUG,需要花费 1 个单位的时间
    如果我再补上单元测试,能再补上 9.9%的业务 BUG,但是需要额外花费 1 个单元的时间

    那么此时我认为,只写 E2E,不写单元是比较划算的。
    这里有两个问题
    1. E2E 测试能不能 COVER 90%的业务问题?
    2. E2E 测试环境的搭建是否真的比单元测试简单?

    其中
    1.我觉得对于中小系统都是适用的,写完正常流和异常流的 E2E,我认为能够覆盖 80 90 的问题。
    2. E2E 的测试环境,如今在各种中大型开发团队,比如阿里,都是日常、预发、线上,三套或以上环境 ,天然就有公司准备好的环境,不需要你再去搭建什么,所有的系统都遵守了这个规则,所以在中大型团队,我认为这个没什么成本。在小型团队,那可能写不写测试都是问题了。

    综合来说,我想说的观点,一句话就是
    “在大部分非核心中小型系统里,只写 E2E 测试是权衡了效率和质量的好选择”
    index90
        18
    index90   5 天前
    @PixelMage sorry,我看了前半句没看后半句,误解了你的意思。

    感觉我们的讨论有点跑偏,e2e 测试和单元测试其实是处在不同维度,解决的具体问题是不一样的,不能用来直接比较,不是一个非零即一的问题。

    单元测试是验证代码逻辑问题,而不是验证业务逻辑问题。
    相反,e2e 测试只能保证业务逻辑正确,但无法保证代码或软件是健壮的。(或者需要很大代价)
    PixelMage
        19
    PixelMage   5 天前
    @index90
    我个人的粗浅理解是,一些核心基础中间件之类的,单测,E2E 我觉得都不能少。
    但是如果是一个业务系统的话,这可能就回到我提出的这个问题了~

    其实我个人的小心思是:既然业务 e2e 测已经 work 了,异常流也 cover 到了,单测带来的代码健壮提升 i don't care,毕竟后面还有 IDE,语言框架,lint, 代码风格检查,开发规约拉着我。

    这样可以提高业务的落地速度,但是要是说后续的可维护可扩展性的,写单测应该是会有提高的,但是提高多大,就不太好说了,估计每个业务系统可能都不一样。

    还是特别感谢你的回复,我收获了不少东西~~对单测的看法也没有那么片面了
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2113 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 58ms · UTC 15:15 · PVG 23:15 · LAX 07:15 · JFK 10:15
    ♥ Do have faith in what you're doing.