บทนำ
การทดสอบการเขียนเป็นสิ่งที่ผู้เริ่มต้นและวิศวกรผู้ช่ำชองมักเลื่อนออกไปสำหรับการพัฒนาในระยะหลัง แต่สิ่งเหล่านี้คือกุญแจสำคัญในการพัฒนาซอฟต์แวร์ที่มีความเสถียรและแข็งแกร่ง
หลักฐานพื้นฐานของ การพัฒนาเพื่อทดสอบ (TDD) กำลังเขียนการทดสอบของคุณก่อนที่คุณจะเริ่มเขียนโค้ด นั่นเป็นเป้าหมายที่ดีในการมุ่งมั่น แต่ต้องใช้วินัยและการวางแผนอย่างมากเมื่อคุณพยายามปฏิบัติตามหลักการ! เพื่อให้กระบวนการทั้งหมดนี้ง่ายขึ้นมาก คุณสามารถใช้เฟรมเวิร์กการทดสอบและการยืนยันที่ใช้งานง่ายและมีประสิทธิภาพ เช่น กาแฟโมคะ และ ชัย.
ในบทความนี้ เราจะเริ่มต้นด้วยการแนะนำคุณให้รู้จักกับไลบรารีทั้งสองนี้ จากนั้นจะแสดงวิธีใช้งานร่วมกันเพื่อสร้างการทดสอบหน่วยที่อ่านง่ายและใช้งานได้อย่างรวดเร็ว
ชัย
Chai เป็นไลบรารีการยืนยันที่ให้ทั้ง BDD (การพัฒนาที่ขับเคลื่อนด้วยพฤติกรรม) และ TDD (การพัฒนาที่ขับเคลื่อนด้วยการทดสอบ) รูปแบบของการเขียนโปรแกรมสำหรับโค้ดทดสอบ และมีไว้เพื่อจับคู่กับไลบรารีการทดสอบที่ช่วยให้คุณจัดระเบียบการทดสอบได้ มักจะจับคู่กับมอคค่า
มี API หลักสามรายการ:
should
expect
assert
var.should.equal(var2)
expect.var.to.be.equal(var2)
assert.equal(var1, var2)
ตลอดบทความนี้ เราจะเน้นที่สไตล์ BDD โดยใช้ Chai's
expect
แม้ว่าการใช้อินเทอร์เฟซ/สไตล์อื่นๆ ตามสัญชาตญาณของคุณเองก็ถือว่าโอเค ที่assert
อินเทอร์เฟซเป็นเฟรมเวิร์กการยืนยัน TDD ทั่วไปที่เหมือนกันที่สุด
expect
ใช้ API ภาษาที่เป็นธรรมชาติมากในการเขียนการยืนยันของคุณ ซึ่งจะทำให้การทดสอบของคุณง่ายต่อการเขียนและปรับปรุงในภายหลัง สิ่งนี้ทำได้โดยการผูกมัด getters เข้าด้วยกันเพื่อสร้างและดำเนินการยืนยัน ทำให้ง่ายต่อการแปลข้อกำหนดเป็นโค้ด:
let user = {name: 'Scott'};
expect(user).to.have.property('name');
หมายเหตุ มาดูกันว่าคุณสามารถอ่านคำยืนยันในภาษาธรรมชาติและเข้าใจสิ่งที่เกิดขึ้นได้อย่างไร นั่นเป็นหนึ่งในข้อดีหลักของการใช้ไลบรารีการยืนยันเช่น Chai!
ตัวอย่างเพิ่มเติมบางส่วนของ getters เหล่านี้คือ:
to
be
is
and
has
have
getters เหล่านี้บางส่วนสามารถถูกล่ามโซ่เข้าด้วยกันและใช้กับวิธีการยืนยันเช่น true
, ok
, exist
และ empty
เพื่อสร้างการยืนยันที่ซับซ้อนในบรรทัดเดียว:
"use strict";
const expect = require('chai').expect;
expect({}).to.exist;
expect(26).to.equal(26);
expect(false).to.be.false;
expect('hello').to.be.string;
expect([1, 2, 3]).to.not.be.empty;
expect([1, 2, 3]).to.have.length.of.at.least(3);
หมายเหตุ สามารถดูรายการวิธีการทั้งหมดที่มีอยู่ได้ โปรดคลิกที่นี่เพื่ออ่านรายละเอียดเพิ่มเติม.
คุณอาจต้องการตรวจสอบรายการที่มีอยู่ ปลั๊กอิน สำหรับชัย. สิ่งเหล่านี้ทำให้การทดสอบคุณสมบัติที่ซับซ้อนมากขึ้นง่ายขึ้นมาก
เอา ชัย-http เช่น ซึ่งเป็นปลั๊กอินที่ช่วยคุณทดสอบเส้นทางเซิร์ฟเวอร์:
"use strict";
const chai = require('chai');
const chaiHttp = require('chai-http');
chai.use(chaiHttp);
chai.request(app)
.put('/api/auth')
.send({username: '[email protected]', password: 'abc123'})
.end(function(err, res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
});
การจัดระเบียบกรณีทดสอบด้วย Mocha – อธิบาย() และมัน()
Mocha เป็นเฟรมเวิร์กการทดสอบสำหรับ Node ที่ให้ความยืดหยุ่นในการรันโค้ดแบบอะซิงโครนัส (หรือซิงโครนัส) แบบอนุกรม ข้อยกเว้นที่ตรวจไม่พบจะแสดงข้างกรณีทดสอบที่มีการแจ้งข้อผิดพลาดดังกล่าว ทำให้ง่ายต่อการระบุอย่างชัดเจนว่าอะไรล้มเหลวและเพราะเหตุใด
ขอแนะนำให้ติดตั้ง Mocha ทั่วโลก:
$ npm install mocha -g
คุณจะต้องให้เป็นการติดตั้งทั่วโลกตั้งแต่ mocha
คำสั่งใช้เพื่อรันการทดสอบสำหรับโปรเจ็กต์ในไดเร็กทอรีในเครื่องของคุณ
โค้ดชิ้นนี้มีไว้ทำอะไร?
it()
ควรส่งคืน X it()
กำหนดกรณีทดสอบ และ Mocha จะดำเนินการแต่ละกรณี it()
เป็นการทดสอบหน่วย หากต้องการจัดระเบียบการทดสอบหลายหน่วยเราทำได้ describe()
ฟังก์ชันการทำงานทั่วไป และจัดโครงสร้างการทดสอบมอคค่า
นี่อาจเป็นคำอธิบายที่ดีที่สุดด้วยตัวอย่างที่เป็นรูปธรรม:
"use strict";
const expect = require('chai').expect;
describe('Math', function() {
describe('#abs()', function() {
it('should return positive value of given negative number', function() {
expect(Math.abs(-5)).to.be.equal(5);
});
});
});
ตัว Vortex Indicator ได้ถูกนำเสนอลงในนิตยสาร describe()
วิธีการที่เรากำหนดไว้ ชื่อทดสอบที่เรียกว่า #abs()
. คุณสามารถทำการทดสอบทีละรายการโดยใช้ชื่อของพวกเขาได้เช่นกัน ซึ่งจะกล่าวถึงในภายหลัง
หมายเหตุ ด้วยการทดสอบมอคค่า คุณไม่จำเป็นต้องทำ require()
วิธีมอคค่าใดก็ได้ วิธีการเหล่านี้มีให้ทั่วโลกเมื่อรันด้วย mocha
คำสั่ง
เพื่อดำเนินการทดสอบเหล่านี้ ให้บันทึกไฟล์ของคุณและใช้ไฟล์ mocha
คำสั่ง:
$ mocha .
Math
#abs()
✓ should return positive value of given number
1 passing (9ms)
ผลลัพธ์คือรายละเอียดของการทดสอบที่ดำเนินการและผลลัพธ์ สังเกตวิธีการซ้อนกัน describe()
การเรียกจะส่งต่อไปยังเอาต์พุตผลลัพธ์ มีประโยชน์ที่จะมีการทดสอบทั้งหมดสำหรับวิธีการหรือคุณลักษณะที่กำหนดซ้อนกัน
วิธีการเหล่านี้เป็นพื้นฐานสำหรับกรอบการทดสอบ Mocha ใช้เพื่อเขียนและจัดระเบียบการทดสอบตามที่คุณต้องการ เราจะดูตัวอย่างหนึ่งของสิ่งนี้ในส่วนถัดไป
แบบทดสอบการเขียนกับมอคค่าและชัย
วิธีที่แนะนำในการจัดระเบียบการทดสอบภายในโปรเจ็กต์ของคุณคือจัดการทดสอบทั้งหมดไว้ในการทดสอบของตัวเอง /test
ไดเรกทอรี ตามค่าเริ่มต้น Mocha จะตรวจสอบการทดสอบหน่วยโดยใช้ลูกกลม ./test/*.js
และ ./test/*.coffee
. จากนั้นมันจะโหลดและรันไฟล์ใด ๆ ที่เรียกไฟล์ describe()
วิธี
ดูคู่มือเชิงปฏิบัติสำหรับการเรียนรู้ Git ที่มีแนวทางปฏิบัติที่ดีที่สุด มาตรฐานที่ยอมรับในอุตสาหกรรม และเอกสารสรุปรวม หยุดคำสั่ง Googling Git และจริงๆ แล้ว เรียน มัน!
เป็นเรื่องปกติที่จะต่อท้ายไฟล์ทดสอบด้วย .test.js
สำหรับไฟล์ต้นฉบับที่มีการทดสอบ Mocha:
├── package.json
├── lib
│ ├── db.js
│ ├── models.js
│ └── util.js
└── test
├── db.test.js
├── models.test.js
├── util.test.js
└── util.js
util.js
ใน test
ไดเร็กทอรีจะไม่มีการทดสอบหน่วยใดๆ มีเพียงฟังก์ชันยูทิลิตี้เพื่อช่วยในการทดสอบ
หมายเหตุ: คุณสามารถใช้โครงสร้างอะไรก็ได้ที่เหมาะกับคุณ ระบบจะเลือกการทดสอบหน่วยโดยอัตโนมัติ
เมื่อพูดถึงการเขียนแบบทดสอบจริงๆ การจัดระเบียบโดยใช้ describe()
วิธีการ คุณสามารถจัดระเบียบตามฟีเจอร์ ฟังก์ชัน ไฟล์ หรือระดับอื่นๆ ได้ตามต้องการ ตัวอย่างเช่น ไฟล์ทดสอบที่จัดระเบียบเพื่ออธิบายการทำงานในระดับฟังก์ชันจะมีลักษณะดังนี้:
"use strict";
const expect = require('chai').expect;
describe('Math', function() {
describe('#abs()', function() {
it('should return positive value of given negative number', function() {
expect(Math.abs(-5)).to.be.equal(5);
});
it('should return positive value of given positive number', function() {
expect(Math.abs(3)).to.be.equal(3);
});
it('should return 0 given 0', function() {
expect(Math.abs(0)).to.be.equal(0);
});
});
});
การรันการทดสอบจะให้ผลลัพธ์แก่คุณ:
$ mocha .
Math
#abs()
✓ should return positive value of given negative number
✓ should return positive value of given positive number
✓ should return 0 given 0
3 passing (11ms)
ยิ่งไปกว่านั้น คุณอาจมีการทดสอบหลายวิธีในไฟล์เดียวด้วย ในกรณีนี้ วิธีการจะถูกจัดกลุ่มตาม Math
วัตถุ:
"use strict";
const expect = require('chai').expect;
describe('Math', function() {
describe('#abs()', function() {
it('should return positive value of given negative number', function() {
expect(Math.abs(-5)).to.be.equal(5);
});
it('should return positive value of given positive number', function() {
expect(Math.abs(3)).to.be.equal(3);
});
it('should return 0 given 0', function() {
expect(Math.abs(0)).to.be.equal(0);
});
});
describe('#sqrt()', function() {
it('should return the square root of a given positive number', function() {
expect(Math.sqrt(25)).to.be.equal(5);
});
it('should return NaN for a given negative number', function() {
expect(Math.sqrt(-9)).to.be.NaN;
});
it('should return 0 given 0', function() {
expect(Math.sqrt(0)).to.be.equal(0);
});
});
});
ซึ่งส่งผลให้:
$ mocha .
Math
#abs()
✓ should return positive value of given negative number
✓ should return positive value of given positive number
✓ should return 0 given 0
#sqrt()
✓ should return the square root of a given positive number
✓ should return NaN for a given negative number
✓ should return 0 given 0
6 passing (10ms)
มอคค่าฮุก – before(), after(), beforeEach() และ afterEach()
เป็นที่ยอมรับว่าการทดสอบหน่วยส่วนใหญ่ไม่ง่ายขนาดนี้ หลายครั้งคุณอาจต้องการทรัพยากรอื่นเพื่อทำการทดสอบ เช่น ฐานข้อมูลหรือทรัพยากรภายนอกอื่นๆ (หรือแบบจำลอง/ต้นขั้ว) เพื่อตั้งค่านี้ เราสามารถใช้สิ่งใดสิ่งหนึ่งต่อไปนี้ ตะขอมอคค่า วิธีการ:
before()
: ทำงานก่อนการทดสอบทั้งหมดในบล็อกที่กำหนดbeforeEach()
: รันก่อนการทดสอบแต่ละครั้งในบล็อกที่กำหนดafter()
: ทำงานหลังจากการทดสอบทั้งหมดในบล็อกที่กำหนดafterEach()
: ทำงานหลังจากการทดสอบแต่ละครั้งในบล็อกที่กำหนด
ตะขอเหล่านี้เป็นสถานที่ที่เหมาะสำหรับการตั้งค่าและการรื้อถอนที่จำเป็นสำหรับการทดสอบของคุณ กรณีการใช้งานทั่วไปประการหนึ่งคือการสร้างการเชื่อมต่อกับฐานข้อมูลของคุณก่อนที่จะรันการทดสอบ:
"use strict";
const expect = require('chai').expect;
let User = require('../models').User;
describe('Users', function() {
let database = null;
before(function(done) {
});
afterEach(function(done) {
});
describe('#save()', function() {
it('should save User data to database', function(done) {
});
});
describe('#load()', function() {
it('should load User data from database', function(done) {
});
});
});
ก่อน ใด ของการทดสอบที่รันอยู่ ฟังก์ชันที่ส่งถึงเรา before()
มีการรันเมธอด (และรันเพียงครั้งเดียวตลอดการทดสอบ) ซึ่งสร้างการเชื่อมต่อกับฐานข้อมูล เมื่อเสร็จแล้ว ชุดการทดสอบของเราก็จะเริ่มทำงาน
เนื่องจากเราไม่ต้องการให้ข้อมูลจากชุดทดสอบชุดหนึ่งส่งผลต่อการทดสอบอื่นๆ ของเรา เราจึงต้องล้างข้อมูลจากฐานข้อมูลของเราหลังจากเรียกใช้ชุดทดสอบแต่ละชุดแล้ว นี่คืออะไร afterEach()
สำหรับ. เราใช้เบ็ดนี้เพื่อล้างข้อมูลฐานข้อมูลทั้งหมดหลังจากนั้น แต่ละ กรณีทดสอบถูกเรียกใช้ ดังนั้นเราจึงสามารถเริ่มต้นจากกระดานชนวนที่สะอาดสำหรับการทดสอบครั้งต่อไป
ทำการทดสอบมอคค่า
สำหรับกรณีส่วนใหญ่ ส่วนนี้ค่อนข้างเรียบง่าย สมมติว่าคุณได้ติดตั้ง Mocha และไปที่ไดเร็กทอรีโปรเจ็กต์แล้ว โปรเจ็กต์ส่วนใหญ่จำเป็นต้องใช้ mocha
คำสั่งที่ไม่มีข้อโต้แย้งเพื่อทำการทดสอบ:
$ mocha
Math
#abs()
✓ should return positive value of given negative number
✓ should return positive value of given positive number
✓ should return 0 given 0
#sqrt()
✓ should return the square root of a given positive number
✓ should return NaN for a given negative number
✓ should return 0 given 0
6 passing (10ms)
สิ่งนี้แตกต่างจากตัวอย่างก่อนหน้านี้เล็กน้อย เนื่องจากเราไม่จำเป็นต้องบอก Mocha ว่าการทดสอบของเราอยู่ที่ใด ในตัวอย่างนี้ รหัสทดสอบอยู่ในตำแหน่งที่คาดไว้ของ /test
.
อย่างไรก็ตาม มีตัวเลือกที่เป็นประโยชน์บางอย่างที่คุณอาจต้องการใช้เมื่อทำการทดสอบ หากการทดสอบบางอย่างของคุณล้มเหลว คุณอาจไม่ต้องการรันทั้งชุดทุกครั้งที่คุณทำการเปลี่ยนแปลง สำหรับบางโปรเจ็กต์ ชุดการทดสอบแบบเต็มอาจใช้เวลาสักครู่จึงจะเสร็จสมบูรณ์ ถือเป็นการเสียเวลาอย่างมากหากคุณต้องทำการทดสอบเพียงครั้งเดียวจริงๆ
สำหรับกรณีเช่นนี้คุณควร บอก Mocha ว่าต้องทดสอบอะไรบ้าง. ซึ่งสามารถทำได้โดยใช้
-g
or-f
ตัวเลือก
หากต้องการรันการทดสอบแต่ละรายการ คุณสามารถระบุ -g
ตั้งค่าสถานะและเพิ่มรูปแบบทั่วไประหว่างการทดสอบที่คุณต้องการเรียกใช้ ตัวอย่างเช่น หากคุณต้องการรันไฟล์ #sqrt()
การทดสอบ:
$ mocha -g sqrt
Math
#sqrt()
✓ should return the square root of a given positive number
✓ should return NaN for a given negative number
✓ should return 0 given 0
3 passing (10ms)
ขอให้สังเกตว่า #abs()
การทดสอบไม่รวมอยู่ในการดำเนินการครั้งนี้ หากคุณวางแผนตามชื่อการทดสอบของคุณ ตัวเลือกนี้สามารถใช้เพื่อดำเนินการทดสอบเฉพาะบางส่วนเท่านั้น
อย่างไรก็ตาม นี่ไม่ใช่ตัวเลือกที่มีประโยชน์เพียงอย่างเดียว ต่อไปนี้เป็นตัวเลือกเพิ่มเติมสำหรับ Mocha ที่คุณอาจต้องการลองดู:
--invert
: กลับด้าน-g
และ-f
ที่ตรงกัน--recursive
: รวมไดเรกทอรีย่อย--harmony
: เปิดใช้งานคุณสมบัติความสามัคคีทั้งหมดในโหนด
หมายเหตุ: คุณสามารถตรวจสอบรายการตัวเลือกทั้งหมดได้โดยใช้ mocha -h
คำสั่งหรือเปิด หน้านี้.
สรุป
โปรดทราบว่าทั้ง Mocha และ Chai สามารถใช้ทดสอบ Node Project ได้ทุกประเภท ไม่ว่าจะเป็นไลบรารี่ เครื่องมือบรรทัดคำสั่ง หรือแม้แต่เว็บไซต์ การใช้ตัวเลือกและปลั๊กอินต่างๆ ที่มีให้คุณ คุณจะสามารถตอบสนองความต้องการในการทดสอบของคุณได้อย่างง่ายดาย ไลบรารีแต่ละไลบรารีเหล่านี้มีประโยชน์อย่างมากในการตรวจสอบความถูกต้องของโค้ด และควรใช้ในโปรเจ็กต์ Node ทั้งหมดของคุณ
หวังว่านี่จะเป็นการแนะนำมอคค่าและชัยที่เป็นประโยชน์ได้ มีอะไรอีกมากมายให้เรียนรู้มากกว่าสิ่งที่ฉันได้นำเสนอที่นี่ ดังนั้นอย่าลืมตรวจสอบเอกสารเพื่อดูข้อมูลเพิ่มเติม