ทดสอบ Node.js Code กับ Mocha และ Chai

บทนำ

การทดสอบการเขียนเป็นสิ่งที่ผู้เริ่มต้นและวิศวกรผู้ช่ำชองมักเลื่อนออกไปสำหรับการพัฒนาในระยะหลัง แต่สิ่งเหล่านี้คือกุญแจสำคัญในการพัฒนาซอฟต์แวร์ที่มีความเสถียรและแข็งแกร่ง

หลักฐานพื้นฐานของ การพัฒนาเพื่อทดสอบ (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 ทั้งหมดของคุณ

หวังว่านี่จะเป็นการแนะนำมอคค่าและชัยที่เป็นประโยชน์ได้ มีอะไรอีกมากมายให้เรียนรู้มากกว่าสิ่งที่ฉันได้นำเสนอที่นี่ ดังนั้นอย่าลืมตรวจสอบเอกสารเพื่อดูข้อมูลเพิ่มเติม

ประทับเวลา:

เพิ่มเติมจาก สแต็ค