มาเขียน Unittest React Apps ด้วย Jest และ Enzyme แบบเริ่มต้นกัน

Kamonwat
3 min readApr 30, 2018

--

ก่อนหน้านี้ก็เขียนโค้ดไปเรื่อย ไม่สนเทสต์ พอแก้ไขโค้ดทีนึงก็บัค พอแก้ตรงนั้นเสร็จ ตรงนี้บัคอีก สุดท้ายกว่าจะแก้ได้ก็เหมือนแก้โค้ดตั้งแต่เริ่มต้น 😂 พอโค้ดยิ่งเยอะแก้ทีนี่ปวดหัวเลย ต้องแก้ตั้งแต่แรกวนลูปแบบนี้ ก็เลยหาวิธีหยุดลูปนี้ โดยการเขียนเทสต์ ซึ่งพอเริ่มรู้จักเริ่มเขียน Unittest ก็รู้สึกดีขึ้น พอแก้ปุ้ปรัน Unittest ผ่านก็โอเค ถ้าไม่ผ่านก็รู้จุดว่าต้องไปแก้ตรงไหนชีวิตดีขึ้นมากเลย ไม่หัวร้อน มีเวลาลั้ลลากับชีวิตมากขึ้น 😎 เลยจะมาเขียนวิธีเขียน Unittest ส่วนของ Frontend (React) แบบเริ่มต้น เพื่อให้เห็นภาพ และเป็นบันทึกไว้ทบทวนในภาษาของตัวเอง 😁

Unittest คือการทดสอบส่วนที่เล็กที่สุดของโค้ด เพื่อให้มั่นใจว่าการทำงานของโค้ด ยังทำงานได้ปกติ เหมือนเดิม

รู้จักกับ Jest และ Enzyme 🚀

Jest คือ JavaScript Testing Framework จาก Facebook ซึ่ง Facebook ได้เปรยไว้ว่า ‘zero-configuration’ ไม่ต้องตั้งค่าใดๆ ก็เริ่มเทสต์ได้เลยยย (สุดยอดดด !) นอกจากนี้ยังมี Test Coverage มาให้พร้อมไม่ต้องติดตั้งเพิ่มสามารถเรียกใช้งานได้เลย (ว้าววว !) ที่ชอบมากๆ เลยคือเวลารันใน CLI แล้วสวยงาม การแสดงผล คือ ดี ! Jest ยังมีความสามารถอื่นๆ อีก เช่น การทำ Mock เป็นต้น สามารถดูได้ที่ Document

Enzyme คือ JavaScript Testing Utility สำหรับ React ที่จะช่วย Render Components ของ React โดยที่เราไม่ต้องเปิด Browser ขึ้นมา Render ทำให้เขียนเทสต์ได้ง่ายขึ้น โดย Enzyme มีความสามารถหลากหลายมาก และทำงานร่วมกับ JavaScript Testing Framework ดังๆได้แทบทุกตัว (บางตัวอาจดังแต่ไม่รองรับก็เป็นได้ 🤪) โดยสามารถดูความสามารถเพิ่มเติม และวิธีนำไปใช้กับ JavaScript Testing Framework ต่างๆได้ที่ Document

เริ่มต้นติดตั้ง และตั้งค่า

ขั้นตอนการสร้างโปรเจค และตั้งค่า Dependencies ต่างๆ ของ React (React เวอร์ชั่น 16) บทความนี้จะถือว่าเตรียมพร้อมแล้ว พร้อมเขียน Unittest (หรือดูตัวอย่างโค้ดทั้งหมดในบทความนี้ที่นี่)

ติดตั้ง Jest Enzyme และ Dependencies ที่เกี่ยวข้อง

บทความนี้จะใช้ Yarn เป็นหลัก ซึ่งสามารถติดตั้ง Yarn ได้ผ่าน Homebrew (brew install yarn) หรือจากเว็บไซต์ของ Yarn

$ yarn add babel-jest enzyme enzyme-adapter-react-16 jest

สำหรับ Enzyme Adapter Package เลือกให้ตรงกับเวอร์ชั่น React ที่เราเขียนอยู่ โดยสามารถดูเวอร์ชั่น Enzyme Adapter Package ที่เข้ากันได้กับเวอร์ชั่น React ได้ที่นี่

ทำการสร้าง และตั้งค่า Enzyme Adapter Package ให้กับ Jest โดยการสร้างไฟล์ชื่อ enzyme.js ที่ configs/ และเขียนโค้ดการตั้งค่า

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

จากนั้นสร้างไฟล์ jest.config.js ที่ Root Project directory และเขียนโค้ดตั้งค่า Jest ให้ไปอ่านไฟล์ข้างต้น

module.exports = {
setupTestFrameworkScriptFile: "./configs/enzyme"
};

หรือเพิ่มโค้ดส่วนของการ Jest ให้ไปอ่านไฟล์ข้างต้นที่ไฟล์ package.json

"jest": {
"setupTestFrameworkScriptFile": "./configs/enzyme"
}

เลือกวิธีใดวิธีหนึ่งว่าจะสร้างไฟล์ jest.config.js ที่ Root Project directory หรือเพิ่มโค้ดที่ไฟล์ package.json

เริ่มเขียนเทสต์กัน 👨🏼‍💻

ทำการสร้างไฟล์ App.js ที่ src/components/ จากนั้นเขียนโค้ดสำหรับสร้าง Components

import React from 'react';function App() {
return (
<div className="app">
<h1>Hello React App</h1>
</div>
);
}
export default App;

บทความนี้จะนำมาแค่ส่วนของการสร้าง Components ส่วนของการให้สามารถ Render ที่หน้าเว็บได้นั้น สามารถดูได้ที่นี่ เพื่อไม่ให้บทความยาวจนเกินไป

สำหรับการเทสต์ เราจะเทสต์ว่าเราสามารถ Render Component ที่มีคำว่า ‘Hello React App’ ได้

Render บน Browser

สร้างไฟล์ App.test.js ที่โฟลเดอร์ tests/ และเริ่มเขียนเทสต์เลยย

import React from 'react';
import { shallow, mount, render } from 'enzyme';
import App from '../src/components/App';
describe('<App />', () => {
it('should render without throwing an error', () => {
const component = shallow(<App />);
expect(component.contains(<h1>Hello React App</h1>)).toBe(true);
});
it('should mount in a full DOM', () => {
const component = mount(<App />);
expect(component.find('.app').length).toBe(1);
});
it('should render to static HTML', () => {
const component = render(<App />);
expect(component.text()).toEqual('Hello React App');
});
});
  • Shallow จะ Render เฉพาะ Component ที่เราอยู่ จะไม่มีการ Render Children Components ทำให้ทำงานได้รวดเร็วที่สุด
  • Render จะ Render Components Render Children Components แต่จะไม่มีการเกิด Components Lifecycle และทุกอย่างที่ Render จะถูก Render ออกมาเป็น Static HTML
  • Mount จะ Render แบบ Full DOM นั่นก็คือ Render Components Render Children Components ทั้งหมด รวมทั้งมีการเกิด Component Lifecycle ทำให้ Mount ทำงานช้าที่สุด เนื่องจากทุกอย่างจะทำงานเหมือนจริง

จากนั้นเพิ่มสคริปต์ที่ไฟล์ package.json

"scripts": {
...
"test": "jest",
"test-coverage": "jest --coverage"
},

จากนั้นเริ่มทำการเทสต์ได้เลยยย ด้วยการรันคำสั่ง

$ yarn test

หรือหากต้องการดู Test Coverage ด้วยก็รันคำสั่ง

$ yarn test-coverage

เมื่อทำการรันเทสต์เสร็จก็จะแสดงผลลัพธ์อันสวยงาม คูลๆ 🤩

Testing success 🎉
Testing with Test Coverage 🚀

สรุป

การเขียน Unittest อาจจะทำต้องใช้เวลาในการเขียนโค้ดมากขึ้น แต่ก็ช่วยลดความเสี่ยงในการเกิด Bug หรือหากเกิด Bug ก็จะช่วยให้เรา หาจุดที่เกิด Bug ได้ง่ายขึ้น (ถ้าเขียนครอบคลุมนะน้า 🤣) อีกทั้งยังช่วยเช็คความถูกต้องในการทำงานของโค้ดให้เราอีกด้วย เพราะฉะนั้นมาเขียน Unittest กันเถอะ เพื่อชีวิตที่ดีในอนาคต 👨🏼‍💻

Source Code

https://github.com/boomauakim/sample-react-app

Reference

https://github.com/airbnb/enzyme

https://gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913

https://stackoverflow.com/questions/44082820/enzyme-when-to-use-shallow-render-or-mount

--

--