V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
tiRolin
V2EX  ›  Go 编程语言

有没有大佬告诉我单元测试用在哪里?这个问题困扰我好久了

  •  
  •   tiRolin · 15 天前 · 5078 次点击

    在学习的时候就经常听人说单元测试很重要,但是我每次看单元测试我都没搞懂这跟我手动 API 测试有啥区别?我感觉单元测试还更麻烦了,因为单元测试还需要自己创建测试数据自己测试核心逻辑和业务逻辑,我手动 API 测试不也能走一遍吗?然后说是单元测试更全面,但是我看单元测试的用例也是要我手写啊,这两个真有区别吗?

    而且单元测试比手动调 api 测试麻烦好多,比如说我现在在做的菜单树功能,我不太理解单元测试我就让 cursor 帮我生成,他框框一顿写就已经有四百行代码了,这要是人力来写这不是写单元测试的时间都要比写功能本身还要花更久的时间了吗?

    是不是实际开发的时候其实大多数简单功能,比如说我的菜单树是不会进行单元测试的,只会做简单的自测,而对于确实很复杂有必要长期维护的核心功能比如支付这种才对做单元测试?

    58 条回复    2025-07-22 18:00:44 +08:00
    manami
        1
    manami  
       15 天前
    单元测试可以在启动的时候就知道通不通过,或者通过率是多少。手动 API 测试没有量化,也不自动
    xwayway
        2
    xwayway  
       15 天前
    方便重构,方便他人接手。

    如果有单测,且覆盖较为完全的话,完全不用担心重构之后漏测了哪个 case ,也不用担心后来人接手改代码把哪个特殊场景漏掉了。
    chendy
        3
    chendy  
       15 天前   ❤️ 4
    用于核心模块重要模块,便于在修改之后确定影响
    换句话说就是普普通通的 crud 犯不上
    tiRolin
        4
    tiRolin  
    OP
       15 天前
    @chendy 大佬,我悟了。我就说怎么经常很多时候感觉单元测试完全是累赘,这是因为不是核心模块啊
    zhnd18
        5
    zhnd18  
       15 天前 via iPhone
    我觉得最重要的是开发流程的改变,可以了解一下 TDD 开发
    iyiluo
        6
    iyiluo  
       15 天前
    代码功能怎么证明功能正常?就是单元测试,起码能给程序员一些信心,单元测试覆盖的越广,底气就越足。否则你上线都战战兢兢,生怕哪里出问题
    dlmy
        7
    dlmy  
       15 天前
    理想中:项目单元测试覆盖率要在 90% 以上
    现实中:先上线,后面再补单元测试跟文档
    Maboroshii
        8
    Maboroshii  
       15 天前
    如果要做单元测试,需要在写代码的时候就做好拆分。
    毕竟很多业务代码是没办法做单测的,依赖一坨、耦合一坨
    EthanDon
        9
    EthanDon  
       15 天前   ❤️ 2
    1. 帮助你想清楚你的代码的边界条件,保持代码的健壮性
    2. 需求开发完,运行一下单测,确保先前兼容,或者如果有挂了,说明边界条件变化了
    3. 方便别人维护你的代码,也方便你自己过了很久以后来维护自己代码
    4. 正如楼上所说,可单测的代码才是代码,单测都写不了,依赖、耦合毛病一堆,屎山一坨

    想象一下,你现在要用一个第三方库,但是有个功能你不知道怎么用,如果 owner 做的好,维护所有情况的单测,你只需要对着看,运行一下,你就知道这个功能的预期效果了。
    oaa
        10
    oaa  
       15 天前
    当你觉得写单元测试很麻烦的时候,说明你想测的逻辑很难触及。这本身就是一个坏味道了。
    想象一下,你写的任意业务逻辑,都可以很方便的被触及到,这不比手动测爽多了。
    lyxxxh2
        11
    lyxxxh2  
       15 天前
    小项目,我都是拿来当 "订单调试",也就订单有些逻辑。
    手工点击:
    1. 需要十几秒,还可能出错,
    2. 手累,不太想动 (这应该是主要)

    复杂的系统,比如 erp,就光一个创建订单。
    商品库存 库存 库存流水 对账 欠款... 都要肉眼去看是否正确,看到想吐。
    直接断言数据怎么样,断言失败再去看。
    而且后续修改代码,运行下测试,也知道各个功能正常。
    cxe2v
        12
    cxe2v  
       15 天前
    @dlmy 你这个现实中是想象的,实际的现实中:上线后,跑步进入下一个需求,上线了的绝不会再给资源让你补测试跟文档
    EthanDon
        13
    EthanDon  
       15 天前
    @EthanDon
    再想象一下,老板让你给一个很复杂的模块加个新功能,你吭哧吭哧搞完了,要交付了,怎么测试?通过 API 自己模拟各种情况吗?可以这么搞,也可以写成单测。
    测完了,你突然想起来这个模块以前就很复杂,有很多情况要回归测试,怎么办,再挨个挨个点 API 吗?这时候有单测的话,你只需要 make test 就结束啦
    redbule
        14
    redbule  
       15 天前
    单测需要良好的程序结构。用的时候嫌弃 java 依赖注入,接口多,测的时候才知道作用。
    软件工程没有捷径,一面简单了,另一面就要承受代价了
    chairuosen
        15
    chairuosen  
       15 天前
    单测的测试数据是 hook 进去的假数据,而不是真的读库。不依赖环境就能单独跑
    layxy
        16
    layxy  
       15 天前
    单元测试一方面用于自测,一方面用于 cicd 流程的卡点,即单元测试覆盖率和结果不达标无法进行某些操作,实际上中间件等偏技术类型的项目单元测试体验比较好,但是在业务场景,尤其是涉及到多个 rpc 调用时,单元测试的心智负担和工作量很大,不但要 mock rpc 服务,还要 mock 数据库操作,而且这样的单元测试覆盖并不全,仅能验证你的代码逻辑没有问题,但是不能验证整体功能没问题
    lambdaq
        17
    lambdaq  
       15 天前
    但是我每次看单元测试我都没搞懂这跟我手动 API 测试有啥区别?


    没区别。单元测试 就是把你手动 API 测试,持久化成一个调用,可以重复执行。
    Rickkkkkkk
        18
    Rickkkkkkk  
       15 天前
    单元测试的意义在于,另外一个人来开发,他搞完之后想看看之前功能是不是对的,总不能手动调 api 的方法测吧。
    wjfz
        19
    wjfz  
       14 天前
    论结果,单测和手动点 API 都是为了保证接口正常运行,但还是有区别的。

    1 、单测不需要在本地启动 server 服务,有时候项目大了,在本地起服务是很麻烦的事情。
    2 、单测可以一次写好到处运行,开发阶段自测,流水线以运行,其他同事可以运行。
    3 、不会产生脏数据。
    4 、高效,能并发同时跑很多单测,但是手动点 API 就不能。
    5 、单测是基于代码和业务的,目前很多 AI 生成单测都不好用。
    ThinkCat
        20
    ThinkCat  
       14 天前
    单元测试是为了保证功能符合预期,并且在长久的迭代中,仍然保证兼容,功能符合预期。
    比如这段功能,不管怎么变更代码,只要功能没有发生变化,以前的单侧输入 abc ,返回或者表现上就应该是 xyz 。并且单测最好是测最小功能单元,是可重复执行的,依赖的数据要 mock ,不随着外部环境的变化而变化
    irisdev
        21
    irisdev  
       14 天前
    起码有两个场景作用很大。1.你要改某个核心算法或者方法,改完之后单元测试跑一遍就知道有没有改坏,没有单元测试就很麻烦 2.单元测试相当于自描述的接口文档了,一般看到测试用例就知道这个方法干啥的,以及哪些场景可能会有坑
    trycatch
        22
    trycatch  
       14 天前
    单元测试核心是“单元”。
    大多数人的代码是不可测试的。
    要想写单元测试,首先让代码可测试,这个过程就优化了代码的结构设计。
    sampeng
        23
    sampeng  
       14 天前 via iPhone
    是没用,很多公司不给写单测时间。
    但是,但凡你改开源代码,面对几十万行不是你写的代码,你靠什么保证你改的东西不影响别人呢
    wanniwa
        24
    wanniwa  
       14 天前
    我一开始也抗拒单测,后来发现当有功能改动漏了什么场景,单测一下就能帮我发现问题,救了好几次命
    edisonwong
        25
    edisonwong  
       14 天前
    不写单测,后人都不知道影响面以及怎么去 mock 、测,靠 api ?复杂情况下你都不知道什么的对的,什么是错的
    MrVito
        26
    MrVito  
       14 天前
    @cxe2v #12 不不不,实际中的现实:上线后,跑步进入下一个需求,过了十天半个月,欸,那谁谁谁,之前的那个需求,你补下测试、文档,输出下报告,下班前给我哈
    COW
        27
    COW  
       14 天前   ❤️ 1
    从你第一句开始,我大概能猜到,你大概率是用错了。
    比如你有一个复杂的表单查询 API ,你通常并不需要去写单元测试去测这个 API ,去模拟各种参数传入调用 API ,这没有必要,这种场景通常用 postman 、jmeter 这类工具去做就可以了。
    单元测试通常是测 API 内部的业务逻辑,也就是针对模块化出来的代码单元去进行测试,当然并不是每个业务逻辑都需要测,涉及非常复杂的业务,你也可以先写单元测试,再写具体的代码逻辑。
    fregie
        28
    fregie  
       14 天前
    如果你觉得没什么用,说明你不需要
    等项目规模大了,自然就会觉得需要了
    reatang
        29
    reatang  
       14 天前
    调 API 的测试已经算是一种集成测试了。
    单元测试主要用在对原子功能的边界进行测试。
    yjxjn
        30
    yjxjn  
       14 天前   ❤️ 1
    你大概率理解错什么是单元测试了。
    单元测试是用于验证函数或方法的准确性。你也可以理解为测试范围只是局部的。
    只要是写的代码就有 bug ,那你如何通过不跑整体,来验证局部代码的正确性呢?你也不可能,100 个模块,你改了 1 个模块,你就让人家负责别的模块的人来帮你一起联调测试吧。
    手动调 api 测试,这已经不是单体测试范围了,是系统测试了。
    这才是一个正规发布流程。
    Request->Dev->UT>IT->ST->UAT->PreProd->Prod
    windyboy
        31
    windyboy  
       14 天前
    单元测试就是吧大,复杂问题转化为多个小的简单问题,逐步解决问题
    WilliamColton
        32
    WilliamColton  
       14 天前
    @yjxjn #29 新手请问一下集成测试和系统测试有什么区别啊?看了一些文章都没理解
    angrylid
        33
    angrylid  
       14 天前
    本意是好的,只不过业务变动频繁最后会导致你需要给测试代码编写测试。
    importmeta
        34
    importmeta  
       14 天前
    那些开源项目, 很多都有单元测试啊, 一方面有用, 另一方面会显得很专业.
    之前上班公司大佬自己写框架, 也会自己写单元测试.
    udisyue
        35
    udisyue  
       14 天前
    单元测试测的是你的代码段有没有问题,而 api 测试通常可能跑完了某一个业务中的部分流程,数据流过了一个或多个服务流转
    如果你的 api 非常简单就是接受数据,然后做个增删改查排序什么的然后返回,那测起来确实跟单元测试没什么区别
    如果你的 api 会要调用其他服务走业务流程,那就有区别了
    joyhub2140
        36
    joyhub2140  
       14 天前
    单元测试最重要的是那个上下文,然后测试的颗粒度可以细分到 method ,并且不依赖业务代码。
    BenHunDun
        37
    BenHunDun  
       14 天前
    当业务复杂的时候, 测试用例一多, 你修改代码后.
    跑单测可能一下子就结束了, 但是手动测试太麻烦了.
    kneo
        38
    kneo  
       14 天前
    我自己写的小项目就有几千个单元测试。我几分钟全跑完。

    我雇你手动跑,一分钟测一个,一天八小时只能测 480 个,一个月 20 天能测一万个。我一个月给你五千块工资,只能给我跑两次完整测试。然后你还总糊弄。实际上这一万次测试的报告,有一千例结果是真的就不错了。信你我不如自己写自动化测试。AI 也能写。别管 AI 蠢不蠢,至少是真干活,还便宜。
    yb2313
        39
    yb2313  
       14 天前
    不是一边写代码一边就写测试, 然后通过测试函数来测试到底能不能跑吗, 一般一个大功能就写一个测试函数
    FaiChou
        40
    FaiChou  
       14 天前
    做好一个功能,这个功能是否能用,通过单元测试走一遍,这就像 FF 的概念,输入必定有固定的输出。

    有时候看别人的库,直接从他的库的单元测试里面“拷贝”其中的 example 实现,比如可以直接这样:

    https://github.com/kishikawakatsumi/SMBClient/blob/main/Tests/SMBClientTests/SMBClientTests.swift
    guanzhangzhang
        41
    guanzhangzhang  
       14 天前
    单元测试可以保障很多方面:
    1. 你开发的功能,如何保证别人后续不改坏了,例如 runc 里有个 cve 就是 int32 大于 linux 的 0-65535 溢出提权成 uid 0 ,人家修复后加单元测试,一看简单明了的测试范围,后续有人改坏了也能看出这个要求
    2. 没有单元测试的下,大型项目依赖很多,每个人都一套环境的话,大小公司能这么多套环境吗,上次谷歌的故障就是开发嫌弃慢,改多人的开发环境怕影响别人,最后没单测提交到生产上线给整崩了
    3.即使项目小,那你功能模糊的参数啥的变来变去完全不记得之前的要求,测试人员每次测不符合预期啥的来找你沟通,你会花时间去耐心沟通吗
    luzemin
        42
    luzemin  
       14 天前
    单元测试的最大意义就是逼着你写出可以单元测试的代码
    shawn4me
        43
    shawn4me  
       13 天前
    大家都好规范,我写单元测试的目的是为了断点调试。可以进去看程序执行过程种的各种数据机构和上下文细节。

    顺便也能保证代码在按预期执行。
    ellermister
        44
    ellermister  
       13 天前
    我写了 n 多代码,至今没明白写单元测试的意义。
    举例要举极端,否则没意义。

    简单的代码,用不着测试,拿很多的教程示例来说 fun(a, b) return a + b; 这种代码有必要测吗?完全没必要?


    复杂的业务逻辑,比如订单系统,整个生命周期里,状态非常多,创建、待付款、付款、欺诈、取消、退款、退一半、业务中断、续费...... 有的状态可以回滚,不同阶段做不同的事情,各种接口提交的参数影响着流程,以及是否触发第三方接口进行同步进行。非常复杂,这种业务如何写单元测试?

    以 api 维度去拆解接口然后测试?还是内部函数最小化的方式拆解接口去写测试?
    无论哪种我都感觉无法覆盖数据,而且每一个函数的测试都要预先填充很多虚假数据进去然后测试?

    既然数据是虚假不变的,那结果可以认为是一定的。测试也没有了意义,我感觉只有把业务各个部件联通起来,写个测试,从开始到结束所有可能性都走一遍,自动化测试,这种才符合实际意义。因为你需要考虑到随机性,包含接口接受参数的随机性(各种异常参数),数据库存储带来的随机性(写入和读出格式并不完全一致),依赖服务崩溃的随机性等(服务意外崩溃时),这样当你成功跑完测试,才有意义啊。

    否则一堆虚假的数据,得到的必然是预定义的结果。感觉没意义。

    以上是我的主要困惑,有没有大佬解释下,如何正确理解单元测试这件事?
    liuhai233
        45
    liuhai233  
       13 天前
    @ellermister 订单系统 这种例子是最好单测的啊。
    每个功能单独测试,单元测试是功能级别的测试,不是整体流程的测试

    比如 续费 这个功能就可以单独写一些单元测试,续费 成功, 失败 边界 1 失败 边界 2 等等

    可以函数的维度去单元测试
    liuhai233
        46
    liuhai233  
       13 天前
    @ellermister 从开始到结束所有可能性都走一遍 这种我理解你可能指的 集成测试

    集成测试和单元测试都需需要的,保证质量的话都需要做
    msg7086
        47
    msg7086  
       13 天前   ❤️ 1
    顺便一提,测试比业务代码长是很正常的。
    要养成正确看待代码量的问题,写一个功能不是只把业务代码写完就算完事的了,是要设计+文档+业务代码+测试代码全加在一起才是完整做完一个功能。不写测试代码的结果就是以后会用成倍的时间去 debug 。成倍,成不知道多少倍。你现在用一周写完的核心代码,以后出了问题可能要用一个月甚至几个月的时间去修补。

    我上一家公司就是被这个拖垮的,修一个小问题要整个 team 出动修很久,修完这里那里炸,全部修完还要整个测试团队十几个人跑两三个星期做手动测试。没几年公司就寄了。

    现在这家公司这个 team 也是接手了一堆不带测试的屎山,我和另外一个人现在在 lead 给整个系统加装测试环境。
    Godjack
        48
    Godjack  
       13 天前
    samnya
        49
    samnya  
       12 天前 via Android
    对的,测试代码比逻辑要长是正常的,你看看复杂的 api 连参数都一大把,测试代码很多时候也是在初始化参数。
    如果在想具体什么时候要用,说明这部分代码还没这么重要。
    我的记忆里有写到测试的部分基本上都和钱有关,包括订单计价、优惠券应用、运费计算等等,这些手动测试本身就更麻烦,而且它属于核心部分,必须要每次部署都测试通过才能上线的。
    reallycool
        50
    reallycool  
       12 天前
    单元测试算是职业程序员和野路子程序员之间的门槛吧,现在各种端的程序员数量比较大,拉低了这个门槛
    micean
        51
    micean  
       12 天前
    单元测试从字面意义上来说就最小一部分的测试,如果是写 framework 、library 、tool 之类的,是很有价值的,当你开发完新功能后把以前的单元测试跑一边就能发现最基本的错误。如果是写业务,往往需要外部环境,连数据状态都是数据库、中间件去维护的,这种情况需要用其他测试方法了
    BestPix
        52
    BestPix  
       11 天前
    太有道理了。我现在没有单元测试,代码每跑一遍出一次问题,脑袋大
    guyeu
        53
    guyeu  
       11 天前
    单元测试还有一个很重要的作用,就是促使程序员编写出模块化程度高的代码。

    代码的模块化,高内聚低耦合巴啦巴啦应该是没有争议的吧?但是很多程序员还是很容易就写出来一坨糨糊一样的东西,如果一开始就考虑到单元测试的要求,程序员为了自己方便,就会去梳理、抽象、拆分,就能相对容易地编写出易测试的代码。

    某种程度上,容易被单元测试 ≈ 可读可维护。
    lscho
        54
    lscho  
       11 天前
    [我手动 API 测试不也能走一遍吗] 是,问题是单元测试就是把手动的东西自动化。项目稍微大一点,几千、几万甚至几十万的最小单元需要测试,你还手动吗
    slert
        55
    slert  
       11 天前
    道理都懂啊 多少人真的大量写单元测试呢 不如大家报出自己的单测覆盖率
    xuecat
        56
    xuecat  
       11 天前
    暂时不咋写单测,但是 git 的三方库不写单测我就很烦,因为很多接口没用例,就靠单测给我看了
    doveshelly
        57
    doveshelly  
       11 天前
    @slert 简单功能懒得写,复杂有难度的需求,我一般还是会很认真写的,因为自己也不保证写的过程中有没考虑漏的地方
    Meld
        58
    Meld  
       10 天前
    @slert 关键模块 100 ,自己插桩自己 mock
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2804 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 07:29 · PVG 15:29 · LAX 00:29 · JFK 03:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.