51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 567|回复: 0
打印 上一主题 下一主题

[资料] 我不写单元测试的原因

[复制链接]
  • TA的每日心情
    无聊
    3 天前
  • 签到天数: 1050 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2023-4-20 13:25:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    在一个多人协作的大型项目中,我们在开发的过程中可能经常会面临到这样的问题:
      ·哎,这次我没有改动到这里啊,这怎么会有bug呢
      · 哎,怎么新加了个功能原来的功能受影响了呢
      · 哎,这里的样式为什么乱掉了
      当我们被提出这些bug的时候,我们是二脸懵逼的,因为这不符合一个程序员的预期!!!那么我们如何能够避免以上的问题,从而将经历投入到更多的开发(写bug)中去呢?笔者在这里试着归纳了一下解决问题的办法
      样式问题需要制定相应的规范
      · 不能使用css,只能用less来书写(大哥,都2888年了还不用less吗)
      · 使用less的类模块化写法
      · 命名风格采用BEN
      (推荐)
      .app{
          width: 100%;
          .center{
              height: 100%
          }
      }


      (不推荐)
      .app{
          width: 100%;
      }
      .center{
          height: 100%
      }


      原有功能的可用性呢?
      其实之前就已经简单的了解过了单元测试,但当时对于单元测试我是持有一种很否定的态度的,因为他太过于鸡肋,都是测试一些很基础的功能,但是当笔者被这次重构折磨之后,有重新思考了下如何能够保证代码的健壮性,抱着这个态度,笔者又去调研了下单元测试到底能够做什么。
      再说它能够做什么之前,我们先来说说它是什么?
      从字面解析来看,那就是把你的代码,拆分成一个一个的单元,然后针对不同的单元,编写不同的测试用例
      那这时候我们就会有一个问题了,那如果单元测试通过了,那到底能不能就不需要测试同学再测试就直接上线了呢?
      按照我们的理想情况,如果我们的测试用例覆盖率达到了5个9以上,那应该是可以直接发布了,但是这个时候其实我们的内心还是会有一些疑虑,就是,那一个一个的模块都已经通过了,那集成在一起会不会有问题呢?这其实也是笔者到现在还不确定的问题。(获取集成测试能够解决?如果你已经有了答案,欢迎下方指正)
      基于此,笔者希望在前端编写测试用例能够实现以下的目标:
      ·先保证一个一个的模块基础功能正常
      · 增加新功能时,原有功能不受影响
      本着实现以上的要求,笔者下来介绍下具体的使用,关于不同测试框架的重点,这篇文章就不详细展开了,最终结合我们的项目,最终采用了facebook的jest+enzyme。重点将展开以下两种react组件类型测试。
      展示型组件测试
      展示型组件测试,意思就是要确保每一次的修改都是符合预期的,这里笔者要着重介绍下jest框架里面的shapshot功能。
      shapshot就是会对组件进行一次快照记录当前的状态,每一次run jest的时候,对比上一次,看看是否有变化。那最完美的情况就是,我们将所有的css样式打包,然后渲染出组件ui,对比上一次的纪录,看看是否有修改,但是很可惜,目前shapshot生成的快照文件里面只有class,并没有相关样式,除非你把所有样式写成style内联,那么他就能记录下你的style样式。看似好像没有达到我们的目标。
      但是仔细想想,这其实就违背了我们单元测试的初衷,笔者这里也大胆猜测下,jest官方在实现这个功能的时候,应该也只是想记录下一步一步的事件后,当前组件的html结构,对比上一次的快照,来看功能是否符合预期。代码的话比较简单:
      describe('XJLayerCard', () => {
          it('renders correctly', () => {
              const wrapper = Enzyme.render(<XJLayerCard {...mockData}/>);
              expect(toJson(wrapper)).toMatchSnapshot();
          })
      })


      功能型组件测试
      功能性组件测试,就是要覆盖到一个组件的基础功能,能够确保每一个修改之后,跑完单元测试,能够确定之前的功能正常。
      一开始我觉得单元测试很鸡肋的原因也是没有深入了解它,这次发现就算是和业务结合很紧密的组件,也能够模拟正常的操作,这里就贴一个和redux结合的组件来举例。
      import React from 'react';
      import Enzyme from 'enzyme';
      import AppInput from '../AppInput';
      import toJson from 'enzyme-to-json'
      import initialStore from '@/../__mocks__/store.js';
      import appInfoData from '@/../__mocks__/appInfo.js'
      import { Provider } from 'react-redux';
      import configureStore from '@/entries/maker/redux/store';
      import { updateAppInfo } from '@/entries/maker/redux/action';
      import moxios from 'moxios';
      import instance from '@/api/instance'
      import Adapter from 'enzyme-adapter-react-16';
      Enzyme.configure({ adapter: new Adapter() });
      let store;
      let wrapper;
      beforeEach(() => {
          moxios.install(instance);
          store = configureStore(initialStore)
          wrapper = Enzyme.mount(
              <Provider store={store}>
                  <AppInput onChange={(obj) => {
                      store.dispatch(updateAppInfo(obj))
                  }}/>
              </Provider>
          )
      })
      afterEach(function () {
          moxios.uninstall(instance);
      })
      describe('demo', () => {
          it('renders correctly', () => {
              expect(toJson(wrapper)).toMatchSnapshot();
          });
          it('click div, select show', () => {
              // 渲染选项框正常
              expect(wrapper.find('.xj-appinput-item').length).toEqual(2);
              // 一开始没有输入框
              expect(wrapper.find('input').length).toEqual(0);
              wrapper.find('.xj-appinput-value-wrapper').at(0).simulate('click');
              expect(wrapper.find('input').length).toEqual(1);
          });
          it('updateAppInfo action', (done) => {
              // 拦截请求
              moxios.stubRequest('/app/get', {
                  status: 200,
                  responseText: 'success'
              });
              // 点击下拉框中的第一个,会触发action
              wrapper.find('.xj-appinput-item').at(0).simulate('click');
              moxios.wait(() => {
                  // mock数据
                  let request = moxios.requests.mostRecent();
                  request.respondWith({
                      status: 200,
                      response: appInfoData
                  }).then((res) => {
                      // input输入框消失
                      expect(wrapper.find('input').length).toEqual(0);
                      // 选中的app展示出来
                      expect(wrapper.find('.xj-appinput-wrapper').length).toEqual(1);
                      expect(toJson(wrapper)).toMatchSnapshot();
                      done();
                  }).catch(err => {
                      console.log(err)
                  })
              });
          })
      })


      可以看到,这里的测试内容是结合了redux,axios库。那其实整个流程就是初始化这个组件,看看渲染的html结构是否符合预期,然后点击下拉框,选中其中第一个,发起请求,拉回详细数据,再观察组件是否展示正常,编写完测试用例后,就已经用代码模拟了整个手工操作,怎么样,是不是很强大?

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-24 12:04 , Processed in 0.063654 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表