Làm trò với Puppeteer – Phần 3: Bắt đầu testing với puppeteer

Bài viết gồm 3 phần

Trong phần này, mình sẽ hướng dẫn các bạn viết automation test trong NodeJS với Puppeteer và Jest. Chúng ta cùng thử viết test tìm kiếm hàng hoá trên lazada nhé.

Kiến thức của phần này tuy cô đọng, ngắn gọn nhưng cần khá nhiều kiến thức nền nên các bạn đọc lại những bài này để nhớ lại kiến thức lại nhé!

  1. Tổng quan về testing, unit test và automation test
  2. Viết Unit Test với C# (Giải thích vai trò của unit test trong việc làm code tốt hơn)
  3. Viết Unit Test với Jasmine (Giải thích các khái niệm hay gặp khi viết unit test)

Selenium và Puppeteer

Với các dự án viết bằng C#, Java, người ta thường chọn JUnit, NUnit để làm testing framework (viết test case, chạy test case, báo cáo tỉ lệ pass/fail).

Đi kèm với chúng thường là Selenium – một thư viện khá mạnh cho phép ta điều khiển  trình duyệt Chrome, Firefox, IE.

So với Selenium thì Puppeteer vẫn còn khá thua kém vì thiếu một số tính năng (Chưa chạy được đồng thời trên nhiều máy, chưa select được xPath) và chỉ có thể chạy được trên trình duyệt Chrome.

Pupeteer vẫn còn thua Selenium về một số khía cạnh

Tuy vậy, nó có chút ưu điểm là do chính team của Google phát triển, dễ cài đặt, cài xong là chạy ngay, còn có thể chạy headless không cần giao diện nên tốc độ chạy sẽ nhanh hơn.

Do vậy, bạn có thể làm theo bài viết để tìm hiểu về cách viết code cho Automation Testing trước. Nếu xác định thực sự muốn theo ngành này thì nên nhớ đầu tư thời gian để học Selenium nhé.

Cài đặt project automation test

Do Puppeteer chạy trên nền NodeJS nên chúng ta sẽ dùng Jest testing framework.

Đây là một testing framework gọn nhẹ, mạnh mẽ, tiện dụng do Facebook chống lưng. Các bạn tìm hiểu thêm về Jest tại đây nhé!

Một trong số các ưu điểm của Jest là dễ cài đặt, cài phát là chạy ngay được luôn, chúng ta cùng làm theo 4 bước sau để khởi tạo project.

  1. Tạo thư mục mới đặt tên là puppet-test
  2. Mở cmd rồi cd vào thư mục này. Lần lượt gõ các lệnh


npm init
npm install –save jest
npm install –save puppeteer

view raw

node.sh

hosted with ❤ by GitHub

3. Mở file packages.json, sửa nội dung script test thành jest như hình dưới:


{
"name": "puppet-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest –verbose true"
},
"author": "",
"license": "ISC",
"dependencies": {
"jest": "^22.0.4",
"puppeteer": "git+https://github.com/GoogleChrome/puppeteer.git"
}
}

view raw

packages.json

hosted with ❤ by GitHub

Vậy là bạn đã cài đặt xong rồi đấy!

Mặc định, Jest sẽ chạy unit test trong những file có đuôi .spec.js hoặc .test.js. Do vậy, chúng ta tạo một file tên number.test.js và code đoạn code sau.


test('One plus one equal 2', async() => {
expect(1 + 1).toBe(2);
});

view raw

number.test.js

hosted with ❤ by GitHub

Sau đó, trong cửa sổ cmd, ta gõ npm run test để chạy unit test. Bạn sẽ thấy kết quả như sau.

Ok, vậy là mọi thứ đã sẵn sàng rồi đấy. Bắt đầu viết automation test thôi nào.

Một số API cần dùng khi viết automation test

Mà khoan đã, trước khi cắm đầu vào code thì phải biết chúng ta nên code cái gì, code ra sao đã chứ!

Như mình đã nói ở bài trước, automation test tức là ta tự động hoá những việc mình làm lúc manual test. Vậy lúc test kiểu thủ công, bạn làm những gì?

Phần lớn những việc bạn làm sẽ là:

  • Đăng nhập
  • Nhập thông tin vào form này form kia
  • Click chuột chỗ này chỗ nọ
  • Sau đó kiểm tra kết quả

Do vậy, đây là những API của pupetter mà chúng ta sẽ dùng để làm những việc trên:

Hai hàm này tìm element trong page dựa vào css selector hoặc xpath

  • page.$(selector): Dùng CSS select để select một element trên trang.
  • page.$x(expression): Dùng xpath để select element trên trang. Cái này các bạn tester thích lắm, vì nhiều khi mấy đứa code không có class hay ID gì cả, dùng xpath mới tiện.
  • Hàm này trả về 1 array chứa các element nên nếu chỉ có 1 element, các bạn check phần tử đầu tiên trong array nhé.

Sau khi tìm được element (link, textbox, button), ta dùng các hàm sau để điền thông tin, click v…v:

  • elementHandle.type(text): Điền thông tin vào textbox
  • elementHandle.click(): Click vào link hay button

Chừng đó là đủ cho chúng ta bắt đầu viết rồi.

Các bạn có thể xem danh sách toàn bộ API tại đây nhé: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md

Bắt đầu viết code thôi nào

Chúng ta sẽ dùng pupeeteer để test ngay lazada.vn cho nó nóng.

Đầu tiên, ta tạo một file mới tên là lazada.test.js.

Chúng ta bắt đầu set up đoạn code mở trình duyệt khi chạy unit test, đóng trình duyệt sau khi chạy xong. Các bạn nên để headless: false để dễ theo dõi trình duyệt nhé.


let puppeteer = require('puppeteer');
let browser = null;
let page = null;
describe('Lazada test', () => {
// Code này được chạy khi bắt đầu chạy unit test
beforeAll(async() => {
browser = await puppeteer.launch();
page = await browser.newPage();
await page.setViewport({
width: 1280,
height: 720
});
// Mặc định, timeout của jest là 5s.
// Vì web load có thể lâu nên ta tăng lên thành 60s.
jest.setTimeout(60000);
});
// Đóng trình duyệt sau khi đã chạy xong các test case
afterAll(async() => {
await browser.close();
});
// Trước khi chạy mỗi test case, vào trang chủ của lazada
beforeEach(async() => {
await page.goto('https://lazada.vn');
});
})

view raw

lazada.test.js

hosted with ❤ by GitHub

1. Test chức năng tìm đồ lót của Lazada.vn

Để test chức năng search, ta thực hiện các bước như sau:

  1. Tìm khung search
  2. Gõ sexy underwear, ấn enter
  3. Sau khi kiểm tra, ta thấy sản phẩm là div có attribute là
    data-qa-locator=product-item
  4.   Đếm số lượng sản phẩm, nếu đủ 40 là ok.
Để ý cái attribute bên phải nhé, đừng nhìn bên trái

Viết code thôi nào


test('Search sexy underwear', async() => {
expect.assertions(1);
// Tìm khung search, gõ sexy underwear và bấm enter
const searchBox = await page.$('#q');
await searchBox.type('sexy underwear');
await searchBox.press('Enter');
// Chờ trang load xong, tìm các phần tử item và đếm nếu đủ 40
await page.waitForNavigation();
const products = await page.$$('div[data-qa-locator=product-item]');
expect(products.length).toBe(40);
});

2. Test nội dung hiển thị trên web tải app

Tương tự, ta cũng làm 2 bước:

  1. Click vào link “Tải App Lazada” góc trên bên trái.
  2. Kiểm tra nội dung hiển thị trong menu

Phần này mình dùng ví dụ xpath cho các bạn làm theo nha. Để lấy xpath của 1 element, ta mở Developer Tools lên, inspect element đó và Copy Xpath.

Nhớ bấm Copy XPath nha

Tiện ghê chưa, khỏi cần viết CSS selector gì luôn! XPath lấy element riêng lẻ rất hiệu quả nhưng muốn lấy 1 list thì khó hơn nhé.

Code cũng ngắn gọn thôi hihi


test('Install app', async() => {
expect.assertions(1);
// Tìm và click vào link
const appDownloadLink = await page.$x('//*[@id="topActionDownload"]');
await appDownloadLink[0].click();
await page.waitForNavigation();
// Tìm element trên menu, lấy innerText của element đó
const breadCrumbHandle = await page.$x('/html/body/header/footer/div[2]/div[1]/ul/li[2]/span');
const text = await page.evaluate(element => element.innerText, breadCrumbHandle[0]);
// Check nội dung element đó có chữ App Mobile tại Lazada
expect(text).toContain('App Mobile tại Lazada');
});

view raw

lazada-app.js

hosted with ❤ by GitHub

Để kiểm tra kết quả, ta chỉ việc gõ npm run test thôi nhé.

Sau khi code đã chạy đúng, các bạn có thể bỏ headless:false đi để chạy test mà không cần mở browser nhé.

 

Bonus: Các bạn vào đây xem toàn bộ source code của bài viết nhe

https://github.com/conanak99/pupeteer-jest-test

Lợi ích của Automation Test

Như các bạn thấy đấy, việc viết script và manual test 2 chức năng trên chỉ mất khoảng 5 phút, nhưng viết automation test để chạy có thể mất 15-30 phút hoặc hơn.

Tuy vậy, khi code của lazada có gì thay đổi, ta chỉ việc mất 10-20 giây để test lại mà thôi.

Với những app phức tạp, việc test phải mất 2-3 ngày, mỗi lần sửa code hoặc thêm chức năng mới, không thể chạy test được mà phải chờ 1-2 tuần mới test 1 lần. Việc này dẫn đến chuyện ta rất dễ dàng bỏ sót bug hoặc tạo thêm bug mới.

Nếu đầu tư viết automation test ngay từ đầu, mỗi lần sửa code hoặc thêm chức năng mới, ta chỉ cần chạy lại automation test, chỉ mất 10-30s mà lại không tốn sức, dễ dàng tìm ra lỗi, đảm bảo hệ thống chạy tốt nữa.

Sửa một con bug, lòi ra 2,3,4 con khác

Đấy, đó chính là lý do mà automation test mang lại rất nhiều value cho cả team và dự án; cũng là lý do mà automation QA engineer rất được săn đón.

Kết

Qua series này, các bạn đã học được cách sử dụng pupeteer, cũng như hiểu được tổng quát về ngành testing và automation test.

Các kiến thức về unit test, automation test trong series tuy không quá nhiều, nhưng cũng đủ để làm nền tảng cho bạn tự học và tự tìm hiểu.

Nếu có hứng thú với chủ đề này, bạn cứ để lại comment nha. Có nhiều người quan tâm thì mình sẽ tìm hiểu và viết thêm.

Lời khuyên cuối cùng của mình là: Nếu thực sự muốn theo đuổi nghiệp automation test thì các bạn nên tìm hiểu thêm về Selenium và một số testing framework khác như Appium, QTP nhé!

Lương của Automation QC Engineer cũng không thua gì senior developer đâu nhe

8 thoughts on “Làm trò với Puppeteer – Phần 3: Bắt đầu testing với puppeteer”

  1. Hiện tại page.xpath hình như ko còn dùng nữa, thay = page.$x
    Tiếp theo ở action await appDownloadLink.click(); sẽ báo lỗi “TypeError: appDownloadLink.click is not a function”. Em đã thử thay = page.click(appDownloadLink) nhưng vẫn lỗi.
    A có thể check giùm e ko ạ?

    Like

  2. Cho mình hỏi, mình dùng puppeteer để cào dữ liệu. Tuy nhiên khi run thì chạy đc 1 lúc, khi web hiện notification lên, xong nó dừng luôn. Mình thử chạy lại, xong nhanh tay vào trong setting của chrome để tắt notification (chrome mỗi lần chạy là nó reset setting lại hết) mà cũng không đc, nó tự đứng lại luôn 😦

    Like

  3. A cho e hỏi e dùng selenium để điều khiển chrome vào một nick instagram . Nó sẽ phải lần lượt vào trang chủ đăng bài , tìm kiếm , thả tim theo id nhất định , nhấn theo dõi … Giờ e muốn gửi ngầm một yêu cầu thả tim không cần phải điều khiển chrome vào id đó để để làm công việc như bình thường , bằng chính nick đó , trên đúng trình duyệt đó thì có được không a. A có thể gợi ý cho e được không. .

    Like

Leave a comment