มาเขียน Test React ด้วย Enzyme กันเถอะ (ฉบับกระชับ)
เกริ่น…
ใช้อะไรบ้าง
- jest
- enzyme
- chai
- sinon
- babel
ทำอะไรบ้าง
1. Initial Project
2. Install package
3. Config
4. เริ่มเขียน Test
1. Initial Project
ใช้ create-react-app my-app ในการ Build Project
https://github.com/facebook/create-react-app
npx create-react-app my-app // build react app
cd my-app // เข้าไดเรกตอรี่
npm start // ทดสอบ run project
2. Install package
ก่อนที่จะเขียน Test ต้องลง package ก่อน ตามนี้
npm install --save-dev jestnpm install --save-dev enzyme enzyme-adapter-react-16npm install --save-dev chainpm install --save-dev sinonnpm install --save-dev @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties
อธิบาย package
jest เป็นตัวรัน test
enzyme เป็นตัว Render Components โดยที่เราไม่ต้องเปิด Browser ขึ้นมา
chai เป็นตัวเปรียบเทียบค่าที่คาดหวัง เขียน test ก็ต้องมีการคาดหวังสิ่งที่เกิด
babel เป็นตัวแปลงโค้ด JavaScript เวอร์ชั่นใหม่ ให้เป็นเวอร์ชั่นที่ Browser สามารถรันได้
3. Config
สร้าง src/setupTest.js
import { configure } from 'enzyme'import Adapter from 'enzyme-adapter-react-16'configure({ adapter: new Adapter() })
สร้าง babel.config.js
module.exports = {presets: ['@babel/preset-env', '@babel/preset-react'],plugins: ['@babel/plugin-proposal-class-properties']}
สร้าง jest.config.js
module.exports = {rootDir: '.',displayName: { name: 'enzyme-setup', color: 'blue' },verbose: true,errorOnDeprecated: true,roots: ['./Tests'],setupFilesAfterEnv:["<rootDir>src/setupTest.js"]}
4. เริ่มเขียน Test
เพิ่ม โค้ดใน package.json
"scripts": {
...“test”: “jest”...
}
สร้าง Tests/App.test.js
อธิบายโค้ด
describe เป็นส่วนที่จะบอกว่า เรากำลัง Test Component ไหนอยู่
describe(‘<MyComponent />’, () => {…})
it เป็นส่วนที่จะบอกว่า เรากำลัง Test Case ไหนอยู่
it(‘renders three <Foo /> components’, () => {…})
shallow เป็นการเรนเดอร์แบบตื้น ไม่ได้ render ทั้ง component ทำให้ทำงานเร็วกว่า mount
const wrapper = shallow(<MyComponent />)
mount เป็นการเรนเดอร์แบบเต็ม render ทั้ง component ทำให้ทำงานช้ากว่า shallow
const wrapper = mount(<Foo onButtonClick={onButtonClick} />)
render เป็นการเรนเดอร์เป็น static html
const wrapper = render(<div className=”myClass” />)
expect เป็นการคาดหวังค่า
ยกตัวอย่างโค้ดด้านล่าง เป็นการคาดหวังว่า จะมี <Foo></Foo> 3 อัน ใน <MyComponent />
const wrapper = shallow(<MyComponent />)
expect(wrapper.find(Foo)).to.have.lengthOf(3)
รันคำสั่ง npm test
อุ๋ย~!! เฟลอะแกร
ถึงตอนนี้ตั้งสติก่อนครับ อ่าน error ก่อน แล้วดูว่ามันบอกอะไรเรา
ถูกต้องครับ เรายังไม่มี MyComponent
สร้าง src/components/MyComponent.js
npm test
ยังเฟล อยู่ใช่ไหม
สร้าง src/components/Foo.js
มาถึงตอนนี้ Structure Project จะประมาณนี้
npm test
อีหยังวะ เฟล อีกแย้ววว ใจเย็นๆครับ อ่าน error ก่อน
อธิบายโค้ด
case 1
const wrapper = shallow(<MyComponent />)
กำหนด shallow <MyComponent />
expect(wrapper.find(Foo)).to.have.lengthOf(3)
คาดหวังว่า เราคาดหวังว่า <Foo></Foo> จะ 3 อัน <MyComponent/>
อ่าน Error
case 1 สังเกตตรง Expected value 3 คือค่าที่เราคาดหวัง
แต่ตรง Received มันนับได้ 0 ก็หมายความว่าตอนนี้มันยังไม่มี <Foo></Foo>
ทำไงดีน๊าา
งั้นก็ไปเพิ่ม <Foo></Foo> สัก 3 อัน ใน Component MyComponent สิ
src/components/MyComponent.js
npm test
เย้ ผ่านละจร้า Case 1
อธิบายโค้ด
Case2
const onButtonClick = sinon.spy()
กำหนด Event ให้กับ onButtonClick
const wrapper = mount(<Foo onButtonClick={onButtonClick} />)
กำหนด mount ส่ง Event onButtonClick ผ่าน props ของ component Foo
wrapper.find(‘button’).simulate(‘click’)
หาแท็ก button แล้วคลิก 1 ครั้ง
อ่าน Error
case 2 สังเกตที่ Component Foo เรายังไม่มีแท็ก button ทำให้โค้ดส่วนนี้
wrapper.find(‘button’).simulate(‘click’) ทำงานไม่ได้
ทำไงดีน๊าา
ก็เพิ่ม <button onClick={onButtonClick}></button> ใน Component Foo สิ
src/components/Foo.js
npm test
เย้ ผ่านละจร้า Case 2 พอถึงตอนนี้ ตบมือให้ตัวเองหน่อยครับ เก่งมากๆ ที่ทนอ่านมาถึงตรงนี้
อธิบายโค้ด
Case3
const wrapper = render(<Foo/>)
กำหนด render <Foo/>
expect(wrapper.text()).to.contain(‘unique’)
คาดหวังว่าจะมีคำว่า unique ใน Component Foo
อ่าน Error
case 3 สังเกตตรง Expected Value เป็น undefined เพราะหาคำว่า unique ไม่เจอ
ส่วนตรง Received มีแต่คำว่า Foo
ทำไงดีน๊าา
ก็เพิ่มคำว่า unique เข้าไปใน Component Foo สิ
src/components/Foo.js
npm test
เย้ ผ่านหมดแล้ว
ศึกษา function อื่นๆ ของ Enzyme ได้ที่ https://airbnb.io/enzyme/
สรุป
หากผิดพลาดประการใด ขออภัยด้วยครับ หวังว่าจะเป็นประโยชน์สำหรับเพื่อนๆที่กำลังศึกษานะครับ ถ้ามีเวลาจะมา Edit ให้ข้อมูลแน่นกว่านี้ และ เป็นประโยชน์มากกว่านี้
อ้างอิง
Enzyme
https://airbnb.io/enzyme/
Jest
https://jestjs.io/
React
https://reactjs.org/
Chai
https://www.chaijs.com/
Babel
https://babeljs.io/
Sinon
https://sinonjs.org/