其他测试框架 强大的全新 Web UI 测试框架 Cypress - 优雅地处理提示消息

非洲赵子龙 for Cypress · 2019年03月07日 · 最后由 非洲赵子龙 回复于 2020年03月25日 · 4877 次阅读

今天群里一位 Qian℡儭‖ 的伙伴问了一个非常好的问题,关于 web 页面中的提示消息如何处理,瞬间就来了兴趣,现在把今晚调试的成果放上来。

自动化有一个古老而经典的原则:
不要显式地使用 wait 这种固定时间的等待

强迫症表示,这个原则适用于提示消息场景吗? 试一试就知道了...

  • 环境准备

web 提示消息一般来说有两种实现方式:

  1. 提示本身就一直存在在页面上,触发某个事件时通过设置 css 属性 display 来显示和隐藏起来;
  2. 提示信息不是一直存在在页面上的,而是在事件触发时,通过新增/删除 Dom 元素来表现 “出现” 和 “消失”

以下 HTML 模拟了上述两种效果:

tip.tmpl

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>js弹框3秒后自动消失</title>
    <link rel="stylesheet" type="text/css" href="/helper/css/bootstrap.css"/>
    <link rel="stylesheet" type="text/css" href="/helper/css/demo.css"/>
</head>
<body>
<button id="alwaysExist" onclick="showModal()">点击弹出模态框-提示一直存在</button>
<button id="addAndDelete">点击出现模态框-新增删除消息Dom</button>
<div class='modal my-modal-alert' id='my-modal-alert'>
    <div class='modal-dialog boxBodySmall'>
        <div class='modal-content'>
            <div class='modal-header boxHeader'>
                <button type='button' class='close boxClose' data-dismiss='modal'>
                    <span aria-hidden='true'>&times;</span><span class='sr-only'>Close</span>
                </button>
                <h4 class='modal-title boxTitle' id='modal-title'>模态框</h4>
            </div>
            <div class='modal-body' id='modal-body-alert'>
                <div id='modal_message'>js弹框自动消失案例</div>
                <span id='num'></span>
            </div>
            <div class='modal-footer boxFooter' id='modal-footer'>
                <button type='button' class='btn btn-default boxButton' data-dismiss='modal'>关闭</button>
                <button type='button' class='btn btn-primary boxButton'>保存</button>
            </div>
        </div>
    </div>
</div>



<script src="/helper/js/jquery-1.11.2.min.js"></script>
<script src="/helper/js/bootstrap.min.js"></script>
<script src="/helper/js/jquery-ui.min.js"></script>

<script>
    var clearFlag = 0;
    var count = 3;//设置3秒后自动消失
    var showModal = function(){
        $("#my-modal-alert").toggle();//显示模态框

        $("#my-modal-alert").draggable({//设置模态框可拖动(需要引入jquery-ui.min.js)
            handle: ".modal-header"
        });

        clearFlag = self.setInterval("autoClose()",1000);//每过一秒调用一次autoClose方法
    }

    var autoClose = function(){
        if(count>0){
            $("#num").html(count + "秒后窗口将自动关闭");
            count--;
        }else if(count<=0){
            window.clearInterval(clearFlag);
            $("#num").html("");
            $("#my-modal-alert").fadeOut("slow");
            count = 3;
            $("#my-modal-alert").toggle();
        }
    }
</script>

<script>
    $("#addAndDelete").click(function () {
        var l = $("body>div").length;
        if(l===1)
        {
            $("body").append(function () {
                return '<div class="addAndDelete">\n' +
                        '    <h4>我是提示消息,点击后会以新增的方式布局到HTML里,3秒后自动消失</h4>\n' +
                        '</div>'
            });
            setTimeout(function () {
                $(".addAndDelete").remove();
            }, 3000);
        }
    });

</script>

</body>
</html>

注:上面的 html 代码是用 go/gin 作为基础框架写的,其中的bootstrapjQuery相关的库,都可以在网上下载到,实在不知道如何运行的可以在群里交流,需要的话,我会把源文件传到群里……唔,好像很啰嗦又不是很高端的样子.jpg

  • 运行效果


    点击第一个按钮,会出现第一张图的弹框,3 秒后消失;点击第二个按钮,出现第二张图的文本提示,同样 3 秒后消失

  • 测试代码示例

测试以上两种情况下,提示信息有没有出现和提示信息有没有正常的消失,一共 4 个用例。

/// <reference types='Cypress' />
describe("百毒网站首页测试用例集", function() {
  beforeEach(() => {
    cy.visit("/");
  });
  it.skip("百度一下按钮文本检查", function() {
    cy.get("#su").then($button_start_search => {
      expect($button_start_search.attr("value")).to.eq("百度一下");
    });
    cy.url().should("include", "www.baidu.com"); // => true
    cy.url().should($url => {
      expect($url).to.contains("www.baidu.com");
      console.log($url);
    });
  });

  it("一直存在-点击后出现提示信息", function() {
    cy.get("#my-modal-alert").then($alert => {
      expect($alert).have.not.property("style");
      cy.get("#alwaysExist")
        .then($triggerButton => {
          $triggerButton.click();
        })
        .then(() => {
          expect($alert).have.attr("style", "display: block;");
        });
    });
  });

  it("一直存在-3秒后提示信息消失", function() {
    cy.get("#my-modal-alert").then($alert => {
      cy.get("#alwaysExist")
        .trigger("click")
        .then(() => {
          cy.get("#my-modal-alert", { timeout: 4000 }).should("not.be.visible");
        });
    });
  });

  it("点击后新增然后自动消失-点击后出现提示信息", function() {
    cy.get("#addAndDelete").click();
    cy.get(".addAndDelete").then($tip => {
      expect($tip).to.exist;
    });
  });

  it("点击后新增然后自动消失-3秒后提示信息消失", function() {
    cy.get("#addAndDelete").click();
    cy.get(".addAndDelete").then($tip => {
      expect($tip).to.exist;
    });
    cy.get(".addAndDelete", {timeout:4000}).should("not.exist");
  });

});

  • 测试结果


运行过程中可以看到,提示信息消失时,我们的关于 “3 秒后提示信息消失” 的两个用例才会通过。

  • 解析

我们没有写任何关于 wait 的函数,一切的发生都尽可能的快,没有无畏的等待。这样的用例才是好的用例哦!should判断会因get传了timeout参数而在超时时间内循环判断,直至成功或超时为止,参考官方Commands关于 should 的描述

遇到一个有趣的问题,为什么expect("xxx").to.exist,xxx 好像随便传什么都能通过?~唔,留到明天研究下...~原来是这样,也就是说,Cypress 采用了包括 ChaiJS 在内的断言方式,而 ChaiJS 的断言是:对exist的判断的话,如果判断的是字符串,那么只要此字符串不是nullundefined,结果都会是 pass,问题解决。

Cypress 入门系列:

注:目前官方团队正在开发 Python 版本,同样的 Free to use,对 JS 恐惧的同学不妨等一等,或者直接 JS 上手,非常简单,VSCode 装上之后,你会爱上 Cypress 和 JS,笔者会慢慢介绍各种 Web UI 自动化复杂场景下 Cypress 的强大应对,目前还没发现 Cypress 无法处理的问题!欢迎一起入坑!QQ 群:947886065.

共收到 5 条回复 时间 点赞

我来了😁,一大早满满的干货,timeout 这种智能判断确实比写死要好,不会浪费时间,学习了🙏 …如你所说我以前用 sublime,现在 vscode 真是爽的一 B,瞬间对 js 提起了兴趣。
我昨天群里提的那个断言函数是还得研究下,也不知道是不是我用错了~

不要显示地使用 wait 这种固定时间的等待

俺们村村长说那个词叫显式😂

槽神 回复

Good catch, 已修正 😄谢谢指正

楼主,有 cypress 的群吗

sunmengshine 回复

Q 群:947886065

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册