新聞中心
不過,端到端測試是困難的、耗時(shí)的,并且有一大堆問題需要解決。但如果你用對了工具的話,效果可能會(huì)事半功倍。

為石臺(tái)等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及石臺(tái)網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、石臺(tái)網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
??
Cypress測試框架提供了快速、簡單、可靠的瀏覽器測試。能夠幫助解決端到端測試的大多數(shù)痛點(diǎn),并使編寫測試變得有趣。但是,有一些錯(cuò)誤是要避免的,這樣就可以充分利用Cypress的優(yōu)勢。
在這篇博文中,我們將介紹5個(gè)常見錯(cuò)誤,這些錯(cuò)誤在使用Cypress測試時(shí)應(yīng)該避免。
使用id和class來選擇元素
使用id和class來選擇元素是有問題的,因?yàn)樗鼈冎饕糜谛袨楹蜆邮侥康?,因此?jīng)常會(huì)發(fā)生更改。這樣做會(huì)導(dǎo)致你可能不想要的脆弱測試。
相反,你應(yīng)該始終嘗試使用data-cy或data-test-id。因?yàn)樗鼈兪菍iT用于測試目的的,這使得它們與行為或樣式分離,因此更可靠。
例如,假設(shè)我們有一個(gè)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)行斷言或操作。盡管這很好,但請記住,如果文本更改,則會(huì)導(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è)命令完成后,才會(huì)運(yùn)行下一個(gè)命令。
// This works
cy.get("[data-testid=element]").then($el => {
// Do something with $el
});
在使用像Promise這樣的命令時(shí),它可能不會(huì)像你期望的那樣工作,因?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)用程序的用戶很可能會(huì)等待加載之類的視覺線索來確定操作的完成,而不是等待任意時(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)是它們只會(huì)等待條件滿足,而不是像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í)需要記住的幾件事:
- 你不能依賴持久存儲(chǔ),無論是測試塊中的變量,還是本地存儲(chǔ)。因?yàn)?,?dāng)我們使用配置中定義的baseURL以外的域發(fā)出一個(gè)Cypress命令時(shí),Cypress會(huì)執(zhí)行一個(gè)拆除和完全重新加載。
- 由于上述相同問題,"before"和 "after"這樣的塊將會(huì)為每個(gè)這樣的測試塊運(yùn)行。
所以在采用此方法并相應(yīng)地調(diào)整測試之前,請注意這些問題。
混合異步和同步代碼
Cypress命令是異步的,它們不返回值,而是生成值。
當(dāng)我們運(yùn)行Cypress時(shí),它不會(huì)立即執(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í)我們會(huì)犯一些錯(cuò)誤,這讓體驗(yàn)變得不有趣。通過避免常見的錯(cuò)誤,我們可以讓端到端測試過程更加順利和有趣。
新聞標(biāo)題:使用Cypress需要避免的5個(gè)E2E測試錯(cuò)誤
文章地址:http://www.dlmjj.cn/article/dhigdih.html


咨詢
建站咨詢
