Тъй като сложността на уеб приложението се увеличава, ръчното тестване на функционалността на предния край вече не може да осигури разумно ниво на увереност. Времето, което преди се отделяше за разработване на нови функции, сега се изразходва за коригиране на нарастващ брой проблеми с регресията...

Моята компания, както много други, се стреми към ежедневно внедряване. Това означава, че новоразработените функции ще имат по-малко от ден за тестване, преди да бъдат пуснати в производство. Това също означава, че вече не можем да разчитаме единствено на ръчно тестване за идентифициране на нови грешки и регресии. За да се приспособим към тази промяна, ние се обърнахме към предната интеграция и тестване на единици.

Интеграционното тестванее процес на тестване на софтуерни модули като група. Това може да означава да използвате инструмент като Selenium, за да прегледате уебсайта си и да се уверите, че всички потребителски функции работят по предназначение (тестове за потребителско изживяване).

Унит тестване е процес на тестване на логиката в отделни софтуерни модули. Това може да бъде полезно, когато искате да се уверите, че вашата функция за валидиране покрива всички крайни случаи или дори ако искате обратна връзка по време на процеса на разработка (някой TDD?).

Тази статия ще се съсредоточи върху внедряването на предни модулни тестове. Нашият „стек“ ще се състои от 1) Karmaкато тестова програма и 2) Mochaкато тестова рамка. Също така ще се уверим, че работи добре с 3) RequireJS.

Карма

Karma е програма за тестване на JavaScript, създадена от екипа на AngularJS. Възможно е да пишете модулни тестове само с Mocha, но Karma предоставя някои мощни функции, които е доста хубаво да имате. Всъщност липсата на онлайн ресурси за свързване на Karma, Mocha и RequireJS ме подтикна да напиша тази статия. Ще използваме Karma за изграждане на зависимости, създаване на тестов сървър, проверка за покритие на кода и провеждане на тестове в множество браузъри.

Първо инсталирайте рамки:

npm install karma --save-dev
npm install karma-mocha --save-dev
npm install karma-chai --save-dev
npm install karma-requirejs --save-dev

Karma идва с вградени добавки за Mocha, Chai и RequireJS. Ще използваме Mocha за писане на тестове, Chai за твърдения и RequireJS за зареждане на AMD модули. Ще ги разгледаме по-подробно по-късно.

След това инсталирайте плъгини (и PhantomJS):

npm install karma-chrome-launcher --save-dev
npm install karma-firefox-launcher --save-dev
npm install karma-opera-launcher --save-dev
npm install karma-safari-launcher --save-dev
npm install karma-phantomjs-launcher --save-dev
npm install phantomjs --save-dev

Karma е мощна с това, че позволява тестовете да се изпълняват едновременно в множество браузъри. Ще поддържаме Firefox, Opera, Chrome, Safari и PhantomJS. Тези добавки за браузър са необходими, за да помогнат на Karma да намери подходящите двоични файлове, което означава, че можете да изпълнявате тестове само на браузъри, които вече са инсталирани на вашата локална машина.

О, и докато сте в това, хвърлете в покритието на кармата

npm install karma-coverage --save-dev

Този плъгин е разклонение на Istanbul, което ще ни даде възможност лесно да проследяваме покритието на кода.

Карма

След това създайте своя конфигурационен файл на karma. Това може да стане с командата „karma init“ или чрез създаване на файл karma.conf.js в основната директория на вашите приложения. Ето как изглежда моят конфигурационен файл:

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['mocha', 'requirejs', 'chai'],
    files: [
        {pattern: './config.js', included: true},
        {pattern: './app/**/*.json', included: false},
        {pattern: './app/**/*.html', included: false},
        {pattern: './app/**/*.js', included: false},
        {pattern: './library/**/*.js', included: false},
        {pattern: './unit-tests/**/*.js', included: false},
        {pattern: './unit-tests/main.js', included: true}
    ],
    exclude: [
        './app/private/header/failure.js'
    ],
    preprocessors: {
        './app/**/*.js': 'coverage'
    },
    coverageReporter: {
      type : 'text-summary',
      dir : 'coverage/',
      includeAllSources : true
    },
    reporters: ['progress', 'junit', 'coverage'],
    browsers: ['PhantomJS', 'Chrome', 'Firefox', 'Safari'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    singleRun: false,
    concurrency: Infinity,
  })
}

Важно е да разберете какво се случва в конфигурационния файл на Karma:

basePath: '',
frameworks: ['mocha', 'requirejs', 'chai'],

basePath се използва за разрешаване на всички относителни пътища, дефинирани в свойствата на файловетеи изключва на конфигурацията.

files: [
    {pattern: 'config.js', included: true},
    {pattern: 'app/**/*.json', included: false},
    {pattern: 'app/**/*.html', included: false},
    {pattern: 'app/**/*.js', included: false},
    {pattern: 'libs/**/*.js', included: false},
    {pattern: 'unit-tests/**/*.js', included: false},
    {pattern: 'unit-tests/main.js', included: true}
],

файловеказва на Karma кои файлове да обслужва, когато стартира своя уеб сървър. Всички файлове, които трябва да бъдат импортирани, тествани или видени в какъвто и да е капацитет, трябва да бъдат включени тук. Файловите шаблони използват библиотеката minimatch — т.е. app/**/*.js ще включва всички файлове във всички поддиректории на директорията на приложението. Задайте included: true само за файлове, които трябва да бъдат включени като таг ‹script› или може да попаднете на грешки с RequireJS.

exclude: [
    './app/failure.js'
],

изключване ви позволява да посочите файлове, които не искате Karma да обслужва. Това е полезно, когато искате да използвате minimatch, за да включите цяла директория минус няколко изключителни файла.

preprocessors: {
    './app/**/*.js': 'coverage'
},
coverageReporter: {
    type : 'text-summary',
    dir : 'coverage/',
    includeAllSources : true
},
reporters: ['progress', 'junit', 'coverage'],

Тази част от конфигурацията е отговорна за отчитането и покритието на кода. Кодът, който трябва да се провери за покритие, е посочен в препроцесорите, а опциите за покритие могат да се променят в coverageReporter. След това желаният изходен формат се посочва в reporters (в този случай „напредък“ показва броя на изпълнените тестове, канали „junit“ резултатите в xml файл и 'coverage' регистрира обобщение на резултатите от покритието.

browsers: ['PhantomJS', 'Chrome', 'Firefox', 'Safari', 'Opera'],    
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
singleRun: true,
concurrency: Infinity,

В този пример браузърите, които тестваме, включват PhantomJS, Chrome, Firefox, Safari и Opera. Karma ще изпълнява уеб сървър на порт 9876. Цветоветев изходния журнал са активирани с logLevelна „информация“. Сървърът следи (autoWatch: true) за автоматични промени на файла. Всяко изпълнение ще тества всички браузъри едновременно (конкурентност: безкрайност) и ще завърши с излизане от всички браузъри/карма (singleRun: вярно).

RequireJS

По-голямата част от работата по настройването на RequireJS вече е свършена, ако сте следвали до този момент. Вече сме включили конфигурационния файл на RequireJS (вижте фрагмента по-долу) и Karma вече е конфигуриран да въвежда RequireJS като рамка.

files: [
    {pattern: './config.js', included: true},
    {pattern: 'unit-tests/main.js', included: true}
]

Трябва да се направи окончателна конфигурация, която ще направим във файла main.js.

var tests = [];
for (var file in window.__karma__.files) {
    if (/\_test\.js$/.test(file)) { tests.push(file); }
}
requirejs.config({
    baseUrl: '/base/app/',
    deps: tests,
    callback: mocha.run
});

Използваме малко regex и факта, че karma обслужва всичките си файлове в window.__karma__.files, за да посочим всичките си тестови файлове (които обозначаваме с _test). Извикването на mocha.run след актуализацията на requirejs.config() ще инициализира тестването!

Ако сте следвали всичко до сега, вие сте готови да започнете да пишете модулни тестове – просто ги маркирайте с „_test.js“. След като сте написали някои тестове, изпълнението им е толкова просто, колкото да напишете „karma start karma.conf.js“ в командния ред (може да се наложи да посочите път, ако не сте инсталирали karma глобално — „/node_modules/karma/ bin/karma start karma.conf.js”).

Приятно тестване!

Актуализация (18.11.2017 г.):

По заявка, ето как изглежда дървото на моите директории след настройка:

Това конкретно приложение е създадено с Backbone.js, така че имам папки, разделени по роля (т.е. администратор) и колекции/модели/изгледи. Няма значение къде поставяте main.js, стига да посочите правилния път в конфигурационния файл на Karma.

Ето как изглежда реалният тест:

Това е опростен тест на опорен изглед. Използваме куката mocha before(), за да инстанцираме изгледа (AddIpDlgView.js), да проверим дали е подклас на основния изглед и да тестваме валидността на няколко IP адреса с addIpDlgView.isValidIPv4(). Зависимостите се импортират с помощта на типичен синтаксис define().

След като започнете да пишете по-сложни модулни тестове, можете да добавяте шпиони, мъничета и подигравки с библиотека като Sinon.js.