js тестване. Тест за познаване на JavaScript – основи

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

Този процес трябва да включва набор от инструменти за контрол на качеството и ефективността за програмиста. Такива инструменти могат да бъдат: модулно и интеграционно тестване, непрекъсната интеграция (Continuous Integration, CI), събиране и анализ на различни показатели (например много дълги методи в nDepend), проверка за съответствие с изискванията на JsLint, FxCop и др.

В тази статия искам да ви кажа как правилно да извършвате автоматично тестване на единици и интеграция на вашия продукт в JavaScript. Всъщност JavaScript не се различава от Java или C# в това отношение.

Agile, TDD и BDD

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

Има и техники за програмиране, които изискват да започнете да кодирате логиката, като напишете единичен тест: Разработка, управлявана от тестове (TDD) и Разработка, управлявана от поведението (BDD). Те често се използват в Agile процеса. Нека разгледаме техните характеристики по-подробно.

Разработка, водена от тестове

Разработката, управлявана от тестове, е итеративен процес на кодиране, който повтаря следните четири стъпки:

Етап 1. Преди да добавите нова част от логиката, създайте единичен тест, за да тествате тази логика;

Стъпка 2. Пуснете теста и се уверете Непропуски;

Стъпка 3. Напишете най-простия код, който ще накара теста да премине;

Стъпка 4. Редактирайте кода според изискванията за качество, премахнете дублирането на код и се уверете, че тестът преминава.

Unit test е код, който тества работата на някакъв компонент (модул) в изолирана среда. Интеграционният тест е код, който тества съвместна работамножество компоненти. Двойните тестове се използват за тестване на модул в изолирана среда, когато зависи от други модули.

Тестови двойки

Разделянето на спомагателните обекти, използвани в модулното тестване, на категории произлиза от книгата xUnit Test Patterns от Gerard Meszaros. Тези категории се наричат ​​заедно "тестови двойни" (тестови двойни). Дублерите са от следните видове:

  • фалшив;
  • манекен.

мъниче изходни стойностиза които се задават предварително. Използва се за имитиране на интерфейса на зависим компонент.

Подигравкае помощен обект поведениекойто е зададен предварително. Използва се за имитиране на интерфейса на зависим компонент и проверка дали се използва правилно по време на теста.

Шпионине помощен обект за проверка на извиканите методи и параметри, предадени им по време на теста.

Фалшиве помощен обект, който имплементира интерфейса на зависим компонент в опростена форма. Например, за целите на тестването на модула, можете да имате база данни в паметта вместо релационната база данни, която се използва в производствената версия на продукта.

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

Разликата между Stub и Mock е как се проверяват резултатите от теста. В случая на Stub състоянието на обекта се проверява в края на теста. В случая на Mock, тестът проверява дали обектът се използва точно както е описано по време на регистрацията. Подробности можете да намерите в бележката Mocks Aren "t Stubs от Мартин Фаулър и тук ще дам само пример.

мъниче Подигравка
"test connect трябва да започне анкета": функция () ( this.client.url = "/my/url"; sinon.stub(ajax, "poll").returns(()); this.client.connect(); sinon.assert. calledWith(ajax.poll, "/my/url"); ) "test connect трябва да започне анкета": функция () ( this.client.url = "/my/url"; var mock = sinon.mock(ajax) mock.expects("poll") .withArgs("/my/url ").returns(()); this.client.connect(); mock.verify(); )

Развитие, водено от поведението

Итеративен подход към разработката софтуерчрез внедряване на функционални изисквания – това е вече познатият стил на разработка чрез тестове, фокусирана върху резултатите. Следните три стъпки се следват последователно в процеса на BDD:

Етап 1. Дефиниране на функционални изисквания към реализирания модул под формата на тестове;

Стъпка 2. Модулно кодиране;

Стъпка 3. Проверка дали всички желания на клиента или бизнес анализатор () са изпълнени чрез проверка на резултатите от текущите тестове.

Когато пишете тестове в стил BDD, е много удобно да използвате Mock обекти поради факта, че те перфектно отразяват функционалните изисквания към компонента. По този начин тестовете в BDD процеса могат да служат като формализирано представяне на задачата ( потребителска история) по отношение Scrum, което ви позволява да спестите време за писане на технически спецификации и документация за готовия продукт.

Каква трябва да бъде рамката за тестване на модули на JavaScript?

Цялата единица на JavaScript и инструментът за тестване на интеграция трябва да се състои от следните компоненти:

  • Assertion библиотека (набор от методи за проверка на състоянието на компонента в края на всеки тест);
  • Mock библиотека (инструмент за генериране на Mock обекти и други "подложки");
  • Тестов бегач (инструмент автоматично стартиранетестове с поддръжка за повечето браузъри, включително iOS и Android браузъри);
  • Блок за свързване към популярни системи за непрекъсната интеграция (Continuous Integration).

Стратегии за тестване на единици на JavaScript

Днес има три стратегии за модулно тестване на JavaScript код (за повече подробности вижте третата глава на книгата на Кристиан Йохансен Test-Driven JavaScript Development):

  • в браузъратестване;
  • без главатестване;
  • Тестване по пътя JsTestDriver.

Тестването в браузъра включва изпълнение на всички модулни и интеграционни тестове от HTML страница, която разработчикът отваря сам в необходимите браузъри. Този подход е прост и интуитивен. Неговият недостатък обаче е, че не предвижда възможност за включване на такива тестове в непрекъснатата интеграция. Освен това ръчното стартиране на HTML страница в десет или повече браузъра и непрекъснатото натискане на "F5" може да бъде досадно за програмиста.

Тестването без глава означава, че целият JavaScript код се тества на емулатор, който може да бъде написан на Java, Ruby, JavaScript, C++ и др. Най-известният емулатор досега е PhantomJS, който е a уебкит, стартиран от командна линия. Сред предимствата на емулатора може да се отбележи, че той може лесно да се използва при непрекъсната интеграция, както и че ви позволява да автоматизирате стартирането на всички тестове от командния ред. Този подход обаче има значителен недостатък - кодът не се тества на реални браузъри, така че съществува риск от пропускане на грешки в браузъра, които не се възпроизвеждат на емулатора. Преди появата на JsTestDriver често можехте да видите тестване в браузъра, комбинирано с тестване без глава, тъй като те се допълват толкова добре.

Тестването е неразделна част от цикъла на разработка на софтуер. Начинаещите екипи за разработка често подценяват неговата роля и проверяват ефективността на приложението по старомодния начин – „работи и това е добре“. Рано или късно тази стратегия се проваля и програмата за проследяване на грешки започва да затрупва безбройната армия от задачи. За да не попаднете в такъв капан, препоръчвам веднъж завинаги да се справите с нюансите на тестване на JavaScript код.

JavaScript вече не е торта!

Предполагам, че няма нужда да ви обяснявам, че днес JavaScript не е просто език, който да подправя нещата. външен видприложения. Но все пак ще обясня и ще направя малко въведение, защото тогава ще ми плащат повече повече пари! 🙂 И така, времената, когато JavaScript се използваше за шеги или правене на менюта, отминаха завинаги. Сега това е независим език, който работи еднакво добре както на клиента, така и на сървъра. Ролята на JavaScript се увеличи значително, което означава, че когато пишете код, не трябва да се притеснявате да използвате практики, които са се доказали в други езици за програмиране.

Какво имам предвид под практики и парадигми? Разбира се, MVC (model view controller) архитектурен модел и модели на организация на кода. Като следвате тези прости трикове, вие ще можете да напишете по-добър код, който не само ще бъде лесен за поддръжка, но и ще има способността да бъде автоматично тестван.

Правила за добри тестове

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

Грешката на повечето тестери

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

На практика всичко се случва малко по-различно. По правило няма отделен тестер. Самият разработчик се опитва да провери работоспособността на програмата, като изпълни последователността от действия, посочени в техническата задача. По-усъвършенстваните ковачници на код автоматизират този вид интеграционно тестване с инструменти като Selenium.

Така програмистът получава възможност да открие само най-грубите грешки. За съжаление, "глупави" и "непредвидени" потребителски действия, както и хитри ходове в бизнес логиката в 99% от случаите остават зад кулисите.

Наличието на отделен тестер също решава проблема частично и до определено време. Дори ако отхвърлим сапьорското му внимание към детайлите, качеството на тестването му ще клони към нула с нарастването на приложението. Ще дам пример от практиката.

Веднъж ми възложиха да разработя малка програма. По функционалност проектът приличаше на най-простия CRM, който внедрих в най-кратки срокове. След като получих дължимото възнаграждение, предадох всички източници на клиента и забравих за проекта за осем месеца. Тогава започна най-интересното. Клиентът реши да разшири сериозно функционалността на програмата и ме повика за помощ. Естествено, взех го и започнах да извайвам функция след функция... В началото не беше трудно, но когато се стигна до цялостната интеграция на функционалността, жужащ рояк бъгове се втурна към мен. Части от код започнаха да влизат в конфликт и трябваше да отделя много време за разрешаване на конфликти. „Е, как не видяхте, че има проблем с вашето приложение?“ ще попитат читателите. Ще отговоря: стартирах го, но поради факта, че приложението се разрасна, просто нямах време и нерви да тествам цялата функционалност масово. Ограничих се да тествам само отделни функции и щедро платих за това. Морал на историята: „Мислете за тестването като за неразделна част от развитието.“

Единичните тестове са като сребърен куршум

Unit тестването е най-добрият начин да си спестите нервите и да увеличите гаранциите, че отделните части от приложението ви ще работят. Ако никога не сте срещали този ужасен звяр, тогава ще обясня накратко. Единичните тестове ви позволяват да автоматизирате процеса на тестване и да изложите всяка функция на вашето приложение на тестове.

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

  • при предаване на низа "string" получаваме "string" като изход;
  • при предаване на термините "ред 9" на изхода получаваме "ред 9";

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

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

Тестове!= допълнителен код

Тестерите, които не са единици, обичат да твърдят, че тестването на единици изисква писане и поддържане допълнителен код. Казват, че крайните срокове в реалните проекти най-често са компресирани и просто не е възможно да се напише допълнителен код.

Когато няма време за тестове

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


Що се отнася до кратките срокове, съгласен съм, но съм готов да споря за частта от допълнителния код. От една страна, да – тестовете изискват допълнителен код, а оттам и време за написването му. От друга страна, този код играе ролята на въздушни възглавници в колата и определено ще се отплати с разрастването на приложението.
  • Cristian Johansen Test-Driven JavaScript Development (goo.gl/mE6Is) е една от малкото книги, които разглеждат JavaScript от гледна точка на писане на тестове.
  • John Resing, Beer Bibo JavaScript Ninja Secrets (goo.gl/xquDkJ) е добра книга, която ще бъде полезна предимно за средно напреднали JS разработчици. Книгата обсъжда подробно въпросите за писане на ефективен код за различни браузъри, нюансите на обработката на събития и много други екстри.
  • Дейвид Фланаган JavaScript. Пълно ръководство» (goo.gl/rZjjk) – Книгата е преиздавана шест пъти и всяко издание е бестселър. Наистина това е най подробно ръководствона JavaScript, който всеки JS разработчик трябва да прочете поне веднъж.
  • PhantomJS + JSCoverage + QUnit или конзолни JS модулни тестове с изчисляване на покритието (goo.gl/FyQ38) - авторът на статията демонстрира използването на куп от горните пакети за събиране на статистика и изчисляване на процента на покритие на кода от тестове.
  • Полезни случаи на използване на PhantomJS - Тази страница показва голям брой бойни употреби на PhantomJS.

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

Не целият код е тестван

Защо казвам, че трябва да помислите за тестване, преди да напишете основния код? Да, защото кодът, който първоначално трябва да бъде обхванат от модулни тестове, е написан в малко по-различен стил. Не всеки код може да бъде тестван. Код, който смесва логика и представяния и дори е натъпкан не разбирам къде, не може да бъде тестван нормално. Тук винаги ви съветвам да следвате няколко прости правила:

  • Няма нужда да пишете големи функции. Всяка функция трябва да решава един проблем, а не 100 500 възможни ситуации. Например, не е необходимо да затваряте кода за изпращане на данни към сървъра във функцията, която отговаря за подготовката им.
  • Функция с повече от десет реда код най-вероятно е лоша функция.
  • Логиката и представянето никога не трябва да вървят заедно.

QUnit - класика на жанра от създателите на jQuery

QUnit е особено популярен сред разработчиците на JavaScript. Първо, той е добре документиран и лесен за използване, и второ, направен е от авторите на jQuery. Библиотеката е подходяща за тестване както на jQuery-базиран, така и на собствен JavaScript код.


Изтегли последна версия QUnit можете от официалния сайт. Библиотеката идва като един JS и CSS файл. Да приемем, че сте разбрали как да заредите необходимите компоненти и ако е така, тогава е време да напишете пробен тест. Нека не отиваме далеч и да се опитаме да тестваме функцията trim().

За да демонстрирам тестовете, създадох прост проект със следната структура:

  • index.html - основният файл, който ще покаже резултатите от теста;
  • qunit-1.12.0.js - QUnit библиотечен файл;
  • example.js - файл, съдържащ кода за тестване (в нашия случай описанието на функцията trim());
  • test.js - файл с тестове;
  • qunit-1.12.0.css - стилове за проектиране на отчет с тестове.

Съдържанието на файла index.html и test.js е показано в листинги 1 и 2. Вторият списък, който ни интересува най-много, е декларацията на тестваната функция (trim()) и тестовия код, за да проверим дали тя работи . Моля, обърнете внимание, че самата функция trim() може да се намира навсякъде, поставих я във втория списък, само за да спестя място в дневника.
Сега нека да разгледаме самите тестове. Библиотеката QUnit.js ни предлага редица методи:

  • test() - обвивка за описание на теста;
  • ok() - твърдението ви позволява да проверите истинността на първия параметър. В нашия пример го предавам като извикване на функцията trim(), която дефинирахме, и го сравнявам със стойността, която очаквам да получа. Ако условието е вярно, тестът е преминат;
  • equal() - методът ви позволява да проверите равенството на първия и втория параметър. Забележете веднага, че този методизвършва нестриктна проверка, така че е подходящ само за скалари;
  • notEqual() е обратното на equal(). Изпълнява се, ако първата стойност не е равна на втората;
  • strictEqual() - подобно на equal() с една разлика - използва строга проверка (тоест проверява и типа данни);
  • notStrictEqual() - обратното на strictEqual();
  • deepEqual() - метод за рекурсивни изрази, използван за примитиви, масиви, обекти;
  • notDeepEqual() - обратното на deepEqual();
  • raises() е твърдение за тестване на функции за обратно извикване, които хвърлят изключение.

Във втория листинг ясно показах как да приложа тези методи на практика. Ако стартирате тестов случай в тази форма, тогава всички тестове ще бъдат преминати успешно (вижте съответната фигура). За да видя разликата между издържаните и неуспешните тестове, леко промених кода на един тест. Умишлено добавих грешен резултат към реда с теста, използвайки strictEqual() (вижте съответната фигура).

Листинг 1. Съдържание на файла index.html Тестване с QUnit



С тестване на прости функции изглежда разбрано. Във всеки случай нямам какво повече да добавя. След това трябва да вземете истинския код и да опитате сами да напишете тестове. Нека да разгледаме друга често срещана задача за разработчиците на JavaScript - тестване на асинхронни функции. Приложение, пълно с JavaScript код, взаимодейства 99% със сървърната страна, използвайки AJAX. Също така е невъзможно да оставите този код без тестване, но писането на тестове ще изглежда малко по-различно. Помислете за пример:

AsyncTest("myAsyncFunc()", функция () ( setTimeout(функция () ( ok(myAsyncFunc() == вярно, "Данните преминаха успешно"); start(); ), 500); ));

Основната разлика между този пример и предишния е, че asyncTest() се използва вместо обвивката test(), което директно заявява, че се интересувам от асинхронно тестване. След това стартирам таймаут от 500 милисекунди. През това време функцията myAsyncFunc() трябва да прехвърли данни към тестовия сървър и, ако всичко е наред, да върне true. Тук идва най-интересният момент. Когато се извика asyncTest(), нишката на изпълнение се спира и когато тестът приключи, той трябва да се стартира сам. За да контролира потока на изпълнение, QUnit предоставя методите start() и stop().


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

AsyncTest("myAsyncFunc()", функция () ( очаквам(3); // Направете три теста тук ok(myAsyncFunc(), "Да направим света по-добър 1"); ok(myAsyncFunc(), "Да направим света по-добър 2 ") ; ok(myAsyncFunc(), "Да направим света по-добро място 3"); setTimeout(function () ( start(); ), 3000); ));

Тествайте за персонализирани действия

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

Списък 3. Регистриране на натискания на клавиши функция KeyLogger(target) ( if (!(this instanceof KeyLogger)) ( return new KeyLogger(target); ) this.target = target; this.log = ; var self = this; this.target. off ("keydown").on("keydown", function(event) ( self.log.push(event.keyCode); )); )

Сега нека опитаме тази функция за тестване. На първо място, в тялото на теста трябва да емулираме натиснатия клавиш. Най-лесният начин да направите това е с библиотеката jQuery, която ви позволява да създадете събитие в няколко реда код (вижте списък 4).

Списък 4. Тестов код за KeyLogger test("Key recording test", function () ( var event, $doc = $(document), keys = KeyLogger($doc); event = $.Event("keydown"); event .keyCode = 9; $doc.trigger(event); equal(keys.log.length, 1, „Регистриран ключ“); равен(keys.log, 9, „Натиснат клавиш с регистриран код 9“); ));

В самото начало на списъка с теста подготвям събитие за емулиране на натискане на клавиш - "keydown". Ще се интересуваме от натискането на клавиша Tab (код 9). След това, използвайки метода trigger(), изпращам подготвеното събитие, след което мога да започна тестване. Първо проверяваме голямата картина - дали е натиснат клавиш и след това неговия код.

DOM под прикритието на тестове

Тъй като Qunit.js ви позволява да тествате персонализирани действия, писането на тестове за DOM също не би трябвало да е проблем. Това е вярно и примерът по-долу ще потвърди думите ми. Няма да го коментирам, просто погледнете кода и всичко ще стане ясно:

Test("Добавяне на нов div елемент", функция () ( var $fixture = $("#qunit-fixture"); $fixture.append("

Това е новият div
"); equal($("div", $fixture).length, 1, "Нов div добавен успешно!"); ));

PhantomJS - стартирайте тестове от конзолата


Писането на тестове с помощта на библиотеката QUnit.js е удобно и просто, но рано или късно ще бъдете посетени от желанието по някакъв начин да автоматизирате стартирането, тестването и събирането на резултати. Например имам отделна виртуална машина в DigitalOcean за този бизнес, която мога да управлявам само с помощта на конзолата.

Проектът PhantomJS решава този проблем достатъчно елегантно. Това не е просто още една рамка за писане на модулни тестове, а пълноценна конзолна версия на двигателя WebKit. Казано по-просто, това приложение емулира браузър. С помощта на PhantomJS наистина не е само да се автоматизира проверката на изпълнението на теста, но и да се решат много задачи, които рано или късно възникват пред разработчика: получаване на резултатите от рендиране на страници във файл (PNG, JPG), функции за наблюдение на мрежата (скорост на зареждане, обща производителност и т.н.), емулация на потребителски действия и т.н. Препоръчвам да не бъдете мързеливи и да прочетете официалната документация по този проект, определено ще намерите нещо интересно за себе си.

PhantomJS може да се компилира за различни платформи (*nix, OS X, Windows). Ако разработвате всичко под Windows, тогава няма проблеми - обединете двоичните файлове и давайте. Могат да възникнат малки затруднения при стартирането, ако имате инсталирани два видео адаптера, единият от които е NVIDIA. В този случай ще трябва да използвате хака, описан в страничната лента.


Нека се опитаме да се запознаем с PhantomJS на практика. За да стартираме тестовете, подготвени в последния раздел, чрез PhantomJS и да получим резултатите от изпълнението в конзолата, ни е необходим специален скрипт за зареждане - run-qunit.js. Отворете конзолата (работя с Windows, така че използвам cmd) и въведете командата във формата

phantom.exe<путь к run-qunit.js> <путь к странице с тестами>

В моя случай командата за стартиране се оказа така:

E:\soft\phantomjs>phantomjs.exe E:\temp\testjsforx\qunit\run-qunit.js файл:///E: /temp/testjsforx/qunit/index.html

Резултатът от неговото изпълнение:

Тестовете са завършени за 2592 милисекунди. 9 твърдения от 9 издържани, 0 неуспешни.

Всички тестове преминаха

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

Проблеми с PhantomJS в Windows

Просто така се случи, но тествах всички примери за тази статия не на Linux, а под добрия стар Windows 7. Оказва се, че PhantomJS има някои проблеми при работа на системи, които използват няколко видео адаптера. На моя лаптоп освен вградения видео чип виси и NVIDIA и поради това PhantomJS категорично отказа да отговори на командата phantom.exit (). В резултат на това, след като скриптът беше изпълнен, процесът PhantomJS не приключи работата си и продължи да виси в паметта. Прозорецът на терминала също спря да отговаря на команди за изход ( не помогна).

Ако сте изправени пред подобен проблем и планирате да използвате PhantomJS на Windows, тогава се пригответе да направите следния хак. отворен панел NVIDIA управление. Намерете елемента "3D настройки" в дървото. От дясната страна опцията „Предпочитан графичен адаптер". По подразбиране. стойността му е зададена на Autoselect. Трябва да го променим на „Високопроизводителен NVIDIA процесор“ или „Интегриран графичен хардуер“. След този прост трик PhantomJS започна да се държи послушно.

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

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

С течение на времето проектът се попълва с нови функционалност, което удължава и усложнява процеса на проверка на работата му. Единичното тестване се използва за автоматизация.

Има 2 подхода за изграждане на тестови сценарии:

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

Какво да тествам

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

Като цяло е изключително важно да се оценят разходите за тестване спрямо времето за разработка. Разбира се, ако не сте ограничени във времето, можете да оставите всяка функция да бъде покрита с тестове. Но като правило разработката се извършва в кратки срокове, така че задачата на анализатор или опитен разработчик е да разбере къде е необходимо тестване. Освен това писането на тестове оскъпява проекта.

Така можем да формулираме 3 случая, когато използването на модулно тестване е оправдано:

1) Ако тестовете позволяват да се идентифицират грешките по-бързо, отколкото при обичайното им търсене.

2) Намалете времето за отстраняване на грешки

3) Позволява ви да тествате често променян код.

От 3-те основни компонента на интерфейса (HTML, CSS, JavaScript), може би само JavaScript кодът трябва да бъде тестван. CSS се валидира само визуално, когато програмист/тестер/клиент гледа GUIв различни браузъри. HTML - маркирането се проверява по същия метод.

Как да тествам

Когато проектирате тестови сценарии, трябва да се ръководите от следните принципи:

  • Вашите тестове трябва да са възможно най-прости.Тогава ще бъде по-вероятно грешката, която се опитвате да повторите, да повлияе на резултатите от внедряването й.
  • Декомпозирайте тестове на големи модули. Grove, за да намерите конкретното местоположение на грешката.
  • Направете тестовете независими.Резултатът от един тест в никакъв случай не трябва да зависи от резултатите от друг.
  • Резултатите от теста трябва да бъдат напълно повторими и очаквани.Всеки път, когато стартирате теста отново, резултатът трябва да е същият като последния път.
  • За всяка грешка в изпълнението на приложението трябва да се създаде тестов скрипт.По този начин ще сте сигурни, че грешката наистина е отстранена и не се показва на потребителите.

Как да тествам

Има няколко библиотеки за модулно тестване на js код. Може би най-често срещаният е QUnit. За да проведем модулни тестове с помощта на тази библиотека, трябва да създадем "sandbox" - проста html страница, в която ще бъде свързана библиотеката за тестване, кодът за тестване и самите тестове.

Функции за тестове:

(function() ( window.stepen = function(int) ( var result = 2; for (var i = 1; i< int; i ++) { result = result * 2; } return result; } window.returnFunc = function() { return "ok"; } })();

Списък с тестове:

Test("stepen()", function() ( equal(stepen(2), 4, "2^2 - метод равен"); ok(stepen(3) === 8, "2^3 - метод OK" ); deepEqual(stepen(5), 32, "2^5 - метод deepEqual"); )); asyncTest("returnFunc()", function() ( setTimeout(function() ( equal(returnFunc(), "ok", "Async Func Test"); start(); ), 1000); ));

Както можете да видите, QUnit поддържа 3 функции за сравняване на резултатите от изпълнението на кода с очаквания:

  • Добре()- счита теста за успешен, ако върнатият резултат е верен
  • равен()- сравнява резултата с очаквания
  • deepEqual()- сравнява резултата с очаквания, като проверява вида му

Резултат от изпълнението:

Както можете да видите, библиотеката QUnit тества кода за няколко браузъра едновременно.

Има редица други библиотеки за модулни тестове. Концепцията за изграждане на тестови скриптове в тях обаче е една и съща, така че след като се справите с един, няма да ви е трудно да преминете към друг.

Важно е да запомните

Характеристика на съвременния js код е асинхронността на неговото изпълнение. Библиотеките за тестване обикновено имат способността да провеждат асинхронни тестове. Но например, ако се опитвате да тествате функция, която, да речем, изпраща заявка за получаване до бекенда и връща отговор от нея, тогава, за да проведете тестове, ще трябва да спрете нишката с функцията stop(), стартирайте функцията, която се тества, и след това рестартирайте нишката с метода start(), като я „опаковате“ в setTimeout(). Тези. трябва да зададете някакъв интервал от време, през който да приключи изпълнението на функцията. Трябва внимателно да изберете продължителността на този сегмент, .k. от една страна, дългата работа на метода може да бъде или функция, или дори необходимост за конкретна реализация на функционалността на приложението, или неправилно поведение.

Тестване на Backbone приложения

За пример за тестване на приложения, написани с Backbone.js, ще използваме проекта, описан в .

Можете да проверите с модулни тестове:

  • Коректност на създаването на модели и контролери
  • Коректност на данните в моделите
  • Изпълнение на методи на контролера (за това те трябва да върнат резултат)
  • Вижте успешно зареждане

Тестови код:

Test("Backbone.js", function() ( ok(sample, "Проверка на пространство от имена"); ok(sample.routers.app, "Router check"); ok(sample.core.pageManager.open("chat") , "Тест за отваряне на страница (извикване на метод на контролера)") ok(sample.core.state, "Model check"); equal(sample.core.state.get("content"), "sintel", "Model data get test "); stop(); ok(function() ( $.ajax(( url: "app/templates/about.tpl", dataType: "text" )).done(function(data) ( self.$el. html(данни); върнати данни; )) ), "Проверка за зареждане на шаблон"); setTimeout(функция() ( начало(); ), 1000); ));

Резултатът от работата с грешки при тестване:

Автоматизация на пробното пускане

Обикновено внедряването на приложение е задача, която трябва да се извършва доста често по време на интензивно развитие. Следователно тази операция обикновено е автоматизирана. Ние използваме Jenkins, инструмент за непрекъсната интеграция, в нашата работа. Идеята е да се комбинира внедряването чрез Jenkins с автоматизирани тестове.

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

/** * Изчакайте, докато тестовото условие е вярно или настъпи таймаут. * Полезно за изчакване * на отговор на сървъра или за промяна на потребителския интерфейс (fadeIn и т.н.). * * @param testFx javascript условие, което се оценява на булево, * може да бъде предадено като низ (напр.: "1 == 1" или * "$("#bar").is(":visible")" или * като функция за обратно извикване. (":visible")" или * като функция за обратно извикване. * @param timeOutMillis е максималното време за изчакване. Ако не е * посочено, се използват 3 сек. */ функция waitFor(testFx, onReady, timeOutMillis) ( var maxtimeOutMillis = timeOutMillis - timeOutMillis: 3001, //< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code } else { if(!condition) { // If condition still not fulfilled // (timeout but condition is "false") console.log(""waitFor()" timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is //"true") console.log(""waitFor()" finished in " + (new Date().getTime() - start) + "ms."); typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it"s supposed to do once the // condition is fulfilled clearInterval(interval); //< Stop this interval } } }, 100); // repeat check every 250ms }; }; if (phantom.args.length === 0 || phantom.args.length >2) console.log("Използване: run-qunit.js URL"); phantom.exit(); ) var page = new WebPage(); // Насочване на извикванията на "console.log()" от // контекста на страницата към основния контекст на Phantom (т.е. текущата страница "this").onConsoleMessage = function(msg) ( console.log(msg); ); page.open(phantom.args, function(status)( if (status !== "success") ( console.log("Невъзможен достъп до мрежата"); phantom.exit(); ) else ( waitFor(function() ( return page.evaluate(function()( var el = document.getElementById("qunit-testresult"); if (el && el.innerText.match("completed")) ( return true; ) return false; )); ), function()( var failedNum = page.evaluate(function()( var el = document.getElementById("qunit-testresult"); console.log(el.innerText); try ( return document.getElementsByClassName("fail" ).innerHTML.length;) catch (e) ( return 0; ) return 10000; )); phantom.exit((parseInt(failedNum, 10) > 0) ? 1: 0); )); ) ));

За да показвате съобщения за резултати в конзолата, трябва да добавите функцията за регистриране към тестовия скрипт.

Сега сайтът е достъпен за тестване на знания по следните теми: HTML, css, JavaScript, PHP, SQL.

Всеки тест се състои от 10въпроси по конкретна тема. Във всеки въпрос се опитах да засегна най-разнообразните области на приложение на даден език, за да проверя възможно най-задълбочено нивото на вашите знания.

Разбира се всичко тестовете са безплатнии всеки може да мине.

Процедура на изпитване:

  1. Следвайте връзката " Започнете да тествате“ на съответния тест.
  2. Отговорете на въпросите, като изберете единственияправилен вариант.
  3. След завършване на тестването ще видите твоят резултат, брой грешки, и анализ на всеки въпросот теста.

внимание!Връщането към предишния въпрос няма да работи, така че преди да отговорите, помислете.

В момента налични тестове

  1. HTML

    • Общо преминат тест: 75424 души
    • Среден резултат: 2,83 от 5точки.

    Проверка на основните знания HTML. Ще трябва да знаете основни HTML таговеи тяхното правилно използване. Също така е необходимо да се разберат характеристиките на стандарта XHTML 1.1.

  2. css

    • Общо преминат тест: 32828 души
    • Среден резултат: 3,37 от 5точки.

    Тестът проверява познанията по осн css. За да преминете успешно теста, трябва да знаете основните типове селектори (техния синтаксис), да знаете основните свойства и техните възможни стойности, както и да знаете предназначението на най-популярните псевдоелементи.

  3. JavaScript

    • Общо преминат тест: 24845 души
    • Среден резултат: 3,31 от 5точки.

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

  4. PHP

    • Общо преминат тест: 33 239 души
    • Среден резултат: 3,03 от 5точки.

    Този тест тества знанията ви по езика PHP. От вас се изисква да знаете основни PHP конструкции, да работите с променливи, сесии, имплементация на пренасочване и други стандартни неща.
    Убедителна молба:Тестът съдържа много въпроси като: "Какво ще изведе скриптът?". Голяма молба, не копирайте и проверете. Бъдете честни със себе си.

  5. SQL

    • Общо преминат тест: 18014 души
    • Среден резултат: 3,28 от 5точки.

    Този тест тества знанията ви по езика SQL заявки. Въпросите обхващат само най-основните познания по този език, без никакво задълбочаване. Ще ви трябват познания за най-основните SQL заявки, както и компетентното им използване.

На примера на просто приложение за калкулатор на Node.js. Ще тестваме с помощта на рамката Mocha.

Какво трябва да може да прави нашето приложение:

  • Събиране, изваждане, деление и умножение на произволни две числа;
  • Показване на предупреждение и изход, ако е въведено нещо различно от число;
  • Трябва да има и интерфейс на командния ред, така че крайният потребител да може да използва приложението.

Какво ни трябва:

  • Node.js и npm
  • Познания по JavaScript: синтаксис и структура на кода, типове данни, математически операции и условни изрази.

След като целите са подредени, можете да започнете да настройвате средата за тестване и разработка.

Настройка на средата

Тъй като използваме Node.js, трябва да създадем локална среда за файлове и зависимости.

Създавайте нова папка калк. От командния ред преминете към тази директория и създайте нов проект с npm init, който ще създаде нов файл package.jsonза нашата програма.

Ще бъдете подканени да въведете името на пакета, версията, описанието и друга информация за пакета. Можете да въведете име calc.jsи продължете да натискате Въведетеза задаване на стойности по подразбиране. Когато стигнете до test command, въведете mocha - това е тестовата рамка, която ще използваме:

тестова команда: мока

След като въведете цялата информация, скриптът ще създаде файл package.json, което изглежда по следния начин:

( "name": "calc.js", "version": "1.0.0", "description": "Прост калкулатор в Node.js", "main": "index.js", "scripts": ( " тест": "мока"), "автор": "", "лиценз": "ISC")

Последната стъпка в тази стъпка е инсталирането на Mocha. Въведете следната команда за инсталиране:

npm install --save-dev mocha

След прилагане на тази команда ще се появи папка node_modules, файл package-lock.json, и във файла package.jsonще се появят следните редове:

"devDependencies": ( "mocha": "^4.0.1")

Създайте файл test.js. Ще използваме вградения модул в Node.js твърдятза да проверите дали истината и истината са верни. Тъй като е вярно, тестът трябва да премине:

Const assert = require("assert"); it("трябва да върне true", () => ( assert.equal(true, true); ));

Сега стартирайте теста от командния ред:

$ npm test > mocha ✓ трябва да върне true 1 преминаване (8ms)

Тестът премина според очакванията, така че настройката на средата е готова. Премахни от test.jsвсичко освен реда const assert = require("assert"); .

Ще използваме файла test.jsпрез целия процес на разработка на приложение. Създайте още два файла: операции.jsза аритметични и валидиращи функции и calc.jsза самото приложение. Използваме толкова много файлове, че не стават твърде дълги и сложни. Ето текущия ни списък с файлове:

  • calc.js;
  • node_modules;
  • операции.js;
  • package-lock.json;
  • package.json;
  • test.js;

Нека добавим първото истински тестза нашето приложение.

Добавяне на математически операции

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

Да започнем с добавянето. Ще напишем тест, който уникално получава очакваната сума от две числа. В кода по-долу проверяваме дали сумата от 1 и 3 е равна с помощта на функцията add() 4:

Const assert = require("assert"); it("намира правилно сумата от 1 и 3", () => ( assert.equal(add(1, 3), 4); ));

След като стартираме теста с командата npm test, виждаме следното:

> mocha 0 преминаване (9ms) 1 неуспешно 1) намира сумата от 1 и 3 правилно: ReferenceError: add не е дефинирано в Context.it (test.js:5:16) npm ГРЕШКА! тестът е неуспешен. Вижте по-горе за повече подробности.

Тестът е неуспешен с ReferenceError: добавянето не е дефинирано. Тестваме функцията add(), която все още не съществува, така че този резултат е съвсем очакван.

Нека създадем функция add() във файл операции.js:

Const add = (x, y) => (+x) + (+y);

Тази функция приема два аргумента x и y и връща тяхната сума. Може би сте забелязали, че пишем (+x) + (+y) вместо x + y. Използваме унарния оператор, за да преведем аргумента към число, в случай че входът е низ.

Забележка: Това използва добавена от ES6 функция със стрелка и имплицитно връщане.

Тъй като използваме Node.js и разделяме кода на няколко файла, трябва да използваме module.exports, за да експортираме кода:

Const add = (x, y) => (+x) + (+y); module.exports = (добавяне)

В началото на файла test.jsимпортираме код от операции.jsс require(). Тъй като използваме функцията чрез променливата на operations, трябва да променим add() на operations.add():

Константни операции = изискват ("./operations.js"); const assert = require("assert"); it("намира правилно сумата от 1 и 3", () => ( assert.equal(operations.add(1, 3), 4); ));

Нека проведем теста:

$ npm test > mocha ✓ намира правилно сумата от 1 и 3 1 преминаване (8ms)

Вече имаме работеща функция и тестовете преминават успешно. Тъй като функциите на другите операции работят по подобен начин, добавянето на тестове за subtract(), multiply() и divide() е лесно:

It("намира правилно сумата от 1 и 3", () => ( assert.equal(operations.add(1, 3), 4); )); it("намира правилно сумата от -1 и -1", () => ( assert.equal(operations.add(-1, -1), -2); )); it("намира правилно разликата между 33 и 3", () => ( assert.equal(operations.subtract(33, 3), 30); )); it("правилно намира произведението на 12 и 12", () => ( assert.equal(operations.multiply(12, 12), 144); )); it("намира правилно частното от 10 и 2", () => ( assert.equal(operations.divide(10, 2), 5); ));

Сега нека създадем и експортираме всички функции в test.js:

Const add = (x, y) => (+x) + (+y); const изваждане = (x, y) => (+x) - (+y); const умножение = (x, y) => (+x) * (+y); const разделяне = (x, y) => (+x) / (+y); module.exports = (събиране, изваждане, умножение, деление, )

И изпълнете нови тестове:

$ npm test > mocha ✓ намира правилно сбора от 1 и 3 ✓ намира правилно сбора от -1 и -1 ✓ намира правилно разликата между 33 и 3 ✓ намира правилно произведението на 12 и 12 ✓ намира правилно частното от 10 и 2 5 преминаване (8ms)

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

Добавяне на валидиране

В момента, когато потребителят въведе номер и избере желаната операция, всичко работи добре. Но какво се случва, ако се опитате да намерите сбора на число и низ? Приложението ще се опита да изпълни операцията, но тъй като очаква число, ще върне NaN.

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

Първо трябва да напишете функция, която ще проверява дали въведеното е число или не. Приложението трябва да работи само с числа, така че ще се справим с три ситуации:

  1. И двата входа са числа.
  2. Единият вход е число, а другият е низ.
  3. И двата входа са низове.
it("отчита грешка при използване на низ вместо число", () => ( assert.equal(operations.validateNumbers("sammy", 5), false); )); it("отчита грешка при използване на два низа вместо числа", () => ( assert.equal(operations.validateNumbers("sammy", "sammy"), false); )); it("успех при използване на две числа", () => ( assert.equal(operations.validateNumbers(5, 5), true); ));

Функцията validateNumbers() ще потвърди и двата параметъра. Функцията isNaN() проверява дали параметърът не е число и ако не е, връща false. В противен случай връща true, което означава успешно валидиране.

Const validateNumbers = (x, y) => ( if (isNaN(x) && isNaN(y)) ( return false; ) return true; )

Не забравяйте да добавите validateNumbers към module.exports в края на файла. Сега можете да стартирате нови тестове:

$ npm тест 1) съобщава за грешка при използване на низ вместо число ✓ съобщава за грешка при използване на два низа вместо числа ✓ успех при използване на две числа 7 преминаване (12ms) 1 неуспешно 1) съобщава за грешка при използване на низ вместо това на число: AssertionError : true == false + очаквано - действително -true + false

Два теста преминаха успешно, но единият се провали. Тестът за две числа беше успешен, както и тестът за два низа. Какво не може да се каже за проверка за въвеждане на низ и число.

Ако погледнем нашата функция отново, можем да видим това и дветепараметрите трябва да са NaN, за да може функцията да върне false. Ако искаме да постигнем същия ефект, когато поне един от параметрите е NaN, трябва да заменим && с || :

Const validateNumbers = (x, y) => ( if (isNaN(x) || isNaN(y)) ( return false; ) return true; )

Ако стартирате npm тест отново след тези промени, всички тестове ще преминат:

✓ съобщава за грешка при използване на низ вместо число ✓ съобщава за грешка при използване на два низа вместо числа ✓ успех при използване на две числа 8 преминаване (9ms)

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

Създаване на интерфейс

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

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

Константни операции = изискват ("./operations.js");

Самият интерфейс ще използва вградения в Node.js Readline CLI модул:

Const readline = изискване ("readline");

След като импортирате всичко необходимо, можете да започнете да създавате приложението. За да създадем интерфейса, ще използваме readline, достъпен чрез променливата rl:

Const rl = readline.createInterface(( input: process.stdin, output: process.stdout ));

Първото нещо, което потребителят трябва да види след стартиране на програмата, е приветствено съобщение и инструкции за употреба. За да направим това, ще използваме console.log() :

Console.log(` Calc.js Отворихте Node.js калкулатор! Версия: 1.0.0. Употреба: потребителят трябва да въведе две числа и след това да избере какво да прави с тях. `);

Преди да навлезем в самите функции на калкулатора, нека проверим дали console.log() работи както трябва. Ще накараме програмата да отпечата съобщение и да излезе. За да направите това, добавете извикване към метода rl.close() в края.

За да стартирате приложението, въведете възел, последван от име на файл:

$ node calc.js Calc.js Отворихте калкулатора Node.js! Версия: 1.0.0. Употреба: Потребителят трябва да въведе две числа и след това да избере какво да прави с тях.

Програмата показва поздравително съобщение и излиза. Сега трябва да добавим потребителско въвеждане. От потребителя се изисква да избере два номера и една операция. Всеки вход ще бъде поискан от метода rl.question():

Rl.question("Въведете първото число: ", (x) => ( rl.question("Въведете второто число: ", (y) => ( rl.question(` Изберете една от следните операции: Добавяне ( +) Изваждане (-) Умножение (*) Деление (/) Вашият избор: `, (избор) => ( // повече код ще се появи тук rl.close(); )); )); ));

На променливата x се присвоява първото число, y второто, а изборът е избраната операция. Сега нашата програма иска въвеждане, но не прави нищо с получените данни.

След третото въвеждане трябва да проверите дали са въведени само числа. За да направим това, ще използваме функцията validateNumbers(). Използвайки оператора NOT, ще проверим дали са въведени числа и ако не, ще излезем от програмата:

If (!operations.validateNumbers(x, y)) ( console.log("Разрешени са само числа! Моля, рестартирайте програмата."); )

Ако всичко е въведено правилно, сега трябва да стартирате съответния метод на операция, създаден по-рано. За да обработим четирите възможни избора, ще използваме оператор switch и ще изведем резултата от операцията. Ако е избрана несъществуваща операция, блокът по подразбиране ще бъде изпълнен, казвайки на потребителя да опита отново:

If (!operations.validateNumbers(x, y)) ( console.log("Могат да се въвеждат само числа! Моля, рестартирайте програмата."); ) else ( switch (choice) ( case "1": console.log(` Сумата $(x) и $(y) е равна на $(operations.add(x, y)).`); прекъсване; случай "2": console.log(`Разликата на $(x) и $(y) е равна $(operations.subtract(x, y)).`); break; case "3": console.log(`Произведението от $(x) и $(y) е равно на $(operations.multiply(x, y) ).`) ; прекъсване; случай "4": console.log(`Private $(x) и $(y) е равно на $(operations.divide(x, y)).`); прекъсване; по подразбиране: console.log ("Моля, рестартирайте програмата и изберете число между 1 и 4."); break; ) )

Забележка Функциите console.log() тук използват шаблонни низове, които позволяват изрази.

/** * Прост Node.js калкулатор, който използва приложението за калкулатор, което използва * вградения интерфейс на командния ред Readline. */ const operations = require("./operations.js"); const readline = изискване ("readline"); // Използвайте readline за създаване на интерфейс const rl = readline.createInterface(( input: process.stdin, output: process.stdout )); console.log(` Calc.js Отворихте Node.js калкулатор! Версия: 1.0.0. Употреба: Потребителят трябва да въведе две числа и след това да избере какво да прави с тях. `); rl.question("Въведете първото число: ", (x) => ( rl.question("Въведете второто число: ", (y) => ( rl.question(` Изберете една от следните операции: Добавяне ( +) Изваждане (-) Умножение (*) Деление (/) Вашият избор: `, (избор) => ( if (!operations.validateNumbers(x, y)) ( console.log("Можете да въвеждате само числа! Моля рестартирайте програмата. "); ) else ( switch (choice) ( case "1": console.log(`Сумата от $(x) и $(y) е равна на $(operations.add(x, y)). `); break; case "2": console.log(`Разликата между $(x) и $(y) е $(operations.subtract(x, y)).`); break; case "3": console.log(`Произведението на $( x) и $(y) е равно на $(operations.multiply(x, y)).`); прекъсване; case "4": console.log(`Private $(x) и $(y) е равно на $(operations. divide(x, y)).`); break; default: console.log("Моля, рестартирайте програмата и изберете число между 1 и 4."); break; ) ) rl.close(); )); )) ; ));

Сега нашето приложение е готово. Нека накрая да проверим работата му. Въведете 999 и 1 и изберете операцията за изваждане:

$ node calc.js Въведете първото число: 999 Въведете второто число: 1 Вашият избор: 2 Разликата между 999 и 1 е 998.

Програмата успешно приключи работата си, показвайки правилния резултат. Поздравления, написахте прост калкулатор с помощта на Node.js и научихте основите на разработката на TDD.



Зареждане...
Връх