本文章基于codeceptjs@1.0.1
這篇文章會介紹一些與頁面交互最常用的actions及其用法。
定位元素
和其他框架定位元素一樣,CSS/Xpath/ID/Name/Text等都是常用的方法。對于webdriverio這個helper來說,基本每一個方法都會接受css和xpath。
I.seeElement('.user'); // element with CSS class user
I.seeElement('//button[contains(., "press me")]'); // button
默認情況下,因為codeceptjs會去猜locator的類型,所以你不用特別指明。我們也可以通過strict locator來告訴codeceptjs locator的類型。
strict locator 就是一組鍵值對,key表示的是locator的類型,value表示的是locator的值。
// locate from element by css
I.seeElement({css: 'div.user'});
// locate form element by xpath
I.seeElement({xpath: '//div[@class=user]'});
// locate form element by name
I.seeElement({name: 'password'});
// locate element by text
I.seeElement({text: 'press me'});
// locate element by id
I.seeElement({id: 'users'});
點擊元素
點擊link或是button算是每個頁面都會有的基本操作了。默認情況下,codeceptjs會采用“完全匹配”的方式通過button text來查找元素并且點擊元素。
// search for link or button
I.click('Login');
如果沒有找到“完全匹配”的,會采用“部分匹配”的方式進行查找。對于可以點擊的圖片,會查找圖片對應的alt
屬性。i.e. 
“imagetext”就是我們可以查找的文本。
為了縮小的查找的范圍,click()方法的第二個參數可以接受一個locator來限定查找的區域。
I.click('Login', '.nav'); // search only in .nav
I.click('Login', {css: 'footer'}); // search only in footer
strict locator和css id xpath都是可以用于click()中來縮小范圍。不過這樣的話,元素定位的范圍就不僅限于link和button了。任何被找到的元素都會被點擊。
// click element by CSS
I.click('#signup');
// click element located by name inside a form
I.click({name: 'submit'}, '#user>form');
填充文本框
填充文本框使用fillField()方法,支持name,lable, Xpath和CSS等locator類型。
// we are using label to match user_name field
I.fillField('Name', 'Miles');
// we can use input name
I.fillField('user[email]','miles@davis.com');
// we are using CSS
I.fillField('#user_name', 'Miles');
I.fillField('#user_email','miles@davis.com');
選取下拉菜單
下拉菜單選值使用selectOption()方法,支持name,lable, Xpath和CSS等locator類型。
// select element by label, choose option by text
I.selectOption('Gender','Male');
// select element by label, option by value
I.selectOption('#user_gender','m');
驗證
為了驗證我們是否到了期望的頁面或是完成了期望的行為,我們需要方法來判斷頁面上是否有我們需要的元素顯示出來。I.see*()
和I.dontSee*()
方法可以驗證當前用戶看到的頁面上元素是否存在。
最常用的是I.see()
和I.dontSee()
.下面的列子可以驗證頁面上的文本是否存在。和其他方法類似,第二個參數可以縮小查找范圍。
// Just a visible text on a page
I.see('Hello');
// text inside .msg element
I.see('Hello', '.msg');
// opposite
I.dontSee('Bye');
I.seeElement()
和I.dontSeeElement()
可以判斷元素的出現與否
I.seeElement('.notice');
I.dontSeeElement('.error');
除此之外,頁面的URL,title和文本框里面的值都是可以驗證的。更多的方法請參考這里。
I.seeInCurrentUrl('/user/miles');
I.seeInField('user[name]', 'Miles');
I.seeInTitle('My Website');
抓取元素
某些時候你需要從頁面獲取一些數據來做驗證或是下一個測試步驟的輸入,比如頁面顯示出來的文本。所有已grab*
開頭的方法可以滿足這個需求。
I.fillField('email', 'miles@davis.com')
I.click('Generate Password');
let password = yield I.grabTextFrom('#password');
I.click('Login');
I.fillField('email', 'miles@davis.com');
I.fillField('password', password);
I.click('Log in!');
上面的grabTextFrom()
方法用于取出元素的文本。所有的grab*()
方法都要用于生成器里面。
Scenario('use page title', function*(I) {
// ...
var password = yield I.grabTextFrom('#password');
I.fillField('password', password);
});
等待wait
在日常造成UI測試失敗的原因中,render太慢造成元素在頁面顯示不出來然后操作無法完成十分常見。于是在各大的測試框架中wait*()
相關方法的出現就用來解決這個問題。
I.waitForElement('#agree_button', 30); // secs
// clicks a button only when it is visible
I.click('#agree_button');
SmartWait
Selenium Webdriver提供了兩種不同類型的waits:
- implicit wait -> 讓webdriver在當定位元素的時候,如果元素沒有立即出現,需要等待一段時間。這個作用域是DOM全局的。
- explicit wait -> 讓webdriver在繼續執行操作之前,等待某個特定的情況發生。比如在點擊某一個link之前,需要等待link加載完成
codeceptjs的SmartWait就是implicit wait的實現。如果需要定位的元素還沒有出現,codeceptjs會在失敗之前等待一段時間。
SmartWait是配置在Helper里面的,比如下面的smartWait: 5000
"helpers": {
"WebDriverIO": {
"url": "http://simple-form-bootstrap.plataformatec.com.br",
"browser": "chrome",
"smartWait": 5000
}
},
注意到SmartWait只在strict locator和標識了type的locator的方法中起作用
I.click('Login'); // DISABLED, not a locator
I.fillField('user', 'davert'); // DISABLED, not a specific locator
I.fillField({name: 'password'}, '123456'); // ENABLED, strict locator
I.click('#login'); // ENABLED, locator is CSS ID
I.see('Hello, Davert'); // DISABLED, Not a locator
I.seeElement('#userbar'); // ENABLED
I.dontSeeElement('#login'); // DISABLED, can't wait for element to hide
I.seeNumberOfElements('button.link', 5); // DISABLED, can wait only for one element
IFrames
within()
方法可以用于IFrame的定位,在within()
內部的方法就會在IFrame中執行。
within({frame: "#editor"}, () => {
I.see('Page');
});