มาทำ API Testing ด้วย Jest + Supertest รันเร็วแรงแบบ Fast & Furious กัน

Traitanit Huangsri
5 min readJul 11, 2021

--

ช่วงนี้กระแสหนังภาคต่ออย่าง Fast & Furious 9 กำลังมาแรง บทความนี้เลยจะขอนำเสนอการทำ Automated API Test ด้วย Jest + Supertest แบบที่รันเทสได้เร็วและแรงไม่แพ้หนังเรื่องนี้กันเลยทีเดียว [เกี่ยวกันมั้ยเนี่ย 😆]

รู้จัก API Testing กันก่อน

API Testing คือการ Exam API ที่ Server หรือ Backend Application ได้ Provide ให้กับ Client เช่น Frontend Web หรือ Mobile App มา Consume ไปใช้งาน โดยปกติหลายคนอาจจะเคยทำ Automated Test ที่ Client Side ที่เป็น Web หรือ Mobile App ไปเลยจะมีข้อเสียหลายอย่างเช่น

  • Flaky Tests ที่เกิดจากการที่ UI Render ไม่ทันตาม Script ที่เราเขียนไว้
  • ต้องมีการทำ Action หลายอย่างที่ UI เช่น type text, click ปุ่ม กว่าจะได้เทส functional ที่เราต้องการจะเทสจริงๆ
  • UI มีการเปลี่ยน UI Design บ่อยๆ ซึ่งถ้าไม่ค่อยได้ตาม update test ก็จะทำให้เทสที่เคยเขียนไว้ใช้งานได้ไม่นาน ต้องมี maintenance cost ที่ค่อนข้างสูง

ข้อดีของการทำ API Testing คือการ “ตัดตอน” การเทสให้ Focus ที่ Messaging Layer หรือ protocol ที่ Client ใช้ในการสื่อสารกับ Server Side ไปเลยนั่นเอง โดยเราจะไม่สนใจเรื่องของ UI อีกต่อไป ซึ่งจะช่วยลดปัญหาที่ซับซ้อนและวุ่นวายในระดับ UI ไปได้มาก และทำให้ Test ของเรามีความ Stable และ Reusable ได้ดียิ่งขึ้น และยังสามารถช่วย verify functionality ต่างๆ ที่มีการเปลี่ยนแปลงไปได้ด้วย

ซึ่งในปัจจุบันก็มี Tools ที่ช่วยให้เราสามารถทำ API Test ได้มากมาย ไม่ว่าจะเป็น Postman, REST Client ต่างๆ ที่สามารถให้เราระบุ API Request ต่างๆ เข้าไปแล้วก็รอเช็คผลของ API Response ได้เลย ซึ่งในวันนี้ผมจะขอนำเสนออีก 1 คู่หูที่คุณสามารถเลือกนำไปใช้ทำ Automated API Testing ได้ซึ่งก็คือ Jest และ Supertest นั่นเอง

รู้จัก Jest คร่าวๆ

Jest คือ Open Source Javascript Testing Framework ที่พัฒนาโดย Facebook ซึ่งสามารถนำไปใช้ทำ Test ได้หลากหลาย Level ทั้ง Unit Test, Integration Test และ End-to-End Test และยังมี feature ที่ช่วยทำให้การรันเทสมีประสิทธิภาพมากขึ้นมากมาย ไม่ว่าจะเป็น snapshot testing, automatic parallel test, mocking, code coverage, etc. เรียกได้ว่า feature เยอะจนจำไม่หมดเลยทีเดียว

ปัจจุบัน Jest มีผู้ดาวน์โหลดไปใช้งานมากกว่า 11 ล้านครั้งต่อสัปดาห์ ได้รับ Stars บน Github Repo มากกว่า 35,000 ดวง​ เรียกได้ว่าเป็น Framework ที่ถ้าใครที่ใช้ Javascript ทุกคนจะต้องรู้จักอย่างแน่นอน

ข้อมูลยอดดาวน์โหลด Jest ต่อสัปดาห์โดยเฉลี่ยในรอบ 2 ปีมากกว่า 11M ครั้ง

รู้จัก “Supertest”

Supertest คือ Node.js library ที่ Provide High-level Fluent API ให้เราสามารถทำ API Testing ได้อย่างง่ายๆ มี syntax ในการเขียนเทสที่ทำให้เราอ่านเข้าใจได้ง่าย และยังสามารถทำงานร่วมกันได้ดีกับ Node.js Server Side Application อย่าง Express หรือ Nest.js ได้เป็นอย่างดีด้วย

ยอดการดาวน์โหลด Supertest ผ่าน npm มากกว่า 2 ล้านครั้งต่อสัปดาห์

“Supertest” ได้รับความนิยมอย่างมาก มีผู้ให้ Github Stars มากกว่า 11,000 ดวง และมีผู้ใช้งาน Library ตัวนี้ทั่วโลกมากกว่า 430,000 คนเลยทีเดียว

Jest + Supertest ทำงานร่วมแล้วจะเป็นไง?

เราสามารถนำโค้ดของ API Test ที่เขียนด้วย “Supertest” มารันอยู่บน Jest Test Runner ได้อย่างง่ายๆ เลย ซึ่งจะทำให้เทสของคุณได้ Benefits หลายๆ อย่างเช่น

  • Automatic Parallel API Test by Jest: รันเทสแบบ parallel by default ซึ่งช่วยประหยัดเวลากันรันเทสได้มาก
  • Integrated with popular Javascript Compiler อย่าง Babel, Webpack ได้ เพื่อที่จะสามารถใช้ syntax ใหม่ๆ ของ ES เวอร์ชันใหม่ๆ ได้
  • Many Test Reports and plugins available มี Test Report ให้เราเลือกใช้ได้อย่างหลาย เช่น Junit, HTML Report

เอาล่ะ เกริ่นมาเยอะ เรามาเริ่มลงมือสร้าง Project ทำ API Testing ด้วย Jest + Supertest กันดีกว่า

1. Create new Project

ผมเลือกใช้ yarn เป็น package manager ในการสร้าง project นะครับ ใครจะใช้ npm ก็ได้ไม่ว่ากัน

sh$ mkdir jest-supertest-example
sh$ yarn init
--------------------------------------------------------------
The following questions will help Jest to create a suitable configuration for your project✔ Would you like to use Jest when running "test" script in "package.json"? … yes✔ Choose the test environment that will be used for testing › node✔ Do you want Jest to add coverage reports? … no✔ Automatically clear mock calls and instances between every test? … no

2. Install Dependencies

2.1 เราจะทำการ Install dependencies ต่างๆ ที่ต้องใช้ทำเทสกันดังนี้ครับ

sh$ yarn add -D jest @types/jest supertest @types/supertest jest-html-reporters

ผมเลือกใช้ jest-html-reporters เป็น ​Test Report ในรูปแบบ ​HTML File ให้กับ API Test ของเรา ซึ่งเด๋วจะแนะนำวิธีใช้งานท้ายบทความนะครับ

ผมจะเลือกใช้ Babel เป็น Javascript Compiler ทำงานร่วมกับ Jest เพื่อที่จะสามารถใช้ syntax ที่เป็น Modern ES Syntax เช่น import ได้นะครับ

sh$ yarn add -D babel-jest @babel/core @babel/preset-env

2.2 ทำการ Config การใช้งาน Babel ที่ไฟล์ babel.config.js

2.3 Init Jest configuration file โดยเราจะได้ไฟล์ jest.config.js ออกมาอยู่ใน root directory ของ project นะครับ

sh$ jest --init

3. เริ่มทำการเขียนเทส

การเขียน ​API Test ด้วย “Supertest” นั้นง่ายมากๆ ครับ โดยในบทความนี้ผมจะลองทำ API Test ไปที่ mock API server ที่ https://reqres.in ดูครับ

3.1 Create new supertest instance และ Reuse ใช้ในทุกๆ เทส

เนื่องจากว่าในทุกๆ Test case ของผมมีการเรียกไปที่ API server เดียวกัน (domain เดียวกัน)​อาจจะต่างกันแค่ Endpoints ดังนั้นผมเลยทำการสร้างไฟล์ที่เอาไว้สำหรับ provide supertest object ที่จะสามารถ reuse ใช้งานได้ในทุกๆ test cases ไว้ดังนี้

โดย Supertest อนุญาตให้เรา listen to event ต่างๆ ได้ (เช่น error, response event) ดังนั้นผมจึงทำการ listen response event ไว้เพื่อที่จะเอาไว้ log http request/response ลงไปใน Test Report อีกที (เผื่อเอาไว้ใช้ debug ในกรณีที่ที่เกิด test failed) นอกจากนี้ผมยังใช้ Library เสริมอย่าง request-to-curl เพื่อใช้ทำการแปลง http request เป็น curl command เผื่อว่าจะเอาไปใช้ call ผ่าน curl ทีหลังได้อีกที

3.2 เริ่มเขียน Test

ในการเขียนเทสนั้นเราจะเขียนตาม Jest API Block Scope ตามนี้ครับ (สำหรับใครที่เคยเขียนเทสบน Jest มาก่อนก็ข้ามส่วนนี้ไปได้เลย)

  • describe: ใช้ระบุ test group หรือจะเรียกว่า test suite ก็ได้ครับ โดยเราอาจจะแบ่งตาม API Endpoints ก็ได้
  • it หรือ test: ใช้ระบุ scope ของ test ของเรานั่นเอง
  • beforeAll: ใช้ระบุ test suite setup ต่างๆ ที่จะทำก่อน 1 ครั้งเริ่ม test ทุกข้อ
  • beforeEach: ใช้ระบุ test case setup ที่จะทำก่อนเริ่มเทสทุกข้อ
  • afterEach: ใช้ระบุ test case teardown ที่จะทำหลังเทสทุกข้อ
  • afterAll: ใช้ระบุ test suite teardown ที่จะทำหลังจากรันเทสครบทุกข้อแล้ว 1 ครั้ง

ยังมี API อื่นๆ ที่สามารถใช้งานได้ สามารถอ่านรายละเอียดเต็มๆ ได้ที่ https://jestjs.io/docs/api เลย

จะเห็นได้ว่าการเขียน API Test ด้วย “Supertest” นั้นจะเป็นลักษณะ Chaining Calls ไปเรื่อยๆ เช่น request.get(‘/users’).expect(200) แบบนี้ได้เลย ดูใช้งานง่ายมากๆ เลยว่ามั้ยครับ ซึ่ง Supertest รองรับการทำ API Test ทุกรูปแบบ HTTP GET/PUT/POST/DELETE etc. รวมถึงการทำ File Upload ที่เป็น multipart-formdata ก็ทำได้เช่นกัน สามารถดูตัวอย่างการใช้งานเต็มๆ ได้ที่ https://github.com/visionmedia/supertest

3.3 ลองรันเทส

เราสามารถรันเทสที่เราเขียนไปได้ง่ายๆ ด้วย Command npx jest ได้เลย

จะเห็นได้ว่าเทสที่เราเขียนไป 2 ข้อ ใช้เวลารันเพียง 2.4 วินาทีเท่านั้น!

ผมจะลองเพิ่มเทสอีกไฟล์หนึ่งเพื่อจะลองทำให้มันรันเทสแบบ parallel ดูครับ

Test ชุดนี้ผมตั้งใจให้มีเทส 1 ข้อที่เมื่อรันแล้วจะ Failed ตลอด เพื่อจะดูว่าเวลาเกิด Error หรือ Failed Tests ขึ้นนั้น เราสามารถ Trace back กลับไปดู Request/Response ใน Test Report ได้เลยไหม?

เมื่อรันเทสอีกครั้งก็จะเห็นว่ามี Test ข้อหนึ่งที่ Failed เพราะ Expect HTTP 200 แต่ Server Return HTTP 400 กลับมาแทน โดยที่การรันเทสครั้งนี้ตัว suite user.spec.js กับ register.spec.js จะรันเทสพร้อมๆ กันแบบ parallel อัตโมตินะครับ ใช้เวลารวมกันทั้งหมดแค่ 1.9 วินาทีเท่านั้น (เร็วกว่าเดิมอีก)

4. Visualize Test Result

เราจะทำการ visualize ผลเทสของเราผ่าน Test Report ที่เรา Config ไว้ในตอนแรก โดยตัว Report จะถูก Generate ทุกครั้งอัตโนมัติเมื่อรันเทสเสร็จ พร้อมทั้งมี HTTP Request / Response ของการทำ API Test ในทุกๆ ครั้งให้ดูด้วย

Test Report ออกมาแล้วสวยงาม

นอกจากผลเทสแต่ละข้อแล้ว ตัว ​Test Report ยังทำการสรุปผลเทสในภาพรวมให้เราด้วยว่ารันเทสไปกี่ข้อ Pass, Fail กี่ข้อ และแต่ละข้อใช้เวลาในการรันเท่าไร และนอกจากนี้เราก็ยังสามารถกดตรงปุ่ม “Info” เพื่อเข้าไปดูรายละเอียดการเทสในแต่ละข้อได้ด้วย ซึ่งจะออกมาหน้าตาแบบนี้

Test Info ที่มี Request /Response ให้ดูได้ด้วย
เมื่อ Test Failed ก็มี log ให้ดูว่า Failed เพราะอะไร?

สรุป

Jest + Supertest ถือเป็นอีกหนึ่ง Combination ที่น่าสนใจและอยากขอแนะนำให้ทุกๆ คนที่จะเริ่มต้นทำ API Testing ลองนำไปปรับใช้งานกันนะครับ หวังว่าทุกคนจะได้ประโยชน์จากการอ่านบทความนี้นะครับ สามารถดูตัวอย่างโค้ดทั้งหมดในบทความนี้ได้จาก Github Repo ของผมด้านล่างนี้เลย Happy Testing!

--

--

Responses (1)