• 自动化测试--protractor


    前戏

    面向模型编程;

    测试驱动开发;

    先保障交互逻辑,再调整细节。---by 雪狼。

    为什么要自动化测试?

    1,提高产出质量。

    2,减少重构时的痛。反正我最近重构多了,痛苦经历多了。

    3,便于新人接手。

    angular自动化测试主要分:端到端测试和单元测试,很明显两者都要熟练掌握。

    端到端测试是从用户的角度出发,认为整个系统是个黑盒,只会有UI暴露给用户,主要是模仿人工操作测试。

    单元测试认为整个系统是白盒,可以用来测试服务,控制器,过滤器还有基础函数等。

    端到端测试使用protractor,今天就扯这个。

    为什么使用Protractor,也就是说Protractor有什么好处,有没有替代品?

    1,不需要基于id,css选择器,xpath等查询元素,你可以基于绑定,模型,迭代器等等进行测试。

    2,避免回调地狱。对比下面的代码就知道了。

    复制代码
    //没有protractor
    driver.getTitle().then(function(title){
        expect(title).toBe('Baidu');
    });
    
    //使用protractor
    expect(browser.getTitle()).toEqual('Baidu');
    复制代码

    替代品:capybara-angular等。

    正事

    前戏做完了,开始办正事吧。

    第一步当然是配置Protractor,别人写好了,我就不累赘了,送上传送门:

    配置

    第二步,掌握最简单的测试(高手可以绕过)

    describe('hello world', function() {
        it('标题是hello world', function() {
            browser.get('测试地址自己搞一个咯');
            expect(browser.getTitle()).toEqual('hello world');
        });
    });

    说白了就是希望指定的链接的标题是"hello world"

    第三步,了解下大体编写流程。

    首先我们必须跳转到指定的页面,跳转页面有两种方法。

    1,browser.get,跳转到指定的页面,还会重新刷新整个页面。

    2,browser.setLocation,更确切的说,是跳转路由,修改#后面部分。

    “等待某个元素出现”而不是“等待页面加载完毕”,如果页面加载完毕之后,马上去获取某个元素,很可能改元素不存在,然后直接报错退出。

    点击某个按钮之后,弹窗,弹窗有渐进动画,具体弹窗内的元素什么时候出现不确定,那么必须“等待某个元素出现”。怎么实现?

    //等待ng-model="password"的出现,最多等待20秒
    browser.wait(function(){
        return browser.isElementPresent(by.model("password"));
    },20000);

    封装页面对象,英文叫PageObject,我也不知道怎么翻译,说白了就是封装组件或者页面的选择器。

    为什么要有这一步?

    先看一段代码:

    复制代码
    describe('angularjs homepage', function() {
      it('should greet the named user', function() {
      browser.get('http://www.angularjs.org');
      element(by.model('yourName')).sendKeys('Julie');
      var greeting = element(by.binding('yourName'));
      expect(greeting.getText()).toEqual('Hello Julie!');
    });
    
    describe('todo list', function() {
      var todoList;
      beforeEach(function() {
      browser.get('http://www.angularjs.org');
      todoList = element.all(by.repeater('todo in todos'));
    });
    
    it('should list todos', function() {
      expect(todoList.count()).toEqual(2);
      expect(todoList.get(1).getText()).toEqual('build an angular app');
    });
    
    it('should add a todo', function() {
      var addTodo = element(by.model('todoText'));
      var addButton = element(by.css('[value="add"]'));
    
      addTodo.sendKeys('write a protractor test');
      addButton.click();
    
      expect(todoList.count()).toEqual(3);
      expect(todoList.get(2).getText()).toEqual('write a protractor test');
    });
    复制代码

    这是没封装的情况。

    1,语义化很差,根本很难看明白在做神马。

    2,重复代码多。browser.get('http://www.angularjs.org');就不止出现了一次。

    3,耦合严重。如果标签结构改动,代码很多地方都要改。

    4,难以维护,随着项目的增长和时间的推移,没有人会乐意在这上面添加其它测试功能。

    问题已经暴露出来了,怎么封装?

    封装之前,建议过一遍官方的教程和API接口,常用的不多,难度不大。传送门

    举个栗子,很简单的。现在有个滚动条。示意图有点丑,别笑。

    封装出来应该如下,这样即使滚动条的代码结构改了什么的,只要改下面的代码,而具体测试逻辑不用动。

    复制代码
    function ScrollBarSelector(model){
        Object.defineProperty(this,"target",{
            get:function(){
                return typeof model == "string" ? element(by.model(model)) : model;
            }
        })
        Object.defineProperty(this,"pre",{
            get:function(){
                return this.target.$(".pre");
            }
        })
    
        Object.defineProperty(this,"next",{
            get:function(){
                return this.target.$(".next");
            }
        })
    
        Object.defineProperty(this,"scrollButton",{
            get:function(){
                return this.target.$(".scrollButton");
            }
        })
        Object.defineProperty(this,"value",{
            get:function(){
                return this.target.$("input").getAttribute("value");
     } })
    }
    复制代码

    测试逻辑,基本上就是,

    点击某个按钮:scrollBar.next.click()

    希望某个输入框的内容为:expect(scrollBar.value).toBe("xx");

    最后,还是附上登录的测试和路由跳转,google上面很多人都在问。很多人问的问题是,登录完了,跳转页面,怎么知道页面跳转了。

    spec.js

    复制代码
    !function(){
        require(".LoginAction.js");
        require(".LogoutAction.js");
        require(".ScrollbarAction.js");
        
        describe("自动登录",function(){
            new LoginAction().execute("GetLiShu","123456");
        })
    
    
        describe('testScrollbar', function () {
            new ScrollbarAction().execute();
        });
    
        describe("退出登录",function(){
            new LogoutAction().execute();
        });
    }();
    复制代码

    LoginAction.js

    复制代码
    !function(){
    
        function LoginAction(){
    
        }
        var prop = LoginAction.prototype;
        prop.execute = function(userName,password){
            beforeEach(function () {
                //先跳转到登录页面
                browser.get("登录页面");
                //等待输入框出来
                browser.wait(function(){
                    return browser.isElementPresent(by.model("username"));
                },20000);
            })
            
            //输入账号密码然后点击登录
            it('自动登录', function () {
                element(by.model("username")).sendKeys(userName);
                element(by.model("password")).sendKeys(password);
                element(by.css(".login-input-btn")).click();
            });
        }
        module.exports = LoginAction;
    }();
    复制代码

    ScrollbarAction.js

    复制代码
    !function(){
        beforeEach(function () {
            browser.setLocation("/app/common/stepper");
        })
        it('测试滚动条', function () {
            var scrollbar = new ScrollbarSelector("vm.scroll");
            
            //等待滚动条出来,最多等待20秒,滚动条出来了,马上处理测试代码
            browser.wait(function(){
                return browser.isElementPresent(numberDefault.mius);
            },20000);
    
            //这里省略很多行测试代码
        });
    }();
    复制代码

    http://www.cnblogs.com/geilishu/p/5801175.html

  • 相关阅读:
    Android 设置 grid 不滚动
    SpringMVC + myBatis + mySQL 全注解 事务配置
    Git学习日志
    linux 下安装maven
    Maven 搭建springMVC 报错 maven web.xml param element param-name is not allowed here
    Python 函数式编程 filter(),map() , reduce()......
    onpropertychange 实时监控input输入框事件实现
    php CI 框架 mysql 事务使用
    This function has none of DETERMINISTIC, NO SQL解决办法
    安装inotify-tools,用inotifywait命令监听文件或目录的访问信息
  • 原文地址:https://www.cnblogs.com/softidea/p/7509919.html
Copyright © 2020-2023  润新知