美文网首页前端自动化测试学习
前端自动化测试BDD与集成测试学习记录

前端自动化测试BDD与集成测试学习记录

作者: Mstian | 来源:发表于2020-06-23 23:31 被阅读0次

    BDD(Behavior Driven Development)行为驱动开发

    集成测试: 完全是用测试脚本去模拟用户操作,比如打开浏览器,点击登录,输入用户名,密码等。然后判断是否达到预期的结果来进行测试。
    概念解释:

    story:一个场景,可以理解成一个步骤,用户某一阶段操作的集合。

    比如在例子TodoList中,用户在header输入框中输入内容,敲击enter键,对应下面任务列表新增一个任务。这就是一个story。

    先看一个BDD的例子:

    import { mount } from '@vue/test-utils'
    import TodoList from '../../TodoList.vue'
    import { createWrapper } from '../../../../utils/utilTest'
    
    it(`
        1. 输入内容
        2. 触发事件
        3. 列表项增加
    `,async () => {
        const wrapper = mount(TodoList)
        let inputEle = createWrapper(wrapper, 'test-input').at(0)
        const content = "hello"
        inputEle.setValue(content)
        await inputEle.trigger('change')
        await inputEle.trigger("keyup.enter")
        const listItem = createWrapper(wrapper,'test-item')
        expect(listItem.length).toBe(1)
        expect(listItem.at(0).text()).toContain(content)
    })
    
    

    首先模拟用户行为,分为三个步骤,第一步输入内容,第二步触发事件,第三步对应列表项增加,依次步骤为指导然后写测试用例,在写的过程中,由于模拟用户行为时,进行了跨组件测试,因此使用集成测试的方案,使用mount进行深度渲染。注意在写有触发事件的测试用例中,使用async/await异步处理方式,否则时间执行结果无法获取到。

    通过例子分析TDD与BDD两种模式

    TDD:

    • 先写测试再写代码
    • 一般结合单元测试使用,是白盒测试(看着代码测试,测试代码与业务代码耦合度高)
    • 测试重点在代码
    • 安全感低(单个组件或模块通过测试,不代表组合在一起就没问题)
    • 速度快(采用shallowMonut方法,只渲染一层)

    BDD:

    • 先写代码再写测试
    • 一般结合集成测试使用,是黑盒测试(从用户角度只关注界面,行为,结果。一般涉及到多组件,不知道具体代码逻辑)
    • 测试重点在UI(DOM)
    • 安全感高(如果测试通过,即可认为在用户端可以放心使用)
    • 速度慢(采用mount方法,将整个组件树都挂载出来)

    Vuex项目测试例子

    import { mount } from '@vue/test-utils'
    import TodoList from '../../TodoList.vue'
    import { createWrapper } from '../../../../utils/utilTest'
    import store from '../../../../store'
    it(`
        1. 输入内容
        2. 触发事件
        3. 列表项增加
    `, async () => {
      const wrapper = mount(TodoList, {
        store
      })
      var inputEle = createWrapper(wrapper, 'test-input').at(0)
      const content = 'hello'
      inputEle.setValue(content)
      await inputEle.trigger('change')
      await inputEle.trigger('keyup.enter')
      const listItem = createWrapper(wrapper, 'test-item')
      expect(listItem.length).toBe(1)
      expect(listItem.at(0).text()).toContain(content)
    })
    
    

    在项目中使用了Vuex时,在测试时需要将store引入到测试组件中,否则测试组件中是没有Vuex的。具体就是在渲染组件的时候进行传参。

    const wrapper = mount(TodoList, {
      store
    })
    

    两种测试模式混合使用

    比如上面代码是对项目功能进行的集成测试

    同时也可以在项目中再使用单元测试

    比如对Vuex中的逻辑进行单元测试

    import store from '../../../../store'
    it("测试提交commit inputValue跟着变化", () => {
      const content = '123'
      store.commit("changeInputValue",content)
      expect(store.state.inputValue).toBe(content)
    })
    
    

    两种测试模式如何选取?

    测试业务的时候一般选择BDD+集成测试

    测试函数库的时候优先选择TDD+单元测试

    一般情况下可以采用两种模式结合使用对项目进行测试。

    异步测试

    比如在组件中需要使用axios获取数据并显示到页面中,此时的测试策略如下:

    首先前端测试不去测试请求返回值的格式以及数据正确与否,这一步应该是由后端支持。否则通过调取后端数据既耗时又耗资源,对于前端测试来说比较慢,等等。

    然后异步测试主要是前端根据与后端协商好的数据格式等,自行模拟一个前端数据,然后进行测试。

    在containers/TodoList文件夹下创建__mocks__文件夹然后创建一个axios.js文件

    const list = {
        success: true,
        data: [
            {
                type: 'div',
                value: 'hello'
            },
            {
                type: 'div',
                value: 'sasasa'
            }
        ]
    }
    
    export default {
        get(url) {
            if (url == "/getList.json") {
                return new Promise((resolved, rejected) => {
                    setTimeout(() => {
                        resolved(list)
                    }, 3000)
                })
            }
        }
    }
    

    __tests__/integration/TodoList.js

    import { mount } from '@vue/test-utils'
    import TodoList from '../../TodoList.vue'
    import { createWrapper } from '../../../../utils/utilTest'
    import store from '../../../../store'
    beforeEach(()=>{
      jest.useFakeTimers()
    })
    it(`
        1. 首次进入从远程获取数据
        2. 将数据展示到列表中
    `, () => {
      const wrapper = mount(TodoList, {
        store
      })
      jest.runAllTimers()
      wrapper.vm.$nextTick().then(() => {
        const listItems = createWrapper(wrapper, 'test-item')
        expect(listItems.length).toBe(2)
      })
    })
    

    需要注意的是:使用setTimeout的时候需要使用jest.useFakeTimers()去做处理,然后在使用异步获取数据的时候,需要使用Vue实例的nextTick()方法中再去做断言。

    模拟异步失败测试:比如axios获取数据失败,组件应该显示0条数据

    设置一个变量控制axios的resolved和rejected执行

    export default {
        get(url) {
            if (url == "/getList.json") {
                return new Promise((resolved, rejected) => {
                    if(this.success){
                        resolved(list)
                    }else{
                        rejected(new Error())
                    }
                })
            }
        }
    }
    

    在测试用例中:

    import axios from '../../__mocks__/axios.js'
    beforeEach(()=>{
      axios.success = true
    })
    it(`
        1. 首次进入从远程获取数据失败时应该展示0条
        2. 将数据展示到列表中
    `, (done) => {
      axios.success = false
      const wrapper = mount(TodoList, {
        store
      })
      wrapper.vm.$nextTick().then(() => {
        const listItems = createWrapper(wrapper, 'test-item')
        expect(listItems.length).toBe(0)
        done()
      })
    })
    
    

    注意,由于$nextTick为异步执行,所以需要配合done方法使用,否则测试代码只会走到nextTick上面便认为测试通过。

    源代码地址:https://github.com/Mstian/inte-test

    相关文章

      网友评论

        本文标题:前端自动化测试BDD与集成测试学习记录

        本文链接:https://www.haomeiwen.com/subject/kvtlfktx.html