把 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