項目
將單元測試框架mocha,斷言chai和puppeteer結合起來做端到端測試:
- 將打開百度首頁
- 搜索Puppeteer,確定有搜索內容
- 清空輸入,返回百度首頁
puppeteer實現自動化
-
安裝puppeteer
npm install puppeteer@2.1.1
-
根據用戶操作,找標籤選擇器
F12->點擊箭頭->更具頁面找標籤
-
找到標籤後,先驗證下,頁面是否存在這個標籤
document.querySelector()
document.querySelectorAll()
- 輸入node 1.js 執行
設定了headless: true,所以不會打開瀏覽器,直接運行出結果
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true,
devtools: false,
timeout: 20000,
});
const page = await browser.newPage();
await page.goto('http://www.baidu.com/');
const title = await page.title()
console.log(title);
await page.type('input[id="kw"]', 'puppeteer');
await page.click('input[id="su"]');
await page.waitFor(2000);
await page.waitForSelector('div[class="result c-container "]');
const links = await page.evaluate(() => {
return Array.from(document.querySelectorAll('div[class="result c-container "]'));
});
console.log(links.length);
await page.waitFor(2000);
await page.$eval('input[id="kw"]', input => input.value = '');
await page.click('input[id="su"]');
await page.waitFor(2000);
})();
知識點補充
-
等待某個 DOM 節點
在對頁面進行操作前,必須等DOM 加載完成才能操作,比如,你要點擊圖片,但是圖片沒加載出來。下面這個是等待搜索結果節點節點出現:await page.waitForSelector('div[class="result c-container ');
-
如果加載時間不夠,需要用時間間隔
await page.waitFor(500);
-
獲取節點集合
下面是獲取搜索結果列表,兩種寫法都可以const links = await page.evaluate(() => { return Array.from(document.querySelectorAll('div[class="result c-container "]')); });; const links = await page.$$eval('div[class="result c-container ', els => Array.from(els).map(el=> el));
-
使用了eval,清空input框
await page.$eval('input[id="kw"]', input => input.value = '');
Mocha+Chai實現測試
將上面的代碼,加入 Mocha+Chai,進行測試
- 安裝Mocha+Chai,看這
- 代碼,注意運行的時候,使用的是mocha 2.js -t 30000
const puppeteer = require('puppeteer'); const { expect } = require('chai'); describe('Baidu search', () => { let browser; let page before(async () => { browser = await puppeteer.launch(); page = await browser.newPage(); await page.goto('http://www.baidu.com/'); }); after(async () => { await browser.close(); }); it('page title', async () => { expect(await page.title()).to.eql('百度一下,你就知道'); }); it('get the list number of results', async () => { await page.type('input[id="kw"]', 'puppeteer'); await page.click('input[id="su"]'); await page.waitFor(2000); await page.waitForSelector('div[class="result c-container "]'); const links = await page.evaluate(() => { return Array.from(document.querySelectorAll('div[class="result c-container "]')); }); expect(links.length).to.be.greaterThan(0); }); it('back to BaiDu page ', async () => { await page.waitFor(2000); await page.$eval('input[id="kw"]', input => input.value = ''); await page.click('input[id="su"]'); await page.waitFor(2000); expect(await page.title()).to.eql('百度一下,你就知道'); }); });
這份代碼實現了,驗證首頁是否打開,搜索是否有信息,搜索清空後,點擊提交,是否返回首頁。
browser和page定義在外面,這樣,其他函數可以使用到。
優化代碼
爲了增加代碼的可維護性,可理解性。我們一些操作封裝起來,使用的時候直接調用它。
執行的時候使用mocha 3.test.js -t 30000
-
3.js
這個裏面寫了獲取標題,搜索,獲取搜索條數,返回首頁幾個方法class BaiDu { constructor(page) { this.page = page; } async getTitle() { return this.page.title(); } async search(word) { await this.page.type('input[id="kw"]', word); await this.page.click('input[id="su"]'); } async getNumber(page) { await this.page.waitForSelector('div[class="result c-container "]'); const links = await this.page.evaluate(() => { return Array.from(document.querySelectorAll('div[class="result c-container "]')); }); return links.length; } async back() { await this.page.$eval('input[id="kw"]', input => input.value = ''); await this.page.click('input[id="su"]'); await this.page.waitFor(2000); } } module.exports = BaiDu;
-
3.test.js
引入BaiDu ,直接調用BaiDu的方法,獲取結果,進行驗證const puppeteer = require('puppeteer'); const { expect } = require('chai'); const BaiDu = require('./3.js'); describe('Baidu search', () => { let browser; let page; before(async () => { browser = await puppeteer.launch(); page = await browser.newPage(); await page.goto('http://www.baidu.com/'); }); after(async () => { await browser.close(); }); it('page title', async () => { const baiDu = new BaiDu(page); expect(await baiDu.getTitle()).to.eql('百度一下,你就知道'); }); it('get the list number of results', async () => { const baiDu = new BaiDu(page); await baiDu.search('puppeteer'); expect(await baiDu.getNumber()).to.be.greaterThan(0); }); it('back to BaiDu page', async () => { const baiDu = new BaiDu(page); await baiDu.back(); expect(await baiDu.getTitle()).to.eql('百度一下,你就知道'); }); });
-
結果