Jest — Javascript Testing on ES6/React

Tanachot Techajarupan
Sunday Tech
Published in
3 min readJan 22, 2019
Jest with Javascript Testing

จะพาไปรู้จัก Jest — Testing Library จากค่าย Facebook
มีตัวช่วยครบครั้นสำหรับ Javascript รวมถึง UI อย่าง React
ที่จะช่วย Improve Quality ของการ Coding เราได้อีกด้วย

Installation

Example source code: github.com/ttanachot/jest-test

ทำการ setup dependencies ให้เราสามารถใช้ Jest กับ ES6 / React

  • jest — Testing library for Javascript
  • babel — Transpile syntax JS เราให้เป็น ES6 โดยมี preset หลายแบบตามสิ่งที่เราใช้งาน
  • regenerator-runtime — A small runtime library จาก Facebook ที่ช่วย wrap generator ไว้ข้างหลังให้เรา
  • enzyme — ตัวช่วยทำ testing ของ React

อย่าลืมสร้าง config ไว้ให้ .babelrc ด้วย จะช่วยเรา unlocked feature ของ ES6 แล้วยังช่วยเรา transform runtime ด้วย

/* .babelrc */{
"presets": ["env", "react", "stage-0"],
"plugins": [
["transform-runtime", {
"polyfill": false,
"regenerator": true
}]
]
}

ในไฟล์ package.json ใส่ให้ scripts ของเราใช้ test เป็น jest รวมถึงใช้ build-in feature ที่บอก code coverage ให้เรา แนะนำให้ใช้เลย ดีงาม

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

Example

เริ่มด้วยเรามีฟังก์ชั่น isPrime โดยที่เราอยากลองจะเขียน testcase อย่างง่าย

สร้างอีกไฟล์หนึ่งขึ้นมา util.test.js ไว้ในทำการ import ไฟล์ util.js เข้ามา

  • เขียนเป็น test-suite ที่รวมเคสที่เกี่ยวเนื่องกันไว้ได้ด้วย
    describe('Test suite', () => { ... });
  • เขียนแบบ standalone ได้เหมือนกัน
    test('should get result correctly', () => { ... });
  • มือใหม่ให้ คิดเคสง่ายก่อนแค่ลองดู input/output

แล้วมาลองรัน terminal ด้วย npm run test เราจะเห็นได้ว่า test suite ที่เราเขียนขึ้นมาใช้งานได้เลยทันที มี Code coverage มาให้ด้วย กี่เปอร์เซ็น ตรงไหนยังไปไม่ถึง ใช้เวลาเท่าไหร่ บอกเรามาหมด

npm run test

ถัดไปด้านล่างคือสิ่งที่ Jest ช่วยในการทำ Testing ของเราให้ใช้งานได้ง่ายขึ้น

Matcher

พื้นฐานของการเขียน Testing ก็คือการเทียบดูว่า result ตรงกับสิ่งที่คาดหวังไว้มั้ย

Jest ก็มี matcher พื้นฐานในการเทียบค่าให้เรามาแล้ว ไม่ว่าจะเทียบค่าตรงๆ หรือจะเป็น regex รวมทั้ง boolean

expect(result).toBe('result');
expect(result).toMatch(/test/);
expect(result).not.toBeNull();
expect(result).toBeThruthy();
expect(result).toBeFalsy();

ลองกับ array ของ object แบบ advance ขึ้นมาหน่อย
รวมถึงการเช็คแบบที่เราไม่ได้สนใจ value เลยก็ได้ขอแค่มีอยู่ก็พอแล้ว

expect(result).toBe(expect.arrayContaining(expected));

สามารถดูเพิ่มเติมได้ที่ : jest-using-matchers

Asynchronous things

ถ้าเรา fetch ใช้ async/await ช่วยจัดการได้เลย
ซึ่งจะช่วยลด LOC ได้ไปพอสมควรเลยนะ ไปดูตัวอย่างกัน

ถ้าเกิดว่าถ้า fetchUsers ไม่ได้มีปัญหาอะไรก็จะ resolves ได้ปกติ

หรือมีปัญหาในเรื่อง request แล้วไม่ได้ก็จะ rejects ไปเลย แถมดัก exception ได้ด้วย

Mock Function

บางที่การสร้างฟังก์ชั่นของเรามีการใช้งาน

  • Read/Write database
  • ไม่ว่าจะเป็น repository หรือจะ ORM library
  • ส่วนที่จำเป็นต้องใช้ network ที่มีการ request/response

โดยรวมเรามองว่ามันเป็น side-effect เราสามารถใช้ Mock เข้ามาเป็นตัวช่วยได้โดยที่เราสามารถ override ให้ result เป็นแบบที่เราต้องการได้เลย

Unit Testing — ES6

Idea ของการเช็คคือเราจะดูว่า steps ในการเรียกฟังก์ชั่นนั้นถูกมั้ย

โดยการเช็คว่า mockFunction นั้นทำงานถูกมั้ย เรียกกี่ครั้ง
expect(mockFunction).toHaveBeenCalledTime(1)

เรายังสามารถเช็คได้ว่า parameters ที่ส่งไปได้รับจริงๆมั้ย
expect(mockFunction).toHaveBeenCalledWith(args1, agrs2, ...);

โดยเรา override ทั้ง node_modules ของ node-fetch ให้เป็น mock ไปซะเลย

UI Testing — React

ขอยกเป็นตัวอย่างง่ายๆ โดยมี React Component ที่เป็น checkbox เมื่อเรากดเลือกก็จะนำ Text ที่เรา set ไว้เป็น props โชว์ขึ้นมา

เรายังมีตัวช่วยในการทำ Test UI กับ React ใช้ library enzyme จากค่าย AirBnB เป็น container ช่วยให้เรา render component แบบ simulate จนไปถึง children

เนื่องจาก React v.16+ จำเป็นต้องใช้ Adapter แปลงให้ backward compatible อาจจะต้องมีการ configuration เพิ่มเติม

ดูเพิ่มเติมได้ที่ : airbnb.io/enzyme/

Summary

Testing Pyramid

การทำ Testing จุดประสงค์หลักคือ การช่วยลดปริมาณ Bug และช่วย Scope การ Coverage ของ Code ที่ถูกเขียนขึ้นมาก่อน โดยเป็นหลักประกันว่าจะช่วยลดปัญหาที่เคยเจอได้อีกด้วย

แน่นอนว่าคุณภาพของ Code จะดีขึ้น และ Maintainance รวมทั้ง Implementation จะค่อนข้าง Flow ได้ดีกว่าการไม่มี Testing ซึ่งแปลว่ามันคือการวางฐานต่อไปในอนาคตได้เร็วขึ้น ช่วยลด cost ทั้งด้าน money และ time โดยที่การเปลี่ยนแปลงของ business requirements อาจจะกระทบ Developer อย่างเราน้อยลง

ไว้เจอกันใหม่ ขอบคุณที่ติดตามครับ

--

--