Jedinično testiranje JavaScript koda: strategije, biblioteke, alati. JavaScript testovi i njihova automatizacija Testovi, svrha i upotreba javascripta

Kreiranje efikasnih test slučajeva može biti izuzetno važno za velike projekte, u kojima se ponašanje dijelova aplikacije može promijeniti iz različitih razloga. Možda je najčešći problem kada velika grupa programera radi na istim ili srodnim modulima. To može dovesti do neplaniranih promjena u ponašanju funkcija koje su napisali drugi programeri. Ili rad u kratkim rokovima dovodi do nenamjernih promjena kritičnih dijelova aplikacije.

Testiranje web aplikacije obično uključuje vizualnu procjenu elemenata stranice i empirijsko procjenu funkcionalnosti funkcionalnosti. Drugim riječima, u kretanju kroz sekcije i izvođenju radnji na dinamičkim elementima.

Vremenom se projekat puni novim funkcionalnostima, što produžava i otežava proces provjere njegovog rada. Za automatizaciju se koristi jedinično testiranje.

Postoje 2 pristupa za izradu testnih scenarija:

  • Whitebox Testing – pisanje testova se zasniva na implementaciji funkcionalnosti. One. Provjeravamo koristeći iste algoritme na kojima se zasniva rad naših sistemskih modula. Ovaj pristup ne garantuje ispravan rad sistema u celini.
  • Blackbox Testing – kreiranje skripte se zasniva na sistemskim specifikacijama i zahtjevima. Na taj način možete provjeriti ispravnost rezultata cijele aplikacije, ali ovaj pristup vam ne dozvoljava da uhvatite male i rijetke greške.
Šta testirati

Možda se čini da je vrijedno testirati svaku funkciju koju implementirate. Ovo nije sasvim tačno. Pisanje testova oduzima vreme programeru, pa je za optimizaciju procesa kreiranja aplikacije vredi pripremiti testove samo za složene, kritične funkcije ili za one funkcije koje zavise od rezultata drugih sistemskih modula. Pokrijte dvosmislenu logiku testovima koji potencijalno mogu uzrokovati greške. Također je vrijedno kreirati testove za one dijelove koda koji se planiraju optimizirati u budućnosti, tako da nakon procesa optimizacije možete provjeriti da li su ispravno izvršeni.

Općenito, izuzetno je važno procijeniti troškove testiranja u odnosu na skučenost razvojnih rokova. Naravno, ako niste vremenski ograničeni, možete dozvoliti da svaka funkcija bude pokrivena testovima. Ali u pravilu se razvoj odvija pod kratkim vremenskim pritiskom, tako da je zadatak analitičara ili iskusnog programera razumjeti gdje je testiranje potrebno. Osim toga, pisanje testova povećava cijenu projekta.

Dakle, možemo formulirati 3 slučaja kada je korištenje jediničnog testiranja opravdano:

1) Ako testovi omogućavaju da se greške identifikuju brže nego kada ih se normalno traži.

2) Smanjite vrijeme otklanjanja grešaka

3) Omogućava vam testiranje često mijenjanog koda.

Od 3 glavne komponente frontenda (HTML, CSS, JavaScript), možda samo JavaScript kod treba da se testira. CSS se testira isključivo vizuelno, gde programer/tester/kupac pregledava GUI u različitim pretraživačima. HTML oznake se provjeravaju korištenjem iste metode.

Kako testirati

Prilikom izrade testnih scenarija, trebali biste se voditi sljedećim principima:

  • Vaši testovi bi trebali biti što jednostavniji.
  • Tada će postojati veća vjerovatnoća da će na rezultate njegove implementacije utjecati upravo bug koji pokušavate ponoviti.
  • Dekomponujte velike jedinične testove.
  • Bolje je pronaći konkretnu lokaciju greške.
  • Učinite testove nezavisnim.
Rezultat jednog testa ni na koji način ne bi trebao ovisiti o rezultatima drugog.

Rezultati testa moraju biti potpuno ponovljivi i očekivani. Svaki put kada ponovo pokrenete test, rezultat bi trebao biti isti kao i prošli put.

Za bilo kakvu grešku u izvršavanju aplikacije, test skripta mora biti kreirana. Na ovaj način ćete biti sigurni da je greška zaista ispravljena i da se ne pojavljuje korisnicima.

Šta testirati< int; i ++) { result = result * 2; } return result; } window.returnFunc = function() { return "ok"; } })();

Postoji nekoliko biblioteka za jedinično testiranje js koda. Možda je najčešći QUnit. Za provođenje jediničnih testova koristeći ovu biblioteku, morat ćemo kreirati „pješčanik“ - jednostavnu html stranicu u koju će biti povezana biblioteka za testiranje, kod koji treba testirati i sami testovi.

Test("stepen()", function() (jednako(stepen(2), 4, "2^2 - jednaka metoda"); ok(stepen(3) === 8, "2^3 - ok metoda" deepEqual(stepen(5), 32, "2^5 - deepEqual method"); asyncTest("returnFunc()", function() ( setTimeout(function() (jednako(returnFunc(), "ok", "Async Func Test"); start(); ), 1000); ));

Kao što vidite, QUnit podržava 3 funkcije za poređenje rezultata izvršenja koda sa očekivanim:

  • ok() – smatra da je test uspješan ako je vraćeni rezultat = istina
  • equal() – upoređuje rezultat sa očekivanim
  • deepEqual() – upoređuje rezultat sa očekivanim, provjerava njegov tip

Rezultat izvršenja:

Kao što vidite, biblioteka QUnit testira kod za nekoliko pretraživača odjednom.

Dostupne su brojne druge biblioteke jediničnih testova. Međutim, koncept izrade testnih scenarija u njima je isti, tako da kada jednom shvatite, neće vam biti teško da se prebacite na drugi.

Važno je zapamtiti

Karakteristika modernog js koda je njegovo asinhrono izvršavanje. Biblioteke za testiranje obično imaju mogućnost izvođenja asinhronih testova. Ali, na primjer, ako pokušavate testirati funkciju koja, recimo, šalje zahtjev za dobivanje na pozadinu i vraća odgovor od nje, tada ćete za izvođenje testova morati zaustaviti nit pomoću stop() funkcije, pokrenuti funkciju koja se testira, a zatim ponovo pokrenite nit metodom start(), "umotavajući je" u setTimeout(). One. morate postaviti određeni vremenski period tokom kojeg funkcija treba da završi izvršenje. Potrebno je pažljivo odabrati trajanje ovog segmenta. S jedne strane dug rad metoda može biti ili karakteristika ili čak potreba za specifičnom implementacijom funkcionalnosti aplikacije ili pogrešno ponašanje.

Testiranje Backbone aplikacija

Za primjer testiranja aplikacija napisanih pomoću Backbone.js, koristit ćemo projekt opisan u.

Možete koristiti jedinične testove da provjerite:

  • Ispravno kreiranje modela i kontrolera
  • Ispravnost podataka u modelima
  • Izvršavanje metoda kontrolera (za to moraju vratiti rezultat)
  • Učitavanje pregleda uspješno

Test kod:

Test("Backbone.js", function() (ok(uzorak, "Provjera prostora imena"); ok(sample.routers.app, "Provjera rutera"); ok(sample.core.pageManager.open("chat") , "Test otvaranja stranice (poziv metode kontrolera)") ok(sample.core.state, "Provjera modela" jednako(sample.core.state.get("content"), "sintel", "Model data get test " " stop() ( $.ajax(( url: "app/templates/about.tpl", dataType: "text")).done(function(data) (self.$el); html(podaci vraćaju se ))), "Provjera učitavanja šablona" (funkcija);

Rezultat rada sa greškama u testiranju:

Automatizacija probnog rada

Obično je implementacija aplikacije zadatak koji se mora obavljati prilično često tokom intenzivnog razvoja. Stoga je ova operacija obično automatizirana. U svom radu koristimo Jenkins, alat za kontinuiranu integraciju. Ideja je da se kombinuje implementacija preko Jenkinsa sa automatizovanim testovima.

QUnit testovi se pokreću u pretraživaču. Phantomjs, softver koji emulira rad pretraživača, pomoći će nam da zaobiđemo ovu funkciju. Phantomjs programeri su već obezbijedili skriptu za pokretanje QUnit testova, ali za ispravan rad Morao sam ga malo modifikovati.

/** * Pričekajte dok testni uvjet ne postane istinit ili dok ne dođe do isteka vremena.< 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("Upotreba: run-qunit.js URL");

phantom.exit(); ) var page = new WebPage(); // Usmjerava pozive "console.log()" iz konteksta Page // u glavni Phantom kontekst (tj. trenutni "ovo") page.onConsoleMessage = function(msg) ( console.log(msg); ); page.open(phantom.args, function(status)( if (status !== "uspjeh") ( console.log("Nije moguće pristupiti mreži"); phantom.exit(); ) else ( waitFor(function() ( vrati page.evaluate(function())( var el = document.getElementById("qunit-testresult"); if (el && el.innerText.match("completed")) (vrati true; ) vrati 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 phantom.exit((parseInt(failedNum, 10) ? 1: ));

Za slanje poruka o rezultatima na konzolu, morate dodati funkciju evidentiranja test skripti.

Testiranje je sastavni dio ciklusa razvoja softvera. Početni razvojni timovi često podcjenjuju njenu ulogu i provjeravaju funkcionalnost aplikacije na staromodan način – „radi, u redu“. Prije ili kasnije, ova strategija ne uspije i program za praćenje grešaka počinje biti zatrpan bezbrojnom vojskom zadataka. Da ne biste upali u takvu zamku, preporučujem jednom za svagda da shvatite nijanse testiranja JavaScript koda.

JavaScript više nije kolač! Vjerovatno ne moram da vam objašnjavam da danas JavaScript nije samo jezik za začinjanje izgleda aplikacije. Ali svejedno ću objasniti i učiniti mali uvod

, jer će mi onda platiti još više novca! 🙂 Dakle, vremena kada se JavaScript koristio za šale ili pravljenje menija su nepovratno prošla. To je sada samostalan jezik koji podjednako dobro radi i na klijentu i na serveru. Uloga JavaScript-a je značajno porasla, što znači da prilikom pisanja koda ne treba da se stidite korišćenja praksi koje su se dokazale u drugim programskim jezicima.

Šta mislim pod praksama i paradigmama? Naravno, MVC (kontrolor prikaza modela) arhitektonski obrazac i obrasci organizacije koda. Prateći ove jednostavne trikove, moći ćete napisati bolji kod koji će biti ne samo lak za održavanje, već će imati i mogućnost automatskog testiranja.
  • Test bi trebao biti što jednostavniji. Što je test složeniji, veća je vjerovatnoća da ćete napraviti greške.
  • Testove je potrebno grupirati u module kako bi kasnije lakše pronašli greške i mogli testirati određene dijelove aplikacije.
  • Svaki test treba da bude nezavisan od drugih testova.
  • Uvijek napišite poseban test svaki put kada pronađete greške.
Greška većine testera

Nije tajna da je najpopularniji metod testiranja oduvijek bio banalan očni test. Njegova suština je jednostavna do sramote - napišete nekoliko hiljada linija koda, riješite problem i pokrenete svoju kreaciju. Igrao sam se, kliknuo - čini se da sve radi, možete ga postaviti na produkcijski server. Sve je krajnje jednostavno, a uz dužnu pažnju programera (idealno pojedinca s nadimkom "tester"), možete se osloniti na ispravan rad aplikacije.

U praksi se sve dešava malo drugačije. Po pravilu ne postoji poseban tester. Programer sam pokušava provjeriti funkcionalnost programa izvodeći redoslijed radnji navedenih u tehničkim specifikacijama. Naprednije kovačnice koda automatizuju ovu vrstu testiranja integracije koristeći alate kao što je Selenium.

Tako programer dobija priliku da detektuje samo najviše grube greške. Nažalost, "glupe" i "nenamjerne" radnje korisnika, kao i lukavi potezi u poslovnoj logici, ostaju iza scene u 99% slučajeva.

Prisutnost posebnog testera također rješava problem djelomično i do određenog vremena. Čak i ako zanemarimo pažnju njegovog sapera na detalje, kvalitet njegovog testiranja će težiti nuli kako aplikacija bude rasla. Dozvolite mi da vam dam primjer iz prakse.

Jednog dana dobio sam zadatak da razvijem mali program. U smislu funkcionalnosti, projekat je ličio na jednostavan CRM, koji sam implementirao u najkraćem mogućem roku. Dobivši zasluženu nagradu, predao sam sve izvore kupcu i zaboravio na projekat na osam mjeseci. Onda je počela zabava. Kupac je odlučio ozbiljno proširiti funkcionalnost programa i pozvao me u pomoć. Naravno, uzeo sam ga i počeo da vajam funkciju za funkcijom... U početku nije bilo teško, ali kada je u pitanju ukupna integracija funkcionalnosti, zujao roj grešaka je pojurio u mom pravcu. Komadi koda su počeli da se sukobljavaju i morali smo da potrošimo mnogo vremena na rešavanje sukoba. “Pa, kako to da niste vidjeli da ima problema s vašom prijavom?” - pitaće se čitaoci. Odgovorit ću: pokrenuo sam je, ali zbog činjenice da je aplikacija narasla, jednostavno nisam imao dovoljno vremena i živaca da masovno testiram svu funkcionalnost. Ograničio sam se na testiranje samo pojedinačnih funkcija i dobro platio za to. Moral priče: “Zamislite testiranje kao sastavni dio razvoja.”

Jedinični testovi su kao srebrni metak

Jedinično testiranje je najbolji način da uštedite svoje živce i povećate garancije funkcionalnosti pojedinih dijelova aplikacije. Ako nikada niste sreli ovu strašnu zvijer, ukratko ću vam objasniti. Jedinični testovi vam omogućavaju da automatizujete proces testiranja i testirate svaku karakteristiku vaše aplikacije.

Nakon što je razvoj završen nova funkcija(moguće je pisati testove prije početka razvoja) programer piše poseban kod za testiranje svog koda. Treba simulirati različite situacije i vratiti vrijednosti. Na primjer, napisali smo funkciju za obrezivanje razmaka (trim). Da bismo testirali njegove performanse, moramo pripremiti nekoliko testova koji će nam omogućiti da konstatujemo da:

  • kada se prosledi string "string" izlaz će biti "string";
  • kada prenosimo termine “line 9”, na izlazu ćemo dobiti “line 9”;

Također možemo dodati testiranje za druge ulazne parametre (na primjer, zamjena znaka za razmak tabulatorom). Općenito, što bolje pokrijemo kod testovima i što više mogućih negativnih opcija pružimo, veće su šanse da će u najvažnijem trenutku ostati malo dlake na glavi.

U JS svijetu, testovi se obično opisuju korištenjem specijalizovanih okvira. Imaju sve što vam je potrebno za to, kao i neke alate za sistematizaciju izvještaja o napretku testiranja.

Testovi!= dodatni kod

Programeri koji ne koriste testiranje jedinica vole da tvrde da testiranje jedinica zahteva pisanje i održavanje dodatnog koda. Kažu da su rokovi u stvarnim projektima često kratki i jednostavno nije moguće napisati dodatni kod.

Kada nema vremena za testove

Ako nema vremena, nema smisla pisati testove za jednostavne funkcije(uzmite isti trim() iz primjera u članku), bolje je fokusirati se na najkritičnije dijelove koda. Isto pravilo treba se pridržavati prilikom pisanja često mijenjanog koda. Tehničke specifikacije živog projekta se često mijenjaju, a neke funkcije se moraju stalno ažurirati. Takve promjene mogu dovesti do toga neprijatne trenutke- modificirani kod dobro funkcionira s novim podacima, ali ne probavlja stare podatke organski. Kako ovdje ne biste uhvatili kvar, bolje je odmah provjeriti takve funkcije. Zapamtite jednostavno pravilo: nema vremena za pokrivanje cijelog koda testovima - pokrijte njegov najvažniji dio.


Slažem se sa kratkim rokovima, ali spreman sam raspravljati o dodatnom kodu. S jedne strane, da - testovi zahtijevaju dodatni kod, a samim tim i vrijeme za njegovo pisanje. S druge strane, ovaj kod igra ulogu vazdušnih jastuka u automobilu i definitivno će se isplatiti kako aplikacija bude rasla.
  • Test-Driven JavaScript Development Cristiana Johansena (goo.gl/mE6Is) je jedna od rijetkih knjiga koja se bavi JavaScriptom iz perspektive pisanja testova.
  • John Resing, Beer Bibo “Tajne JavaScript Nindže” (goo.gl/xquDkJ) je dobra knjiga koja će prvenstveno biti korisna za JS programere sa prosječnim nivoom obuke. Knjiga detaljno razmatra pitanja pisanja efektivnog koda za više pretraživača, nijanse obrade događaja i mnoge druge dobrote.
  • David Flanagan JavaScript. Kompletan vodič(goo.gl/rZjjk) – knjiga je preštampana šest puta, a svako izdanje postaje bestseler. Zaista, ovo je najviše detaljan vodič u JavaScript-u, koji svaki JS programer mora pročitati barem jednom.
  • PhantomJS + JSCoverage + QUnit ili konzolni JS jedinični testovi sa proračunom pokrivenosti (goo.gl/FyQ38) - autor članka demonstrira upotrebu gomile navedenih paketa za prikupljanje statistike i izračunavanje procenta pokrivenosti koda testovima.
  • Korisni primjeri korištenja PhantomJS-a - stranica predstavlja veliki broj borbenih aplikacija PhantomJS-a.

Kada nemate vremena i muči vas želja da odustanete od pisanja testova, razmislite tri puta. Možda bi u ovom slučaju bilo prikladnije pokriti samo najzahtjevnije dijelove koda testovima, umjesto da potpuno napustimo testiranje. Uvijek razmišljajte s pogledom na budućnost, kao da bi za mjesec dana vaš program mogao porasti do neviđenih razmjera. Nije svaki kod testiran

Zašto kažem da morate razmisliti o testiranju prije pisanja glavnog koda? Da, jer je kod koji bi u početku trebao biti pokriven jediničnim testovima napisan u malo drugačijem stilu. Ne može se svaki kod testirati. Kod u kojem su logika i reprezentacije pomiješani, pa čak i nabijeni ko zna gdje, nemoguće je ispravno testirati. Ovdje vam uvijek savjetujem da se pridržavate nekoliko jednostavnih pravila:

  • Nema potrebe pisati odlične funkcije. Svaka funkcija treba da riješi jedan problem, a ne 100.500 mogućih situacija. Na primjer, nema potrebe stavljati kod za slanje podataka na server u funkciju odgovornu za njihovu pripremu.
  • Funkcija koja se sastoji od više od deset linija koda je najvjerovatnije loša funkcija.
  • Logika i prezentacija nikada ne bi trebali ići zajedno.
QUnit - klasik kreatora jQueryja

QUnit je posebno popularan među JavaScript programerima. Prvo, dobro je dokumentovan i jednostavan za korišćenje, a drugo, kreirali su ga autori jQuery-ja. Biblioteka je pogodna za testiranje koda kreiranog u jQuery baza, i izvorni JavaScript.


Preuzmi najnovija verzija QUnit možete koristiti sa službene web stranice. Biblioteka dolazi kao jedan JS i CSS fajl. Pretpostavimo da ste shvatili učitavanje potrebnih komponenti, i ako jeste, onda je vrijeme da napišete test test. Hajde da ne idemo daleko i pokušamo da testiramo funkciju trim().

Da bih demonstrirao testove, napravio sam jednostavan projekat sa sljedećom strukturom:

  • index.html - glavna datoteka koja će prikazati rezultate testa;
  • qunit-1.12.0.js - datoteka biblioteke QUnit;
  • example.js - datoteka koja sadrži kod za testiranje (u našem slučaju, opis funkcije trim());
  • test.js - fajl sa testovima;
  • qunit-1.12.0.css - stilovi za dizajniranje izveštaja sa testovima.

Sadržaj fajlova index.html i test.js predstavljen je u listama 1 i 2. Najviše nas zanima drugi listing, koji sadrži deklaraciju funkcije koja se testira (trim()) i testni kod za provjeru njene funkcionalnost. Imajte na umu da se sama funkcija trim() može nalaziti bilo gdje;
Pogledajmo sada same testove. Biblioteka QUnit.js nudi nam brojne metode:

  • test() - omot za opisivanje testa;
  • ok() - tvrdnja vam omogućava da provjerite istinitost prvog parametra. U našem primjeru, prosljeđujem mu poziv trim() funkciji koju smo definirali i upoređujem je s vrijednošću koju očekujem da dobijem. Ako je uslov tačan, test je prošao;
  • equal() - metoda vam omogućava da provjerite jednakost prvog i drugog parametra. Napominjemo odmah da ovu metodu obavlja slabu provjeru, tako da je pogodan samo za skalarne veličine;
  • notEqual() je suprotnost od equal(). Izvršava se ako prva vrijednost nije jednaka drugoj;
  • strictEqual() - slično kao equal() sa samo jednom razlikom - koristi strogu provjeru (odnosno, također provjerava tip podataka);
  • notStrictEqual() - metoda je suprotna od strictEqual();
  • deepEqual() - metoda za rekurzivne tvrdnje, koja se koristi za primitive, nizove, objekte;
  • notDeepEqual() - metoda je suprotna od deepEqual();
  • raises() je izjava za testiranje funkcija povratnog poziva koje izbacuju izuzetak.

U drugom popisu jasno sam pokazao kako ove metode primijeniti u praksi. Ako pokrenete primjer testa u ovom obliku, tada će svi testovi uspješno proći (pogledajte odgovarajuću sliku). Da vidim razliku između testova koji su prošli i onih koji nisu uspjeli, malo sam izmijenio kod za jedan test. Namjerno sam dodao pogrešan rezultat u testnu liniju koristeći strictEqual() (pogledajte odgovarajuću sliku).

Listing 1. Sadržaj datoteke index.html Testiranje sa QUnit-om

Čini se da smo riješili testiranje jednostavnih funkcija. U svakom slučaju, nemam više šta da dodam. Zatim morate uzeti pravi kod i pokušati sami napisati testove. Pogledajmo još jedan zadatak koji se često susreće za JavaScript programere - testiranje asinhronih funkcija. Aplikacija punjena JavaScript kodom komunicira 99% sa serverskom stranom koristeći AJAX. Ni ovaj kod ne možete ostaviti neoznačenim, ali pisanje testova će izgledati malo drugačije. Pogledajmo primjer:

AsyncTest("myAsyncFunc()", function () ( setTimeout(function () ( ok(myAsyncFunc() == true, "Podaci su uspješno preneseni"); start(); ), 500); ));

Glavna razlika između ovog primjera i prethodnog je u tome što se asyncTest() koristi umjesto omota test() čime se direktno navodi da sam zainteresiran za asinkrono testiranje. Zatim pokrećem timeout od 500 milisekundi. Za to vrijeme, funkcija myAsyncFunc() bi trebala prenijeti podatke na test server i, ako je sve u redu, vratiti true. Tu dolazi najzanimljiviji trenutak. Kada se pozove asyncTest(), nit izvršenja je zaustavljena i mora se sama pokrenuti kada se test završi. Za kontrolu toka izvršenja, QUnit ima start() i stop() metode.


Testiranje asinhronih funkcija pomoću QUnit biblioteke je prilično jednostavno. Posljednji primjer koji bih želio pogledati uključuje pisanje testa koji izvodi više asinhronih provjera. Glavno pitanje koje se nameće u takvim problemima je optimalno mjesto za pokretanje niti izvršavanja. Zvanični dokument predlaže korištenje nečeg sličnog

AsyncTest("myAsyncFunc()", function () (očekujte(3); // Ovdje radimo tri provjere ok(myAsyncFunc(), "Učiniti svijet boljim mjestom 1"); ok(myAsyncFunc(), "Učiniti svijet bolje mjesto 2") ; ok(myAsyncFunc(), "Činimo svijet boljim mjestom 3"); setTimeout(function () ( start (), 3000 ));

Testirajte prilagođene radnje

Uvek treba da zapamtite da je mnogo stvari o interfejsu napisano u JavaScript-u. Na primjer, korisnik klikne na makroa i nešto bi se trebalo dogoditi kao odgovor na njegov klik. U projektima postoji ogromna količina takvog "interfejs" koda, a takođe ga treba pokriti testovima. Pogledajmo kako možemo simulirati korisnikov pritisak na tipku i napisati poseban test za ovu akciju. Zamislimo da imamo određenu funkciju koja bilježi pritisnute tipke. Naveo sam njen kod u trećem popisu.

Listing 3. Funkcija zapisivanja pritisaka na tipke KeyLogger(target) (if (!(ova instanca KeyLogger-a)) (vrati novi KeyLogger(target); ) this.target = target; this.log = ; var self = this; this.target. off ("keydown").on("keydown", function(event) (self.log.push(event.keyCode); ));

Pokušajmo sada testirati ovu funkciju. Prije svega, u tijelu testa trebamo emulirati pritisnutu tipku. Najlakši način da to uradite je sa jQuery bibliotekom, koja vam omogućava da kreirate događaj u nekoliko redova koda (pogledajte Listing 4).

Listing 4. Test kod za KeyLogger test("Key logging test", funkcija () (var događaj, $doc = $(document), ključevi = KeyLogger($doc); event = $.Event("keydown"); događaj .keyCode = 9 $doc.trigger(događaj jednak (keys.log.length, 1, "Key recorded"));

Na samom početku liste testova pripremam događaj koji će oponašati pritisak na tipku - “keydown”. Biće nas zainteresovani da pritisnemo taster Tab (šifra 9). Zatim, koristeći trigger() metodu, šaljem pripremljeni događaj, nakon čega mogu započeti testiranje. Prvo provjeravamo ukupnu sliku - da li je tipka pritisnuta, a zatim njen kod.

DOM pod krinkom testova

Budući da vam Qunit.js omogućava testiranje radnji korisnika, ni pisanje testova za DOM ne bi trebalo biti problem. Ovo je zaista istina, a primjer u nastavku će potvrditi moje riječi. Neću to komentirati, samo pogledajte kod i sve će vam biti jasno:

Test ("Dodaj novi element div", funkcija () ( var $fixture = $("#qunit-fixture"); $fixture.append("Ovo je novi div"); equal($("div", $fixture).length, 1 , "Novi div je uspješno dodan!" ));

PhantomJS - pokretanje testova sa konzole

Pisanje testova pomoću biblioteke QUnit.js je zgodno i jednostavno, ali prije ili kasnije će vas pogoditi želja da nekako automatizirate pokretanje, testiranje i prikupljanje rezultata. Na primjer, imam poseban za ovu stvar virtuelna mašina u DigitalOceanu, kojim mogu upravljati samo pomoću konzole.

Projekat PhantomJS vam omogućava da ovaj problem riješite prilično elegantno. Ovo nije samo još jedan okvir za pisanje jediničnih testova, već puna konzolna verzija WebKit motora. Pojednostavljeno rečeno, ova aplikacija emulira pretraživač. Uz pomoć PhantomJS-a moguće je ne samo automatizirati verifikaciju izvršenja testa, već i riješiti mnoge probleme koji prije ili kasnije iskrsnu pred programerom: dobijanje rezultata renderiranja stranice u datoteku (PNG, JPG), funkcije mrežnog monitora (brzina učitavanja, ukupne performanse, itd.), emulacija radnji korisnika i tako dalje. Preporučujem da odvojite vrijeme i pročitate zvaničnu dokumentaciju o ovom projektu, sigurno ćete pronaći nešto zanimljivo za sebe.

PhantomJS se može kompajlirati za različite platforme (*nix, OS X, Windows). Ako sve razvijate pod Windowsom, onda nema problema - spojite binarne datoteke i samo naprijed. Manje poteškoće s pokretanjem mogu nastati ako imate instalirana dva video adaptera, od kojih je jedan NVIDIA. U ovom slučaju, morat ćete koristiti hack opisan u bočnoj traci.


Pokušajmo se upoznati sa PhantomJS-om u praksi. Da bismo pokrenuli testove pripremljene u zadnjem odeljku kroz PhantomJS i dobili rezultate izvršenja u konzolu, potrebna nam je posebna skripta za učitavanje - run-qunit.js. Otvorite konzolu (radim na Windows-u, pa koristim cmd) i ukucajte komandu u formatu

phantom.exe

U mom slučaju, komanda za pokretanje je izgledala ovako:

E:\soft\phantomjs>phantomjs.exe E:\temp\testjsforx\qunit\run-qunit.js file:///E: /temp/testjsforx/qunit/index.html

Rezultat njegovog izvršenja:

Testovi su završeni za 2592 milisekunde. 9 tvrdnji od 9 je prošlo, 0 nije uspjelo.

Svi testovi su prošli

Svakako je potrebno svoj kod pokriti testovima, i nije bitno u kojoj mjeri aplikaciju kreirate. Još jednom vas podsjećam: čak i najmanji programi se pretvaraju u nespretna čudovišta koja treba podržati i dodati funkcionalnost. Dobro testiran kod je ključ uspjeha i kvaliteta. Da, nije lako odmah početi pisati kod pogodan za automatske testove, ali vjerujte mi, sva ova muka će se više nego isplatiti u budućnosti. To je sve što imam za danas, sretno!

PhantomJS problemi na Windows-u

To se jednostavno dogodilo, ali sam sve primjere u ovom članku testirao ne na Linuxu, već na dobrom starom Windowsu 7. Ispostavilo se da PhantomJS ima manjih problema pri radu na sistemima koji koriste nekoliko video adaptera. Pored integrisanog video čipa, moj laptop ima i NVIDIA, i zbog toga je PhantomJS kategorički odbijao da odgovori na komandu phantom.exit(). Kao rezultat toga, nakon izvršavanja skripte, PhantomJS proces nije završio svoj rad i nastavio je da visi u memoriji. Prozor terminala je također prestao da odgovara na komande za isključivanje (nije pomoglo).

Ako ste suočeni sa sličnim problemom i planirate koristiti PhantomJS na Windowsu, onda se pripremite za sljedeći hak. Otvorite panel NVIDIA menadžment. Pronađite stavku "3D postavke" u stablu. WITH desnu stranu Trebala bi se pojaviti opcija "Preferirani grafički adapter". Podrazumevano. njegova vrijednost je postavljena na “Auto select”. Moramo ga promijeniti u “NVIDIA High-Performance Processor” ili “Integrated Graphics Hardware”. Nakon ovog jednostavnog trika, PhantomJS se počeo ponašati poslušno.

Jednog dana, moj prijatelj je izrazio svoje čuđenje kako se JavaScript može koristiti za pisanje ozbiljnih poslovnih proizvoda, budući da nema kompajler. Zapravo, odlučujuću ulogu u kreiranju visokokvalitetnog koda ne igra činjenica da postoji kompajler za programski jezik, već pravilno odabran i dobro podešen tehnički proces kreiranja softverskog sistema.

Ovaj proces treba da uključi skup sredstava za kontrolu kvaliteta i efektivnosti rada programera. Takvi alati mogu biti: testiranje jedinica i integracije, kontinuirana integracija (Continuous Integration, CI), prikupljanje i analiza različitih metrika (na primjer, vrlo duge metode u nDependu), provjera usklađenosti sa zahtjevima JsLint, FxCop, itd.

U ovom članku želim vam reći kako pravilno izvršiti automatsko testiranje jedinica i integracije vašeg proizvoda u JavaScript-u. U stvari, u tom pogledu, JavaScript jezik se suštinski ne razlikuje od Jave ili C#.

Agile, TDD i BDD

Obično se preporučuje kreiranje automatizovanih testova jedinica i integracije za završenu funkcionalnost kako bi se smanjio rizik od regresijskih grešaka kada se kod promeni u budućnosti. U slučaju JavaScript-a, takvi testovi mogu uvelike pojednostaviti testiranje funkcionalnosti sistema u različitim pretraživačima automatizacijom koraka za osiguranje takvog testiranja. Osim toga, pisanje testa jedinice ili integracije za svaku zatvorenu grešku u proizvodu može biti dobra ideja.

Postoje i tehnike programiranja koje zahtijevaju da započnete kodiranje logike pisanjem jediničnog testa: Test-Driven Development (TDD) i Behavior-Driven Development (BDD). Često se koriste u Agile procesu. Pogledajmo bliže njihove karakteristike.

Test-Driven Development

Razvoj vođen testom je iterativni proces pisanja koda koji ponavlja sljedeća četiri koraka:

Korak 1. Prije nego što dodate novi dio logike, kreirajte jedinični test da biste testirali tu logiku;

Korak 2. Pokrenite test i uvjerite se da jeste Ne propusnice;

Korak 3. Napišite najjednostavniji kod koji će učiniti da test bude uspješan;

Korak 4. Uredite kod kako biste zadovoljili zahtjeve kvaliteta, uklonite dupliciranje koda i osigurajte da je test prošao.

Jedinični test je kod koji testira rad određene komponente (modula) u izolovanom okruženju. Integracijski test se odnosi na kod koji testira kako više komponenti rade zajedno. Za testiranje modula u izoliranom okruženju kada ovisi o drugim modulima, koriste se test dvojnici.

Test Doubles

Podjela pomoćnih objekata koji se koriste u jediničnom testiranju u kategorije potiče iz knjige xUnit Test Patterns Gerarda Meszarosa. Ove kategorije se zajednički nazivaju “test dvojnici”. Postoje sljedeće vrste podstudija:

  • Fake;
  • Dummy.

Stub izlazne vrijednosti za koje su unapred specificirani. Koristi se za simulaciju interfejsa zavisne komponente.

Mock je pomoćni objekat ponašanješto je unapred određeno. Koristi se za simulaciju interfejsa zavisne komponente i testiranje da li se ispravno koristi u testu.

Spy je pomoćni objekat za inspekciju pozvanih metoda i parametara koji su im proslijeđeni tokom testa.

Lažni je pomoćni objekat koji implementira interfejs zavisne komponente u pojednostavljenom obliku. Na primjer, u svrhu testiranja jedinica, možete imati bazu podataka u memoriji umjesto relacijske baze podataka koja se koristi u radna verzija proizvod.

Dummy je pomoćni objekat čija je referenca ili prosljeđivanje potrebna potpisom metode ili bilo kojim drugim ugovorom, ali čija se stvarna vrijednost nikada ne koristi.

Razlika između Stuba i Mock-a je način na koji se provjeravaju rezultati testa. U slučaju Stub-a, stanje objekta se provjerava na kraju testa. U slučaju Mock-a, test potvrđuje da se objekt koristi tačno kako je opisano tokom registracije. Detalje možete pronaći u bilješci Martina Fowlera Ruganje nije zaglavlje, a ovdje ću navesti samo primjer.

Stub Rugati se
"testno povezivanje bi trebalo da počne sa ispitivanjem": function () ( this.client.url = "/my/url"; sinon.stub(ajax, "poll").returns()); .assert.calledWith(ajax.poll, "/my/url" ) "testno povezivanje bi trebalo da počne sa ispitivanjem": funkcija () ( this.client.url = "/my/url"; var mock = sinon.mock(ajax) mock.expects("poll") .withArgs("/my/url" ").returns(); this.client.connect(); mock.verify(); )
Razvoj vođen ponašanjem

Iterativni pristup razvoju softvera kroz implementaciju funkcionalnih zahtjeva je već poznati stil razvoja orijentiran na rezultate. U BDD procesu, sljedeća tri koraka se izvode uzastopno:

Korak 1. Utvrđivanje funkcionalnih zahtjeva za implementirani modul u obliku testova;

Korak 2. Kodiranje modula;

Korak 3. Provjera da su sve želje kupca ili poslovnog analitičara () ispunjene provjerom rezultata tekućih testova.

Prilikom pisanja testova u BDD stilu, vrlo je zgodno koristiti Mock objekte zbog činjenice da savršeno odražavaju funkcionalne zahtjeve za komponentu. Dakle, testovi u BDD procesu mogu poslužiti kao formalizovana reprezentacija problema (korisničke priče) u Scrum terminima, što štedi vrijeme na pisanju tehničkih specifikacija i dokumentacije za gotov proizvod.

Šta bi trebao biti JavaScript okvir za testiranje jedinica?

Kompletna JavaScript jedinica i alat za testiranje integracije trebao bi se sastojati od sljedećih komponenti:

  • Biblioteka tvrdnji (skup metoda za provjeru stanja komponente na kraju svakog testa);
  • Mock biblioteka (alat za generisanje lažnih objekata i drugih “duplikata”);
  • Test runner (alat za automatsko pokretanje testova sa podrškom za većinu pretraživača, uključujući iOS i Android pretraživače);
  • Blok povezivanja na popularne sisteme kontinuirane integracije.
Strategije za jedinično testiranje JavaScript koda

Danas postoje tri strategije za jedinično testiranje JavaScript koda (za više detalja, pogledajte treće poglavlje knjige Test-Driven JavaScript Development od Christiana Johansena):

  • In-Browser testiranje;
  • Testiranje bez glave;
  • Testiranje duž putanje JsTestDriver.

In-Browser testiranje uključuje pokretanje svih testova jedinica i integracije sa HTML stranice koju programer samostalno otvara u željenim pretraživačima. Ovaj pristup je jednostavan i intuitivan. Međutim, njegov nedostatak je što ne predviđa mogućnost uključivanja takvih testova u kontinuiranu integraciju. Dodatno, ručno pokretanje HTML stranice u deset ili više pretraživača i stalno pritiskanje "F5" može biti zamorno za programera.

Bezglavo testiranje znači da se sav JavaScript kod testira na emulatoru, koji može biti napisan u Javi, Ruby, JavaScript, C++, itd. Najpoznatiji emulator danas je PhantomJS, koji je WebKit motor koji se pokreće komandna linija. Među prednostima emulatora može se istaći da se lako može koristiti u kontinuiranoj integraciji, kao i da vam omogućava automatizaciju pokretanja svih testova iz komandne linije. Međutim, ovaj pristup ima značajan nedostatak - kod se ne testira pravi pretraživači, tako da postoji rizik da propuste greške pretraživača koje se ne mogu reproducirati na emulatoru. Prije pojave JsTestDriver-a, često se moglo vidjeti da je In-Browser testiranje kombinovano sa bezglavim testiranjem, jer se savršeno nadopunjuju.

Javascript je veoma popularan jezik za web razvoj na strani klijenta. JavaScript je dinamički jezik i baziran je na izradi prototipa. Uprkos imenu, ne pripada Java jeziku, iako koristi sličnu sintaksu nalik C-u i slične konvencije imenovanja.

Nedavno je Javascript počeo da dobija sve veću popularnost. To leži u osnovi ovoga moderna tehnologija kao AJAX. Poznavanje javascript-a takođe može biti korisno za programiranje na strani servera za fleksibilnu konfiguraciju sistema.

Ciljna publika JavaScript testa

Ovaj test se preporučuje za stručnjake koji žele da testiraju svoje osnovno znanje o JavaScript-u. Test se takođe može koristiti za konsolidaciju znanja od strane programera odmah nakon upoznavanja sa JavaScript jezikom.

U višim obrazovne institucije Ovaj test će biti od interesa za studente tehničkih specijalnosti iz oblasti "Softversko inženjerstvo" ili " Softver Internet".

preduslovi za javascript test

Prije polaganja ovog testa, morate imati barem osnovno razumijevanje jezika Javascript.

Test je prvenstveno namijenjen stručnjacima koji su nedavno naučili JavaScript. Stoga, ovaj test ne pokriva tako složene teme kao što su OOP u JavaScript-u ili specijalizovani JavaScript API-ji.

JavaScript test struktura

Test pitanja pokrivaju sljedeće teme:

  • osnovne konstrukcije JavaScript jezika (deklaracija varijabli, funkcija, itd.);
  • operatori (grananje, petlje);
  • rad sa stringovima u JavaScript-u;
  • rad sa nizovima u JavaScript-u;
  • "JavaScript - HTML" paket (oznake koje se koriste za integraciju)
  • drugi koncepti koji nisu uključeni u gore navedene teme.
Dalji razvoj JavaScript testa

Sledeći korak u razvoju Javascript testa biće kreiranje pitanja na osnovu postojećih tema testa. Proširivanje liste pitanja će povećati interes za ponovno polaganje testa i za provjeru znanja i za učenje.

Koristeći primjer jednostavne aplikacije kalkulatora na Node.js. Mi ćemo testirati koristeći Mocha framework.

Šta bi naša aplikacija trebala moći:

  • Zbrajati, oduzimati, dijeliti i množiti bilo koja dva broja;
  • Prikaži upozorenje i izađi ako je uneto nešto drugo osim broja;
  • Mora postojati i interfejs komandne linije da bi krajnji korisnik koristio aplikaciju.

Šta nam treba:

  • Node.js i npm;
  • Poznavanje JavaScripta: sintaksa i struktura koda, tipovi podataka, matematičke operacije i uslovni izrazi.

Sada kada ste riješili svoje ciljeve, možete početi s postavljanjem okruženja za testiranje i razvoj.

Postavljanje okruženja

Pošto koristimo Node.js, moramo kreirati lokalno okruženje za datoteke i zavisnosti.

Kreiraj novi folder calc. Na komandnoj liniji idite na ovaj direktorij i kreirajte novi projekt s naredbom npm init, koji će kreirati novi fajl package.json za naš program.

Od vas će biti zatraženo da unesete naziv paketa, verziju, opis i druge informacije o paketu. Možete unijeti ime calc.js nastavite pritiskati Enter za dodjelu zadanih vrijednosti. Kada dođete do naredbe za testiranje, unesite mocha - ovo je okvir za testiranje koji ćemo koristiti:

test komanda: mocha

Nakon unosa svih informacija, skripta će kreirati datoteku package.json, koji izgleda otprilike ovako:

( "name": "calc.js", "version": "1.0.0", "description": "Jednostavan kalkulator na Node.js", "main": "index.js", "scripts": ( " test": "mocha" ), "autor": "", "licenca": "ISC" )

Posljednji korak u ovoj fazi je instaliranje Mocha. Unesite sljedeću naredbu za instalaciju:

Npm install --save-dev mocha

Nakon korištenja ove naredbe, folder će se pojaviti node_modules, fajl package-lock.json, i u datoteci package.json pojavit će se sljedeći redovi:

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

Kreirajte fajl test.js. Koristićemo modul ugrađen u Node.js tvrditi da proveri da li je istina i istina istinita. Pošto je ovo tačno, test bi trebao proći:

Const assert = require("assert"); it("treba vratiti true", () => ( assert.equal(true, true); ));

Sada pokrenite test iz komandne linije:

$ npm test > mocha ✓ bi trebao vratiti istinito 1 prolaz (8ms)

Test je prošao kako se očekivalo, tako da smo gotovi sa podešavanjem okruženja. Ukloni iz test.js sve osim reda const assert = require("assert"); .

Koristićemo fajl test.js tokom cijelog procesa kreiranja aplikacije. Kreirajte još dva fajla: operations.js za aritmetičke i validacijske funkcije i calc.js za samu aplikaciju. Koristimo toliko mnogo fajlova da ne postanu predugi i složeni. Evo naše trenutne liste fajlova:

  • calc.js;
  • node_modules;
  • operations.js;
  • package-lock.json;
  • package.json;
  • test.js;

Dodajmo prvi pravi test za našu aplikaciju.

Zbrajanje matematičkih operacija

Prije svega, naša aplikacija mora biti u stanju sabirati, oduzimati, dijeliti i množiti bilo koja dva broja. To znači da za svaku od ovih operacija moramo kreirati posebnu funkciju.

Počnimo sa sabiranjem. Napisaćemo test u kojem će se definitivno dobiti očekivani zbir dva broja. U kodu ispod provjeravamo da li je zbroj 1 i 3 jednak koristeći add() funkciju 4:

Const assert = require("assert"); it("ispravno pronalazi zbir 1 i 3", () => ( assert.equal(add(1, 3), 4); ));

Nakon pokretanja testa pomoću naredbe npm test, vidimo sljedeće:

> mocha 0 prolazni (9ms) 1 neuspješan 1) ispravno pronalazi zbir 1 i 3: ReferenceError: add nije definiran na Context.it (test.js:5:16) npm ERR! Test nije uspio. Za više detalja pogledajte gore.

Test nije uspio s porukom ReferenceError: add nije definiran. Testiramo funkciju add() koja još ne postoji, pa je ovaj rezultat sasvim očekivan.

Kreirajmo funkciju add() u datoteci operations.js:

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

Ova funkcija uzima dva argumenta x i y i vraća njihov zbir. Možda ste primijetili da pišemo (+x) + (+y) umjesto x + y. Koristimo unarni operator za prebacivanje argumenta na broj u slučaju da je input string.

Napomena Ovo koristi funkciju strelice dodanu u ES6 i implicitni povratak.

Pošto koristimo Node.js i dijelimo kod na više datoteka, moramo koristiti module.exports za izvoz koda:

Const add = (x, y) => (+x) + (+y); module.exports = (dodaj)

Na početku fajla test.js uvozimo kod iz operations.js koristeći require() . Pošto koristimo funkciju preko varijable operacije, moramo promijeniti add() u operations.add() :

Const operacije = zahtijevaju("./operations.js"); const assert = zahtijevaju("assert"); it("ispravno pronalazi zbir 1 i 3", () => ( assert.equal(operations.add(1, 3), 4); ));

Pokrenimo test:

$ npm test > mocha ✓ ispravno pronalazi zbir 1 i 3 1 (8ms)

Sada imamo funkcionalnu funkciju i testovi prolaze. Budući da druge funkcije operacije rade slično, dodavanje testova za subtract() , multiply() i divide() je jednostavno:

It("ispravno pronalazi zbir 1 i 3", () => ( assert.equal(operations.add(1, 3), 4); )); it("ispravno pronalazi zbir -1 i -1", () => ( assert.equal(operations.add(-1, -1), -2); )); it("ispravno pronalazi razliku između 33 i 3", () => ( assert.equal(operations.subtract(33, 3), 30); )); it("ispravno pronalazi proizvod 12 i 12", () => ( assert.equal(operations.multiply(12, 12), 144); )); it("ispravno pronalazi količnik 10 i 2", () => ( assert.equal(operations.divide(10, 2), 5); ));

Sada kreirajmo i izvezemo sve funkcije u test.js:

Const add = (x, y) => (+x) + (+y); const oduzimanje = (x, y) => (+x) - (+y); const multiply = (x, y) => (+x) * (+y); const podjela = (x, y) => (+x) / (+y); module.exports = ( dodaj, oduzmi, pomnoži, podijeli, )

I pokrenimo nove testove:

$ npm test > mocha ✓ tačno pronalazi zbir 1 i 3 ✓ tačno pronalazi zbir -1 i -1 ✓ tačno nalazi razliku 33 i 3 ✓ tačno pronalazi proizvod 12 i 12 ✓ tačno pronalazi količnik 10 i 2 5 prolaza (8ms)

Svi testovi su prošli uspješno, tako da sada možemo biti sigurni da će glavne funkcije naše aplikacije raditi ispravno. Sada možete izvršiti dodatnu provjeru valjanosti.

Dodavanje validacije

On trenutno kada korisnik unese broj i odabere željenu operaciju, sve radi kako treba. Međutim, šta se događa ako pokušate pronaći zbir broja i niza? Aplikacija će pokušati izvršiti operaciju, ali pošto očekuje broj, vratit će NaN.

Umjesto vraćanja neke čudne vrijednosti, vrijeme je da uradite drugi zadatak - učinite da aplikacija prikaže upozorenje i izađite ako uneseni argument nije broj.

Prvo morate napisati funkciju koja će provjeriti da li je unos broj ili ne. Aplikacija mora raditi samo s brojevima, tako da ćemo rješavati tri situacije:

  • Oba ulaza su brojevi.
  • Jedan ulaz je broj, a drugi niz.
  • Oba ulaza su nizovi.
  • it("prijavljuje grešku kada se koristi niz umjesto broja", () => ( assert.equal(operations.validateNumbers("sammy", 5), false); )); it("prijavljuje grešku kada se koriste dva niza umjesto brojeva", () => ( assert.equal(operations.validateNumbers("sammy", "sammy"), false); )); it("uspjeh kada se koriste dva broja", () => ( assert.equal(operations.validateNumbers(5, 5), true); ));

    Funkcija validateNumbers() će provjeriti oba parametra. IsNaN() funkcija provjerava da li je parametar broj, a ako nije, vraća false. U suprotnom, vraća true, što ukazuje na uspješnu provjeru valjanosti.

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

    Ne zaboravite dodati validateNumbers u module.exports na kraju datoteke. Sada možete pokrenuti nove testove:

    $ npm test 1) prijavljuje grešku kada se koristi niz umjesto broja ✓ prijavljuje grešku kada se koristi dva niza umjesto broja ✓ uspjeh kada se koristi dva broja 7 prolaz (12ms) 1 neuspješan 1) prijavljuje grešku kada se koristi niz umjesto broja: AssertionError : true == false + očekivano - stvarno -true +false

    Dva testa su prošla, ali jedan nije uspio. Test za dva broja je prošao uspješno, kao i test za dva niza. Isto se ne može reći za provjeru unosa niza i brojeva.

    Ako ponovo pogledate našu funkciju, primijetit ćete to oboje parametri moraju biti NaN da bi funkcija vratila false. Ako želimo postići isti efekat kada je barem jedan od parametara NaN , moramo && zamijeniti sa || :

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

    Ako ponovo pokrenete npm test nakon ovih promjena, svi testovi će proći:

    ✓ prijavljuje grešku kada se koristi niz umjesto broja ✓ prijavljuje grešku kada se koristi dva niza umjesto broja ✓ uspjeh kada se koriste dva broja 8 prolazi (9ms)

    Testirali smo svu funkcionalnost naše aplikacije. Funkcije uspješno izvode matematičke operacije i provjeravaju unos. Završna faza je kreiranje korisničkog interfejsa.

    Kreiranje interfejsa

    Već imamo potrebne funkcije, ali ih korisnik još ne može koristiti. Stoga nam je potreban interfejs. Za našu aplikaciju kreiraćemo interfejs komandne linije.

    Trenutno fajl calc.js treba da bude prazan. Ovdje će biti pohranjena naša aplikacija. Prvo morate uvesti funkcije iz operations.js:

    Const operacije = zahtijevaju("./operations.js");

    Sam interfejs će koristiti Readline CLI modul ugrađen u Node.js:

    Const readline = require("readline");

    Nakon što uvezete sve što vam je potrebno, možete početi kreirati svoju aplikaciju. Za kreiranje sučelja koristit ćemo readline, dostupnom putem varijable rl:

    Const rl = readline.createInterface(( ulaz: process.stdin, izlaz: process.stdout ));

    Prvo što bi korisnik trebao vidjeti nakon pokretanja programa je poruka dobrodošlice i upute za korištenje. Za ovo ćemo koristiti console.log() :

    Console.log(` Calc.js Otvorili ste kalkulator u Node.js! Verzija: 1.0.0. Upotreba: Korisnik mora da unese dva broja, a zatim da izabere šta da radi sa njima. `);

    Prije nego što pređemo na same funkcije kalkulatora, provjerimo radi li console.log() kako se očekuje. Natjerat ćemo program da ispiše poruku i izaći. Da biste to učinili, dodajte poziv metodi rl.close() na kraju.

    Da pokrenete aplikaciju, unesite naziv čvora i datoteke:

    $ node calc.js Calc.js Otvorili ste Node.js kalkulator! Verzija: 1.0.0. Upotreba: Korisnik mora uneti dva broja, a zatim izabrati šta će sa njima.

    Program prikazuje poruku dobrodošlice i izlazi. Sada moramo dodati korisnički unos. Od korisnika se traži da uradi sledeće: odabere dva broja i jednu operaciju. Svaki unos će biti zatražen metodom rl.question():

    Rl.question("Unesite prvi broj: ", (x) => ( rl.question("Unesite drugi broj: ", (y) => ( rl.question(` Odaberite jednu od sljedećih operacija: Sabiranje ( +) Oduzimanje (-) Množenje (*) Deljenje (/) Vaš izbor: `, (izbor) => ( // kod rl.close(); ));

    Varijabli x dodjeljuje se prvi broj, y drugi i odabire se odabrana operacija. Sada naš program traži unos, ali ne radi ništa s podacima koje prima.

    Nakon trećeg unosa, potrebno je provjeriti da li su uneseni samo brojevi. Da bismo to učinili, koristit ćemo funkciju validateNumbers(). Koristeći NOT operator, provjerit ćemo da li su brojevi uneseni i, ako nisu, prekinuti program:

    If (!operations.validateNumbers(x, y)) ( console.log("Mogu se unijeti samo brojevi! Ponovo pokrenite program."); )

    Ako je sve ispravno uneseno, sada morate pokrenuti metodu koja odgovara operaciji, kreiranoj ranije. Za obradu četiri moguće opcije izbora, koristićemo izraz switch i prikazati rezultat operacije. Ako je odabrana nepostojeća operacija, izvršit će se zadani blok koji će korisniku reći da pokuša ponovo:

    If (!operations.validateNumbers(x, y)) ( console.log("Mogu se unijeti samo brojevi! Ponovo pokrenite program."); ) else ( prekidač (izbor) ( slučaj "1": console.log(` Zbir $(x) i $(y) jednak je $(operations.add(x, y)).` case "2": console.log(`Razlika od $(x) i $(); y) je $(operations.subtract(x, y)).` case "3": console.log(`Proizvod $(x) i $(y) je $(operations.multiply(x); , y)).`) ; ponovo pokrenite program i odaberite broj od 1 do 4."); prekid; ) )

    Napomena Funkcije console.log() ovdje koriste nizove šablona koji dozvoljavaju izraze.

    /** * Jednostavan kalkulator u Node.js koji koristi aplikaciju kalkulatora koja koristi * ugrađeni interfejs komandne linije Readline.

    */ const operations = require("./operations.js"); const readline = zahtijevaju("readline"); // Koristi readline za kreiranje sučelja const rl = readline.createInterface(( input: process.stdin, output: process.stdout )); console.log(` Calc.js Otvorili ste kalkulator u Node.js! Verzija: 1.0.0. Upotreba: Korisnik mora da unese dva broja, a zatim da izabere šta da radi sa njima. `); rl.question("Unesite prvi broj: ", (x) => ( rl.question("Unesite drugi broj: ", (y) => ( rl.question(` Odaberite jednu od sljedećih operacija: Sabiranje ( +) Oduzimanje (-) Množenje (*) Deljenje (/) Vaš izbor: `, (izbor) => ( if (!operations.validateNumbers(x, y)) ( console.log("Mogu se unositi samo brojevi! Molimo ponovo pokrenite program. "); ) else (prekidač (izbor) (slučaj "1": console.log(`Zbroj $(x) i $(y) je $(operations.add(x, y)). ` case "2": console.log(`Razlika između $(x) i $(y) je $(operations.subtract(x, y))); console.log(`Proizvod $(x) i $(y) jednak je $(operations.multiply(x, y)).`); $(x) i $(y) jednaki su $(operacijama. divide(x, y)).`); ) break ;

    Sada je naša aplikacija spremna. Provjerimo njegov rad posljednji put. Unesite 999 i 1 i odaberite operaciju oduzimanja:

    Program je uspješno završio svoj rad, dajući ispravan rezultat. Čestitamo, napisali ste jednostavan kalkulator koristeći Node.js i naučili osnove TDD razvoja.

    Pregled