Angular Testing part 3
Jasmine Report & 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
สรุปว่า 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')}
แล้วรัน
เอาเป็นว่า part นี้ไว้เท่านี้ เพื่อนๆก็คงพอทราบแล้วว่า Jasmine Report และ Code Coverage นั้นมีประโยชน์มาก มันเป็นการันตีว่า unit test และโค้ดที่เราเขียนมีคุณภาพเชื่อถือได้มากน้อยเพียงใด
part หน้าพบกับ Karma Test Runner ครับ