使用Cypress需要避免的5個(gè)E2E測試錯(cuò)誤
譯文【51CTO.com快譯】不過,端到端測試是困難的、耗時(shí)的,并且有一大堆問題需要解決。但如果你用對了工具的話,效果可能會事半功倍。
Cypress測試框架提供了快速、簡單、可靠的瀏覽器測試。能夠幫助解決端到端測試的大多數(shù)痛點(diǎn),并使編寫測試變得有趣。但是,有一些錯(cuò)誤是要避免的,這樣就可以充分利用Cypress的優(yōu)勢。
在這篇博文中,我們將介紹5個(gè)常見錯(cuò)誤,這些錯(cuò)誤在使用Cypress測試時(shí)應(yīng)該避免。
使用id和class來選擇元素
使用id和class來選擇元素是有問題的,因?yàn)樗鼈冎饕糜谛袨楹蜆邮侥康模虼私?jīng)常會發(fā)生更改。這樣做會導(dǎo)致你可能不想要的脆弱測試。
相反,你應(yīng)該始終嘗試使用data-cy或data-test-id。因?yàn)樗鼈兪菍iT用于測試目的的,這使得它們與行為或樣式分離,因此更可靠。
例如,假設(shè)我們有一個(gè)input元素:
<input
id="main"
type="text"
class="input-box"
name="name"
data-testid="name"
/>
應(yīng)該使用id或class來測試這個(gè)元素,而應(yīng)該使用data- tested:
// Don't
cy.get("#main").something();
cy.get(".input-box").something();
// Do
cy.get("[data-testid=name]").something();
有時(shí)需要使用文本(如按鈕標(biāo)簽)來進(jìn)行斷言或操作。盡管這很好,但請記住,如果文本更改,則會導(dǎo)致測試失敗。
將Cypress命令視為Promise
Cypress測試由Cypress命令組成,例如Cypress .get和Cypress .visit。類似于Promise,但不是真正的Promise。
這意味著,我們不能在使用它們時(shí)像使用async-await這樣的語法。例如:
// This won't work
const element = await cy.get("[data-testid=element]");
// Do something with element
如果你需要在一個(gè)命令完成后執(zhí)行某些操作,你可以在cy.then命令的幫助下完成。它將保證只有在前一個(gè)命令完成后,才會運(yùn)行下一個(gè)命令。
// This works
cy.get("[data-testid=element]").then($el => {
// Do something with $el
});
在使用像Promise這樣的命令時(shí),它可能不會像你期望的那樣工作,因?yàn)镃ypress命令類似于Promise,但不是真正的Promise。
在Cypress測試中使用任意等待
在編寫Cypress測試時(shí),我們希望在真實(shí)場景中模擬真實(shí)用戶的行為。由于網(wǎng)絡(luò)延遲和設(shè)備限制等因素,現(xiàn)實(shí)世界中的應(yīng)用程序是異步的和緩慢的。
在為這類應(yīng)用程序編寫測試時(shí),我們傾向于在cy.wait命令中使用任意值。這種方法的問題在于,雖然它在開發(fā)中運(yùn)行良好,但不能保證一直穩(wěn)定。因?yàn)榈讓酉到y(tǒng)依賴于像網(wǎng)絡(luò)請求這樣的東西,這些東西是異步的,幾乎不可能預(yù)測的。
// Might work (sometimes)
cy.get("[data-testid=element]").performSomeAsyncAction();
// Wait for 1000 ms
cy.wait(1000);
// Do something else after the action is completed
相反,我們應(yīng)該等待視覺元素加載完成。它不僅更接近真實(shí)世界的用例,而且給出了更可靠的結(jié)果。想想看,使用應(yīng)用程序的用戶很可能會等待加載之類的視覺線索來確定操作的完成,而不是等待任意時(shí)間。
// The right way
cy.get("[data-testid=element]").performSomeAsyncAction();
// Wait for loading to finish
cy.get("[data-testid=loader]").should("not.be.visible");
// Now that we know previous action has been completed; move ahead
例如,Cypress命令cy.get在斷言之前等待元素,當(dāng)然你可以修改預(yù)定義的超時(shí)值,timeout很酷的一點(diǎn)是它們只會等待條件滿足,而不是像cy.wait命令那樣等待整個(gè)持續(xù)時(shí)間
在Cypress測試中使用不同的域
Cypress的一個(gè)限制是,它不允許在單個(gè)測試中使用多個(gè)域名。
如果你嘗試在單個(gè)測試塊中使用多個(gè)域,Cypress將拋出安全警告。
如果真要在一個(gè)測試中需要訪問多個(gè)域。我們可以通過將測試邏輯分割到單個(gè)測試文件中的多個(gè)測試塊來實(shí)現(xiàn)。例如,你可以把它想象成一個(gè)多步驟測試:
describe("Test Page Builder", () => {
it("Step 1: Visit Admin app and do something", {
// ...
});
it("Step 2: Visit Website app and assert something", {
// ...
});
});
我們在Webiny使用類似的方法來測試Page Builder應(yīng)用程序。
當(dāng)以這種方式編寫測試時(shí)需要記住的幾件事:
- 你不能依賴持久存儲,無論是測試塊中的變量,還是本地存儲。因?yàn)?,?dāng)我們使用配置中定義的baseURL以外的域發(fā)出一個(gè)Cypress命令時(shí),Cypress會執(zhí)行一個(gè)拆除和完全重新加載。
- 由于上述相同問題,"before"和 "after"這樣的塊將會為每個(gè)這樣的測試塊運(yùn)行。
所以在采用此方法并相應(yīng)地調(diào)整測試之前,請注意這些問題。
混合異步和同步代碼
Cypress命令是異步的,它們不返回值,而是生成值。
當(dāng)我們運(yùn)行Cypress時(shí),它不會立即執(zhí)行命令,而是串行讀取它們并將它們排隊(duì)。只有在它一個(gè)一個(gè)地執(zhí)行它們之后。因此,如果你編寫的測試混合了異步和同步代碼,你將得到錯(cuò)誤的結(jié)果。例如:
it("does not work as we expect", () => {
cy.visit("your-application") // Nothing happens yet
cy.get("[data-testid=submit]") // Still nothing happening
.click() // Nope, nothing
// Something synchronous
let el = Cypress.$("title") // evaluates immediately as []
if (el.length) {
// It will never run because "el.length" will immediately evaluates as 0
cy.get(".another-selector")
} else {
/*
* This code block will always run because "el.length" is 0 when the code executes
*/
cy.get(".optional-selector")
}
})
相反,使用cy.then命令在命令完成后運(yùn)行代碼。例如:
it("does work as we expect", () => {
cy.visit("your-application") // Nothing happens yet
cy.get("[data-testid=submit]") // Still nothing happening
.click() // Nope, nothing
.then(() => {
// placing this code inside the .then() ensures
// it runs after the cypress commands 'execute'
let el = Cypress.$(".new-el") // evaluates after .then()
if (el.length) {
cy.get(".another-selector")
} else {
cy.get(".optional-selector")
}
})
})
總結(jié)
Cypress是端到端測試的強(qiáng)大工具,但有時(shí)我們會犯一些錯(cuò)誤,這讓體驗(yàn)變得不有趣。通過避免常見的錯(cuò)誤,我們可以讓端到端測試過程更加順利和有趣。
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】