CodeceptJS
CodeceptJS是基于現(xiàn)代web技術(shù)的E2E自動化測試框<wbr>架,具有特殊的BDD風(fēng)格語法土铺;基于 Feature 和 Scenario 兩個粒度來組織測試讓它看起來更有 E2E 測試的樣子萤悴,它支持最新的ES6語法瘾腰,<wbr>同時也屏蔽各種復(fù)雜的回調(diào)細(xì)節(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上跑一跑柳沙,每天定時運(yùn)行岩灭,<wbr>自動做回歸測試,想想都覺得很美好赂鲤。 那么問題來了噪径,CI server上沒有安裝測試工具所需的環(huán)境依賴怎么辦?<wbr>在哪個環(huán)境運(yùn)行数初,DEV找爱,QA,UAT泡孩?<wbr>運(yùn)行完以后有report嗎车摄?
別急,都有現(xiàn)成的解決方案仑鸥。
在CI server上啟動一個包含測試環(huán)境依賴的docker吮播,<wbr>先讓測試運(yùn)行在最可控的QA環(huán)境,<wbr>搜索一款最適合當(dāng)前工具的report眼俊,比如allure意狠,<wbr>跟devops小哥哥pair一下,<wbr>jenkinsfile就生成了疮胖,<wbr>E2E自動化測試每天定時跑起來了环戈,<wbr>測試運(yùn)行失敗就會發(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>對于編寫測試代碼來說確實(shí)很方便遮晚,不用辛辛苦苦找元素定位了,<wbr>可是有些元素通過文本作為定位符找不到啊拦止,<wbr>而且通過文本找元素好像很慢县遣?還有哪些元素定位的方式?
CodeceptJS的操作就支持amOnPage汹族,<wbr>click艺玲,fillField嗎?我還有一些其他的操作鞠抑,<wbr>應(yīng)該怎么寫啊忌警?
CodeceptJS的斷言只支持see嗎搁拙?<wbr>我還有地方要用not see,它也能支持嗎法绵?
這幾個問題拋出了學(xué)習(xí)一個自動化測試工具的基本路徑箕速,<wbr>那就是學(xué)習(xí)元素定位符,操作朋譬,斷言盐茎,<wbr>其中元素定位符對于一般的UI自動化測試工具都是通用的,<wbr>而操作和斷言徙赢,每個工具提供的語法不一樣字柠。然而,<wbr>一旦掌握一種工具狡赐,其他任何工具學(xué)習(xí)起來都很快窑业。學(xué)好數(shù)理化,<wbr>走遍天下都不怕~
持續(xù)優(yōu)化
此刻枕屉,我的元素定位符常柄,操作,斷言已經(jīng)寫得很溜了搀擂。 當(dāng)我開始寫越來越多的測試后發(fā)現(xiàn)西潘,每個測試都要登陸一下,<wbr>怎么樣才能減少這種重復(fù)操作呢哨颂? 除了登錄喷市,我的代碼中很多重復(fù)操作,怎么樣封裝他們咆蒿,<wbr>方便調(diào)用呢东抹? dev小伙伴升級了依賴庫蚂子,導(dǎo)致元素定位變化了,<wbr>我需要大面積修改元素定位符缭黔,怎樣才能提高元素定位符的通用性食茎,<wbr>避免此類情況再次發(fā)生?
第一步馏谨,提取公共元素别渔,比如文本框,<wbr>當(dāng)我需要使用某個文本框時只需要輸入文本框的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放到一個文件里喊儡,當(dāng)我在任何頁面需要click tab時拨与,只需要寫上tab上的文字就可以了,<wbr>codeceptjs對button和link做了一層封裝艾猜,<wbr>所以看到quickstart里面买喧,click sign in的元素定位符只需要寫上文字就可以了;
第三步匆赃,提取公共function淤毛,比如登錄,<wbr>搜索等不同頁面常用操作放到common function文件里面算柳;
第四步低淡,提取每個頁面的公共function,<wbr>針對一個頁面的某個feature如果有多種測試場景瞬项,<wbr>此時公共function可以復(fù)用蔗蹋。
場景設(shè)計(jì)的巧思
測試場景設(shè)計(jì)需要許多巧思,<wbr>這樣才能讓E2E在日常運(yùn)行中更為流暢囱淋。
- 盡可能精簡纸颜。因?yàn)镋2E保證的是主要功能和流程正確,<wbr>摻雜太多細(xì)節(jié)驗(yàn)證會讓代碼復(fù)雜度急劇增加绎橘,維護(hù)成本太高胁孙,<wbr>同時還會讓自己陷入我到底應(yīng)該把哪些測試點(diǎn)加入到E2E的焦慮中<wbr>。先用20%的精力做成80%的事情称鳞,再用剩下的80%<wbr>的精力想想怎么拔高20%涮较,比如提高團(tuán)隊(duì)的質(zhì)量意識。
- 每個測試場景盡可能獨(dú)立冈止。這樣在其中一個場景報錯時狂票,<wbr>不會影響其他場景的測試結(jié)果,<wbr>并且任何時候想單獨(dú)運(yùn)行某個或某幾個測試都可以立即運(yùn)行熙暴,<wbr>不用修改代碼才能運(yùn)行闺属。場景獨(dú)立帶來的副作用就是慌盯,<wbr>會有許多重復(fù)操作,這時就需要封裝來解決這些冗余代碼掂器。
- 在測試套件中進(jìn)行登錄操作亚皂。測試場景獨(dú)立的話,<wbr>每個測試開始前都需要進(jìn)行登錄操作国瓮,這會拉慢測試運(yùn)行速度灭必,<wbr>如果測試工具支持的話,<wbr>設(shè)置為在每個測試套件開始前進(jìn)行登錄操作乃摹,<wbr>這會大大減少重復(fù)的登錄操作禁漓。
- 需要考慮數(shù)據(jù)的初始化。<wbr>數(shù)據(jù)初始化的方案要么是通過頁面操作去造數(shù)據(jù)孵睬,<wbr>它的缺點(diǎn)是添加了大量和測試場景無關(guān)的額外操作播歼,<wbr>使得代碼復(fù)雜加運(yùn)行時間變長;要么通過API造數(shù)據(jù)掰读,<wbr>但需要E2E測試工具支持荚恶;要么通過連接數(shù)據(jù)庫,<wbr>直接向數(shù)據(jù)庫插入數(shù)據(jù)磷支,缺點(diǎn)是數(shù)據(jù)庫表之間關(guān)聯(lián)關(guān)系復(fù)雜的話,<wbr>難以摸清這些關(guān)聯(lián)關(guān)系食寡,容易造出臟數(shù)據(jù)雾狈,<wbr>同時連接數(shù)據(jù)庫也需要E2E測試工具支持;<wbr>我最傾向的方式是在不受影響的環(huán)境中運(yùn)行E2E抵皱,<wbr>使用提前準(zhǔn)備好的固定數(shù)據(jù)善榛,當(dāng)然用完就失效的數(shù)據(jù),<wbr>比如跟狀態(tài)相關(guān)的數(shù)據(jù)呻畸,還是只能通過前三種方式創(chuàng)建移盆。
- 需要考慮數(shù)據(jù)使用后的還原。這樣才能在下次運(yùn)行同一個測試時伤为,<wbr>不會因?yàn)閿?shù)據(jù)被改變而失敗咒循。
- 加tag區(qū)分不同環(huán)境的測試。<wbr>針對不同環(huán)境運(yùn)行的測試場景不一樣的情況绞愚,<wbr>加tag區(qū)分不同環(huán)境叙甸,運(yùn)行時加上tag參數(shù)即可。
更多思考
E2E總是被詬病位衩,運(yùn)行太慢裆蒸,維護(hù)頻繁,反饋太晚糖驴。<wbr>但在實(shí)際使用過程中僚祷,E2E發(fā)現(xiàn)了不少新功能破壞舊功能的情況佛致,<wbr>然而單元測試沒有發(fā)現(xiàn)這些問題(UT覆蓋率也很高)。<wbr>那么為了更好地使用E2E辙谜,就需要不斷優(yōu)化它俺榆。運(yùn)行太慢,<wbr>那么就在多個docker里面并發(fā)運(yùn)行筷弦;維護(hù)頻繁肋演,<wbr>那么就盡量用不容易變化的元素定位符,并且多封裝烂琴,<wbr>一旦發(fā)生變化改動也不會很多爹殊;反饋太晚,額奸绷。梗夸。。<wbr>它的屬性就是如此号醉,<wbr>用它來做日常的回歸測試保證舊功能完好是個不錯的選擇反症。
最后的成果
目前我們的項(xiàng)目上,一共有31個測試場景畔派,<wbr>單個docker容器里面運(yùn)行全部測試耗時大概13分鐘铅碍,<wbr>每次部署QA或者UAT后自動trigger E2E分別在不同環(huán)境運(yùn)行,<wbr>再也不用擔(dān)心Dev的重構(gòu)或者環(huán)境部署不當(dāng)造成的bug沒有及時<wbr>發(fā)現(xiàn)了线椰。另外胞谈,因?yàn)橛泻芏喙苍睾凸膊襟E的封裝,<wbr>添加新的測試代碼也很容易憨愉。唯一令人頭大的點(diǎn)就是烦绳,<wbr>它有時候有點(diǎn)不穩(wěn)定,報一些手動操作沒有的bug配紫,這類bug debug起來很難径密,也不知道算不算bug。躺孝。享扔。