zoukankan      html  css  js  c++  java
  • vue自动化单元测试

     1 // 引用vue和需要测试的组件
     2 import Vue from 'vue'
     3 import HelloWorld from '@/components/HelloWorld'
     4 // 创建测试套件,一个测试组件写一个测试套件
     5 describe('HelloWorld.vue', () => {
     6   // 测试用例,用来测试不同的方法或者显示的内容
     7   it('should render correct contents', () => {
     8     const Constructor = Vue.extend(HelloWorld)
     9     const vm = new Constructor().$mount()
    10     // 判断页面中是否有msg所渲染出来的内容
    11     // 等价document.querySelector('.hello h1')
    12     expect(vm.$el.querySelector('.hello h1').textContent)
    13       .to.equal('Welcome to Your Vue.js App')
    14   })
    15 })

     模仿微博的自动化测试代码:

      1 import Vue from 'vue'
      2 import SineWeibo from '@/components/SinaWeibo'
      3 import {mount} from 'vue-test-utils'
      4 // 创建测试套件
      5 describe('SinaaWeibo.vue',()=>{
      6 // 创建测试实例------点击发布按钮,发布新内容&&个人微博数量+1
      7   it('点击发布按钮,发布新内容&&个人微博数量+1',()=>{
      8     // 找到要测试的组件实例,进行挂载
      9     const wrapper=mount(SineWeibo);
     10     // 找到发表微博的输入内容
     11     const textArea=wrapper.find('.weibo-publish-wrapper textarea')
     12     // 发布按钮
     13     const buttonOfPublish = wrapper.find('.weibo-publish-wrapper button')
     14     // weiboNews是从mock中获取的数据,是微博的初始值
     15     const lengthOfWeiboNews = wrapper.vm.weiboNews.length;
     16     // 右边的关注/粉丝/微博和其数量:2是微博数
     17     const countOfMyWeibo=wrapper.vm.profileData[2].num;
     18     // 模拟新的微博内容
     19     wrapper.setData({newWeiboContent:{
     20         imgUrl: '../../static/image/profile.jpg',
     21         name: 'Lee_tanghui',
     22         resource: '刚刚 来自 网页版微博',
     23         content: '欢迎来到我的微博',
     24         images: []
     25       }})
     26     // 触发发布按钮事件
     27     buttonOfPublish.trigger('click')
     28     // 获取增加后的微博条数,和右边的微博数量
     29     const lengthOfWeiboNewsAfterPublish=wrapper.vm.weiboNews.length;
     30     const countOfMyWeiboAfterPublish=wrapper.vm.profileData[2].num
     31     //断言: 发布后的微博条数是在原来的基础上+1;
     32     expect(lengthOfWeiboNewsAfterPublish).to.equal(lengthOfWeiboNews + 1);
     33     //断言: 个人微博数量是在原来的基础上+1;
     34     expect(countOfMyWeiboAfterPublish).to.equal(countOfMyWeibo + 1);
     35   })
     36   // 测试实例:当文本框无内容时候,不能发表微博到列表,且弹出提示框
     37   it('当文本框中无内容时, 不能发布空微博到微博列表, 且弹出提示框',()=>{
     38     const wrapper=mount(SineWeibo);
     39     // 找到发布框内容
     40     const textArea = wrapper.find('.weibo-publish-wrapper textarea');
     41     // 找到发布按钮
     42     const buttonOfPublish = wrapper.find('.weibo-publish-wrapper button');
     43     // 获取下方微博条数
     44     const lengthOfWeiboNews = wrapper.vm.weiboNews.length;
     45     // 获取右边微博数
     46     const countOfMyWeibo = wrapper.vm.profileData[2].num;
     47     // 设置发表微博,但是content的内容为空
     48     //设置textArea的绑定数据为空
     49     wrapper.setData({newWeiboContent: {
     50         imgUrl: '../../static/image/profile.jpg',
     51         name: 'Lee_tanghui',
     52         resource: '刚刚 来自 网页版微博',
     53         content: '',
     54         images: []
     55       }});
     56     // 触发发布按钮
     57     buttonOfPublish.trigger('click');
     58     // 获取发表后的下方微博条数
     59     const lengthOfWeiboNewsAfterPublish = wrapper.vm.weiboNews.length;
     60     // 获取发表后的下右边微博数
     61     const countOfMyWeiboAfterPublish = wrapper.vm.profileData[2].num;
     62     // 断言:发表前后的微博条数是相等的
     63     //断言: 没有发布新内容
     64     expect(lengthOfWeiboNewsAfterPublish).to.equal(lengthOfWeiboNews);
     65     //断言: 个人微博数量不变
     66     expect(countOfMyWeiboAfterPublish).to.equal(countOfMyWeibo);
     67   });
     68 
     69 
     70   // 测试实例:当点击"关注", 个人头像下关注的数量会增加1个, 且按钮内字体变成"取消关注
     71    it('当点击"关注", 个人头像下关注的数量会增加1个, 且按钮内字体变成"取消关注',()=>{
     72       // 获取wrapper
     73      const wrapper = mount(SineWeibo);
     74      // 获取“关注”button
     75      const buttonOfAddAttendion = wrapper.find('.add');
     76      // 获取右边的关注数量
     77      const countOfMyAttention = wrapper.vm.profileData[0].num;
     78      // 触发“关注”button
     79      buttonOfAddAttendion.trigger('click');
     80      // 获取右边的关注数量
     81      const countOfMyAttentionAfterClick = wrapper.vm.profileData[0].num;
     82      // 断言1:右边的关注数量等于原来的+1;
     83      expect(countOfMyAttentionAfterClick).to.equal(countOfMyAttention + 1);
     84      // 断言2:button的text变为“取消关注”
     85      expect(buttonOfAddAttendion.text()).to.equal('取消关注');
     86 
     87    })
     88 
     89 
     90   // 测试实例:当点击"取消关注", 个人头像下关注的数量会减少1个, 且按钮内字体变成"关注
     91    it('当点击"取消关注", 个人头像下关注的数量会减少1个, 且按钮内字体变成"关注',()=>{
     92      const wrapper=mount(SineWeibo)
     93      // 找到“取消关注”按钮
     94      const buttonOfUnAttendion = wrapper.find('.cancel');
     95      // 获取右边关注人数
     96      const countOfMyAttention = wrapper.vm.profileData[0].num;
     97      // 触发“取消关注”按钮的点击事件
     98      buttonOfUnAttendion.trigger('click');
     99      // 获取右边关注人数
    100      const countOfMyAttentionAfterClick = wrapper.vm.profileData[0].num;
    101      //  断言1:右边的人数为原来的人数-1
    102      expect(countOfMyAttentionAfterClick).to.equal(countOfMyAttention - 1);
    103      //  断言2:cancel的text变成"关注"
    104      expect(buttonOfUnAttendion.text()).to.equal('关注');
    105    })
    106 
    107   it('当点击"收藏"时, 我的收藏会增加1个数量, 且按钮内文字变成"已收藏"', () => {
    108     const wrapper = mount(SineWeibo);
    109     const buttonOfCollect = wrapper.find('.uncollectedWeibo');
    110     const countOfMyCollect = Number(wrapper.find('.collect-num span').text());
    111 
    112     //触发点击事件
    113     buttonOfCollect.trigger('click');
    114     const countOfMyCollectAfterClick = Number(wrapper.find('.collect-num span').text());
    115 
    116     //断言: 我的收藏数量会加1
    117     expect(countOfMyCollectAfterClick).to.equal(countOfMyCollect + 1);
    118     //断言: 按钮内文字变成已收藏
    119     expect(buttonOfCollect.text()).to.equal('已收藏');
    120   })
    121 
    122   it('当点击"已收藏"时, 我的收藏会减少1个数量, 且按钮内文字变成"收藏"', () => {
    123     const wrapper = mount(SineWeibo);
    124     const buttonOfUnCollect = wrapper.find('.collectedWeibo');
    125     const countOfMyCollect = Number(wrapper.find('.collect-num span').text());
    126 
    127     //触发点击事件
    128     buttonOfUnCollect.trigger('click');
    129     const countOfMyCollectAfterClick = Number(wrapper.find('.collect-num span').text());
    130 
    131     //断言: 我的收藏数量会减1
    132     expect(countOfMyCollectAfterClick).to.equal(countOfMyCollect - 1 );
    133     //断言: 按钮内文字变成已收藏
    134     expect(buttonOfUnCollect.text()).to.equal('收藏');
    135   });
    136 
    137   it('当点击"已收藏"时, 我的收藏会减少1个数量, 且按钮内文字变成"收藏"', () => {
    138     const wrapper = mount(SineWeibo);
    139     const buttonOfUnCollect = wrapper.find('.collectedWeibo');
    140     const countOfMyCollect = Number(wrapper.find('.collect-num span').text());
    141 
    142     //触发点击事件
    143     buttonOfUnCollect.trigger('click');
    144     const countOfMyCollectAfterClick = Number(wrapper.find('.collect-num span').text());
    145 
    146     //断言: 我的收藏数量会减1
    147     expect(countOfMyCollectAfterClick).to.equal(countOfMyCollect - 1 );
    148     //断言: 按钮内文字变成已收藏
    149     expect(buttonOfUnCollect.text()).to.equal('收藏');
    150   });
    151 
    152   it('当点击"赞", 我的赞会增加1个数量, 且按钮内文字变成"取消赞"', () => {
    153     const wrapper = mount(SineWeibo);
    154     const buttonOfLike = wrapper.find('.dislikedWeibo');
    155     const countOfMyLike = Number(wrapper.find('.like-num span').text());
    156 
    157     //触发点击事件
    158     buttonOfLike.trigger('click');
    159     const countOfMyLikeAfterClick = Number(wrapper.find('.like-num span').text());
    160 
    161     //断言: 我的赞会增加1个数量
    162     expect(countOfMyLikeAfterClick).to.equal(countOfMyLike + 1);
    163     //断言: 按钮内文字变成取消赞
    164     expect(buttonOfLike.text()).to.equal('取消赞');
    165   });
    166 
    167   it('当点击"取消赞", 我的赞会减少1个数量, 且按钮内文字变成"赞"', () => {
    168     const wrapper = mount(SineWeibo);
    169     const buttonOfDislike = wrapper.find('.likedWeibo');
    170     const countOfMyLike = Number(wrapper.find('.like-num span').text());
    171 
    172     //触发点击事件
    173     buttonOfDislike.trigger('click');
    174     const countOfMyLikeAfterClick = Number(wrapper.find('.like-num span').text());
    175 
    176     //断言: 我的赞会增加1个数量
    177     expect(countOfMyLikeAfterClick).to.equal(countOfMyLike - 1);
    178     //断言: 按钮内文字变成取消赞
    179     expect(buttonOfDislike.text()).to.equal('赞');
    180   });
    181 })

    模仿微博的vue 代码:

    <template>
      <div class="weibo-page">
        <nav>
          <span class="weibo-logo"></span>
          <div class="search-wrapper">
            <input type="text" placeholder="大家正在搜: 李棠辉的文章好赞!">
            <img v-if="!iconActive" @mouseover="mouseOverToIcon" src="../../static/image/search.png" alt="搜索icon">
            <img v-if="iconActive" @mouseout="mouseOutToIcon" src="../../static/image/search-active.png" alt="搜索icon">
          </div>
        </nav>
        <div class="main-container">
          <aside class="aside-nav">
            <ul>
              <li :class="{ active: isActives[indexOfContent] }" v-for="(content, indexOfContent) in asideTab" :key="indexOfContent" @click="tabChange(indexOfContent)">
                <span>{{content}}</span>
                <span class="count">
                  <span v-if="indexOfContent === 1" class="collect-num">
                  (
                    <span>{{collectNum}}</span>
                  )
                  </span>
                  <span v-if="indexOfContent === 2" class="like-num">
                  (
                    <span>{{likeNum}}</span>
                  )
                  </span>
                </span>
              </li>
            </ul>
          </aside>
          <main class="weibo-content">
            <div class="weibo-publish-wrapper">
              <img src="../../static/image/tell-people.png"></img>
              <textarea v-model="newWeiboContent.content"></textarea>
              <button @click="publishNewWeiboContent">发布</button>
            </div>
            <div
              class="weibo-news"
              v-for="(news, indexOfNews) in weiboNews"
              :key="indexOfNews">
              <div class="content-wrapper">
                <div class="news-title">
                <div class="news-title__left">
                  <img :src="news.imgUrl">
                  <div class="title-text">
                    <div class="title-name">{{news.name}}</div>
                    <div class="title-time">{{news.resource}}</div>
                  </div>
                </div>
                <button
                  class="news-title__right add"
                  v-if="news.attention === false"
                  @click="attention(indexOfNews)">
                  <i class="fa fa-plus"></i>
                  关注
                </button>
                 <button
                  class="news-title__right cancel"
                  v-if="news.attention === true"
                  @click="unAttention(indexOfNews)">
                  <i class="fa fa-close"></i>
                  取消关注
                </button>
              </div>
              <div class="news-content">{{news.content}}</div>
              <div class="news-image" v-if="news.images.length">
                <img
                v-for="(img, indexOfImg) in news.images"
                :key="indexOfImg"
                :src="img">
              </div>
              </div>
              <ul class="news-panel">
                <li
                  :class="{uncollectedWeibo: !news.collect, collectedWeibo: news.collect}"
                  @click="handleCollect(indexOfNews)">
                  <i class="fa fa-star-o" :class="{collected: news.collect }"></i>
                  {{news.collect ? "已收藏" : '收藏'}}
                </li>
                <li>
                  <i class="fa fa-external-link"></i>
                  转发
                </li>
                <li>
                  <i class="fa fa-commenting-o"></i>
                  评论
                </li>
                <li
                  :class="{dislikedWeibo: !news.like, likedWeibo: news.like}"
                  @click="handleLike(indexOfNews)">
                  <i class="fa fa-thumbs-o-up" :class="{liked: news.like}"></i>
                  {{news.like ? '取消赞' : '赞'}}
                </li>
              </ul>
            </div>
    
          </main>
          <aside class="aside-right">
            <div class="profile-wrapper">
              <div class="profile-top">
                <img src="../../static/image/profile.jpg">
              </div>
              <div class="profile-bottom">
                <div class="profile-name">Lee_tanghui</div>
                <ul class="profile-info">
                  <li
                    v-for="(profile, indexOfProfile) in profileData"
                    :key="indexOfProfile">
                    <div class="number">{{profile.num}}</div>
                    <div class="text">{{profile.text}}</div>
                  </li>
                </ul>
              </div>
            </div>
          </aside>
        </div>
        <footer>
           Wish you like my blog! --- LITANGHUI
        </footer>
      </div>
    </template>
    
    <script>
      //引入假数据
      import * as mockData from '../mock-data.js'
    
      export default {
        created() {
          //模拟获取数据
          this.profileData = mockData.profileData;
          this.weiboNews = mockData.weiboNews;
          this.collectNum = mockData.collectNum;
          this.likeNum = mockData.likeNum;
    
        },
        data() {
          return {
            iconActive: false,
            asideTab: ["首页", "我的收藏", "我的赞"],
            isActives: [true, false, false],
            profileData: [],
            weiboNews: [],
            collectNum: 0,
            likeNum: 0,
            newWeiboContent:   {
              imgUrl: '../../static/image/profile.jpg',
              name: 'Lee_tanghui',
              resource: '刚刚 来自 网页版微博',
              attention:false,
              content: '',
              images: []
            },
          }
        },
        methods: {
          mouseOverToIcon() {
            this.iconActive = true;
          },
          mouseOutToIcon() {
            this.iconActive = false;
          },
          tabChange(indexOfContent) {
            this.isActives.forEach((item, index) => {
              index === indexOfContent ?
                this.$set(this.isActives, index, true) :
                this.$set(this.isActives, index, false);
            })
          },
          publishNewWeiboContent() {
            if(!this.newWeiboContent.content) {
              alert('请输入内容!')
              return;
            }
            const newWeibo = JSON.parse(JSON.stringify(this.newWeiboContent));
            this.weiboNews.unshift(newWeibo);
            this.newWeiboContent.content = '';
            this.profileData[2].num++;
          },
          attention(index) {
            this.weiboNews[index].attention = true;
            this.profileData[0].num++;
          },
          unAttention(index) {
            this.weiboNews[index].attention = false;
            this.profileData[0].num--;
          },
          handleCollect(index) {
            this.weiboNews[index].collect = !this.weiboNews[index].collect;
            this.weiboNews[index].collect ?
            this.collectNum++ :
            this.collectNum--;
          },
          handleLike(index) {
            this.weiboNews[index].like = !this.weiboNews[index].like;
            this.weiboNews[index].like ?
            this.likeNum++ :
            this.likeNum--;
          }
        }
      }
    </script>
    
    <style lang="less">
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    
      .weibo-page {
        display: flex;
        flex-direction: column;
      }
    
      nav {
        display: flex;
        height: 60px;
        line-height: 60px;
        background-color: #f0f0f0;
        align-items: center;
        .weibo-logo {
          margin-left: 13%;
           100px;
          height: 28px;
          background: url("../../static/image/WB_logo.png") no-repeat;
          cursor: pointer;
        }
        .search-wrapper {
          display: flex;
          position: relative;
           25%;
          input {
             100%;
            height: 24px;
            padding-left: 10px;
          }
          img {
            position: absolute;
            right: 10px;
            top: 4px;
             20px;
            height: 20px;
            cursor: pointer;
          }
        }
    
      }
    
      .main-container {
        display: flex;
        justify-content: center;
        background-color: #000;
        padding-top: 16px;
        color: #fff;
        .aside-nav {
           11.31%;
          ul {
            list-style: none;
            li {
              height: 34px;
              line-height: 34px;
              padding-left: 10px;
              cursor: pointer;
              font-weight: bold;
              background-color: rgb(19, 19, 19);
            }
            li:hover {
              background-color: rgb(66, 66, 66);
            }
            .active {
              background-color: rgb(66, 66, 66);
            }
          }
        }
        .weibo-content {
           45.41%;
          color: #000;
          .weibo-publish-wrapper {
            background: #fff;
            position: relative;
            padding: 10px 10px 54px 10px;
            textarea {
              display: block;
               100%;
              height: 95px;
              padding: 10px;
            }
            button {
              position: absolute;
              right: 10px;
              bottom: 10px;
               82px;
              height: 30px;
              background: #ff8140;
              border: 1px solid #f77c3d;
              color: #fff;
              box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.25);
              cursor: pointer;
            }
          }
          .weibo-news {
            background: #fff;
            margin: 10px 0;
            .content-wrapper {
              padding: 20px 20px 4px 20px;
            }
            .news-title {
              display: flex;
              justify-content: space-between;
              .news-title__left {
                display: flex;
                img {
                   50px;
                  height: 50px;
                  vertical-align: text-top;
                }
                .title-text {
                  display: flex;
                  flex-direction: column;
                  justify-content: space-around;
                  margin-left: 10px;
                }
                .title-name {
                  color: #333;
                  font-size: 14px;
                  font-weight: 700;
                }
                .title-time {
                  color: #808080;
                  margin-bottom: 2px;
                  font-size: 12px;
                }
              }
              .news-title__right {
                align-self: center;
                 58px;
                height: 22px;
                line-height: 22px;
                background: #fff;
                border: 1px solid #d9d9d9;
                cursor: pointer;
                img {
                  position: relative;
                  left: 1px;
                  top: 2px;
                }
                i {
                  color: #ff8140;
                }
              }
              .cancel {
                 86px;
              }
            }
            .news-content {
              padding: 10px 0 10px 60px;
              font-size: 14px;
            }
            .news-image {
              padding: 10px 0 0 60px;
              img {
                 110px;
                height: 110px;
                margin-right: 10px;
              }
            }
            .news-panel {
              display: flex;
              list-style: none;
              border-top: 1px solid #f2f2f5;
              li {
                 25%;
                height: 22px;
                line-height: 22px;
                margin: 7px 0;
                text-align: center;
                border-left: 1px solid #f2f2f5;
                color: #808080;
                cursor: pointer;
                .collected {
                  color: #ff8140;
                }
                .like {
                  color: #ff8140;
                }
              }
            }
          }
        }
        .aside-right {
           17.41%;
          margin-left: 10px;
          .profile-top {
            position: relative;
            height: 75px;
            background: url('../../static/image/profile-bg.jpg');
            img {
              position: absolute;
              bottom: -30px;;
              left: 50%;
              margin-left: -30px;
               60px;
              height: 60px;
              border-radius: 50%;
            }
          }
          .profile-bottom {
            height: 118px;
            padding-top: 30px;
            background: #fff;
            color: #000;
            .profile-name {
              text-align: center;
              font-weight: 700;
            }
            .profile-info {
              display: flex;
              list-style: none;
              padding-top: 10px;
              li {
                 33.333%;
                border-left: 1px solid #f2f2f5;
                cursor: pointer;
                div {
                  text-align: center;
                }
                .number{
                  font-weight: 700;
                }
              }
            }
          }
        }
      }
    
      footer {
        height: 100px;
        line-height: 100px;
        text-align: center;
        font-size: 12px;
        font-weight:700;
      }
    </style>
  • 相关阅读:
    Objects in this class cannot be updated outside
    操作系统原理好书推荐
    Can't initialize OCI
    比较好的GIS blog
    栅格数据开发
    arcgis 本地地图服务 silverlight 调用报错 .
    (转载)Rasterdataset Load data耗时
    网络达人梁宏达
    arcengine总结(1)栅格数据开发
    MyNPOI V1.2发布并开放源码,让.NET Excel导出将简单进行到底【转】
  • 原文地址:https://www.cnblogs.com/yangguoe/p/9394838.html
Copyright © 2011-2022 走看看