博为峰老师直接接听

400-029-09** 400-029-0997 转 18567
查看完整号码
扫码拨号
微信扫码拨号

对单元测试的思考(稳定性建设)

2024/5/13 16:27:56

背景单测是很常见的技术的名词,但背后的逻辑和原理你是否清楚,...

背景单测是很常见的技术的名词,但背后的逻辑和原理你是否清楚,让我们一起review一下。1. 单测是什么???单测是单元测试,主要是测试一个最小逻辑块。比如一个函数、一个react、vue?组件。2.为什么要写单测???这里有短期和长远,两个方面做打算:短期:希望开发者在开发过程中,就要想清楚多种case的情况,来检测这个最小单元的可靠性举个例:describe("test getUriEnd", () => { it("case1", async () => { const ret = getUriEnd(...); expect(ret).toBe("..."); }); it("case2", async () => { const ret = getUriEnd(...); expect(ret).toBe("..."); }); it("case3", async () => { const ret = getUriEnd(""); expect(ret).toBe("error"); }); it("case4", async () => { const ret = getUriEnd([]); expect(ret).toBe("error"); });});长期:从长期的维护角度来看的话,各个最小单元都是可能有被修改的风险。如果有完整的单侧的case,是可以保证:迭代、修改后的功能单元,不是会出现一些边缘问题并且长期来看:单侧也可以作为一个这个功能单元的使用说明书的作用。帮助开发更好的理解功能。3.单测是跑在什么环境的???是跑在node环境的。那为什么可以测试一些和浏览器环境相关的操作?比如:document.createElementtest("use jsdom in this test file", () => { const element = document.createElement("div"); expect(element).not.toBeNull(); });要设置当前单测运行的环境,否则上面的单测会报错,因为单测是跑在node环境的(我这里以jest为例)在jest内,需要配置?testEnvironment: "jsdom"??(不主动配置的话,这里是node,代表node环境)。jest文档:jestjs.io/zh-Hans/doc…那jest是怎么做到模拟浏览器环境的?jest用的是jsdom:github.com/jsdom/jsdom?(jsdom模拟浏览器环境的原理,可以参考jsdom的官网)。本质还是运行在node内,只不过用了jsdom来模拟浏览器环境。4.单测的原理是什么???原理是:给最小单元:提供运行时环境(node或浏览器环境,且包含对应依赖)。让这个最小单元在这个环境里面去执行,跑case,检验是否符合预期。5.单测中需要注意哪些问题?为什么单测会引发这些问题???单测的核心问题就是准备环境,为了让单测可以正常执行,我们需要准备好上下游环境,还有依赖环境。比如你要测试一个vue组件的props,那么你就需要为他准备好相关的vue实例,往单测的node环境里面注入Vue,例如?import { shallowMount } from "@vue/test-utils"import { shallowMount } from "@vue/test-utils"import Drawer from "@/components/common/drawer.vue"test("test drawer", () => { const wrapper = shallowMount(Drawer, { propsData: { direction: "top", show: true, canConfirm: true, title: "my drawer", leftText: "left text", rightText: "right text" } }) const text = wrapper.text() expect(text).toContain("my drawer") expect(text).toContain("left text") expect(wrapper.get(".drawer-top")).not.toBeNull() wrapper.find(".header-right").trigger("click") wrapper.find(".header-left").trigger("click") expect(wrapper.emitted()).toHaveProperty("onConfirm") expect(wrapper.emitted()).toHaveProperty("onCancel")})如果涉及到路由相关的话,那么还需要准备路由相关依赖。有些依赖实在不好准备的话,需要设置mock(比如依赖一个额外的SDK,但这个SDK没法在node里面的跑)。import { mount, createLocalVue } from "@vue/test-utils"import Register from "@/components/xxx.vue"import Vuex from "vuex"const localVue = createLocalVue()localVue.use(Vuex)jest.mock("@xxx/sdk.css", () => { // 这里设mock return ""})describe("test register", () => { const store = new Vuex.Store({ actions: {}, state: { form: { formData: { selectCountry: "", }, }, }, getters: { "user/userCountry": () => "" }, }) const wrapper = mount(Register, { store, localVue, mocks: { // 这里也可以设mock $route: { query: {} } } }) it("should vm", () => { expect(wrapper.vm).toBeTruthy() }) it("should xxx", () => { expect(wrapper.find("#xxxdom").exists()).toBeTruthy() })})如果涉及到接口请求的话,接口是下游rpc或者是服务发现的话,那么单侧环境是肯定调不通的。因为有环境隔离。这种情况下就只能Mock数据了。为什么单测会引发这些问题,感觉这么麻烦?因为单测是运行在node环境里跑,相当于本地,本地去掉下游rpc服务或走服务发现,本来就是不行的,因为环境隔离。本地加代理,也只能调通测试环境rpc服务单测环境是一个“干净”的环境,不主动准备的话 是没有node_modules的。如果你的测试单元 有各种依赖,单测环境肯定是没有的,除非你自己准备好 或者?mock模拟/代理掉6.哪些场景适合写单测???首先写单测肯定是有成本的,我个人认为,非常重要的toC项目才有必要写单测;先覆盖核心功能;功能单一的函数或组件是很适合写单测的。7.怎么定义一个单测写的好不好???单纯不考虑成本的话,那么一个单测的好坏应该是看这一个单元的功能覆盖率 + 边界case的覆盖情况。越多越好。8.对单测成本和收益的思考???团队内的任何决策都是有成本的,单测也不例外,需了解成本和收益后,再考虑在团队内推进。单测成本:主要是开发成本:写单测、code review,边界case覆盖。单测收益:未来的维护成本会更低,项目质量、稳定性更好。有利于倒逼开发写出高质量的代码、关注稳定性。我个人思考,还是想低成本得到所有好处(“我都要”):选择性写单测个人认为写单测的条件:toC且核心流程 + 很难自测的部分(边界case) + e2e或快照测试很难覆盖到的部分某些业务场景,后续肯定也是要自测的话,那这部分相关的可以不用写单测。e2e或快照测试,能覆盖到的,可以不写单测。链接:https://juejin.cn/post/7220054775298834487本文经授权转载,转载文章所包含的文字来源于作者。如因内容或版权等问题,请联系进行删除点击下方“阅读原文”,寻找职业新风向~

添加微信咨询
小博老师 @成都博为峰

提供专业的课程咨询服务

微信号:bwf******zx

立即咨询

“成都博为峰”是成都市锦江区博为峰职业技能培训学校有限公司在教育宝平台开设的店铺,若该店铺内信息涉嫌虚假或违法,请点击这里向教育宝反馈,我们将及时进行处理。

机构评分

环境:4.0师资:4.0服务:4.0效果:4.0

公示信息

店铺名称:成都博为峰

单位名称:成都市锦江区博为峰职业技能培训学校有限公司

账号名称:cdbwfjy(180******75)

所属城市:四川成都

入驻时长:22年

在线客服:在线聊

微信咨询

返回顶部