Angular.js自動(dòng)化測(cè)試之protractor詳解
前戲
- 面向模型編程;
- 測(cè)試驅(qū)動(dòng)開發(fā);
- 先保障交互邏輯,再調(diào)整細(xì)節(jié)。---by 雪狼。
為什么要自動(dòng)化測(cè)試?
1,提高產(chǎn)出質(zhì)量。
2,減少重構(gòu)時(shí)的痛。反正我最近重構(gòu)多了,痛苦經(jīng)歷多了。
3,便于新人接手。
angular自動(dòng)化測(cè)試主要分:端到端測(cè)試和單元測(cè)試,很明顯兩者都要熟練掌握。
端到端測(cè)試是從用戶的角度出發(fā),認(rèn)為整個(gè)系統(tǒng)是個(gè)黑盒,只會(huì)有UI暴露給用戶,主要是模仿人工操作測(cè)試。
單元測(cè)試認(rèn)為整個(gè)系統(tǒng)是白盒,可以用來(lái)測(cè)試服務(wù),控制器,過(guò)濾器還有基礎(chǔ)函數(shù)等。
端到端測(cè)試使用protractor,今天就扯這個(gè)。
為什么使用Protractor,也就是說(shuō)Protractor有什么好處,有沒(méi)有替代品?
1,不需要基于id,css選擇器,xpath等查詢?cè)兀憧梢曰诮壎?,模型,迭代器等等進(jìn)行測(cè)試。
2,避免回調(diào)地獄。對(duì)比下面的代碼就知道了。
//沒(méi)有protractor driver.getTitle().then(function(title){ expect(title).toBe('Baidu'); }); //使用protractor expect(browser.getTitle()).toEqual('Baidu');
替代品:capybara-angular等。
正文
前戲做完了,開始辦正事吧。
第一步當(dāng)然是配置Protractor,別人寫好了,我就不累贅了,送上傳送門:
第二步,掌握最簡(jiǎn)單的測(cè)試(高手可以繞過(guò))
describe('hello world', function() { it('標(biāo)題是hello world', function() { browser.get('測(cè)試地址自己搞一個(gè)咯'); expect(browser.getTitle()).toEqual('hello world'); }); });
說(shuō)白了就是希望指定的鏈接的標(biāo)題是"hello world"
第三步,了解下大體編寫流程。
首先我們必須跳轉(zhuǎn)到指定的頁(yè)面,跳轉(zhuǎn)頁(yè)面有兩種方法。
1,browser.get,跳轉(zhuǎn)到指定的頁(yè)面,還會(huì)重新刷新整個(gè)頁(yè)面。
2,browser.setLocation,更確切的說(shuō),是跳轉(zhuǎn)路由,修改#后面部分。
“等待某個(gè)元素出現(xiàn)”而不是“等待頁(yè)面加載完畢”,如果頁(yè)面加載完畢之后,馬上去獲取某個(gè)元素,很可能改元素不存在,然后直接報(bào)錯(cuò)退出。
點(diǎn)擊某個(gè)按鈕之后,彈窗,彈窗有漸進(jìn)動(dòng)畫,具體彈窗內(nèi)的元素什么時(shí)候出現(xiàn)不確定,那么必須“等待某個(gè)元素出現(xiàn)”。怎么實(shí)現(xiàn)?
//等待ng-model="password"的出現(xiàn),最多等待20秒 browser.wait(function(){ return browser.isElementPresent(by.model("password")); },20000);
封裝頁(yè)面對(duì)象,英文叫PageObject,我也不知道怎么翻譯,說(shuō)白了就是封裝組件或者頁(yè)面的選擇器。
為什么要有這一步?
先看一段代碼:
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'); });
這是沒(méi)封裝的情況。
1,語(yǔ)義化很差,根本很難看明白在做神馬。
2,重復(fù)代碼多。browser.get('http://www.angularjs.org');
就不止出現(xiàn)了一次。
3,耦合嚴(yán)重。如果標(biāo)簽結(jié)構(gòu)改動(dòng),代碼很多地方都要改。
4,難以維護(hù),隨著項(xiàng)目的增長(zhǎng)和時(shí)間的推移,沒(méi)有人會(huì)樂(lè)意在這上面添加其它測(cè)試功能。
問(wèn)題已經(jīng)暴露出來(lái)了,怎么封裝?
封裝之前,建議過(guò)一遍官方的教程和API接口,常用的不多,難度不大。傳送門。
舉個(gè)栗子,很簡(jiǎn)單的。現(xiàn)在有個(gè)滾動(dòng)條。示意圖有點(diǎn)丑,別笑。
封裝出來(lái)應(yīng)該如下,這樣即使?jié)L動(dòng)條的代碼結(jié)構(gòu)改了什么的,只要改下面的代碼,而具體測(cè)試邏輯不用動(dòng)。
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"); } }) }
測(cè)試邏輯,基本上就是,
點(diǎn)擊某個(gè)按鈕:scrollBar.next.click()
希望某個(gè)輸入框的內(nèi)容為:expect(scrollBar.value).toBe("xx");
最后,還是附上登錄的測(cè)試和路由跳轉(zhuǎn),google上面很多人都在問(wèn)。很多人問(wèn)的問(wèn)題是,登錄完了,跳轉(zhuǎn)頁(yè)面,怎么知道頁(yè)面跳轉(zhuǎn)了。
spec.js
!function(){ require(".LoginAction.js"); require(".LogoutAction.js"); require(".ScrollbarAction.js"); describe("自動(dòng)登錄",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 () { //先跳轉(zhuǎn)到登錄頁(yè)面 browser.get("登錄頁(yè)面"); //等待輸入框出來(lái) browser.wait(function(){ return browser.isElementPresent(by.model("username")); },20000); }) //輸入賬號(hào)密碼然后點(diǎn)擊登錄 it('自動(dòng)登錄', 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('測(cè)試滾動(dòng)條', function () { var scrollbar = new ScrollbarSelector("vm.scroll"); //等待滾動(dòng)條出來(lái),最多等待20秒,滾動(dòng)條出來(lái)了,馬上處理測(cè)試代碼 browser.wait(function(){ return browser.isElementPresent(numberDefault.mius); },20000); //這里省略很多行測(cè)試代碼 }); }();
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- JavaScript 實(shí)現(xiàn)自己的安卓手機(jī)自動(dòng)化工具腳本(推薦)
- JavaScript 常見安全漏洞和自動(dòng)化檢測(cè)技術(shù)
- 使用auto.js實(shí)現(xiàn)自動(dòng)化每日打卡功能
- PyQt5內(nèi)嵌瀏覽器注入JavaScript腳本實(shí)現(xiàn)自動(dòng)化操作的代碼實(shí)例
- Angular.js項(xiàng)目中使用gulp實(shí)現(xiàn)自動(dòng)化構(gòu)建以及壓縮打包詳解
- nodejs前端自動(dòng)化構(gòu)建環(huán)境的搭建
- Angular.Js的自動(dòng)化測(cè)試詳解
- 從零搭建docker+jenkins+node.js自動(dòng)化部署環(huán)境的方法
- python接口自動(dòng)化(十七)--Json 數(shù)據(jù)處理---一次爬坑記(詳解)
- JavaScript揭秘:實(shí)現(xiàn)自動(dòng)化連連看游戲
相關(guān)文章
使用 Github Actions 自動(dòng)部署 Angular 應(yīng)用到 Github Pages的方法
這篇文章主要介紹了使用 Github Actions 自動(dòng)部署 Angular 應(yīng)用到 Github Pages,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07AngularJS中實(shí)現(xiàn)用戶訪問(wèn)的身份認(rèn)證和表單驗(yàn)證功能
這篇文章主要介紹了AngularJS中實(shí)現(xiàn)用戶訪問(wèn)的身份認(rèn)證及表單驗(yàn)證功能的方法,Angular是Google開發(fā)的一款瀏覽器端的高人氣JavaScript框架,需要的朋友可以參考下2016-04-04走進(jìn)AngularJs之過(guò)濾器(filter)詳解
本篇文章主要介紹了AngularJs之過(guò)濾器(filter)詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02angular-ngSanitize模塊-$sanitize服務(wù)詳解
本篇文章主要介紹了angular-ngSanitize模塊-$sanitize服務(wù)詳解 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06AngularJS 將再發(fā)布一個(gè)重要版本 然后進(jìn)入長(zhǎng)期支持階段
目前團(tuán)隊(duì)正在開發(fā) AngularJS 1.7.0,而 1.7 的開發(fā)周期將一直持續(xù)到 2018 年 6 月 30 日2018-01-01如何以Angular的姿勢(shì)打開Font-Awesome詳解
這篇文章主要給大家介紹了關(guān)于如何以Angular的姿勢(shì)打開Font-Awesome的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Angular具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04快速解決angularJS中用post方法時(shí)后臺(tái)拿不到值的問(wèn)題
今天小編就為大家分享一篇快速解決angularJS中用post方法時(shí)后臺(tái)拿不到值的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08AngularJS中的API(接口)簡(jiǎn)單實(shí)現(xiàn)
本文主要介紹AngularJS API(接口),這里對(duì)AngularJS API的知識(shí)做了詳細(xì)講解,并附簡(jiǎn)單代碼實(shí)例,有需要的小伙伴可以參考下2016-07-07angularjs 獲取默認(rèn)選中的單選按鈕的value方法
下面小編就為大家分享一篇angularjs 獲取默認(rèn)選中的單選按鈕的value方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02