CodeceptJS
CodeceptJS是基于現(xiàn)代web技術(shù)的E2E自動化測試框<wbr>架,具有特殊的BDD風格語法;基于 Feature 和 Scenario 兩個粒度來組織測試讓它看起來更有 E2E 測試的樣子,它支持最新的ES6語法,<wbr>同時也屏蔽各種復雜的回調(diào)細節(jié),<wbr>所有的測試用例都是以第一人稱來做,<wbr>讓測試代碼閱讀起來更像是自然語言。
Quick Start
第一步,先讓測試跑起來
按照quick start搭建了環(huán)境,寫出了第一個測試-登陸,感覺so easy.
Feature('My First Test');
Scenario('test something', ({ I }) => {
I.amOnPage('https://github.com');
I.click('Sign in');
I.fillField('username', 'myName');
I.fillField('password', 'myPassword');
I.click('Sign in');
I.see('Welcome, myName');
});
CI
第一個測試成功了,趕緊放到CI上跑一跑,每天定時運行,<wbr>自動做回歸測試,想想都覺得很美好。 那么問題來了,CI server上沒有安裝測試工具所需的環(huán)境依賴怎么辦?<wbr>在哪個環(huán)境運行,DEV,QA,UAT?<wbr>運行完以后有report嗎?
別急,都有現(xiàn)成的解決方案。
在CI server上啟動一個包含測試環(huán)境依賴的docker,<wbr>先讓測試運行在最可控的QA環(huán)境,<wbr>搜索一款最適合當前工具的report,比如allure,<wbr>跟devops小哥哥pair一下,<wbr>jenkinsfile就生成了,<wbr>E2E自動化測試每天定時跑起來了,<wbr>測試運行失敗就會發(fā)送消息到日常工作群,及時發(fā)現(xiàn)問題~
pipeline {
agent {
kubernetes {
label 'swgen2-e2e'
defaultContainer 'jnlp'
yaml """
apiVersion: v1
kind: Pod
metadata:
labels:
app: swgen2-e2e-app
spec:
containers:
- name: codecepjs
image: codeception/codeceptjs
command:
- cat
tty: true
"""
}
}
stages {
stage('Run e2e in qa') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
container('codecepjs') {
sh 'codeceptjs run --grep @qa -o \'{ "helpers": {"TestCafe": {"url": "https://swgen2-qa.successwareg2.com"}}}\' --plugins allure'
}
}
}
}
}
post {
always {
script {
allure([
includeProperties: false,
jdk: '',
properties: [],
reportBuildPolicy: 'ALWAYS',
results: [[path: 'output']]
])
}
}
failure {
slackSend(color: '#FF0000',
channel: '#swplatform-jenkins',
message: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL}) \nCommitter: (${getCommitter()})")
}
fixed {
slackSend(color: '#00FF00',
channel: '#swplatform-jenkins',
message: "BACK TO NORMAL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
}
}
}
新的問題
CodeceptJS支持語義化的元素定位符,<wbr>可以自動判斷定位符類型并且尋找元素,<wbr>對于編寫測試代碼來說確實很方便,不用辛辛苦苦找元素定位了,<wbr>可是有些元素通過文本作為定位符找不到啊,<wbr>而且通過文本找元素好像很慢?還有哪些元素定位的方式?
CodeceptJS的操作就支持amOnPage,<wbr>click,fillField嗎?我還有一些其他的操作,<wbr>應(yīng)該怎么寫啊?
CodeceptJS的斷言只支持see嗎?<wbr>我還有地方要用not see,它也能支持嗎?
這幾個問題拋出了學習一個自動化測試工具的基本路徑,<wbr>那就是學習元素定位符,操作,斷言,<wbr>其中元素定位符對于一般的UI自動化測試工具都是通用的,<wbr>而操作和斷言,每個工具提供的語法不一樣。然而,<wbr>一旦掌握一種工具,其他任何工具學習起來都很快。學好數(shù)理化,<wbr>走遍天下都不怕~
持續(xù)優(yōu)化
此刻,我的元素定位符,操作,斷言已經(jīng)寫得很溜了。 當我開始寫越來越多的測試后發(fā)現(xiàn),每個測試都要登陸一下,<wbr>怎么樣才能減少這種重復操作呢? 除了登錄,我的代碼中很多重復操作,怎么樣封裝他們,<wbr>方便調(diào)用呢? dev小伙伴升級了依賴庫,導致元素定位變化了,<wbr>我需要大面積修改元素定位符,怎樣才能提高元素定位符的通用性,<wbr>避免此類情況再次發(fā)生?
第一步,提取公共元素,比如文本框,<wbr>當我需要使用某個文本框時只需要輸入文本框的label就能定位<wbr>到它了;
//封裝公共元素
editInput: function (inputName, text) {
let locator = `//label[contains(., "${inputName}")]/preceding-sibling::input`;
this.clearField(locator);
this.appendField(locator, text);
},
//
第二步,提取公共step,比如click tab作為common step放到一個文件里,當我在任何頁面需要click tab時,只需要寫上tab上的文字就可以了,<wbr>codeceptjs對button和link做了一層封裝,<wbr>所以看到quickstart里面,click sign in的元素定位符只需要寫上文字就可以了;
第三步,提取公共function,比如登錄,<wbr>搜索等不同頁面常用操作放到common function文件里面;
第四步,提取每個頁面的公共function,<wbr>針對一個頁面的某個feature如果有多種測試場景,<wbr>此時公共function可以復用。
場景設(shè)計的巧思
測試場景設(shè)計需要許多巧思,<wbr>這樣才能讓E2E在日常運行中更為流暢。
- 盡可能精簡。因為E2E保證的是主要功能和流程正確,<wbr>摻雜太多細節(jié)驗證會讓代碼復雜度急劇增加,維護成本太高,<wbr>同時還會讓自己陷入我到底應(yīng)該把哪些測試點加入到E2E的焦慮中<wbr>。先用20%的精力做成80%的事情,再用剩下的80%<wbr>的精力想想怎么拔高20%,比如提高團隊的質(zhì)量意識。
- 每個測試場景盡可能獨立。這樣在其中一個場景報錯時,<wbr>不會影響其他場景的測試結(jié)果,<wbr>并且任何時候想單獨運行某個或某幾個測試都可以立即運行,<wbr>不用修改代碼才能運行。場景獨立帶來的副作用就是,<wbr>會有許多重復操作,這時就需要封裝來解決這些冗余代碼。
- 在測試套件中進行登錄操作。測試場景獨立的話,<wbr>每個測試開始前都需要進行登錄操作,這會拉慢測試運行速度,<wbr>如果測試工具支持的話,<wbr>設(shè)置為在每個測試套件開始前進行登錄操作,<wbr>這會大大減少重復的登錄操作。
- 需要考慮數(shù)據(jù)的初始化。<wbr>數(shù)據(jù)初始化的方案要么是通過頁面操作去造數(shù)據(jù),<wbr>它的缺點是添加了大量和測試場景無關(guān)的額外操作,<wbr>使得代碼復雜加運行時間變長;要么通過API造數(shù)據(jù),<wbr>但需要E2E測試工具支持;要么通過連接數(shù)據(jù)庫,<wbr>直接向數(shù)據(jù)庫插入數(shù)據(jù),缺點是數(shù)據(jù)庫表之間關(guān)聯(lián)關(guān)系復雜的話,<wbr>難以摸清這些關(guān)聯(lián)關(guān)系,容易造出臟數(shù)據(jù),<wbr>同時連接數(shù)據(jù)庫也需要E2E測試工具支持;<wbr>我最傾向的方式是在不受影響的環(huán)境中運行E2E,<wbr>使用提前準備好的固定數(shù)據(jù),當然用完就失效的數(shù)據(jù),<wbr>比如跟狀態(tài)相關(guān)的數(shù)據(jù),還是只能通過前三種方式創(chuàng)建。
- 需要考慮數(shù)據(jù)使用后的還原。這樣才能在下次運行同一個測試時,<wbr>不會因為數(shù)據(jù)被改變而失敗。
- 加tag區(qū)分不同環(huán)境的測試。<wbr>針對不同環(huán)境運行的測試場景不一樣的情況,<wbr>加tag區(qū)分不同環(huán)境,運行時加上tag參數(shù)即可。
更多思考
E2E總是被詬病,運行太慢,維護頻繁,反饋太晚。<wbr>但在實際使用過程中,E2E發(fā)現(xiàn)了不少新功能破壞舊功能的情況,<wbr>然而單元測試沒有發(fā)現(xiàn)這些問題(UT覆蓋率也很高)。<wbr>那么為了更好地使用E2E,就需要不斷優(yōu)化它。運行太慢,<wbr>那么就在多個docker里面并發(fā)運行;維護頻繁,<wbr>那么就盡量用不容易變化的元素定位符,并且多封裝,<wbr>一旦發(fā)生變化改動也不會很多;反饋太晚,額。。。<wbr>它的屬性就是如此,<wbr>用它來做日常的回歸測試保證舊功能完好是個不錯的選擇。
最后的成果
目前我們的項目上,一共有31個測試場景,<wbr>單個docker容器里面運行全部測試耗時大概13分鐘,<wbr>每次部署QA或者UAT后自動trigger E2E分別在不同環(huán)境運行,<wbr>再也不用擔心Dev的重構(gòu)或者環(huán)境部署不當造成的bug沒有及時<wbr>發(fā)現(xiàn)了。另外,因為有很多公共元素和公共步驟的封裝,<wbr>添加新的測試代碼也很容易。唯一令人頭大的點就是,<wbr>它有時候有點不穩(wěn)定,報一些手動操作沒有的bug,這類bug debug起來很難,也不知道算不算bug。。。