codeceptjs學習筆記 - 安裝和基本知識

本文章基于codeceptjs@1.0.1

codeceptjs介紹

codeceptjsCodeception測試框架下的一個項目,是運行在nodejs的UI測試框架, 能使場景驅動的驗收測試簡單化指巡。

"Modern Era Acceptance Testing Framework for NodeJS"是codeceptjs官網(wǎng)最顯著的標語,那作為一個UI測試框架稳摄,究竟有哪些特點:

  • 從用戶角度編寫。codeceptjs提供的API具有declarative testing的特點饲宿,從用戶行為的角度抽象出了許多與瀏覽器的交互動作厦酬,測試代碼非常易讀易懂。codeceptjs提供的API由于其易讀性也可以當成DSL來使用瘫想,這些DSL隱藏了后端webdriver服務的復雜性弃锐,可以讓使用者更加專注到測試場景的編寫中
  • 所有的交互動作來自于對象I。對象I的方法都被描述為用戶訪問網(wǎng)站可能產生的行為殿托,易讀易寫易維護霹菊,對非技術人員也很友好
  • 對多個后端API兼容。codeceptjs支持多個webdriver實現(xiàn) i.e. webdriverio, protractor and phantomjs, 我們可以很簡單在他們之間切換。這些不同的webdriver實現(xiàn)在codeceptjs里面叫做Helper旋廷,正是下面這些Helper給對象I提供了actions
  • 同步鸠按。我們不用關心js中的異步問題 i.e. promises & callback。測試場景是線性的
  • 基于Mocha測試框架饶碘。
  • 可以編寫出易讀易懂的場景驅動的驗收測試目尖。可以寫成BDD style
  • Smart locator扎运。Smart locators: use names, labels, matching text, CSS or XPath to locate elements
  • 互動式debug shell瑟曲。可以在測試執(zhí)行時隨時暫停然后嘗試codeceptjs提供地不同的API
  • 提供了方便的命令行工具幫助創(chuàng)建測試豪治《床Γ可以通過命令一步創(chuàng)建tests, pageobjects, stepobjects
  • 支持web和mobile端的測試

說了這么多特點,它長什么樣子呢负拟?一個簡單的demo如下:

Feature('CodeceptJS demo');

Scenario('check Welcome page on site', (I) => {
  I.amOnPage('/');
  I.see('Welcome');
});

是不是可以基本當plain text來讀烦衣?:)

codeceptjs安裝

環(huán)境檢查

在安裝codeceptjs之前,你要確保你的node版本是大于6.11的

$ node -v              
v8.3.0
安裝codeceptjs

使用npm全局安裝codeceptjs掩浙,這樣的話我們就可以在shell里面直接使用codeceptjs命令

[sudo] npm install -g codeceptjs

本地安裝, 這樣的話我們可以執(zhí)行./node_modules/.bin/codeceptjs

npm install --save-dev codeceptjs

安裝browser driver

全局安裝webdriverio
[sudo] npm install -g webdriverio

本地安裝webdriverio
npm install webdriverio --save-dev

全局安裝protractor
[sudo] npm install -g protractor

本地安裝protractor
npm install protractor --save-dev

全局安裝nightmare
[sudo] npm install -g nightmare nightmare-upload

本地安裝nightmare
npm install nightmare nightmare-upload --save-dev

全局安裝codeceptjs+webdriverio
[sudo] npm install -g codeceptjs-webdriverio

本地安裝codeceptjs+webdriverio
[sudo] npm install codeceptjs-webdriverio --save-dev

全局安裝codeceptjs+nightmare
[sudo] npm install -g codeceptjs-nightmare

本地安裝codeceptjs+nightmare
[sudo] npm install codeceptjs-nightmare --save-dev

全局安裝codeceptjs+protractor
[sudo] npm install -g codeceptjs-protractor

本地安裝codeceptjs+protractor
[sudo] npm install codeceptjs-protractor --save-dev

安裝完之后你可以通過codeceptjs命令查看codeceptjs的版本和常用命令參數(shù)介紹

?  codeceptjs-demo git:(master) ? codeceptjs
CodeceptJS v1.0.1

  Usage:  [options] [command]


  Options:

    -h, --help  output usage information


  Commands:

    init [path]                          Creates dummy config in current dir or [path]
    shell|sh [options] [path]            Interactive shell
    list|l [path]                        List all actions for I.
    def [path]                           List all actions for I.
    generate:test|gt [path]              Generates an empty test
    generate:pageobject|gpo [path]       Generates an empty page object
    generate:object|go [options] [path]  Generates an empty support object (page/step/fragment)
    generate:helper|gh [path]            Generates a new helper
    run [options] [test]                 Executes tests
    run-multiple [options] [suites...]   Executes tests multiple

其中參數(shù)list可以列出對象I所有的動作花吟,也就是我們可以利用的瀏覽器交互API

?  codeceptjs-demo git:(master) ? codeceptjs list
List of test actions: --
 WebDriverIO I.defineTimeout(timeouts)
 WebDriverIO I.amOnPage(amOnPage)
 WebDriverIO I.click(click)
 WebDriverIO I.doubleClick(doubleClick)
 WebDriverIO I.rightClick(rightClick)
 ..........
安裝selenium-standalone

因為這些helper i.e. webdriverio, protractor都是需要selenium作為后端與browser通信的服務,所以我們也需要安裝selenium厨姚。

下面的命令會安裝selenium standalone server以及相應的browser driver

npm install selenium-standalone@latest -g
selenium-standalone install
selenium-standalone start

詳細的selenium-standalone資料請參考這里

codeceptjs基礎知識

命令行使用

codeceptjs init可以用在當我們需要初始化一個測試項目的時候衅澈。這個命令會創(chuàng)建和配置一些文件來搭建我們的測試環(huán)境。
?  codeceptjs-init: codeceptjs init

  Welcome to CodeceptJS initialization tool
  It will prepare and configure a test environment for you

Installing to /Users/diyu/workspace/codeceptjs_demo/codeceptjs-init
? Where are your tests located? ./*_test.js
? What helpers do you want to use? WebDriverIO
? Where should logs, screenshots, and reports to be stored? ./output
? Would you like to extend I object with custom steps? Yes
? Do you want to choose localization for tests? English (no localization)
? Where would you like to place custom steps? ./steps_file.js
Configure helpers...
? [WebDriverIO] Base url of site to be tested http://localhost
? [WebDriverIO] Browser in which testing will be performed chrome
Steps file created at /Users/diyu/workspace/codeceptjs_demo/codeceptjs-init/steps_file.js
Config created at /Users/diyu/workspace/codeceptjs_demo/codeceptjs-init/codecept.json
Directory for temporary output files created at `_output`
Almost done! Create your first test by executing `codeceptjs gt` (generate test) command
?  codeceptjs-init: ll
total 16
-rw-r--r--  1 diyu  staff   291B  8 27 22:39 codecept.json
drwxr-xr-x  2 diyu  staff    68B  8 27 22:39 output
-rw-r--r--  1 diyu  staff   281B  8 27 22:39 steps_file.js

如上所示谬墙,一些測試文件今布、配置文件和輸出目錄都創(chuàng)建好了。具體到這些文件是干嘛的芭梯,里面內容是什么险耀,之后的學習筆記后提到弄喘。

codeceptjs gt會創(chuàng)建測試文件
?  codeceptjs-init: codeceptjs gt
Creating a new test...
----------------------
? Filename of a test first
? Feature which is being tested first demo
Test for first was created in /Users/diyu/workspace/codeceptjs_demo/codeceptjs-init/first_test.js
?  codeceptjs-init: ll
total 24
-rw-r--r--  1 diyu  staff   291B  8 27 22:39 codecept.json
-rw-r--r--  1 diyu  staff    66B  8 27 23:50 first_test.js
drwxr-xr-x  2 diyu  staff    68B  8 27 22:39 output
-rw-r--r--  1 diyu  staff   281B  8 27 22:39 steps_file.js
?  codeceptjs-init: cat first_test.js

Feature('first demo');

Scenario('test something', (I) => {

});

first_test.js 就是被創(chuàng)建的測試文件

codeceptjs run 會運行測試玖喘。加上參數(shù)--steps會輸出詳細的執(zhí)行過程
?  codeceptjs-init: codeceptjs run --steps
CodeceptJS v1.0.1
Using test root "/Users/diyu/workspace/codeceptjs_demo/codeceptjs-init"

first demo --
 test something
 ? OK in 1ms

  OK  | 1 passed   // 2s
codeceptjs gpo會創(chuàng)建一個page object file。這個命令可以快速簡單的幫助你實現(xiàn)page object設計模式
?  codeceptjs-init codeceptjs gpo
Creating a new page object
--------------------------
? Name of a page object landingPage
? Where should it be stored ./pages/landingPage.js
Updating configuration file...
Page object for landingPage was created in /Users/diyu/workspace/codeceptjs_demo/codeceptjs-init/pages/landingPage.js
Use landingPagePage as parameter in test scenarios to access it
?  codeceptjs-init ll
total 24
-rw-r--r--  1 diyu  staff   375B  8 29 21:30 codecept.json
-rw-r--r--  1 diyu  staff    66B  8 27 23:50 first_test.js
drwxr-xr-x  2 diyu  staff    68B  8 27 22:39 output
drwxr-xr-x  3 diyu  staff   102B  8 29 21:30 pages
-rw-r--r--  1 diyu  staff   281B  8 27 22:39 steps_file.js

landingPage.js被創(chuàng)建在pages目錄下面蘑志,這個文件里面會有l(wèi)andingPage的元素定位和基本操作累奈。一個簡單的demo如下

'use strict';

let I;

module.exports = {

  _init() {
    I = actor();
  },

  fields: {
    email: '#user_basic_email',
    password: '#user_basic_password'
  },
  submitButton: {css: '#new_user_basic input[type=submit]'},

  sendForm(email, password) {
    I.fillField(this.fields.email, email);
    I.fillField(this.fields.password, password);
    I.click(this.submitButton);
  }
}

通過參數(shù)傳遞的方式,我們可以在測試文件里面注入頁面元素和操作

Feature('CodeceptJS Demonstration');

Before((I) => { // or Background
  I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation');
});

Scenario('test some forms', (I, docsPage) => {
  docsPage.sendForm('hello@world.com','123456');
  I.see('User is valid');
  I.dontSeeInCurrentUrl('/documentation');
});

這樣的話急但,最簡單的page object就可以用了

Actions and Assertions

下面通過一個簡單的demo來看下codeceptjs測試文件長什么樣子

Feature('CodeceptJS Demonstration');

Scenario('test some forms', (I) => {
  I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation');
  I.fillField('Email', 'hello@world.com');
  I.fillField('Password', '123456');
  I.checkOption('Active');
  I.checkOption('Male');
  I.click('Create User');
  I.see('User is valid');
  I.dontSeeInCurrentUrl('/documentation');
});

可以看出

  • 所有的頁面操作都由對象I調用執(zhí)行澎媒,而I的方法都來自于Helper
  • see(),dontSee()方法是用來做驗證的波桩〗渑可以在頁面上找到指定元素進行驗證.如果第二個參數(shù)提供,可以縮小元素查找范圍镐躲。I.see('User is valid', '.alert-success');
  • Feature和Scenario來源于mocha
  • fillField(), checkOption()和click()這些方法工作原理類似储玫,都是通過name, css和xpath找到元素并與之交互

Grabber

當我們需要從頁面中抓取元素然后用到后續(xù)測試的時候侍筛,我們可以使用帶grab前綴的方法。它的用法如下

var assert = require('assert');

Feature('CodeceptJS Demonstration');

Scenario('test page title', function*(I) {
  I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation');
  var title = yield I.grabTitle();
  assert.equal(title, 'Example application with SimpleForm and Twitter Bootstrap');
});

grad()要被使用在generator里面撒穷,所以帶有yield關鍵字

debug

codeceptjs可以通過兩種方式進行測試代碼開發(fā)中的調試

  • 在測試文件中使用pause()方法
?  codeceptjs-init codeceptjs run --steps
CodeceptJS v1.0.1
Using test root "/Users/diyu/workspace/codeceptjs_demo/codeceptjs-init"

CodeceptJS Demonstration --
 test some forms
 ? I am on page "http://simple-form-bootstrap.plataformatec.com.br/documentation"
 ? I fill field "Email", "hello@world.com"
 ? I fill field "Password", "123456"
 ? I check option "Active"
 Interative debug session started
 Use JavaScript syntax to try steps in action
 Press ENTER to continue
 I.
Exiting interactive shell....
 ? I check option "Male"
 ? I click "Create User"
 ? I see "User is valid"
 ? I dont see in current url "/documentation"
 ? OK in 12581ms

注意到中間突然出現(xiàn)了交互式的debug session匣椰,這就是pause()的作用

  • 下面這種codeceptjs shell來進行調試
?  codeceptjs-init codeceptjs shell
String interactive shell for current suite...
 Interative debug session started
 Use JavaScript syntax to try steps in action
 Press ENTER to continue
 I.amOnPage('www.hupu.com')
 I.

通過這個互動的debug session,我們可以一步步的輸入不同的action來觀察瀏覽器的行為

Before()/After()

codeceptjs也提供了測試框架必不可少的用作測試準備setup和清理teardown的方法端礼。Before()和Background()可以用于抽取公共方法或做測試準備工作禽笑,After()可以用于測試收尾清理工作。

Before()和Background()會在所有Scenario()之前執(zhí)行一樣蛤奥,After()會在所有Scenario()之后執(zhí)行佳镜。

下面的測試代碼片段中Before()會在所有Scenario()方法之前執(zhí)行。Before()也可以換成Background()喻括。

Feature('CodeceptJS Demonstration');

Before((I) => { // or Background
  I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation');
});

After((I) => {
  I.clearCookie();
});

Scenario('test some forms', (I) => {
  I.click('Create User');
  I.see('User is valid');
  I.dontSeeInCurrentUrl('/documentation');
});

Scenario('test title', (I) => {
  I.seeInTitle('Example application');
});

BeforeSuite()/AfterSuite()

當你需要在所有的測試Scenario()之前進行復雜的setup和teardown邀杏,BeforeSuite()/AfterSuite()會是好的選擇。BeforeSuite()會在所有的Scenario(), Before()之前調用運行唬血;同理望蜡,AfterSuite()會在所有的Scenario(), Before()之后調用運行;這兩個方法有且只運行一次拷恨。

由于BeforeSuite()/AfterSuite()有可能是在瀏覽器打開之前運行脖律,所有BeforeSuite()/AfterSuite()只能訪問到I對象。BeforeSuite()/AfterSuite()只會在聲明的文件中生效腕侄,所以不同的文件就可以有不同的BeforeSuite()/AfterSuite()了小泉。

BeforeSuite((I) => {
  I.syncDown('testfolder');
});

AfterSuite((I) => {
  I.syncUp('testfolder');
  I.clearDir('testfolder');
});

within('section', ()=>{})

使用within('section', ()=>{})可以讓一系列I對象的方法在頁面某個特定區(qū)域執(zhí)行.這樣可以鎖定具體的執(zhí)行范圍。

Feature('within demo')

Scenario('login github', (I)=>{
    I.amOnPage('https://github.com');
    within('.form-signup-home', () => {
      I.fillField('user[login]', 'User');
      I.fillField('user[email]', 'user@user.com');
      I.fillField('user[password]', 'user@user.com');
      I.click('button');
    });
    I.see('There were problems creating your account.');
});

Comments I.say()

給測試場景添加注釋冕杠,可以使用I.say()微姊。

Feature('within demo')

Scenario('login github', (I)=>{
    I.amOnPage('http://www.baidu.com');
    I.say('Above is the link for baidu search engine');
});

Skip test

使用xScenario()可以跳過測試的執(zhí)行。

只執(zhí)行一個測試場景

使用Scenario.only()可以只運行該測試分预。

Reporter

之前提到codeceptjs是基于mocha的兢交,所有mocha的--reporter也對codeceptjs有效。我們可以用下面命令指定report的格式

codeceptjs run --steps --reporter spec (這是default的report格式)

spec可以替換為dot, nyan, tap等笼痹。詳細內容請參考這里配喳。

XML report

使用mocha-junit-reporter可以產生一個xml報告,這對jenkins非常友好凳干。

安裝 npm i mocha-junit-reporter

把報告放到output目錄下

"mocha": {
  "reporterOptions": {
      "mochaFile": "output/result.xml"
  }
},

使用codeceptjs run --reporter mocha-junit-reporter 來執(zhí)行測試產生xml報告晴裹,最終的報告會被放在 output/result.xml。

HTML report

因為codeceptjs是基于mocha的救赐,所以我們可以使用mochawesome來產生好看的HTML報告涧团。

安裝 npm i mochawesome

把報告放到output目錄下

"mocha": {
  "reporterOptions": {
      "reportDir": "output"
  }
},

使用codeceptjs run --reporter mochawesome 來執(zhí)行測試產生html報告,最終的報告會被放在 output/mochawesome.html。

對于失敗的測試泌绣,我們需要有截圖喳瓣,我們可以使用下面的配置來實現(xiàn)

"helpers": {
    "Mochawesome": {
        "uniqueScreenshotNames": "true"
    }
  },

Test Options

Feature()和Scenario()的第二個參數(shù)可以是一對鍵值對,這個參數(shù)的作用是為測試場景提供一些選項比如timeout和retry

Feature('My feature', {key: val});

Scenario('My scenario', {key: val}, (I) => {});
Timeout

默認狀態(tài)下赞别,測試場景是沒有timeout的畏陕,我們可以通過傳遞下面的鍵值對來設置feature級別或是scenario級別的timeout

// set timeout to 5s
Feature('Stop me', {timeout: 5000});

// set timeout to 1s
Scenario("Stop me faster", {timeout: 1000}, (I) => {});

// disable timeout for this scenario
Scenario("Don't stop me", {timeout: 0}, (I) => {});
Retries

UI測試是不穩(wěn)定的,有些時候我們需要rerun來讓相應的測試場景通過仿滔。我們可以通過在Feature()和Scenario()中傳遞retries鍵值對來實現(xiàn)惠毁。


//所有scenario失敗后都會retry3次
Feature('Complex JS Stuff', {retries: 3})

//這個scenario失敗后只會retry1次
Scenario('Not that complex', {retries: 1}, (I) => {
  // test goes here
});
//這個scenario失敗后會retry3次
Scenario('Really complex', (I) => {
  // test goes here
});
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市崎页,隨后出現(xiàn)的幾起案子鞠绰,更是在濱河造成了極大的恐慌,老刑警劉巖飒焦,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜈膨,死亡現(xiàn)場離奇詭異,居然都是意外死亡牺荠,警方通過查閱死者的電腦和手機翁巍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來休雌,“玉大人灶壶,你說我怎么就攤上這事¤厩” “怎么了驰凛?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長担扑。 經常有香客問我恰响,道長,這世上最難降的妖魔是什么涌献? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任胚宦,我火速辦了婚禮,結果婚禮上洁奈,老公的妹妹穿的比我還像新娘间唉。我一直安慰自己绞灼,他們只是感情好利术,可當我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著低矮,像睡著了一般印叁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天轮蜕,我揣著相機與錄音昨悼,去河邊找鬼。 笑死跃洛,一個胖子當著我的面吹牛率触,可吹牛的內容都是我干的。 我是一名探鬼主播汇竭,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼葱蝗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了细燎?” 一聲冷哼從身側響起两曼,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎玻驻,沒想到半個月后悼凑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡璧瞬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年户辫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤锉。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡寸莫,死狀恐怖,靈堂內的尸體忽然破棺而出档冬,到底是詐尸還是另有隱情膘茎,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布酷誓,位于F島的核電站披坏,受9級特大地震影響,放射性物質發(fā)生泄漏盐数。R本人自食惡果不足惜棒拂,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玫氢。 院中可真熱鬧帚屉,春花似錦、人聲如沸漾峡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽生逸。三九已至牢屋,卻和暖如春且预,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烙无。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工锋谐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人截酷。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓涮拗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親迂苛。 傳聞我的和親對象是個殘疾皇子多搀,可洞房花燭夜當晚...
    茶點故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內容