Angular Testing part 3

Phai Panda
4 min readNov 2, 2019

--

Jasmine Report & Code Coverage

ตัวอย่าง Code Coverage

เพื่อนๆอาจถามว่า โถ่ เมื่อไรจะพาไปเขียน Angular Testing สักที พิรี้พิไรคอยท่า Jasmine อยู่นี่แหละไม่ไปไหนสักที ก็จริงครับ ใจเย็นนิดหนึ่ง ผมสัญญาว่าจะพาไปแน่นอน

จากทั้ง 2 parts ก่อนหน้า

Jasmine Report

ที่ผ่านเพื่อนๆเห็นแล้วว่า Jasmine ได้ report ผลลัพธ์ออก 2 รูปแบบใหญ่ๆคือ ผ่านทั้งหมด กับ ไม่ผ่าน กรณีที่ผ่านทั้งหมดเราจะเห็นจุด (dot) ซึ่งแต่ละจุดแทนด้วย spec มันช่างน่ารักเพราะไม่มีคำอธิบายอะไรเลยนอกจากจุดแล้วก็จุด ส่วนกรณีไม่ผ่านเราจะเห็นตัว F ปรากฏขึ้นแทนจุดนั้นๆพร้อมคำอธิบาย

กรณีผ่านทั้งหมดจาก 5 specs

Started
.....
5 specs, 0 failures

กรณีไม่ผ่าน สมมติเป็นจุดที่ 4 จาก 5 specs

Started
...F.
Failures:
1) Song should have a valid constructor
Message:
Expected null not to be null.
5 specs, 1 failure

simple ใช่ไหมล่ะครับ

เท่าที่ผมเข้าใจ Jasmine จะแสดง

  • จุด (dot) แทน Success
  • F แทน Fault
  • และ * แทน Pending

เอาล่ะ ณ เวลานี้เราต้องการอะไรที่ อื่ม… ใช้คำว่า ดูดีกว่านี้ครับ ไม่สิ ต้องบอกว่าให้ดูมีเรื่องราวมากกว่านี้ เรื่องราวของความคาดหวังที่ว่าผ่านทั้งหมดอะไรบ้าง ไม่ผ่านอะไรบ้าง ประมาณนั้น

เพื่อบรรลุเป้าหมาย เราต้องการ jasmine-spec-reporter

jasmine-spec-reporter

โหลดมา

npm i -D jasmine-spec-reporter

เปิดดู package.json ส่วนของ devDependencies

...
"devDependencies": {
"@types/jasmine": "^3.4.4", "jasmine": "^3.5.0", "jasmine-spec-reporter": "^4.2.1", "ts-node": "^8.4.1", "typescript": "^3.6.4"}
...

โปรเจกต์นี้ของเรา root project คือ contacts ซึ่งมี sub folder ที่สำคัญดังนี้ถูกไหม

contacts/data
contacts/spec

และภายใน spec folder จะมี

spec/player
spec/song

ให้เพื่อนๆสร้าง helpers folder ขึ้นมา ภายในสร้างไฟล์ชื่อ reporter.js

spec/helpers/reporter.js

จากนั้นเปิดดูไฟล์ jasmine.json ซึ่งอยู่ ณ root project มันต้องมีเนื้อหาอย่างนี้

{    "spec_dir": "spec",    "spec_files": [        "**/*[sS]pec.js",        "**/*[sS]pec.ts"    ],    "helpers": [        "helpers/**/*.js"    ],   "stopSpecOnExpectationFailure": false,   "random": false}

กล่าวคือ jasmine-spec-reporter จะมองหาไฟล์ชื่อ reporter.js ตาม configuration ที่กำหนดไว้ใน jasmine.json นี้

เมื่อทุกอย่างเรียบร้อยแล้ว ให้เปิดไฟล์ reporter.js แล้วลงมือ

const SpecReporter = require('jasmine-spec-reporter').SpecReporter;jasmine.getEnv().clearReporters();jasmine.getEnv().addReporter(new SpecReporter({    suite: {        displayNumber: true,    },    summary: {        displaySuccessful: false,        displayFailed: false,        displayPending: false,    },}));

อธิบายส่วนของ suite

  • displayNumber เป็น true จะให้หมายเลขลำดับของ suite ทั้งหมด

อธิบายส่วนของ summary

  • displaySuccessful เป็น true ควรเห็นผลสรุปของ specs ที่ผ่าน
  • displayFailed เป็น true จะเห็นผลสรุปของ specs ที่ไม่ผ่าน (ถ้ามี)
  • displayPending เป็น true จะเห็นผลสรุปของ specs ที่ pending (ถ้ามี)

ดูเพิ่มเติมเกี่ยวกับ jasmine spec reporter configuration

เรียบร้อยแล้วรัน

npm run test

หากว่าผมไปแก้ spec ที่ไม่ผ่านให้ผ่าน

หมายเหตุ เพื่อนๆสังเกตไหม เวลาที่ spec ไม่ผ่าน มันจะมี npm ERR! ปรากฏออกมา สืบเนื่องจาก Jasmine ตรวจสอบค่าของตัวแปร passed

ค่าเจ้ากรรมนี้หากว่าเป็น true มันจะ return exit(0) แต่หากเป็น false มันจะ return exit(1) อ้างอิง

ฉะนั้นถ้าเพื่อนๆต้องการบอกกับ npm ว่า exit(1) ก็เงียบไว้ไม่ต้องพ่นอะไรออกมาทั้งนั้น เพื่อนๆก็รันด้วยคำสั่ง --silent แบบนี้ครับ

npm run test --silent
เห็นไหม spec ไม่ผ่าน มันเงียบ ERR! ไปแล้ว

สรุปว่า Jasmine Report แบบ console เราได้สิ่งที่เรียกว่าเรื่องราวสมความตั้งใจ

ต่อไปคือ Code Coverage

Code Coverage

ลอกมาจาก Wiki เลยนะ Code Coverage หรือ Test Coverage ก็คือ

is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs.

มันเป็นการวัดปริมาณน่ะครับ ว่าพอใจไหมเท่านี้เท่านั้นเปอร์เซนต์ โดยวัดจาก

  • ตัวโค้ดที่เขียนว่าประกอบไปด้วยอะไรบ้าง อย่างละเท่าไร
  • เรียกใช้งานไหมหรือแค่ประกาศไว้เอาเท่ห์ เช่น function ที่สร้างไม่เคยถูกเรียกที่ไหนเลย
  • เคาะบรรทัดมากไปหรือเปล่า เผื่อไว้ปลูกบ้านก็บอกมา
  • รวมไปถึง spec ที่คาดหวังมีทางเลือก if-else ถ้า if ทำ else ก็จะไม่ทำ แต่ถ้า else ทำ if ก็จะไม่ทำ อย่างนี้เรียก branches และจะให้ผลเป็น 50% ต่อ if-else คู่ใดๆ เป็นต้น

อ้างอิง

ผมยังไม่เห็นว่ามันจำเป็นยังไงเลยพี่

เออน้อง ไม่ต้องไปเซตหรอก เสียเวลา

report แบบนี้จะเอาให้ใครดู ไม่ต้องทำหรอก

แต่เราจะทำครับ (ขำ) ​ซึ่งแท้จริงมี tool หลายตัวให้เลือกใช้ ผมขอเลือกเป็น nyc แล้วกัน

NYC

จัดสิ

npm i -D nyc

จากนั้นเพิ่ม config เหล่านี้ใน package.json

แล้วรัน

npm run coverage --silent

เพราะ npm run coverage จะไปเรียก nyc ให้ทำงานหลังจากทำงาน npm run test เสร็จก่อน เราจึงได้ผลลัพธ์ทั้ง report และ code coverage ตามลำดับ

coverage summary กล่าวว่า

  • คำสั่งที่เขียนทั้งหมด (statements) มีจำนวน 22 คำสั่ง จึงคิดเป็น 100%
  • ทางเลือกหรือทางแยก (branches) เช่น if-else ไม่มีเลย คิดเป็น 100%
  • จำนวนฟังก์ชัน 7 ฟังก์ชัน ทุกฟังก์ชันเรียกใช้งานหมด จึงคิดเป็น 100%
  • บรรทัด ไม่ว่าจะเป็นจากคำสั่ง (statements) หรือเคาะปุ่ม Enter ที่สนใจมีจำนวน 22 บรรทัด ไม่น่าเกียจไม่แปลก จึงคิดเป็น 100%

ให้เพื่อนๆสังเกตที่ package.json ส่วนของ nyc reporter มันได้ generage ผลลัพธ์ 3 ประเภท ได้แก่

...
"reporter": [
"text", "text-summary", "html"],...

text ก็คือตารางที่เห็นในรูปข้างต้น

text-summary ก็คือส่วนที่เรียกว่า Coverge summary ที่เห็นในรูปข้างต้น

html จะสร้าง HTML report อันนี้ให้คัดลอก path ของ index.html ตามรูปด้านล่างนี้ครับ

แล้ววางบน Address bar ของ Browser

ว้าว! สวยงามใช่ไหมล่ะ

บางคนสงสัย มันเป็น 100% ตลอดเลยไหม คำตอบคือ ไม่ มันขึ้นอยู่กับคุณภาพของโค้ดที่เขียน ทดลองสิ

ไฟล์ player.spec.js ลองประกาศฟังก์ชันที่ไม่ถูกเรียกใช้งาน

describe('Player', function() { ... })function printHello() {    console.log('hello')}

แล้วรัน

มันบอกเลยว่าบรรทัดที่ 26 มีปัญหา

เอาเป็นว่า part นี้ไว้เท่านี้ เพื่อนๆก็คงพอทราบแล้วว่า Jasmine Report และ Code Coverage นั้นมีประโยชน์มาก มันเป็นการันตีว่า unit test และโค้ดที่เราเขียนมีคุณภาพเชื่อถือได้มากน้อยเพียงใด

part หน้าพบกับ Karma Test Runner ครับ

--

--

No responses yet