把 puppeteer 融入調試流程,調試體驗爽翻了!
最近一直在做業務需求,表單類的,每次調試都要填一堆東西,而且項目需要登錄,經常需要來一遍登錄流程,再填寫表單來調試。這個流程還是比較繁瑣的。
於是我在想,自動化測試工具 puppeteer 是可以通過腳本來自動執行瀏覽器操作的,能不能調試的時候讓 puppeteer 幫我自動做了頁面操作的一些流程呢?
我試了一下還真可以,用 puppeteer 來自動執行腳本,並且過程中還可以打斷點調試,調試體驗簡直不要太爽。
這篇文章就來分享下。
首先,react 項目我是通過 vscode debugger 來調試的:
在 .vscode > launch.json 的調試配置文件裏新增一個 chrome 類型的調試配置,輸入調試的 url。
然後點擊 debug 啓動:
執行到代碼中的斷點就會在 vscode 裏斷住:
這樣就可以在 vscode 裏斷點調試 react 項目了。
但登錄還是比較麻煩的,用戶名密碼我經常忘,而且登錄之後還要填一些表單,也很麻煩。
這時候我想到了 puppeteer。
它是可以自動執行腳本的。
比如這樣一段腳本:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto('http://localhost:8000/login');
await page.waitForSelector('#username');
const $username = await page.$('#username');
await $username.type('1111111', {
delay: 100
});
const $password = await page.$('#password');
await $password.type('testtest', {
delay: 100
});
const $button = await page.$('button[type="submit"]');
await $button.click();
})();
用 puppeteer 啓動一個瀏覽器,headless 設爲 false 就是需要界面。
打開新頁面,加載 login 的 url,等出現 #username 的元素之後之後,輸入用戶名和密碼,然後點擊提交。
這個腳本還是很容易理解的。
跑下試試:
流程倒是對了,只是顯示的不對,加個 viewport 的設置就好了:
width、height 爲 0 會自適應。
自動跑登錄腳本成功了。
那問題來了,斷點調試和自動化測試能不能一起跑呢?
看起來這倆都是跑了一個瀏覽器,應該能融合纔對。
這個就要從 puppeteer 和調試的實現原理來看了。
調試是基於調試協議的,比如網頁調試是 Chrome DevTools Protocol。
Chrome DevTools 對接了 CDP 可以調試網頁,我們用 VSCode Debugger 能調試網頁同樣也是對接了 CDP。
puppeteer 能控制瀏覽器執行一些腳本,也是基於 CDP。
這倆都需要瀏覽器在調試模式啓動,也就是指定 remote-debugging-port。
我們前面跑 react 項目的調試是用的 launch 的方式,它會自動跑一個調試瀏覽器,然後連接上 ws 調試服務。
其實它還有 attach 的方式:
attach 的方式不單獨跑調試瀏覽器,而是連接上已有的瀏覽器來調試。所以需要指定調試服務的端口。
既然 puppeteer 和調試都要以調試模式跑瀏覽器,那我們就等 puppeteer 跑起 chrome 之後,vscode debugger 再 attach 上它來調試。
這樣不就既能自動化測試,又能斷點調試了麼?
我們來試一下:
puppeteer 啓動 chrome 的時候,我指定了調試端口爲 9999。
然後跑下 puppeteer 腳本,把 chrome 跑起來:
之後,去 react 項目裏啓動調試,只不過這次是 attach:
依然是能正常斷點調試的:
而且現在還可以跑自動化腳本了!
我們改造下 puppeteer 腳本,改成每次輸入內容的時候才跑對應的腳本。
const puppeteer = require('puppeteer');
const readline = require('readline');
(async () => {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: {
width: 0,
height: 0
},
debuggingPort: 9999
});
const page = await browser.newPage();
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', async (str) => {
if (str === 'login') {
await login(page);
} else if (str === 'baidu') {
await baidu(page);
}
});
})();
async function baidu(page) {
await page.goto('http://www.baidu.com');
}
async function login(page) {
await page.goto('http://localhost:8000/login');
await page.waitForSelector('#username');
const $username = await page.$('#username');
await $username.type('1111111', {
delay: 100
});
const $password = await page.$('#password');
await $password.type('testtest', {
delay: 100
});
const $button = await page.$('button[type="submit"]');
await $button.click();
}
主要是加了 readline 模塊,這是 node 內置模塊,用於一行行讀取流的輸入用的。
我指定了輸入 baidu 的時候打開 baidu,輸入 login 的時候打開 localhost:8000,然後執行登錄腳本。
試一下:
然後我們把 vscode debugger 也 attach 上。
之後再跑 puppeteer 的腳本。
猜下這時候會發生什麼?
執行了自動化測試腳本,並且還在斷點處斷住了!
這樣我們就不用再手動點點點,可以用腳本自動跑一些流程,而且還可以斷點調試這個流程。
我們再改一下腳本:
click 之後,又輸入了密碼,然後再 click:
斷住的時候瀏覽器不會執行代碼,這時候自動化腳本也就執行不了,可以專心根據調用棧作用域等調試代碼,調試完之後,釋放斷點,自動化腳本纔會繼續執行。
這樣我們就完美的把 puppeteer 的自動化測試和 VSCode Debugger 的網頁斷點調試結合在了一起。
總結
我們會用 VSCode Debugger 斷點調試網頁,會用 puppeteer 寫自動化測試的腳本來測試某條流程。
這倆其實完全可以結合在一起用,因爲他們都是基於 CDP,會啓動一個調試模式的瀏覽器。只要 VSCode Debugger attach 到 puppeteer 啓動的瀏覽器就好了。
融合在一起之後,你可以寫 puppeteer 腳本來自動化一些流程,比如自動登錄、自動填寫表單等,這個過程還可以斷點調試,斷點釋放之後再執行後續自動化腳本。
兩者簡直是完美的配合。
把 puppeteer 融入調試流程,調試體驗爽翻了!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/lAKomnFaMoff1lV_9VqcCg