摘要:上也有幾個臨時方案,目前我傾向使用自帶的來查看。在打開的測試的瀏覽器中打開切到按下用戶按,輸入,選擇重新刷新并統(tǒng)計代碼執(zhí)行覆蓋率。那么,起來為了高撩質(zhì)測量試代碼,起來。
不很久不很久以前
據(jù)說某家公司有兩位前端,天天擼bug,為啥嘞?只怪測試MM傾人國,輕語哥哥有bug。?(??????)?? 可是最近兩位有點犯愁 Σ(っ °Д °;)っ。測試MM有幾次提了緊急bug,都在旁邊鼓勵他們改bug了,可是線上bug重現(xiàn)排查比較麻煩,而且改了后還發(fā)現(xiàn)沒改好,惹得測試MM潸然淚下,好生埋汰。怎么辦呢?
前端君666某天發(fā)現(xiàn)了E2E測試神器cypress后,暗中偷練神功,改bug越來越6,測試MM每天笑著對他說,666你真6,MM好喜歡呀(??? ? ???) 另一位前端君555每天面對堆積如山的bug長吁短嘆,測試MM提完新bug后都不理他了≡ ̄﹏ ̄≡
作為一個追求代碼永無bug、順帶跟測試MM溝通產(chǎn)品的有理想的前端 (? ??_??)?,我覺得有必要學(xué)習(xí)一下怎么使用cypress來進(jìn)行E2E測試,以此來提高代碼質(zhì)量。那么我們來看看怎么入門cypress測試框架。
cypress三問 - 你是誰cypress是在mocha式API基礎(chǔ)上構(gòu)建的一套開箱可用的E2E測試框架,對比其他測試框架,它提供一套自己的最佳實踐方案,無需其他測試工具庫,配置方便簡單但功能異常強(qiáng)大,可以使用webpack項目配置,還提供了一個強(qiáng)大的GUI圖形工具。入門簡單,上手方便,怎么舒服怎么來呀 (?????)
cypressGUI方式的測試使用真實瀏覽器,非GUI方式使用chrome-headless,不是用模擬方式進(jìn)行測試,更真實的展現(xiàn)實際環(huán)境中的測試過程和結(jié)果。
cypress三問 - 你有啥優(yōu)勢cypress有幾大自帶的強(qiáng)大功能:
自帶GUI工具,想測啥就點啥,還可以查看整個測試過程,想錄屏還可以錄屏喲(錄屏可以發(fā)給測試MM看,保準(zhǔn)她說哥哥真厲害喲。 一般人我不告訴他?乛?乛?)
測試的每一步都有snapshot,可以通過GUI工具查看每個過程的頁面狀態(tài),不是截圖而是真是的頁面DOM環(huán)境喲!
自帶數(shù)據(jù)mock和請求攔截機(jī)制,還原線上數(shù)據(jù)引起的bug別提有多輕松了
和wepbakc配置,實現(xiàn)無論修改測試文件還是被測試代碼都可以自動重測
小Tips:可以給測試用例加上only或者skip來避免重測測試文件里的所有用例: it.only("只測試這個喲); it.skip("不要測這個");
cypress三問 - 怎么用 安裝yarn add cypress 或者 npm install cypress
安裝完畢后,./node_modules/.bin/cypress install安裝cypress環(huán)境(包括GUI工具)
配置package.json: 配置GUI和非GUI(terminal)兩種方式來運行cypress
"scripts": { "cypress": "cypress run", "cypress-gui": "cypress open",
?? 配置好后 先運行 yarn cypress[-gui] 或者 npm run cypress[-gui](中括號意思是可選)來初始化cypress,__生成默認(rèn)配置和目錄__
cypress.json(與package.json同級目錄): cypress提供比較靈活的配置,可以根據(jù)自己需要定制行為,以下列一下我對一個項目的配置
{ "baseUrl": "http://localhost:8080", // 本地開發(fā)服務(wù)地址(webpack-dev-server) "integrationFolder": "src", // 自定義"src"為測試文件根目錄,默認(rèn)是"cypress/integration" "testFiles": "**/*.cypress.spec.js", // 自定義測試文件的匹配正則,默認(rèn)是"**/*.*",即所有文件 "videoRecording": false, // 關(guān)閉錄屏功能, 如果開啟錄屏功能,記得將"cypress/screenshots"目錄加入".gitignore",防止不小心將錄屏加到git中 "viewportHeight": 800, // 設(shè)置測試環(huán)境的頁面視圖的高度 "viewportWidth": 1600 // 設(shè)置測試環(huán)境的頁面視圖的寬度 }
cypress/plugins/index.js: cypress運行環(huán)境配置,可以用來配置webpack等。以下是配置webpack別名范例。默認(rèn)這里不需要配置。
// 參考官方例子地址 https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/preprocessors__typescript-webpack/cypress/plugins/index.js const wp = require("@cypress/webpack-preprocessor"); const path = require("path"); function resolve(dir) { return path.join(__dirname, "../..", dir); } module.exports = on => { const options = { webpackOptions: { resolve: { alias: { "@": resolve("src"), cypress: resolve("cypress") } } } }; on("file:preprocessor", wp(options)); };萬事俱備,測測測
簡單的一個例子
describe("測試頁面包含某元素", () => { it("有云 "前端哥哥們真帥,前端妹妹們真漂亮"", () => { cy.contains("前端哥哥們真帥,前端妹妹們真漂亮"); }); it("要有一個鏈接", () => { cy.get("a").should("have.length", 1); }); it("不存在class含有abc的元素", () => { cy.get(".abc").should("have.length", 0); }); });
互動的例子
describe("一起動", () => { it("獲取輸入框,輸入文字并按enter鍵", () => { const text = "not exist"; // type api用法: https://docs.cypress.io/api/commands/type.html#Usage cy.get("input").type(`${text}{enter}`); }); it("點擊按鈕", () => { cy.get("button").click(); }); });
網(wǎng)絡(luò)請求mock例子
Tip1: cy.route的路徑匹配是嚴(yán)格的,所以要注意是否需要加通配符。如 cy.route("/api/search", [])不會攔截/api/search?keyword=abc,只會攔截/api/search。Tip2: cy.route的method要注意,默認(rèn)是GET,cy.route("/api/posts") 和 cy.route("POST", "/api/posts") 是不一樣的。
describe("要啥給啥", () => { beforeEach(() => { cy.server(); // 一定要在 cy.route 前調(diào)用 cy .fixture("/posts/list.json") // 我們在 cypress/fixtures 內(nèi)創(chuàng)建mock用的數(shù)據(jù) .as("postsData"); // 給 mock 數(shù)據(jù)取別名,以后 cy.route 使用 cy .route("/api/posts", "@postsData") .as("getPostsRoute"); // 給請求取別名,以供 cy.wait 使用 }) it("進(jìn)入列表頁,攔截列表請求接口", () => { cy.wait("@getPostsRoute"); // 等待被攔截的接口請求完成 cy.get(".post").should("have.length", 10); // 要有10條數(shù)據(jù)被渲染到頁面上 }); })
實際場景例子: 結(jié)合上面所有姿勢,我們現(xiàn)在測試搜索頁面的搜索、操作結(jié)果
describe("test search page", () => { // 幾個 route 路徑變量 const searchRoutePath = "/api/items/activities?query=*"; const deleteActivityRoutePath = "/api/activities/*/items/batch?num_iids[]=*"; const undoActivityRoutePath = "/api/activities/*/items/undo"; function search(keyword) { // 將搜索行為和等待搜索返回封裝起來 cy .fixture("items/activities.json") // 處理mock數(shù)據(jù),只返回符合搜索結(jié)構(gòu)的數(shù)據(jù) .then(data => data.filter(item => item.title.indexOf(keyword) !== -1)) .as("searchResult"); cy.server(); cy.route(searchRoutePath, "@searchResult").as("searchRoute"); const input = cy.get("input"); input.clear(); // 清空輸入框內(nèi)文本 input.type(`${keyword}{enter}`); cy.wait("@searchRoute"); } before(() => { // 進(jìn)行所有測試前,先訪問搜索頁 cy.visit("/activities/search"); }); it("should show no data tip when search result is empty", () => { const text = "not exist"; search(text); cy.contains(`沒有找到關(guān)于 ${text} 的結(jié)果`); }); it("should remove activity from list when clean successful", () => { search("成功"); cy .route("delete", deleteActivityRoutePath, { success: 0, fail: 0, waiting: 0, }) .as("deleteActivityResponse"); // within是讓cy執(zhí)行的context保持在".activities-search"這個dom節(jié)點內(nèi) // 默認(rèn)cy的執(zhí)行是以上一個cy命令結(jié)果作為context // 如 "cy.get("a"); cy.get("span")",cy會在上一個命令找到的"a"標(biāo)簽中查找"span" cy.get(".activities-search").within(() => { const items = cy.get(".result-item"); items.should("have.length", 1); const applyList = items.get(".apply-list"); applyList.should("not.be.visible"); // 每個數(shù)據(jù)項內(nèi)詳細(xì)內(nèi)容區(qū)域是隱藏的 const toggleBtn = items.get(".item-apply-count"); toggleBtn.click(); // 點擊顯示詳細(xì)內(nèi)容區(qū) applyList.should("be.visible"); applyList.children().should("have.length", 1); // 詳細(xì)內(nèi)容區(qū)內(nèi)數(shù)據(jù)只有1條 const cleanBtn = cy.contains("退出"); cleanBtn.click(); // 點擊詳細(xì)內(nèi)容區(qū)里的“退出”按鈕 cy.wait("@deleteActivityResponse"); // 等待“退出”請求返回 cy.get(".apply-list").should("be", null); // 退出成功后,詳細(xì)內(nèi)容區(qū)數(shù)據(jù)減1,即空 }); }); });幾個必讀文檔
network-requests : https://docs.cypress.io/guide...
assertions : https://docs.cypress.io/guide...
recipes 示例 : https://docs.cypress.io/examp...
code completion 代碼提示: https://docs.cypress.io/guide...
關(guān)于測試覆蓋率目前cypress沒有內(nèi)置測試覆蓋率統(tǒng)計功能,github上有專門的issue在跟蹤這個,后續(xù)應(yīng)該會有。issue上也有幾個臨時方案,目前我傾向使用chrome自帶的來查看。在GUI打開的測試的瀏覽器中打開devtools,切到Sources, 按下cmd+shift+p(windows用戶按ctrl+shift+p),輸入coverage,選擇重新刷新并統(tǒng)計代碼執(zhí)行覆蓋率。
那么,high起來為了高(撩)質(zhì)(測)量(試)代(M)碼(M),high起來。喜歡前端MM的可以手把手教起來了 (¬_¬)
本文章首發(fā)于本人公眾號:楓之葉。有興趣的可以長按下方二維碼關(guān)注。^v^
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/94439.html
摘要:前言官方文檔目前只支持英文,好處是官方入門視頻很多,對于英文水平不好的也很容易入手優(yōu)缺點優(yōu)點只要你學(xué)好語法上應(yīng)該不是很大問題獲取類似,對前端同學(xué)來說是好處缺點內(nèi)置的工具集成了谷歌內(nèi)核,決定你只能是在谷歌瀏覽器上測試,但隨著新版的內(nèi)核采用內(nèi)核 前言 官方文檔:https://docs.cypress.io 目前只支持英文,好處是官方入門視頻很多,對于英文水平不好的也很容易入手; 優(yōu)缺點 ...
摘要:我之前寫過關(guān)于的文章,,最近在工作中用到比較多了,頓時覺得確實是比較優(yōu)秀的一個。 我之前寫過關(guān)于cypress的文章,https://segmentfault.com/a/11...,最近在工作中用到cypress比較多了,頓時覺得cypress確實是比較優(yōu)秀的一個。 1. 軟件安裝. 2. 安裝cypress 安裝cypress客戶端:http://download.cypress...
摘要:是一款開箱即用可以跑在瀏覽器上的測試工具。同樣,測試了也可以直接調(diào)試。這個時候我們的測試文件就可以訪問了,點擊之后發(fā)現(xiàn)他需要我們編寫測試用例,那么接下來就手把手教你編寫基本的測試用例。 What is E2E? 所謂的E2E就是end-to-end。 假設(shè)我們編寫的每個功能程序都是一個黑匣子,最終用戶也只會看到這個黑匣子,那么站在用戶的角度來看并不需要知道這個黑匣子內(nèi)部是什么東西也不...
摘要:閱讀原文目前測試工具有哪些項目不需要不需要端到端測試一般都需要一個容器,來運行前端應(yīng)用。向快速,一致和可靠的無剝落測試問好。 閱讀原文 1. 目前E2E測試工具有哪些? 項目 Web Star puppeteer Chromium (~170Mb Mac, ~282Mb Linux, ~280Mb Win) 31906 nightmare Electron 15502 ...
閱讀 3644·2021-11-23 10:10
閱讀 3407·2019-08-30 14:03
閱讀 2144·2019-08-30 13:09
閱讀 3469·2019-08-29 15:29
閱讀 1611·2019-08-29 11:23
閱讀 2074·2019-08-28 18:28
閱讀 2920·2019-08-26 13:34
閱讀 2223·2019-08-26 11:32