V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
tsingke
V2EX  ›  程序员

单元测试有落地效果好的团队吗?

  •  1
     
  •   tsingke · 2022-09-20 17:58:08 +08:00 · 7334 次点击
    这是一个创建于 825 天前的主题,其中的信息可能已经有所发展或是发生改变。

    团队推单元测试,但是效果很差,开发写单测意愿很低,反馈浪费时间,收益很小,不愿意写。

    59 条回复    2022-09-22 16:17:35 +08:00
    y2xworm
        1
    y2xworm  
       2022-09-20 18:04:13 +08:00
    目前经历过的公司除了增加开发难度貌似没啥 bug 能减少的, 特别是改了一些核心功能直接导致一大片单元测试过不了的, 可能代码五分钟改单元测试要改一天😑
    WispZhan
        2
    WispZhan  
       2022-09-20 18:07:19 +08:00 via Android
    几个问题,
    1. 你在团队属于什么角色,是谁在主导?
    2. 采用的什么 TDD 模式,ATDD 、UTDD 或者其他?
    3. 团队里平均水平如何?
    chendy
        3
    chendy  
       2022-09-20 18:09:23 +08:00
    UT 的作用:1. 发现系统设计的问题 2. 及时变更导致的问题
    所以,只对重要且变更比较多的模块写 UT
    Chad0000
        4
    Chad0000  
       2022-09-20 18:17:10 +08:00
    我在引领组里改进架构,也在思考要不要上单元测试。或者 API 测试就行?

    同求经验分享。
    superrichman
        5
    superrichman  
       2022-09-20 18:25:55 +08:00 via Android   ❤️ 4
    单元测试还没写完,需求都改了 10 次。
    除非需求没变化,比如一些工具类,一般写好就不会改,不然单元测试收益很低。
    oxromantic
        6
    oxromantic  
       2022-09-20 18:31:07 +08:00   ❤️ 2
    如果项目周期一半或者一大半的时间不能用来安排测试计划以及写单元测试,那么就不要搞,单元测试需要的时间比实际功能多一些
    lululau
        7
    lululau  
       2022-09-20 18:33:55 +08:00
    6L 正解,你一秒钟时间都不给,写个锤子啊;给足了时间谁不喜欢写测试啊,拿着开发的工资写不用动脑子的用例,我就问,谁不喜欢写测试?
    lululau
        8
    lululau  
       2022-09-20 18:36:39 +08:00
    测试也是个技术活,也不是完全不用动脑子,用例怎么组织,测试代码怎么复用,测试数据怎么组织管理,外部依赖怎么弄,你个 team leader 都不知道怎么搞,我写个锤子啊
    wu67
        9
    wu67  
       2022-09-20 19:09:42 +08:00
    国内这个开发环境, 特别是跟政企有关的项目, 单元测试想都不要想. 上头都拼命催你出界面, 写业务都忙死忙活了, 还整什么测试, 写完丢给测试人员干黑盒就完事了.
    Jooooooooo
        10
    Jooooooooo  
       2022-09-20 19:13:20 +08:00
    单元测试最大的毛病就是, 随着需求迭代得不停维护. 这个成本某些时候比开发需求还大, 自然没人愿意搞.
    matrix1010
        11
    matrix1010  
       2022-09-20 19:35:22 +08:00 via iPhone
    团队推广单元测试 /集成测试,首先对团队要求就比较高。连看英文文档都费劲的,你让他写测试肯定只会大幅增加他的工作时间。但如果团队水平足够,而且比较拥抱开源,那写测试可能都不用推广,大家都会自觉去做
    yiqiao
        12
    yiqiao  
       2022-09-20 19:53:31 +08:00
    对重构来说确实很有用,特别是复杂业务测试起来有奇效,
    但是就是需求变动太快周期太短。
    tediorelee
        13
    tediorelee  
       2022-09-20 20:05:40 +08:00
    进公司的时候才知道有 UT 这个东西,适应了一段时间之后写起来熟练一点了,要求是 branch95, function96.5 ,没达到过不了 Jenkins 的 CI
    ksedz
        14
    ksedz  
       2022-09-20 20:29:49 +08:00
    在上家公司的时候推过,指标是代码的行覆盖率。
    个人感觉实际用起来能发现不少问题,对功能的正确性更有信心了,明显减少了维护时间。
    可能对强类型语言的效果有限。
    mikeSbV2
        15
    mikeSbV2  
       2022-09-20 20:29:49 +08:00
    单元测试?目前的环境想都别想哦。

    写单元单测试的时间,起码占开发时间的三分之二。

    而且,动不动就更改需求,别想了。

    例如:公司上周才上线的需求,下周马上就大改,UI 大改,交互逻辑大改。用户都还未熟悉新功能的交互,立马就改了。还写个 P
    kkkiio
        16
    kkkiio  
       2022-09-20 20:54:16 +08:00 via iPhone
    推行单元测试要以低工作量的方式来推,因为
    1. 没人想增加自己的工作量
    2. 推行说明之前没写过,开发需要学习如何写单元测试,更要学习如何写出更容易被单元测试的代码
    3. 商业考虑性价比,在边边角角浪费时间是不合适的,而且越是边缘的代码一般越不稳定,越容易导致单元测试失效
    neochen13
        17
    neochen13  
       2022-09-20 21:31:37 +08:00
    别说单元测试,就连接口文档,以及注释你都很难找到全的
    xy90321
        18
    xy90321  
       2022-09-20 22:13:40 +08:00 via iPhone
    UT 不是 mc/dc 100% 都不会 release 到 IT 环境
    不写 UT 只 Coding ?那找 5K 工资的外派就可以了…
    zhaogaz
        19
    zhaogaz  
       2022-09-20 22:19:28 +08:00
    不对,问题不对。
    1. 要看提出单测的出发点是啥,然后再去针对解决问题,问题不一定用单测解决
    2. 单测有很多错误的实践方式,需要有懂的人给你讲,什么场景合适,什么场景不合适。
    - 有的是代码设计问题,导致写不出来
    - 有的是业务不适合
    - 有的是写法不对,导致反复返工,改改改成本过高,废弃
    3. 我觉得可能要多想想,问题不一定是表面的问题
    microxiaoxiao
        20
    microxiaoxiao  
       2022-09-20 23:14:35 +08:00
    有点点用吧。我这分子覆盖率要达到 80%。不然都 CI 直接拦截,merge 不了。主要的用途就是确保基本没有问题,而不是靠人的水平来决定。强行提高一下代码的质量。
    varrily
        21
    varrily  
       2022-09-20 23:25:54 +08:00
    我们要求覆盖 70%,gitlab ci 强制检测,未通过无法 merge ,包括 codestyle check 。

    一开始也不适应,后来也习惯了,一旦覆盖完整,后续逻辑变更会有很大帮助,减少隐患。

    跨团队合作还是很有必要的,减少不必要的沟通,避免低级错误。
    Macolor21
        22
    Macolor21  
       2022-09-20 23:34:10 +08:00
    infra 团队, UT 是必须的,还有 IT 、smoke testing ,chaos testing
    dustynight
        23
    dustynight  
       2022-09-21 00:37:08 +08:00
    我们是 CI 强制要求,不过要求比较低,大概是 line 80%,branch 70%这样,主要是考虑到老代码。
    ichou
        24
    ichou  
       2022-09-21 00:39:37 +08:00
    核心项目( 10 年了)覆盖率 96%,新项目全双百(行覆盖率 100% 分支覆盖率 100%)
    加上 commit message 要求比较严格,需求简单交代本次修改的上下文
    所以现在写起代码不用担心踩坑儿,即便是祖传代码也是敢动的,没有那种瞻前顾后的心理负担


    有了这些基础,加上 QA 的一些自动化测试,我们团队已经践行 ship / show / ask 很久了
    比起无穷无尽的 Code Review 和测试回归,效率高了不知多少倍,人力释放出来了,打码人的幸福感还提升了

    反正我觉得,真 TM 爽
    ichou
        25
    ichou  
       2022-09-21 00:46:15 +08:00   ❤️ 1
    @dustynight
    老代码可以不检查整体覆盖率,直接检查当前 PR 中被变更的行有没有被 100% 覆盖
    测试覆盖率慢慢就上去了,也不会因为补测试把人逼疯(大概吧 😂)
    binux
        26
    binux  
       2022-09-21 00:53:11 +08:00 via Android   ❤️ 1
    公司:代码都是屎山,不敢动。
    我:没时间写单元测试,能拉出屎就不错了。

    论屎山是怎么来的
    SeaTac
        27
    SeaTac  
       2022-09-21 01:44:53 +08:00 via iPhone
    不写 unit test 的组我是不敢去
    akira
        28
    akira  
       2022-09-21 04:40:09 +08:00
    测试代码你给时间了么。。
    petercui
        29
    petercui  
       2022-09-21 08:46:33 +08:00
    @y2xworm 重构的时候就知道好了,当然,你们也可能不会重构而是直接重写。
    risky
        30
    risky  
       2022-09-21 09:06:32 +08:00
    单元测试不一定需要项目采用 TDD ,单元测试需要好的程序架构,不然 mock 都不好做,极其痛苦
    heguangyu5
        31
    heguangyu5  
       2022-09-21 09:10:38 +08:00   ❤️ 6
    来分享一下我们最近在做的事,这事要是没有测试保障,很难做成.

    我们是做 SASS 招聘管理系统的,开发语言是 PHP,2010 年开始开发,2012 年开始引入 PHPUnit 写单元测试,2020 年做过一次统计,当时代码库有代码约 900 万行. https://zhuanlan.zhihu.com/p/150548910

    然后这两年我们想做本地部署,大家知道,PHP 项目做本地部署基本就等于交出了源码.
    这是我们不期望的,我们自认为自己产品做的不错,一个几十万元的本地部署项目就把源码给出去太亏了.

    那怎么办呢?经过一番调研,我们打算将 PHP 转译成 C,然后编译成二进制,这就好了.
    于是就有了我们的 PHP 编译器 BPC. https://github.com/bob-php-compiler/bpc-release
    但是 BPC 最终转译出来的 C 代码是否等价于 PHP 呢?
    单元测试此时帮了大忙.

    1. php 自身及扩展是都有相对完整的测试的,就在 php 源码的 tests 目录里.所以 bpc 如果能够顶替掉 php 解释器,然后还能通过测试的话,那就是最强有力的保障了.然后在 tests 的帮助下,我们实现了 runtime 及需要的扩展. https://github.com/bob-php-compiler/bpc-php-7.2.19-tests
    2. 接下来要用 bpc 把 phpunit 编译出来,有了 phpunit,就能确保编译过后的二进制的运行结果和 php 解释器的运行结果一致了. https://github.com/bob-php-compiler/bpc-phpunit.phar-4.8.36
    3. 我们的项目是基于 zend framework 1 的,zf1 的单元测试也是用 phpunit 写的,编译 zf1 library,编译 zf1 tests,运行结果一致,zend 就没问题了. https://github.com/bob-php-compiler/zf1
    4. 接下来就是我们自己的招聘管理系统了.同样有 phpunit 写的测试保障,只要编译出来运行测试没问题,那就是 99.99%没问题了.

    在测试的保障下,现在我们虽然开发的时候用的是 php 解释器,但将来部署出去的话,整个服务器上就几个二进制文件,是没有 php 环境的,测试已经保证了转译后的 C 代码运行结果和 php 一样,这就放心交出去了.

    试想如果没有单元测试保障,每一步心里都是忐忑的,还怎么做事呀.
    dog82
        32
    dog82  
       2022-09-21 09:27:35 +08:00
    小公司或草台班子根本不写 UT ,因为根本不给写 UT 的时间,即使给了时间,写完单元测试需求都变了 10 次了

    大公司产品级的,核心模块肯定要写
    nothingistrue
        33
    nothingistrue  
       2022-09-21 10:16:00 +08:00   ❤️ 1
    迄今为止,就在对日外包当中接触过完整实行的单元测试,不过那是纯人工的单元测试,不是像 Junit 这样的靠测试代码的单元测试。体验上,跟你们开发的反馈差不多,极度消耗时间,且表面上看没收益(对于项目来说是另一码事)。

    不管你是调通后再做测试(人工单元测试只能这样),还是编码完成就做测试,单元测试时间跟编码时间的配比,都要至少大于 1:1 。如果不给单元测试分配时间成本,或者在这上面压缩成本,那就不如不做。这个时间成本不一定会提高总成本,因为如果做好单元测试,那么集成测试跟系统测试的成本必然会减小。我参与那个对日外包开发,测试时间基本全部分配到了单元测试上,后面的集成、系统、交付测试的时间非常短。

    收益这方面有点复杂,开发过程和考核指标,以及个人的职业发展规划,都会影响对收益的观感。如果你们不管多复杂的开发过程和考核指标,最终都是以项目是否收到尾款作为实际的考核依据,那么单元测试就真得是零收益。如果开发过程上不把编码人跟代码绑定起来,最常见的就是项目结束了就把人派去其他项目,那么单元测试不但是零收益,还是为他人栽树的负收益。如果个人职业规划没有向项目管理、需求或业务方向上发展的话,那么不止单元测试,所有测试对于编码人员来说都是零收益。

    最后一方面,单元测试是谁推的也很重要。作为代码质量的一部分,单元测试应当是开发人员自行作为推动动力的。QA 推动也能推起来,不过会遇到阻力的。而假如是开发人员和 QA 之外的人推动,那基本就是全阻力。
    857681664
        34
    857681664  
       2022-09-21 10:20:03 +08:00   ❤️ 4
    我刚加入团队的时候整个项目是没有单元测试的,那时候经常出现改一处问题,又出现好几处其他地方的问题,于是我花了一个月的时间,在项目上搭建了单元测试的框架,并写了第一批测试用例(大约 100 个左右),覆盖了主要业务流程的 6,70%。
    对于我来说,单元测试不止有业务迭代,重构时的保障作用,更重要的是,对于修 bug ,测试功能能更快地复现现场。有些功能 /bug 的场景是需要 mq 的,如果在页面上操作需要准备数据,然后经过很多步骤,才能进入待测试方法,而且本地调试很容易误消费消息,带来很多干扰。如果用单元测试,我只需要准备消费者需要的对象,然后在测试方法里调用即可。
    我写完第一批测试用例,在团队内推广单元测试的时候,大部分同事也是抱着业务迭代紧,没时间写的想法,也几乎不会去写新的测试,直到后面出现 bug ,我教他们如何复现,如何验证,然后他们也开始觉得测试也挺好用的。
    当然我能做完这一切的原因是,我刚加入的时候完全没有需求的压力,只有修复 bug 的任务,所以我才能一边修 bug ,一边验证这一套单元测试的框架。
    所以,如果你的团队完全没有意识到测试的重要性,也完全没有给单元测试安排时间,那么建议还是放弃单元测试,让测试人员去做,除非你能说服领导单元测试的好处,能在每次迭代中留有单元测试的时间,那可以在团队中尝试加入单元测试
    Chad0000
        35
    Chad0000  
       2022-09-21 10:35:37 +08:00
    @857681664
    我正在架构的微服务全部基于 API ,我感觉这样重现 BUG 会简单些。
    xaplux
        36
    xaplux  
       2022-09-21 10:42:47 +08:00
    感觉不太容易,目前大部分单元测试并不能覆盖所有测试用例
    abc635073826
        37
    abc635073826  
       2022-09-21 11:29:37 +08:00   ❤️ 1
    挺好的,最后我们团队被开了,很落地
    binux
        38
    binux  
       2022-09-21 11:39:02 +08:00 via Android
    @xaplux 有没有一种可能,写完单元测试之后你还可以写集成测试。
    Huelse
        39
    Huelse  
       2022-09-21 11:50:11 +08:00
    以前很追求单元测试各种测试,现在除了基础类基本不写,API 测试就行
    exonuclease
        40
    exonuclease  
       2022-09-21 13:13:36 +08:00
    至少需要接口比较稳定的 infra 写起来才比较容易 不稳定的比如 UI 还是用 e2e 测试吧
    单元测试的用处不止是 detect bug 可以强制程序员写出容易扩展的代码
    muyiluop
        41
    muyiluop  
       2022-09-21 13:51:36 +08:00
    我不知道怎么写单元测试。比如一个仓库入库出库和物流的业务,这个要怎么写
    AyaseEri
        42
    AyaseEri  
       2022-09-21 14:11:50 +08:00
    业务稳定了才开始写单元测试,不稳定的时候写单元测试是找死。
    msg7086
        43
    msg7086  
       2022-09-21 14:31:22 +08:00
    觉得写测试浪费时间,收益小,有几种可能。
    1. 项目活不了那么久,要么天天改,要么月月倒闭,一个系统写完了,用不了几天就扔了。
    2. 资历太浅,没有经历过技术债把公司拖死的事。
    3. 大牛,可以白板水笔写项目一遍过无 bug 的人。

    我自己的业余项目基本上都有测试,主要做集成测试。
    公司项目也都有测试,测试覆盖不够的话 code review 也过不了。
    kiwi95
        44
    kiwi95  
       2022-09-21 14:38:47 +08:00 via Android
    @superrichman 写好了就不会改的东西反而是不怎么需要单元测试。单元测试一个重要的作用就是保证迭代中的改动不会 break 旧的逻辑。
    magichacker
        45
    magichacker  
       2022-09-21 15:02:29 +08:00
    @varrily 怎么感觉咱俩是在一个团队的呢,哈哈哈哈
    a132811
        46
    a132811  
       2022-09-21 15:11:22 +08:00
    @y2xworm 我是通过单元测试保证功能稳定的。没有单元测试,我都不敢做太大的迭代、重构。每次 git commit, 默认都要在 pre-commit 走一下 unittest(可以只测试修改过的目录)才会放心。
    -------------

    你们的 UnitTest 应该是测试的输入、输出吧。

    你们修改核心的功能,有影响到输入输出吗?如果影响到了,说明你们修改属于 break changes (这是可接受的). 否则就是你们的设计存在问题
    ------------
    我的体会是:
    1. 单元测试的 mock 需要好的框架设计、也需要一些技巧和技术,这个话题可以展开说
    2. 单元测试不必追求覆盖率、不必追求完全的 mock ,但是新增修改、核心代码,应该尽量覆盖
    gkiwi
        47
    gkiwi  
       2022-09-21 15:11:57 +08:00
    我手里有个线上业务的 node server ,搞不好会导致 app 崩溃那种,但是不可能我每次改动就让 QA 给测试,所以只能补充单侧,然后每次改动后跑跑单侧;否则靠人肉测试 会崩~
    Seulgi
        48
    Seulgi  
       2022-09-21 16:25:53 +08:00   ❤️ 1
    国内公司搞业务的状态,其实做不了单元测试. 首先是时间上, 没有给开发人员写单元测试的时间, 一个合格的单元测试, 测试用例, 覆盖率, 部分简单业务来说, 可能写业务 30 分钟, 单元测试得 1 个小时或者更多.
    另一个就是国内业务需求变动太大, 如果需求频繁变动, 导致的是单元测试得重写. 单元测试的一个目的是, 相关业务变动时, 复用单元测试保证之前的测试用例能通. 这是矛盾的.
    yule111222
        49
    yule111222  
       2022-09-21 17:01:32 +08:00
    很多人觉得写测试做 TDD 会延迟交付。。。其实恰恰相反,就算不考虑自动化测试带来的长期价值,哪怕只是一次性的也比正常写代码更快。前提是架构足够整洁,易于测试,和开发人员知道怎么写真正跟实现解耦的测试。
    所以 TDD 要真正落地并不容易,往往需要团队里有真正懂这个的 Teach Leader 来负责
    yule111222
        50
    yule111222  
       2022-09-21 17:04:56 +08:00
    真正的测试驱动开发,是可以利用测试用例一步步推演出代码实现的,比正常写代码更快
    感兴趣的可以参阅《匠艺整洁之道》或者极客时间上找找测试驱动开发的课程
    另外 ATDD 和 UTDD 是两种不同的模式,要根据工程业务复杂度和实际情况选择占比,通常来说如果业务非常复杂我更推荐 UTDD ,可以大幅加快开发实现速度
    yule111222
        51
    yule111222  
       2022-09-21 17:10:54 +08:00
    如果架构足够整洁,可以让领域层的业务逻辑代码完全跟外部依赖(其他服务和数据库,MQ 等)解耦
    zmcity
        52
    zmcity  
       2022-09-21 17:19:49 +08:00   ❤️ 1
    我们这里后端开发是这样做的,写业务代码之前先写好主要的接口,和单元测试,interface 和 unit test 的 pr review 过之后,才允许提交业务代码,业务代码实现的 pr 需要贴前面两个 pr 的链接并通过测试。
    不过对管理者考验也是很大的,需要有一个看到需求就能有大概框架的 tech lead ,否则就会陷入反复修改 interface 和 unittest 的死循环。
    matrix1010
        53
    matrix1010  
       2022-09-21 19:01:21 +08:00 via iPhone
    最好的办法还是团队建立的时候就规范好开发流程。团队和代码成型后再想推测试是很难的。因为很多代码的结构可能根本就无法测试
    xavierchow
        54
    xavierchow  
       2022-09-21 22:45:28 +08:00
    我们从源头上抓起, 招聘的代码测试环节就有要求写测试代码,不写测试大概率是招不进来的。
    进来后鼓励采用 TDD 方式开发,不写测试代码没人给 review PR ,就 merge 不回去主干分支,然后 CI 也会检查覆盖率。
    之所以一直这么做,是团队真的获得了巨大收益(低缺陷率,低耦合模块结构,可以大胆重构 /加功能等等)
    https://github.com/Wiredcraft/test-backend#functionality
    ccc1924
        55
    ccc1924  
       2022-09-21 22:54:32 +08:00
    看项目

    如果需求经常变化,或者项目周期非常短,没有写单元测试的必要
    kkeep
        56
    kkeep  
       2022-09-21 22:56:05 +08:00 via Android
    cqdev
        57
    cqdev  
       2022-09-21 23:18:24 +08:00
    为了单元测试而写单元测试是没有意义的。
    业务 => 功能代码 => 单元测试 :这里的单元测试是测试的代码逻辑并不是测业务。
    业务 => 单元测试 => 功能代码:这里的单元测试是基于你对业务的理解写出来的,测的是业务。
    cqdev
        58
    cqdev  
       2022-09-21 23:19:36 +08:00
    TDD 对于我来说,最大的收益就是信心,勇气,还有 context
    Akiya
        59
    Akiya  
       2022-09-22 16:17:35 +08:00
    取决于需要速度还是需要质量
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4858 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:58 · PVG 17:58 · LAX 01:58 · JFK 04:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.