Skip to content

自动化测试

统计信息:字数 5546 阅读12分钟

2021-10

开课吧的课程,整体废话比较多,条理性不强

手写 expect 测试函数

// 自定义单元测试函数
function test(description, fn) {
  try {
    fn();
    console.log(description, '通过测试');
  } catch (e) {
    console.error(e);
    console.log(description, '测试失败');
  }
}

function expect(ret) {
  return {
    toBe(arg) {
      if (ret !== arg) {
        throw Error(`测试不符合,预期是${arg},实际是${ret}`);
      }
    }
  };
}

test('test add fn', () => {
  expect(add(1, 2)).toBe(2);
});

VUE 中的测试

Vue 中的组件可以测试,可以使用官方的测试组件

// Vue Test Utils
import { shallowMount } from '@vue/test-utils';
import MyCom from './MyComponent.vue';

// 挂载组件
const wrapper = shallowMount(MyCom);

describe("test component", () => {

  // 判断组件的生命周期函数
  it('create fn', () => {
    expect(typeof MyCom.created).tobe('function');
  });

  // 判断函数的默认值
  it('test fn result', () => {
    expect(typeof MyCom.data).toBe('function');
    const defaultData = MyComponent.data();
    expect(defaultData.message).toBe('hello');
  });

  if('updates the rendered message', async () => {
    const wrapper = shallowMount(MyCom);
    wrapper.setData({ message: 'foo' });
    await wrapper.vm.$nextTick();
    expect(wrapper.text()).toBe('foo');
  });
});

具体测试案例

生命周期函数可以在默认环境下直接测试(不依赖于浏览器或者node环境);DOM 点击事件需要依赖第三方库实现

<template>
    <div id="app">
    <h1>{{message}}</h1>
    <button @click="update"></button>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      message: 'init',
    }
  },
  created() {
    this.message = 'created'
  },
  methods: {
    update() {
      this.message = 'update'
    }
  }
}
</script>

<style>
</style>

在 package.json 中配置 jest

{
  "jest": {
    "preset": "@vue/cli-plugin-unit-jest",
    "collectCoverage": true,
    "collectCoverageFrom": ["src/**/*.{js,vue}"]
  }
}

测试文件 app.spec.js

import App from '../../src/App.vue';
import { mount } from '@vue/test-utils';

describe('test app', () => {
  it('init state', () => {
    expect(typeof App.created).toBe('function');
  });

  it('component data', () => {
    let defaultData = App.data();
    expect(defaultData.message).toBe('init');
  });

  it('test click btn', () => {
    const wrapper = mount(App);
    wrapper.find('button').trigger('click');
    expect(wrapper.vm.message).toBe('update');
    // dom 更新需要时间,所以在 nextTick 测试
    Vue.nextTick(() => {
      expect(wrapper.find('h1').html()).toBe('<h1>update</h1>')
    });
  });

  // 或者写成 es6 的语法
  it('test es6 click btn', async () => {
    expect(wrapper.text()).toContain('0');
    const btn = wrapper.find('button');
    btn.trigger('click');
    await Vue.nextTick();
    expect(wrapper.text()).toContain('1');
  });
});

解释:点击后,更新会引发 DOM 变化,需要使用 Vue.nextTick 等待 Vue 完成 DOM 更新。

可以把 vue-test-utils.vuejs.org 中的全部案例敲一次,这样基本的 VUE 测试就没问题了。

api 异步函数测试

import axios from 'axios';

export default {
  data() {
    return {
      value: null
    }
  },
  methods: {
    async fetchResults() {
      const response = await axios.get('mock/service');
      this.value = response.data;
    }
  }
}

这样可以 mock 假数据测试

import { shallowMount } from '@vue/test-utils';
import Foo from './Foo';

jest.mock('axios');

it('fetch async when btn clicked', () => {
  const wrapper = shallowMount(Foo);
  wrapper.find('button').trigger('click');
  expect(wrapper.vm.value).toBe('value');
});

如果是 ts 更改配置

npm install --save-dev ts-jest

package.json 更改配置(正则匹配入口)

{
  "jest": {
    "transform": {
      "^.+\\.tsx?$": 'ts-jest'
    }
  }
}

node 中的测试(koa)

通常需要登录验证,或者数据获取

describe('test koa', () => {
  beforeAll(() => {
    fs.writeFileSync('../db.json', JSON.stringify({}));
  });
  afterAll(() => {
    fs.removeFileSync('../db.json', JSON.stringify({}));
  })
  it('read data', () => {
    let db = new Kdb('db.json');
    expect(db.getState()).toEqual({});
  })
  it('read key', () => {
    let db = new Kdb('db.json');
    expect(db.get('todos').read()).toEqual([]);
  })
})

中间件测试

const request = require('supertest');
const assert = require('assert');
const Koa = require('koa');

describe('app content', () => {
  const app1 = new Koa();
  app1.context.msg = 'MichaelAn';
  const app2 = new Koa();

  it('merge perperties', () => {
    app1.use((ctx, next) => {
      assert.equal(ctx.msg, 'MichaelAn');
      ctx.body = 'xx';
      ctx.status = 200;
    });
    return request(app1.listen())
    .get('/')
    .expect('xx')
    .expect(200)
  });
})

附加1:自定义 github 徽章:https://shields.io/

附加2:github 有时候网速很慢,克隆代码较慢技巧:打开 gitee 码云,从 github 导入到码云,然后直接下载;gitee 应该做了一下缓存和代理,这样下载代码就很快了。然后更新代码时,可以更改 remote source。

附加3:cloc 可以统计某个目录下面的文件类型和数量(通常测试文件是代码的2倍)


Last update: November 9, 2024