تست کد Node.js با 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 تمرکز خواهیم کرد expect رابط کاربری، اگرچه استفاده از رابط ها/سبک های دیگر مطابق با شهود خود کاملاً مشکلی ندارد. این assert اینترفیس مشابه ترین چارچوب های ادعایی TDD است.

expect از یک API زبان بسیار طبیعی برای نوشتن ادعاهای شما استفاده می‌کند، که نوشتن تست‌های شما را آسان‌تر می‌کند و در ادامه مسیر بهبود می‌یابد. این کار با زنجیر کردن گیرنده‌ها برای ایجاد و اجرای ادعا انجام می‌شود و ترجمه نیازمندی‌ها به کد را آسان‌تر می‌کند:

let user = {name: 'Scott'};


expect(user).to.have.property('name');

توجه داشته باشید: ببینید چگونه می‌توانید ادعا را به زبان طبیعی بخوانید و بفهمید که چه خبر است؟ این یکی از مزایای اصلی استفاده از یک کتابخانه ادعایی مانند چای است!

چند نمونه دیگر از این گیرنده ها عبارتند از:

  • to
  • be
  • is
  • and
  • has
  • have

تعداد کمی از این گیرنده‌ها را می‌توان به هم متصل کرد و با روش‌های ادعایی مانند 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);

توجه داشته باشید: لیست کاملی از روش های موجود را می توان یافت اینجا کلیک نمایید.

همچنین ممکن است بخواهید فهرست موجود را بررسی کنید پلاگین ها برای چای اینها آزمایش ویژگی های پیچیده تر را بسیار آسان تر می کند.

گرفتن chai-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);
    });

سازماندهی موارد تست با موکا – describe() و it()

موکا یک چارچوب آزمایشی برای 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);
        });
    });
});

در describe() روش، a را تعریف کردیم نام آزمون، به نام #abs(). شما می توانید به صورت جداگانه تست ها را با نام آنها نیز اجرا کنید - این بعداً پوشش داده خواهد شد.

توجه داشته باشید: با تست های موکا، شما نیازی به این کار ندارید require() هر یک از روش های موکا این روش‌ها در صورت اجرا به صورت جهانی ارائه می‌شوند mocha فرمان

برای اجرای این تست ها، فایل خود را ذخیره کرده و از آن استفاده کنید mocha فرمان:

$ mocha .

  Math
    #abs()
      ✓ should return positive value of given number 


  1 passing (9ms)

خروجی تجزیه و تحلیل تست های انجام شده و نتایج آنها است. توجه کنید که چگونه تو در تو describe() تماس ها به خروجی نتایج منتقل می شوند. مفید است که همه آزمایش‌های یک روش یا ویژگی معین در کنار هم قرار بگیرند.

این روش ها اساس چارچوب تست موکا هستند. از آنها برای نوشتن و سازماندهی آزمون های خود به هر نحوی که دوست دارید استفاده کنید. یک نمونه از این را در بخش بعدی خواهیم دید.

تست های نوشتاری با موکا و چای

روش توصیه شده برای سازماندهی تست های خود در پروژه این است که همه آنها را در خود آنها قرار دهید /test فهرست راهنما. به‌طور پیش‌فرض، موکا با استفاده از globs، آزمایش‌های واحد را بررسی می‌کند ./test/*.js و ./test/*.coffee. از آنجا، هر فایلی را که فراخوانی می کند بارگیری و اجرا می کند describe() روش.

راهنمای عملی و عملی ما برای یادگیری Git را با بهترین روش ها، استانداردهای پذیرفته شده در صنعت و برگه تقلب شامل بررسی کنید. دستورات Google Git را متوقف کنید و در واقع یاد گرفتن آی تی!

معمول است که پسوند فایل های آزمایشی را با آن اضافه کنید .test.js برای فایل های منبع حاوی تست های موکا:

├── 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)

قلاب موکا – قبل ()، 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() است برای. ما از این قلاب برای پاک کردن تمام داده های پایگاه داده استفاده می کنیم هر test case اجرا شده است، بنابراین می توانیم برای آزمایش های بعدی از یک صفحه تمیز شروع کنیم.

اجرای تست های موکا

برای اکثر موارد، این بخش بسیار ساده است. با فرض اینکه قبلاً 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)

این کمی متفاوت از نمونه‌های قبلی ما است، زیرا ما نیازی به گفتن مکان آزمایش‌های ما به موکا نداشتیم. در این مثال، کد تست در محل مورد انتظار قرار دارد /test.

با این حال، گزینه‌های مفیدی وجود دارد که ممکن است بخواهید هنگام اجرای آزمایش‌ها از آنها استفاده کنید. برای مثال، اگر برخی از تست‌های شما ناموفق هستند، احتمالاً نمی‌خواهید هر بار که تغییری ایجاد می‌کنید، کل مجموعه را اجرا کنید. برای برخی از پروژه ها، مجموعه آزمایشی کامل ممکن است چند دقیقه طول بکشد. اگر واقعاً فقط نیاز به اجرای یک تست داشته باشید، زمان تلف شده زیادی است.

برای مواردی مانند این، شما باید به موکا بگویید کدام آزمایش را اجرا کند. این را می توان با استفاده از -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() تست ها در این اجرا گنجانده نشدند. اگر مطابق با نام آزمون خود برنامه ریزی می کنید، از این گزینه می توان فقط برای اجرای بخش های خاصی از آزمون های خود استفاده کرد.

با این حال، اینها تنها گزینه های مفید نیستند. در اینجا چند گزینه دیگر برای موکا وجود دارد که ممکن است بخواهید آنها را بررسی کنید:

  • --invert: معکوس -g و -f کبریت
  • --recursive: شامل دایرکتوری های فرعی
  • --harmony: تمام ویژگی های هارمونی را در Node فعال کنید

توجه داشته باشید: با استفاده از گزینه می توانید لیست کامل گزینه ها را بررسی کنید mocha -h فرمان، یا روشن است این صفحه.

کجا بیشتر بدانیم؟ این موضوع بسیار بیشتر از آن چیزی است که بتوانیم در یک مقاله کوتاه پوشش دهیم، بنابراین اگر می‌خواهید بیشتر بدانید، توصیه می‌کنیم به بخش رسمی مراجعه کنید. موچا و چای مستندات.

نتیجه

به خاطر داشته باشید که هر دو Mocha و Chai را می توان برای آزمایش تقریباً هر نوع پروژه Node، خواه کتابخانه، ابزار خط فرمان یا حتی یک وب سایت، استفاده کرد. با استفاده از گزینه ها و افزونه های مختلف در دسترس شما، باید بتوانید به راحتی نیازهای تست خود را برآورده کنید. هر یک از این کتابخانه ها برای اعتبارسنجی کد شما بسیار مفید است و باید تقریباً در تمام پروژه های Node شما استفاده شود.

امیدواریم که این به عنوان مقدمه ای مفید برای موکا و چای خدمت کرده باشد. چیزهای بیشتری برای یادگیری نسبت به آنچه در اینجا ارائه کرده ام وجود دارد، بنابراین برای اطلاعات بیشتر حتماً اسناد را بررسی کنید.

تمبر زمان:

بیشتر از Stackabuse