<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                &emsp;&emsp;網頁在提測流轉給 QA 后,如何能幫他們更有效而準確的完成測試,是我一直在思考的一個問題。 &emsp;&emsp;QA 他們會對網頁編寫測試用例,在提測之前會讓我們將優先級最高的用例跑通,這在一定程度上能夠避免頻繁的返工,保證測試的順暢。 &emsp;&emsp;自己之前想過做 UI 的單元測試,一有修改就跑一遍用例,但是維護成本太高,并且每次留給我們的開發時間并不多。 &emsp;&emsp;最近在看多份測試記錄的 BUG 單中發現,45%~70% 之間的 BUG 都是內容性問題,例如網頁中缺了個字、少了段話、圖片呈現不對等問題。 &emsp;&emsp;這些用肉眼看,其實很容易辨別。只要有個工具,能呈現不同操作下的網頁,就可以大大提升 QA 的驗收效率。 &emsp;&emsp;于是就想到了[Puppeteer](https://pptr.dev/)(傀儡師),它是一個 Node.js 庫,提供了一套 API 控制 Chrome 或 Chromium 瀏覽器,可生成頁面快照截圖、模擬用戶行為等。 &emsp;&emsp;Chromium 是 Chrome 的開源版本,兩者在界面、功能等方面會存在些區別。 &emsp;&emsp;雖然 Puppeteer 可以模擬用戶行為,但是它不能模擬用戶在客戶端 WebView 中的行為,例如點擊頭像進入用戶客戶端中的主頁。 &emsp;&emsp;簡單理解,就是 Puppeteer 能呈現 Chrome 瀏覽器中的頁面,但如果要測試客戶端的樣式兼容性和各種交互行為,就無法實現了。 &emsp;&emsp;而內容展示異常的問題,無論是在哪一端,都能表現一致,因此可以用 Puppeteer 來作為自動化測試工具。 ## 一、服務端實現 &emsp;&emsp;當前 Puppeteer 的最新版本是 19.2.2,API 分為 20 多個模塊,可查找頁面 DOM 元素、屏幕截圖、處理 WebSocket、模擬移動端設備、植入腳本、請求攔截等操作。 &emsp;&emsp;我當前的目標是查看頁面內容,所以在頁面中也需要有些交互。 &emsp;&emsp;先基于 KOA,快速搭建一個新項目,因為 Puppeteer 庫比較大,所以為了不影響其他項目的構建和運行,就單獨開了個項目。 &emsp;&emsp;再引入相關的 Node 庫,fs 用于創建目錄,path 用于拼接絕對路徑,[config](https://github.com/node-config/node-config)用于讀取配置文件。 ~~~ const puppeteer = require('puppeteer'); const fs = require('fs'); const path = require('path'); const config = require('config'); const domain = config.get('domain'); ~~~ &emsp;&emsp;接著是聲明一條路由,例如用 get 方法訪問 test/game,傳遞類型和環境。 ~~~ router.get("/test/game", async (ctx) => { const { type, env = "www" } = ctx.query; let data = []; switch (type) { case "1": data = await hot(env); break; } ctx.body = { code: 0, data }; }); ~~~ &emsp;&emsp;hot() 函數就是自動化測試的主體,核心邏輯其實就是點擊某一欄,呈現頁面后,再截一張圖。 ~~~ async function hot(env) { const savePath = path.resolve(__dirname, "../static/hot"); // 將相對路徑轉換成絕對路徑 const iPhone = puppeteer.KnownDevices["iPhone 6"]; // 模擬iPhone 6 // 當指定目錄不存在時,就將其創建,Sync 后綴表示同步,recursive 參數表示遞歸創建 !fs.existsSync(savePath) && fs.mkdirSync(savePath, { recursive: true }); // 要返回的圖片路徑 const paths = []; /** * 本地環境可以不需要配置 args * 但是在 Linux 服務器中在啟動 puppeteer 時,默認要帶上 --no-sandbox 參數 */ return puppeteer.launch({ args: ["--no-sandbox", "--disable-setuid-sandbox"] }).then(async (browser) => { const page = await browser.newPage(); // 創建新的瀏覽器上下文 await page.emulate(iPhone); // 模擬設備 // 默認主頁 await page.goto(`https://${env}.xxx.com/game/hot.html`, { waitUntil: "networkidle0" // 等待到沒有網絡請求 }); // 截圖 await screenshot(page, `${savePath}/1.png`); paths.push(`${domain}/static/hot/1.png`); // 查找符合樣式的菜單欄 const tabs = await page.$$(".green_calss"); // 點擊第二個菜單欄 tabs[1].tap(); await page.waitForNetworkIdle(); await screenshot(page, `${savePath}/2.png`); paths.push(`${domain}/static/hot/2.png`); // 點擊第三個菜單欄 tabs[2].tap(); await page.waitForNetworkIdle(); await screenshot(page, `${savePath}/3.png`); paths.push(`${domain}/static/hot/3.png`); await page.close(); await browser.close(); return paths; }); } ~~~ &emsp;&emsp;path.resolve()、fs.existsSync() 和 fs.mkdirSync() 都是 Node.js 提供的[方法](http://www.hmoore.net/pwstrick/fe-questions/3006880)。 &emsp;&emsp;page.[goto()](https://pptr.dev/api/puppeteer.page.goto)可跳轉到指定 URL 的網頁,networkidle0 可等待到頁面無網絡請求。 &emsp;&emsp;在自動化測試時,需要有個頁面完成的時間點,如果用延時的方式,會不太準確,所以就想到了網絡請求。 &emsp;&emsp;我們這邊的網頁以移動端居多,所以需要選擇要模擬的設備,例如 iPhone 6。 &emsp;&emsp;page.$$() 是[ElementHandle](https://pptr.dev/api/puppeteer.elementhandle)提供的一個方法,相當于 Document.querySelectorAll() 方法。 &emsp;&emsp;tabs\[1\].[tap()](https://pptr.dev/api/puppeteer.elementhandle.tap)就是模擬用戶觸摸屏幕,另外支持的事件還包括 click()、drag()、focus() 等。 &emsp;&emsp;screenshot() 是一個截屏函數,內部調用 page.[screenshot()](https://pptr.dev/api/puppeteer.page.screenshot)方法,可截取完整頁面,包括滾動區域。 ~~~ async function screenshot(page, savePath) { await page.screenshot({ path: savePath, type: "png", fullPage: true //邊滾動邊截圖 }); } ~~~ ## 二、界面實現 &emsp;&emsp;前端界面目前比較簡潔,就一個活動下拉框和一個環境下拉框,以及一個提交按鈕。 &emsp;&emsp;提交后,就會從后臺拿到頁面快照,這些快照都會按照寫好的腳本生成。 :-: ![](https://img.kancloud.cn/65/ce/65cee42b422b421e8409fb701ac2abf1_1600x1624.png =800x) **1)遇到的問題** &emsp;&emsp;在實際使用中注意到,如果頁面內包含一塊定高區域,那么隱藏區域就需要滾動后才能呈現。 &emsp;&emsp;當網頁中有一個資源阻塞加載時,若是 waitUntil 參數的值是 networkidle0,那頁面就會報超時的錯誤。 ~~~ await page.goto(url, { waitUntil: ["networkidle0"] }); ~~~ &emsp;&emsp;但如果 goto() 方法不加等待時機,那就會一直等下去,沒有結果。 ~~~ await page.goto(url); ~~~ &emsp;&emsp;可以改成[networkidle2](https://pptr.dev/api/puppeteer.puppeteerlifecycleevent/),networkidle0 是指在 500ms 內沒有任何網絡連接,而 networkidle2 是指網絡連接個數不超過 2 個。 &emsp;&emsp;在部署到服務器后,由于字體的問題,頁面內的中文會出現亂碼,解決辦法就是給服務器安裝中文字體。 :-: ![](https://img.kancloud.cn/fd/9a/fd9a60b5b2600c4ea8010c3398c80775_702x752.png =400x) 參考資料: [Automating Google Chrome with Node.js](https://tutorialzine.com/2017/08/automating-google-chrome-with-node-js) [京喜前端自動化測試之路](https://jelly.jd.com/article/5e9d5ca110f7500156d48b42) [深入了解自動化:那些項目適合自動化測試](https://zhuanlan.zhihu.com/p/51407643) [Puppeteer中文](https://puppeteer.bootcss.com/api) [Puppeteer 入門教程](https://www.r9it.com/20171106/puppeteer.html) ***** > 原文出處: [博客園-Node.js躬行記](https://www.cnblogs.com/strick/category/1688575.html) [知乎專欄-Node.js躬行記](https://zhuanlan.zhihu.com/pwnode) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看