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 相关文章推荐
用javascript实现的仿Flash广告图片轮换效果
Apr 24 Javascript
按给定几率进行随机抽取的js代码
Dec 28 Javascript
读jQuery之六 缓存数据功能介绍
Jun 21 Javascript
JavaScrip调试技巧之断点调试
Oct 22 Javascript
JavaScript代码里的判断小结
Aug 22 Javascript
jquery实现全选、不选、反选的两种方法
Sep 06 Javascript
利用python分析access日志的方法
Oct 26 Javascript
详解angularJS动态生成的页面中ng-click无效解决办法
Jun 19 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
Jul 11 Javascript
微信小程序动画(Animation)的实现及执行步骤
Oct 28 Javascript
小程序实现授权登陆的解决方案
Dec 02 Javascript
jQuery 常用特效实例小结【显示与隐藏、淡入淡出、滑动、动画等】
May 19 jQuery
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代码解析
2016/06/24 PHP
[原创]php token使用与验证示例【测试可用】
2017/08/30 PHP
laravel 框架结合关联查询 when()用法分析
2019/11/22 PHP
firefox中JS读取XML文件
2006/12/21 Javascript
Prototype 学习 工具函数学习($方法)
2009/07/12 Javascript
Web前端设计模式  制作漂亮的弹出层
2010/10/29 Javascript
js图片向右一张张滚动效果实例代码
2013/11/23 Javascript
BootStrap的alert提示框的关闭后再显示怎么解决
2016/05/17 Javascript
轻松掌握JavaScript状态模式
2016/09/07 Javascript
angular.js指令中transclude选项及ng-transclude指令详解
2017/05/24 Javascript
详解Vue.js之视图和数据的双向绑定(v-model)
2017/06/23 Javascript
jquery动态赋值id与动态取id方法示例
2017/08/21 jQuery
详解Vue.js Mixins 混入使用
2017/09/15 Javascript
node.js的exports、module.exports与ES6的export、export default深入详解
2017/10/26 Javascript
基于 Vue.js 之 iView UI 框架非工程化实践记录(推荐)
2017/11/21 Javascript
vuejs 切换导航条高亮(路由菜单高亮)的方法示例
2018/05/29 Javascript
jQuery插件实现的日历功能示例【附源码下载】
2018/09/07 jQuery
微信小程序sessionid不一致问题解决
2019/08/30 Javascript
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
浅谈机器学习需要的了解的十大算法
2017/12/15 Python
对pandas写入读取h5文件的方法详解
2018/12/28 Python
tensorflow 重置/清除计算图的实现
2020/01/19 Python
tensorflow使用L2 regularization正则化修正overfitting过拟合方式
2020/05/22 Python
PySide2出现“ImportError: DLL load failed: 找不到指定的模块”的问题及解决方法
2020/06/10 Python
详解python爬取弹幕与数据分析
2020/11/14 Python
办公室副主任岗位职责
2013/11/25 职场文书
十佳班主任事迹材料
2014/01/18 职场文书
小学运动会入场式解说词
2014/02/18 职场文书
行政专员的岗位职责
2014/03/10 职场文书
2014和解协议书范文
2014/09/15 职场文书
村党支部书记个人对照材料汇报
2014/10/26 职场文书
出租车拒载检讨书
2015/01/28 职场文书
天坛导游词
2015/02/02 职场文书
工厂仓管员岗位职责
2015/04/01 职场文书
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA