vue+mocha+chai+vue-cli-test-utils写单元测试时,关于测试用例的一些疑问

一、问题背景
初次写单元测试,对于复杂的测试样例不知道怎么写,而且更重要的是,不确定自己写的断言是否合理。

请教:下面几个我想实现的测试用例,应该如何写,并且,这几个断言是合理的吗?不合理的话,应该怎么做呢?

二、代码

Manage.vue

<template lang="pug">
    div
        s-tabs.mins.mb-5(@tab-change="tabChange" ref="testtab")
            s-tabs-nav
                s-tab(href="tab-word") 敏感词管理
                s-tab(href="tab-categoryReson") 类型原因管理

            s-tabs-content
                s-tabs-item(id="tab-word")
                    s-row.mb-2
                        s-col(xs12
                            sm8
                            lg6
                            xl4
                            v-for="(item, index) in categoryListWithoutData")
                            s-checkbox(
                                :label="item.name"
                                v-model="categoryListWithoutData[index].isCheck"
                                @change="categoryListChange")
                    
                    s-row.mb-4
                        s-checkbox(
                            v-model="isCheckeAll"
                            label="全选"
                            @change="allCheckChange")
                        

                    s-row.mb-4.justify-space-bwtween
                        s-search-box(:search="searchWord")
                            template(slot="base")
                                s-search-column
                                    s-input(v-model="wordSearchParams.wordName"
                                        placeholder="输入敏感词进行搜索"
                                        width="300px")
                        
                        router-link.right.ml-10(:to="'/sensitive-word/createWord'" target="_blank")
                            s-btn 新增

                    s-table.highlight(:data="wordList"
                        max-height="840"
                        border)
                        template(slot="empty")
                            Loading(v-if="isLoading")
                            span(v-else) 暂无数据

                        s-table-column(label="词类型")
                            template(slot-scope="scope")
                                span {{scope.row && scope.row.category_name}}

                        s-table-column(label="原因" min-width="120px")
                            template(slot-scope="scope")
                                span {{scope.row.reason}}

                        s-table-column(label="词汇" min-width="220px")
                            template(slot-scope="scope")
                                span(v-for="(item, index) in scope.row.word_list"
                                    :class="{'text-error': wordSearchParams.wordName != '' && item.word == wordSearchParams.wordName}") {{ item.word }}
                                    i(v-if="index < scope.row.word_list.length - 1") ,&nbsp;

                        s-table-column(label="操作" min-width="80")
                            template(slot-scope="scope")
                                router-link.underline(
                                    target="_blank"
                                    :to="{name: 'editWord', query: { 'category_id': scope.row.category_id, 'reason_id': scope.row.reason_id }}") 编辑
                            
                                //- a.underline(href="javascript:void(0);" @click="gotoEdit") 编辑
                    
                    Pagination(v-if="wordPageInfo.total" :page="wordPageInfo" :change="changeWordPage")

                
                s-tabs-item(id="tab-categoryReson")
                    s-tabs(min)
                        s-tabs-nav
                            s-tab(href="tab-category") 词类型
                            s-tab(href="tab-reason") 违禁原因
                        s-tabs-content
                            s-tabs-item(id="tab-category")
                                s-row.justify-space-bwtween
                                    s-search-box(:search="searchCategory")
                                        template(slot="base")
                                            s-search-column
                                                s-input(v-model="categorySearchParams.categoryName"
                                                    placeholder="输入词类型进行搜索"
                                                    width="300px")
                                    s-btn(@click.native="createCategory") 新增

                                s-table.highlight(:data="categoryListWithData"
                                    border)
                                    template(slot="empty")
                                        Loading(v-if="isLoading")
                                        span(v-else) 暂无数据

                                    s-table-column(label="序号")
                                        template(slot-scope="scope")
                                            span {{scope.$index + 1}}

                                    s-table-column(label="创建时间" min-width="100px")
                                        template(slot-scope="scope")
                                            span {{scope.row.created_time}}

                                    s-table-column(label="词类型" min-width="180px")
                                        template(slot-scope="scope")
                                            span {{scope.row.name}}
                                    
                                    s-table-column(label="词汇数量" min-width="180px")
                                        template(slot-scope="scope")
                                            span {{scope.row.word_count}}

                                    s-table-column(label="操作")
                                        template(slot-scope="scope")
                                            a.mr-4.underline(href="javascript:void(0)" @click="editCategory(scope.row)") 编辑
                                            a.underline(href="javascript:void(0)" @click="deleteCategory(scope.row)") 删除

                                Pagination(v-if="categoryPageInfo.total" :page="categoryPageInfo" :change="changeCategoryPage")


                            s-tabs-item(id="tab-reason")
                                s-row.justify-space-bwtween
                                    s-search-box(:search="searchReason")
                                        template(slot="base")
                                            s-search-column
                                                s-input(v-model="reasonSearchParams.reason"
                                                    placeholder="输入违禁原因进行搜索"
                                                    width="300px")
                                    s-btn(@click.native="createReason") 新增

                                s-table.highlight(:data="reasonListWithData"
                                    border)
                                    template(slot="empty")
                                        Loading(v-if="isLoading")
                                        span(v-else) 暂无数据

                                    s-table-column(label="序号")
                                        template(slot-scope="scope")
                                            span {{ (reasonPageInfo.per_page ) * (reasonPageInfo.current_page - 1) + scope.$index + 1 }}

                                    s-table-column(label="创建时间" min-width="100px")
                                        template(slot-scope="scope")
                                            span {{scope.row.created_time}}

                                    s-table-column(label="违禁原因" min-width="180px")
                                        template(slot-scope="scope")
                                            span {{scope.row.reason}}
                                    
                                    s-table-column(label="词汇数量" min-width="180px")
                                        template(slot-scope="scope")
                                            span {{scope.row.word_count}}

                                    s-table-column(label="操作")
                                        template(slot-scope="scope")
                                            a.mr-4.underline(href="javascript:void(0)" @click="editReason(scope.row)") 编辑
                                            a.underline(href="javascript:void(0)" @click="deleteReason(scope.row)") 删除

                                Pagination(v-if="reasonPageInfo.total" :page="reasonPageInfo" :change="changeReasonPage")
                
</template>

<script>
import loading from '@/mixins/loading'
import pagination from '@/mixins/pagination'
import sensitiveWordApi from '@/api/sensitiveWord'
import CreateWord from '@/views/common/sensitiveWord/CreateWord';
import CreateCategory from '@/views/common/sensitiveWord/CreateCategory';
import CreateReason from '@/views/common/sensitiveWord/CreateReason';
import EditCategory from '@/views/common/sensitiveWord/EditCategory';
import EditReason from '@/views/common/sensitiveWord/EditReason';
import DeleteCategory from '@/views/common/sensitiveWord/DeleteCategory';
import DeleteReason from '@/views/common/sensitiveWord/DeleteReason';
import { trimObject } from '@/util';

export default {
    name: 'sensitiveWord',
    mixins: [loading, pagination],
    data() {
        return {
            isCheckeAll: false,
            channelList: [],
            wordList: [],
            categoryListWithoutData: [],
            categoryListWithData: [],
            categoryPageInfo: {
                current_page: 1
            },
            categorySearchParams: {
                categoryName: ''
            },
            reasonListWithData: [],
            reasonPageInfo: {
                current_page: 1
            },
            reasonSearchParams: {
                reason: ''
            },
            isLoading: true,
            curTab: 'tab-detail',
            wordPageInfo: {
                current_page: 1
            },
            wordSearchParams: {
                wordName: ''
            }
        }
    },
    mounted() {
        sensitiveWordApi.getCategoryListWithoutData()
        .then((data)=> {
            // let categoryIdList = [];
            this.categoryListWithoutData = data;

            // 默认不用勾选全部词类型
            // for(let i = 0; i < this.categoryListWithoutData.length; i++) {
            //     this.categoryListWithoutData[i].isCheck = false;
            // }

            Promise.all([
                sensitiveWordApi.getWordList(),
                sensitiveWordApi.getCategoryListWithData({is_paging: 1}),
                sensitiveWordApi.getReasonListWithData({is_paging: 1}),
            ]).then((datas)=> {
                this.wordList = datas[0].items;
                this.wordPageInfo = {
                    current_page: datas[0].page_info.page,
                    total: datas[0].page_info.total,
                    per_page: datas[0].page_info.page_size
                };

                this.categoryListWithData = datas[1].category_list;
                this.categoryPageInfo = {
                    current_page: datas[1].page_info.page,
                    total: datas[1].page_info.total,
                    per_page: datas[1].page_info.page_size
                };

                
                this.reasonListWithData = datas[2].reason_list;
                this.reasonPageInfo = {
                    current_page: datas[2].page_info.page,
                    total: datas[2].page_info.total,
                    per_page: datas[2].page_info.page_size
                };

                this.isLoading = false;
            })
        })
    },
    methods: {
        allCheckChange() {
            if(this.isCheckeAll) {
                this.checkAllCategory()
            } else {
                this.notCheckAllCategory()
            }
            this.searchWord();
        },
        createWord() {
            this.$starfish.dialog.open({
                component: CreateWord,
                props: {}
            });
        },
        createCategory() {
            this.$starfish.dialog.open({
                component: CreateCategory,
                props: {
                    reloadFun: this.searchCategory
                }
            });
        },
        createReason() {
            this.$starfish.dialog.open({
                component: CreateReason,
                props: {
                    reloadFun: this.searchReason
                }
            });
        },
        editCategory(item) {
            this.$starfish.dialog.open({
                component: EditCategory,
                props: {
                    data: {
                        category: item
                    },
                    reloadFun: this.searchCategory
                }
            });
        },
        editReason(item) {
            this.$starfish.dialog.open({
                component: EditReason,
                props: {
                    data: {
                        reason: item
                    },
                    reloadFun: this.searchReason
                }
            });
        },
        deleteCategory(item) {
            this.$starfish.dialog.open({
                component: DeleteCategory,
                props: {
                    data: {
                        category: item
                    },
                    reloadFun: this.searchCategory
                }
            });
        },
        deleteReason(item) {
            this.$starfish.dialog.open({
                component: DeleteReason,
                props: {
                    data: {
                        reason: item
                    },
                    reloadFun: this.searchReason
                }
            });
        },
        /* getCategoryListWithData() {
            this.isLoading = true;
            sensitiveWordApi.getCategoryListWithData().then((data)=> {
                this.categoryListWithData = data.category_list;
                this.categoryPageInfo = {
                    current_page: data.page_info.page,
                    total: data.page_info.total,
                    per_page: data.page_info.page_size
                };
                this.isLoading = true;
            });
        }, */
        /* getReasonListWithData() {
            this.isLoading = true;

            sensitiveWordApi.getReasonListWithData().then((data)=> {
                this.reasonListWithData = data.reason_list;
                this.reasonPageInfo = {
                    current_page: data.page_info.page,
                    total: data.page_info.total,
                    per_page: data.page_info.page_size
                };
                this.isLoading = true;
            });
        }, */
        tabChange(tab) {
            this.curTab = tab;
        },
        categoryListChange() {
            this.wordPageInfo.current_page = 1;

            // 更新全选按钮状态
            if(this.getCategoryIdList().length == this.categoryListWithoutData.length) {
                this.isCheckeAll = true;
            } else {
                this.isCheckeAll = false;
            }

            this.searchWord();
        },
        searchWord() {
            this.isLoading = true;

            let params = {
                category_id_list: this.getCategoryIdList().length > 0? JSON.stringify(this.getCategoryIdList()): '',
                word_name: this.wordSearchParams.wordName,
                page: this.wordPageInfo.current_page,
                limit: this.wordPageInfo.per_page
            }
            
            sensitiveWordApi.getWordList(trimObject(params)).then((data)=> {
                this.wordList = data.items;
                this.wordPageInfo = {
                    current_page: data.page_info.page,
                    total: data.page_info.total,
                    per_page: data.page_info.page_size
                };

                this.isLoading = false;
            })
            
        },
        searchCategory() {
            this.isLoading = true;

            let params = {
                category_name: this.categorySearchParams.categoryName,
                is_paging: 1,
                page: this.categoryPageInfo.current_page
            }
            
            sensitiveWordApi.getCategoryListWithData(trimObject(params)).then((data)=> {
                this.categoryListWithData = data.category_list;
                this.categoryPageInfo = {
                    current_page: data.page_info.page,
                    total: data.page_info.total,
                    per_page: data.page_info.page_size
                };

                this.isLoading = false;
            })
            
        },
        searchReason() {
            this.isLoading = true;

            let params = {
                reason: this.reasonSearchParams.reason,
                is_paging: 1,
                page: this.reasonPageInfo.current_page
            }
            
            sensitiveWordApi.getReasonListWithData(trimObject(params)).then((data)=> {
                this.reasonListWithData = data.reason_list;
                this.reasonPageInfo = {
                    current_page: data.page_info.page,
                    total: data.page_info.total,
                    per_page: data.page_info.page_size
                };

                this.isLoading = false;
            })
            
        },
        changeWordPage(page) {
            this.wordPageInfo.current_page = page;
            this.searchWord()
        },
        getCategoryIdList() {
            let categoryIdList = []

            for(let i = 0; i < this.categoryListWithoutData.length; i++) {
                if(this.categoryListWithoutData[i].isCheck) {
                    categoryIdList.push(this.categoryListWithoutData[i].id)
                }
            }

            return categoryIdList
        },
        notCheckAllCategory() {
            for(let i = 0; i < this.categoryListWithoutData.length; i++) {
                this.categoryListWithoutData[i].isCheck = false;
            }
        },
        checkAllCategory() {
            for(let i = 0; i < this.categoryListWithoutData.length; i++) {
                this.categoryListWithoutData[i].isCheck = true;
            }
        },
        changeCategoryPage(page) {
            this.categoryPageInfo.current_page = page;
            this.searchCategory()
        },
        changeReasonPage(page) {
            this.reasonPageInfo.current_page = page;
            this.searchReason()
        },
    }
}
</script>

<style lang="scss" scoped>
.search-box {
    max-width: none;
}
.underline {
    text-decoration: underline;
}
.justify-end {
    justify-content: flex-end;
}
.justify-space-bwtween {
    justify-content: space-between;
}
.item-flex-end {
    align-self: flex-end;
}
.text-ellipsis {
    overflow: hidden;
    max-width: 100%;
    text-overflow: ellipsis;
    white-space: nowrap;
}
</style>

Manage.spec.js

import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import Vue from 'vue'
import Manage from '@/views/common/sensitiveWord/Manage.vue'

describe('Manage.vue', () => {
  const Constructor = Vue.extend(Manage);
  const vm = new Constructor().$mount();

  it('包含data钩子', () => {
    // 测试用例应该如何实现?另外,这个断言是否合理?不合理的话,应该如何写才合理呢
  });

  it('页面加载时,应该先加载敏感词类型列表', ()=> {
    // 测试用例应该如何实现?另外,这个断言是否合理?不合理的话,应该如何写才合理呢
  });

  it('categoryListWithoutData应该是一个数组', ()=> {
    // 测试用例应该如何实现?另外,这个断言是否合理?不合理的话,应该如何写才合理呢
  })

  it('点击新增按钮时,应该在新标签中打开新增敏感词页面', ()=> {
    // 测试用例应该如何实现?另外,这个断言是否合理?不合理的话,应该如何写才合理呢
  })

  it('点击查询按钮时,应该根据筛选项获取敏感词列表', ()=> {
    // 测试用例应该如何实现?另外,这个断言是否合理?不合理的话,应该如何写才合理呢
  })

})

三、延伸问题
1、初次接触,不知道从哪里开始写起,是否有什么先后顺序、规律可遵循?(有的话,求分享一下关键词、或者资料链接,谢谢)

阅读 1.8k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题