Angular.js自动化测试之protractor详解


Posted in Javascript onJuly 07, 2017

前戏

  • 面向模型编程;
  • 测试驱动开发;
  • 先保障交互逻辑,再调整细节。---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" 

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

Angular.js自动化测试之protractor详解

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

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接口,常用的不多,难度不大。传送门。

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

Angular.js自动化测试之protractor详解

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

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);

  //这里省略很多行测试代码
 });
}();

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js活用事件触发对象动作
Aug 10 Javascript
23个超流行的jQuery相册插件整理分享
Apr 25 Javascript
js判断选择的时间是否大于今天的代码
Aug 20 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
Apr 10 Javascript
jQuery控制TR显示隐藏的三种常用方法
Aug 21 Javascript
jQuery弹出层插件Lightbox_me使用指南
Apr 21 Javascript
jQuery插件扩展测试实例
Jun 21 Javascript
Javascript实现从小到大的数组转换成二叉搜索树
Jun 13 Javascript
React-Native做一个文本输入框组件的实现代码
Aug 10 Javascript
深入理解与使用keep-alive(配合router-view缓存整个路由页面)
Sep 25 Javascript
vue 实现强制类型转换 数字类型转为字符串
Nov 07 Javascript
详解JavaScript 作用域
Jul 14 Javascript
vue.js全局API之nextTick全面解析
Jul 07 #Javascript
js浏览器滚动条卷去的高度scrolltop(实例讲解)
Jul 07 #Javascript
解决AjaxFileupload 上传时会出现连接重置的问题
Jul 07 #Javascript
基于rem的移动端响应式适配方案(详解)
Jul 07 #Javascript
详谈js模块化规范
Jul 07 #Javascript
使用JavaScript实现alert的实例代码
Jul 06 #Javascript
vuejs手把手教你写一个完整的购物车实例代码
Jul 06 #Javascript
You might like
PHP通用分页类page.php[仿google分页]
2008/08/31 PHP
PHP设计模式之责任链模式的深入解析
2013/06/13 PHP
php根据日期判断星座的函数分享
2014/02/13 PHP
使用PHP编写发红包程序
2015/07/22 PHP
使用PHP和JavaScript判断请求是否来自微信内浏览器
2015/08/18 PHP
php实现学生管理系统
2020/03/21 PHP
解决php扩展安装不生效问题
2019/10/25 PHP
Laravel框架源码解析之模型Model原理与用法解析
2020/05/14 PHP
JavaScript语言中的Literal Syntax特性分析
2007/03/08 Javascript
Javascript在IE和FireFox中的不同表现简析
2012/12/03 Javascript
JavaScript获得表单target属性的方法
2015/04/02 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
Java Mybatis框架入门基础教程
2015/09/21 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
2016/01/27 Javascript
JavaScript记录光标在编辑器中位置的实现方法
2016/04/22 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
微信小程序Server端环境配置详解(SSL, Nginx HTTPS,TLS 1.2 升级)
2017/01/12 Javascript
node.js实现登录注册页面
2017/04/08 Javascript
element vue validate验证名称重复 输入框与后台重复验证 特殊字符 字符长度 及注意事项小结【实例代码】
2018/11/20 Javascript
node.js express框架简介与实现
2019/07/23 Javascript
vue配置nprogress实现页面顶部进度条
2019/09/21 Javascript
理解Proxy及使用Proxy实现vue数据双向绑定操作
2020/07/18 Javascript
谈谈JavaScript令人迷惑的==与+
2020/08/31 Javascript
python爬虫实战之最简单的网页爬虫教程
2017/08/13 Python
PyTorch线性回归和逻辑回归实战示例
2018/05/22 Python
Python2和Python3的共存和切换使用
2019/04/12 Python
python 处理微信对账单数据的实例代码
2019/07/19 Python
Python 添加文件注释和函数注释操作
2020/08/09 Python
马来西亚时装购物网站:ZALORA马来西亚
2017/03/14 全球购物
Lee牛仔裤澳大利亚官网:美国著名牛仔裤品牌
2017/09/02 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
工程总经理工作职责
2013/12/09 职场文书
视光学毕业生自荐书范文
2014/02/13 职场文书
房屋租赁合同补充协议
2014/10/11 职场文书
党员教师群众路线个人整改措施
2014/10/28 职场文书