js testiranje. Test znanja JavaScript - osnove

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

Ovaj proces treba da uključi skup alata za kontrolu kvaliteta i efikasnosti za 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, JavaScript se u tom pogledu ne razlikuje od Jave ili C#.

Agile, TDD i BDD

Općenito se preporučuje kreiranje automatskih jediničnih i integracijskih testova za izvršenu funkcionalnost kako bi se smanjio rizik od regresijskih grešaka prilikom promjene koda u budućnosti. U slučaju JavaScripta, ovi testovi mogu znatno olakšati provjeru da sistem radi u različitim pretraživačima automatizacijom koraka kako bi se osiguralo da radi. Osim toga, pisanje jedinice ili integracijskog testa za svaku zatvorenu grešku u proizvodu može poslužiti kao dobra usluga.

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. Razmotrimo njihove karakteristike detaljnije.

Test Driven Development

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

Korak 1. Prije dodavanja novog dijela logike, kreirajte jedinični test da biste testirali tu logiku;

Korak 2. Pokrenite test i uvjerite se u to Ne propusnice;

Korak 3. Napišite najjednostavniji kod koji će učiniti da test prođe;

Korak 4. Uredite kod u skladu sa zahtjevima kvalitete, uklonite dupliciranje koda i uvjerite se da je test prošao.

Jedinični test je kod koji testira rad neke komponente (modula) u izolovanom okruženju. Integracijski test je kod koji testira zajednički rad više komponenti. Test dupli se koriste za testiranje modula u izolovanom okruženju kada zavisi od drugih modula.

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" (test dupli). Dupleri su sljedećih tipova:

  • lažni;
  • Dummy.

Stub izlazne vrijednosti za koje su unapred određene. Koristi se za oponašanje interfejsa zavisne komponente.

Rugati se je pomoćni objekat ponašanje koji je unapred postavljen. Koristi se za oponašanje interfejsa zavisne komponente i testiranje da li se pravilno koristi tokom testa.

Špijun je pomoćni objekat za inspekciju pozvanih metoda i parametara koji su im prosleđeni tokom testa.

Lažna je pomoćni objekat koji implementira interfejs zavisne komponente u pojednostavljenom obliku. Na primjer, za potrebe jediničnog testiranja, možete imati bazu podataka u memoriji umjesto relacijske baze podataka koja se koristi u produkcijskoj verziji proizvoda.

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

Razlika između Stub-a 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 provjerava da li se objekt koristi tačno kako je opisano tokom registracije. Detalji se mogu naći u bilješci Martina Fowlera Rugaju se ne zaglavi, a ja ću ovdje dati samo primjer.

Stub Rugati se
"testno povezivanje bi trebalo da počne sa ispitivanjem": funkcija () ( this.client.url = "/my/url"; sinon.stub(ajax, "poll").returns(()); this.client.connect(); sinon.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 softver kroz implementaciju funkcionalnih zahtjeva – to je već poznati stil razvoja vođenog testom, fokusiran na rezultate. Sljedeća tri koraka se uzastopno prate u BDD procesu:

Korak 1. Definisanje funkcionalnih zahtjeva za implementirani modul u obliku testova;

Korak 2. Kodiranje modula;

Korak 3. Provjera da li su ispunjene sve želje kupca ili poslovnog analitičara () 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 formalizovani prikaz zadatka ( korisnička priča) u smislu Scrum, što vam omogućava da uštedite 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 "podstudija");
  • Test trkač (instrument auto start testovi s podrškom za većinu pretraživača, uključujući iOS i Android pretraživače);
  • Blok povezivanja na popularne sisteme kontinuirane integracije (Continuous Integration).

Strategije testiranja jedinica JavaScripta

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

  • u pretraživaču testiranje;
  • bez glave testiranje;
  • Testiranje usput JsTestDriver.

In-Browser testiranje uključuje pokretanje svih testova jedinica i integracije sa HTML stranice koju programer samostalno otvara u potrebnim 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. Takođe, 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 daleko je PhantomJS, koji je a webkit, pokrenut iz 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 na stvarnim pretraživačima, tako da postoji rizik da propuste greške pretraživača koje se ne reproduciraju na emulatoru. Prije pojave JsTestDriver-a, često ste mogli vidjeti testiranje u pregledniku u kombinaciji sa bezglavim testiranjem, jer se tako dobro nadopunjuju.

Testiranje je sastavni dio ciklusa razvoja softvera. Početni razvojni timovi često potcjenjuju njenu ulogu i provjeravaju performanse aplikacije na starinski način - "radi, i to je u redu". Prije ili kasnije, ova strategija ne uspije i program za praćenje grešaka počinje nadvladavati bezbrojnu vojsku zadataka. Kako ne biste upali u takvu zamku, preporučujem da se jednom za svagda pozabavite nijansama testiranja JavaScript koda.

JavaScript više nije kolač!

Pretpostavljam da ne moram da vam objašnjavam da danas JavaScript nije samo jezik za začinjanje stvari. izgled aplikacije. Ali svejedno ću objasniti i napraviti mali uvod, jer ću tada biti više plaćen više novca! 🙂 Dakle, vremena kada se JavaScript koristio za šale ili pravljenje menija su zauvijek prošla. Sada je to nezavisan 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 pogleda modela) arhitektonski obrazac i obrasci organizacije koda. Prateći ove jednostavne trikove, moći ćete napisati bolji kod koji ne samo da će biti lak za održavanje, već će imati i mogućnost automatskog testiranja.

Pravila za dobre testove

  • Test bi trebao biti što jednostavniji. Što je test teži, veća je vjerovatnoća da ćete napraviti greške.
  • Testove treba grupirati u module kako bi kasnije bilo lakše pronaći greške i mogli testirati određene dijelove aplikacije.
  • Svaki test ne bi trebao ovisiti o drugim testovima.
  • Uvek napišite poseban test svaki put kada pronađete grešku.

Greška većine testera

Nije tajna da je najpopularniji način testiranja uvijek bio banalan očni test. Njegova suština je jednostavna za sramotu - napisao sam nekoliko hiljada linija koda, riješio problem i pokrenuo svoju kreaciju. Igrao sam se, kliknuo - izgleda da sve radi, možete ga postaviti na borbeni 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 operativnost programa izvodeći redoslijed radnji navedenih u tehničkom zadatku. Naprednije kovačnice koda automatizuju ovu vrstu testiranja integracije pomoću alata kao što je Selenium.

Tako programer dobija priliku da otkrije samo najgrublje greške. Nažalost, "glupe" i "nepredviđene" radnje korisnika, kao i lukavi potezi u poslovnoj logici u 99% slučajeva ostaju iza kulisa.

Prisutnost posebnog testera također rješava problem djelomično i do određenog vremena. Čak i ako odbacimo njegovu sapersku pažnju na detalje, kvalitet njegovog testiranja će težiti nuli kako aplikacija bude rasla. Navest ću primjer iz prakse.

Jednom sam dobio zadatak da razvijem mali program. Po funkcionalnosti, projekat je ličio na najjednostavniji CRM, koji sam implementirao u najkraćem mogućem roku. Dobivši zasluženu naknadu, predao sam sve izvore naručiocu i zaboravio na projekat na osam mjeseci. Tada je počelo najzanimljivije. 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 morao sam da provedem dosta vremena rešavajući konflikte. “Pa, kako niste vidjeli da postoji problem s vašom prijavom?” pitaće čitaoci. Odgovorit ću: pokrenuo sam je, ali zbog činjenice da je aplikacija porasla, jednostavno nisam imao vremena i živaca da masovno testiram svu funkcionalnost. Ograničio sam se na testiranje samo pojedinačnih funkcija i velikodušno 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 sačuvate svoje živce i povećate garancije da će pojedini dijelovi vaše aplikacije raditi. Ako nikada niste sreli ovu strašnu zvijer, ukratko ću vam objasniti. Jedinični testovi vam omogućavaju da automatizujete proces testiranja i izložite svaku karakteristiku vaše aplikacije testovima.

Nakon završetka razvoja 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 njegovu izvedbu, moramo pripremiti nekoliko testova koji će nam omogućiti da potvrdimo da:

  • kada prosljeđujemo string "string" dobijamo "string" kao izlaz;
  • kada se prosledi termin "red 9" na izlazu dobijamo "red 9";

Također možemo dodati testiranje za druge ulazne parametre (na primjer, zamijeniti razmak tabulatorom). Općenito, što bolje pokrijemo kod testovima i što više predvidimo moguće negativne opcije, veće su šanse da u najvažnijem trenutku ostane malo dlake na glavi.

U JS svijetu, testovi se obično pišu pomoću specijalizovanih okvira. Imaju sve što vam je potrebno za to, kao i neke alate za organiziranje izvještaja o napretku testiranja.

Testovi!= dodatni kod

Testeri koji nisu jedinični vole da tvrde da testiranje jedinica zahteva pisanje i održavanje dodatni kod. Kažu da su rokovi u stvarnim projektima najčešće komprimirani i jednostavno nije moguće napisati dodatni kod.

Kada nema vremena za testove

U nedostatku 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. Projektni zadaci živog projekta se često mijenjaju, a neke karakteristike moraju se stalno ažurirati. Takve promjene mogu dovesti do neugodnih trenutaka - promijenjeni kod dobro funkcionira s novim podacima, ali ne probavlja organski stare. Ovdje, kako ne biste uhvatili grešku ovdje, bolje je odmah provjeriti takve funkcije. Zapamtite jednostavno pravilo: nema vremena za pokrivanje cijelog koda testovima - pokrijte njegov najvažniji dio.


Što se tiče kratkih rokova, slažem se, ali spreman sam da raspravljam o dijelu dodatnog koda. 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.
  • Cristian Johansen Test-Driven JavaScript Development Development (goo.gl/mE6Is) je jedna od rijetkih knjiga koja sagledava JavaScript iz perspektive pisanja testova.
  • John Resing, Beer Bibo JavaScript Ninja Secrets (goo.gl/xquDkJ) je dobra knjiga koja će prvenstveno biti korisna za srednje JS programere. Knjiga detaljno razmatra pitanja pisanja efektivnog koda za više pretraživača, nijanse rukovanja događajima i mnoge druge dobrote.
  • David Flanagan JavaScript. Kompletan vodič» (goo.gl/rZjjk) - Knjiga je preštampana šest puta i svako izdanje je bestseler. Zaista, ovo je najviše detaljan vodič na 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 gore navedenih paketa za prikupljanje statistike i izračunavanje procenta pokrivenosti koda testovima.
  • Korisni slučajevi upotrebe PhantomJS-a - Ova stranica prikazuje veliki broj borbenih upotreba PhantomJS-a.

Kada nema vremena, a želja da odbijete pisanje testova muči, 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 narasti do neviđene veličine.

Nije testiran sav kod

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 testirati sav kod. Kod koji miješa logiku i reprezentacije, pa čak i natrpan, ne razumijem gdje, ne može se normalno testirati. Ovdje vam uvijek savjetujem da se pridržavate nekoliko jednostavnih pravila:

  • Nema potrebe za pisanjem velikih funkcija. Svaka funkcija treba da riješi jedan problem, a ne 100500 mogućih situacija. Na primjer, ne morate objesiti kod za slanje podataka na server u funkciji odgovornoj za njihovu pripremu.
  • Funkcija s više od deset linija koda je najvjerovatnije loša funkcija.
  • Logika i prezentacija nikada ne bi trebali ići zajedno.

QUnit - klasik žanra od kreatora jQueryja

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


Skinuti najnoviju verziju QUnit možete sa službene stranice. Biblioteka dolazi kao jedan JS i CSS fajl. Pretpostavimo da ste shvatili kako učitati potrebne komponente, a ako jeste, onda je vrijeme da napišete probni 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 datoteke index.html i test.js prikazan je u listama 1 i 2. Drugi popis koji nas najviše zanima je deklaracija funkcije koja se testira (trim()) i testni kod za provjeru da radi . Imajte na umu da se sama funkcija trim() može nalaziti bilo gdje, stavio sam je u drugi listing samo da uštedim prostor u dnevniku.
Pogledajmo sada same testove. Biblioteka QUnit.js nudi nam brojne metode:

  • test() - omot za opis 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 sa 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. Primetite to odmah ovu metodu obavlja nestrogu provjeru, tako da je pogodan samo za skalare;
  • notEqual() je suprotnost od equal(). Izvršava se ako prva vrijednost nije jednaka drugoj;
  • strictEqual() - slično kao equal() sa jednom razlikom - koristi strogu provjeru (odnosno, također provjerava tip podataka);
  • notStrictEqual() - suprotno od strictEqual();
  • deepEqual() - metoda za rekurzivne izjave, koja se koristi za primitive, nizove, objekte;
  • notDeepEqual() - suprotno od deepEqual();
  • raises() je tvrdnja za testiranje funkcija povratnog poziva koje izbacuju izuzetak.

U drugom popisu jasno sam pokazao kako ove metode primijeniti u praksi. Ako pokrenete test slučaj u ovom obliku, svi testovi će biti uspješno prošli (pogledajte odgovarajuću sliku). Da vidim razliku između prolaska testova i neuspjelog testa, malo sam promijenio kod jednog testa. Namjerno sam dodao pogrešan rezultat u red s testom koristeći strictEqual() (pogledajte odgovarajuću sliku).

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



Uz testiranje jednostavnih funkcija čini se razumljivim. 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. Također je nemoguće ostaviti ovaj kod bez testiranja, ali pisanje testova će izgledati malo drugačije. Razmotrimo primjer:

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

Glavna razlika između ovog i prethodnog primjera je u tome što se umjesto omota testa() koristi asyncTest(), čime se direktno navodi da sam zainteresiran za asinkrono testiranje. Zatim pokrećem vremensko ograničenje od 500 milisekundi. Za to vrijeme, funkcija myAsyncFunc() bi trebala prenijeti podatke na test server i, ako je sve u redu, vratiti true. Dolazi najzanimljiviji trenutak. Kada se pozove asyncTest(), nit izvršenja se zaustavlja, a kada je test završen, mora se pokrenuti sam. Da kontroliše tok izvršenja, QUnit obezbeđuje start() i stop() metode.


Testiranje asinhronih funkcija s bibliotekom QUnit je prilično jednostavno. Posljednji primjer koji bih želio pogledati je pisanje testa koji izvodi više asinhronih provjera. Glavno pitanje koje se postavlja u takvim zadacima je optimalno mjesto za početak niti izvršenja. Zvanični dokument predlaže korištenje nečeg sličnog

AsyncTest("myAsyncFunc()", function () (očekujte(3); // Uradite tri testa ovdje ok(myAsyncFunc(), "Učiniti svijet boljim 1"); ok(myAsyncFunc(), "Učiniti svijet boljim 2 ") ; ok(myAsyncFunc(), "Učiniti svijet boljim mjestom 3"); setTimeout(function () ( start(); ), 3000); ));

Testirajte prilagođene radnje

Uvek treba da zapamtite da je mnogo svih vrsta interfejsa napisano u JavaScript-u. Na primjer, korisnik klikne na svodnika i nešto bi se trebalo dogoditi kao odgovor na njegov klik. U projektima postoji ogromna količina takvog "interfejs" koda, a također ga treba pokriti testovima. Pogledajmo kako možemo simulirati korisnički pritisak na tipku i napisati poseban test za ovu akciju. Zamislimo da imamo neku funkciju koja bilježi pritisnute tipke. Dao sam joj šifru 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); )); )

Sada ćemo isprobati ovu funkciju da testiramo. 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 linija koda (pogledajte Listing 4).

Listing 4. Test kod za KeyLogger test("Test snimanja ključa", funkcija () (var događaj, $doc = $(dokument), ključevi = KeyLogger($doc); događaj = $.Event("keydown"); događaj .keyCode = 9; $doc.trigger(event); equal(keys.log.length, 1, "Ključ je evidentiran"); equal(keys.log, 9, "Taster pritisnut sa kodom 9 evidentiran"); ));

Na samom početku listinga sa testom pripremam događaj za emulaciju pritiska 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 širu sliku - da li je tipka pritisnuta, a zatim njen kod.

DOM pod krinkom testova

Budući da vam Qunit.js omogućava testiranje prilagođenih radnji, pisanje testova za DOM ne bi trebao biti problem. To je tačno, a primjer u nastavku će potvrditi moje riječi. Neću to komentirati, samo pogledajte kod i sve će vam biti jasno:

Test("Dodavanje novog elementa div", funkcija () ( var $fixture = $("#qunit-fixture"); $fixture.append("

Ovo je novi div
"); equal($("div", $fixture).length, 1, "Novi div je uspješno dodan!"); ));

PhantomJS - pokrenite testove sa konzole


Pisanje testova pomoću biblioteke QUnit.js je zgodno i jednostavno, ali prije ili kasnije će vas posjetiti želja da nekako automatizirate pokretanje, testiranje i prikupljanje rezultata. Na primjer, imam zasebnu virtuelnu mašinu u DigitalOceanu za ovaj posao, kojom mogu upravljati samo pomoću konzole.

Projekat PhantomJS rješava ovaj problem dovoljno 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, zaista nije samo za automatizaciju provjere izvršenja testa, već i za rješavanje mnogih zadataka koji prije ili kasnije iskrsnu pred programerom: prenošenje rezultata renderiranja stranica u datoteku (PNG, JPG), funkcije mrežnog monitora (brzina učitavanja, ukupne performanse, itd.), emulacija radnji korisnika i tako dalje. Preporučujem da ne budete lijeni i pročitate službenu 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 pokrenemo testove pripremljene u prošlom odeljku kroz PhantomJS i dobijemo rezultate izvršenja u konzoli, 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<путь к run-qunit.js> <путь к странице с тестами>

U mom slučaju, komanda za pokretanje je ispala 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

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

Problemi sa PhantomJS-om na Windows-u

Tako se dogodilo, ali sam sve primjere za ovaj članak testirao ne na Linuxu, već pod dobrim starim Windows 7. Ispostavilo se da PhantomJS ima nekih problema kada radi na sistemima koji koriste nekoliko video adaptera. Na mom laptopu, pored integrisanog video čipa, druži se i NVIDIA, pa je zbog toga PhantomJS kategorički odbijao da odgovori na komandu phantom.exit (). Kao rezultat toga, nakon što je skripta izvršena, PhantomJS proces nije završio svoj rad i nastavio je da visi u memoriji. Prozor terminala je takođe prestao da odgovara na izlazne komande ( nije pomoglo).

Ako se suočavate sa sličnim problemom i planirate koristiti PhantomJS na Windowsu, pripremite se za sljedeći hak. otvoreni panel NVIDIA kontrola. Pronađite stavku "3D postavke" u stablu. Na desnoj strani, opcija "Preferirano grafički adapter". Podrazumevano. njegova vrijednost je postavljena na Autoselect. Moramo ga promijeniti u "NVIDIA procesor visokih performansi" ili "Integrirani grafički hardver". Nakon ovog jednostavnog trika, PhantomJS se počeo ponašati poslušno.

Stvaranje efikasnih test slučajeva može biti kritično za velikih projekata, u slučaju da 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 neplanirane promjene u ponašanju funkcija koje su napisali drugi programeri. Ili rad u kratkim rokovima dovodi do nenamjerne promjene u kritičnim dijelovima aplikacije.

Testiranje web aplikacije obično se sastoji od vizualne procjene elemenata stranice i empirijske procjene performansi funkcionalnosti. Drugim riječima, u navigaciji kroz sekcije i izvođenju radnji na dinamičkim elementima.

Vremenom se projekat puni novim funkcionalnost, što produžava i otežava proces provjere njegovog rada. Jedinično testiranje se koristi za automatizaciju.

Postoje 2 pristupa za izradu testnih scenarija:

  • bijela kutijatestiranje– pisanje testova se zasniva na implementaciji funkcionalnosti. One. proveravamo iste algoritme na kojima se zasniva rad modula našeg sistema. Ovaj pristup ne garantuje ispravan rad sistema u celini.
  • crna kutijatestiranje– skriptiranje se zasniva na specifikacijama i sistemskim 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 kao dobra ideja da testirate svaku funkciju koju implementirate. Ovo nije sasvim tačno. Pisanje testova oduzima vreme programeru, pa je za optimizaciju procesa rada na kreiranju aplikacije vredi pripremiti testove samo za složene, kritične ili one funkcije koje zavise od rezultata drugih modula sistema. Pokrijte testove dvosmislenom logikom koja potencijalno može sadržavati 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 biti sigurni da su ispravno izvršeni.

Općenito, izuzetno je važno procijeniti troškove testiranja u odnosu na ograničenost vremena razvoja. Naravno, ako niste vremenski ograničeni, možete pustiti da svaka funkcija bude pokrivena testovima. Ali u pravilu se razvoj odvija u kratkom vremenskom periodu, tako da je zadatak analitičara ili iskusnog programera da shvati 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 identifikaciju grešaka brže nego kod njihovog uobičajenog pretraživanja.

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 vizuelno potvrđuje samo kada programer/tester/kupac pogleda GUI u raznim pretraživačima. HTML - markiranje se provjerava istom metodom.

Kako testirati

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

  • Vaši testovi bi trebali biti što jednostavniji. Tada će biti vjerovatnije da će bug koji pokušavate ponoviti utjecati na rezultate njegove implementacije.
  • Dekomponujte testove velikih modula. Grove da pronađe konkretnu lokaciju greške.
  • Učinite testove nezavisnim. Rezultat jednog testa ni u kom slučaju ne bi trebao ovisiti o rezultatima drugog.
  • Rezultati testa bi trebali 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, mora se kreirati test skripta. Na ovaj način ćete biti sigurni da je greška zaista ispravljena i da se ne pojavljuje korisnicima.

Kako testirati

Postoji nekoliko biblioteka za jedinično testiranje js koda. Možda je najčešći QUnit. Da bismo proveli jedinične testove koristeći ovu biblioteku, potrebno je da kreiramo "peščanik" - jednostavnu html stranicu u koju će biti povezana biblioteka za testiranje, kod koji se testira i sami testovi.

Funkcije za testove:

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

Test lista:

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 metoda"); )); 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:

  • uredu()- smatra da je test uspješan ako je povratni rezultat = istina
  • jednako()- upoređuje rezultat sa očekivanim
  • deepEqual()- upoređuje rezultat sa očekivanim, provjeravajući njegov tip

Rezultat izvršenja:

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

Postoji niz drugih biblioteka za jedinične testove. Međutim, koncept izgradnje testnih skripti u njima je isti, tako da nakon što se bavite jednim, neće vam biti teško da se prebacite na drugi.

Važno je zapamtiti

Karakteristika modernog js koda je asinhronost njegovog izvršavanja. 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 backendu i vraća odgovor od njega, tada da biste izvršili testove, morat ćete 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 podesiti neki vremenski interval tokom kojeg bi se izvršavanje funkcije trebalo završiti. Potrebno je pažljivo odabrati trajanje ovog segmenta, .k. s jedne strane, dug rad metode može biti ili karakteristika ili čak potreba za konkretnu implementaciju funkcionalnosti aplikacije, ili nepravilno ponašanje.

Testiranje Backbone aplikacija

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

Možete provjeriti jediničnim testovima:

  • Ispravnost izrade modela i kontrolera
  • Ispravnost podataka u modelima
  • Izvršavanje metoda kontrolera (za to moraju vratiti rezultat)
  • Pogledajte uspješno učitavanje

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"); equal(sample.core.state.get("content"), "sintel", "Podaci modela dobiju test "); stop(); ok(function() ( $.ajax(( url: "app/templates/about.tpl", dataType: "text" )).done(function(data) (self.$el. html(podaci); vrati podatke; )) ), "Provjera učitavanja predloška"); setTimeout(function() ( start(); ), 1000); ));

Rezultat rada sa greškama u testiranju:

Automatizacija probnog rada

Uobičajeno je da 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 pretraživač, pomoći će nam da zaobiđemo ovu funkciju. Phantomjs programeri su već dali skriptu za izvršavanje QUnit testova, ali je morala biti malo modifikovana da bi ispravno radila.

/** * Pričekajte dok testni uvjet ne postane istinit ili dok ne dođe do isteka vremena. * Korisno za čekanje * na odgovor servera ili za promjenu korisničkog interfejsa (fadeIn, itd.). * * @param testFx javascript uslov koji se procjenjuje na boolean, * može se proslijediti kao string (npr.: "1 == 1" ili * "$("#bar").is(":visible")" ili * kao funkcija povratnog poziva. * @param onReady šta učiniti kada je testFx uslov ispunjen, * može se proslijediti kao string (npr.: "1 == 1" ili * "$("#bar").is (":visible")" ili * kao funkcija povratnog poziva. * @param timeOutMillis maksimalna količina vremena za čekanje. Ako nije navedeno *, koristi se 3 sekunde. */ function 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("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 (vrati document.getElementsByClassName("fail" ).innerHTML.length; ) catch (e) ( return 0; ) return 10000; )); phantom.exit((parseInt(failedNum, 10) > 0) ? 1: 0); )); ) ));

Da biste prikazali poruke rezultata u konzoli, morate dodati funkciju evidentiranja test skripti.

Sada je na stranici dostupno testiranje znanja o sljedećim temama: HTML, css, JavaScript, PHP, SQL.

Svaki test se sastoji od 10 pitanja na određenu temu. U svakom pitanju pokušao sam da se dotaknem najrazličitijih oblasti primene određenog jezika kako bih što detaljnije proverio nivo vašeg znanja.

Naravno, sve testovi su besplatni i svako može proći.

Procedura testiranja:

  1. Pratite link " Počnite sa testiranjem" odgovarajućeg testa.
  2. Odgovorite na pitanja odabirom jedini ispravna opcija.
  3. Po završetku testiranja, vidjet ćete tvoj rezultat, broj grešaka, i analizu svakog pitanja sa testa.

Pažnja! Povratak na prethodno pitanje neće raditi, pa prije nego što odgovorite, razmislite.

Trenutno dostupni testovi

  1. HTML

    • Ukupno položen test: 75424 ljudi
    • Prosječna ocjena: 2.83 od 5 bodova.

    Test osnovnog znanja HTML. Morat ćete znati osnovne stvari HTML oznake i njihovu pravilnu upotrebu. Također je potrebno razumjeti karakteristike standarda XHTML 1.1.

  2. css

    • Ukupno položen test: 32828 ljudi
    • Prosječna ocjena: 3.37 od 5 bodova.

    Testom se provjerava poznavanje osnova css. Da biste uspješno položili test, morate poznavati osnovne tipove selektora (njihovu sintaksu), znati osnovna svojstva i njihove moguće vrijednosti, kao i znati svrhu najpopularnijih pseudoelemenata.

  3. JavaScript

    • Ukupno položen test: 24845 ljudi
    • Prosječna ocjena: 3.31 od 5 bodova.

    Ovaj kviz testira vaše znanje JavaScript jezika. Pitanja iz testa pokrivaju različita područja primjene dati jezik. Mnogo je pitanja o razumijevanju "malih" nijansi. Inače, od vas se traži da znate osnovne stvari: rad sa varijablama, osnovne JavaScript funkcije, prioritete operatora itd.

  4. PHP

    • Ukupno položen test: 33239 ljudi
    • Prosječna ocjena: 3.03 od 5 bodova.

    Ovaj kviz testira vaše znanje PHP jezika. Od vas se traži da poznajete osnovne PHP konstrukcije, rad sa varijablama, sesije, implementaciju preusmeravanja i druge standardne stvari.
    Uvjerljiv zahtjev: Test sadrži mnoga pitanja poput: "Šta će skripta proizvesti?". Velika molba, nemojte kopirati i provjeriti. Budite iskreni prema sebi.

  5. SQL

    • Ukupno položen test: 18014 ljudi
    • Prosječna ocjena: 3.28 od 5 bodova.

    Ovaj test testira vaše znanje jezika SQL upiti. Pitanja pokrivaju samo najosnovnije znanje ovog jezika, bez ikakvog produbljivanja. Trebat će vam poznavanje najosnovnijih SQL upita, kao i njihovo kompetentno korištenje.

Na primjeru 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;
  • Također mora postojati sučelje komandne linije kako bi krajnji korisnik mogao koristiti aplikaciju.

Šta nam treba:

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

Kada su ciljevi razvrstani, možete započeti postavljanje okruženja za testiranje i razvoj.

Postavljanje okruženja

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

Stvoriti novi folder calc. U komandnoj liniji, prijeđite u ovaj direktorij i kreirajte novi projekat sa npm init, koji će kreirati novi fajl package.json za naš program.

Od vas će se tražiti da unesete naziv paketa, verziju, opis i druge informacije o paketu. Možete unijeti ime calc.js i nastavite da pritiskate Enter za dodjelu zadanih vrijednosti. Kada dođete do test komande, upišite 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 u Node.js", "main": "index.js", "scripts": ( " test": "mocha" ), "autor": "", "licenca": "ISC" )

Posljednji korak u ovom koraku je instaliranje Mocha. Unesite sljedeću naredbu za instalaciju:

npm install --save-dev mocha

Nakon primjene ove naredbe, pojavit će se folder 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 ugrađeni modul u Node.js tvrditi da proveri da li je istina i istina istinito. Pošto je 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 je podešavanje okruženja završeno. Ukloni iz test.js sve osim linije const assert = require("assert"); .

Koristićemo fajl test.js kroz proces razvoja aplikacije. Kreirajte još dva fajla: operations.js za aritmetičke i validacijske funkcije i calc.js za samu aplikaciju. Koristimo toliko mnogo fajlova da nisu predugi i komplikovani. 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.

Dodavanje matematičkih operacija

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

Počnimo sa sabiranjem. Napisaćemo test koji na jedinstven način dobija očekivani zbir dva broja. U kodu ispod, provjeravamo da li je zbroj 1 i 3 jednak koristeći add() 4 funkciju:

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

Nakon pokretanja testa sa naredbom npm test, vidimo sljedeće:

> mocha 0 prolazni (9ms) 1 neuspješan 1) pronalazi zbir 1 i 3 ispravno: 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 ReferenceError: add nije definiran. Testiramo add() funkciju, koja još ne postoji, pa je ovaj rezultat sasvim očekivan.

Kreirajmo add() funkciju 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 ulaz niz.

Napomena Ovo koristi funkciju strelice koju je dodao 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 sa 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 uspješno. Pošto funkcije drugih operacija rade na sličan način, 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 pokrenite nove testove:

$ npm test > mocha ✓ tačno pronalazi zbir 1 i 3 ✓ tačno pronalazi zbir -1 i -1 ✓ tačno nalazi razliku između 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žemo napraviti dodatnu provjeru valjanosti.

Dodavanje validacije

U trenutku 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 budući da očekuje broj, vratit će NaN .

Umjesto vraćanja nekih čudnih vrijednosti, vrijeme je da uradimo drugi zadatak - da napravimo da aplikacija pokaže upozorenje i izađe ako ulazni argument nije broj.

Prvo morate napisati funkciju koja će provjeriti je li unos broj ili ne. Aplikacija bi trebala raditi samo s brojevima, tako da ćemo se nositi s tri situacije:

  1. Oba ulaza su brojevi.
  2. Jedan ulaz je broj, a drugi niz.
  3. 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 potvrditi oba parametra. IsNaN() funkcija provjerava da li parametar nije broj, a ako nije, vraća false . U suprotnom, vraća true , što znači 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 brojeva ✓ uspjeh kada se koriste dva broja 7 prolaze (12ms) 1 neuspješno 1) prijavljuje grešku kada se umjesto broja koristi niz broja: AssertionError : true == netačno + očekivano - stvarno -true + false

Dva testa su prošla, ali jedan nije uspio. Test za dva broja je bio uspješan, kao i test za dva niza. Šta se ne može reći o provjeri unosa niza i broja.

Ako ponovo pogledamo našu funkciju, to možemo vidjeti 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 brojeva ✓ uspjeh kada se koriste dva broja 8 prolaznih (9ms)

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

Kreiranje interfejsa

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

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

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

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

Const readline = require("readline");

Nakon što uvezete sve što vam je potrebno, možete početi kreirati aplikaciju. Za kreiranje sučelja koristit ćemo readline , dostupnu preko 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 Node.js kalkulator! Verzija: 1.0.0. Upotreba: korisnik mora uneti dva broja, a zatim odabrati šta će s njima. `);

Prije nego što uđemo u same funkcije kalkulatora, provjerimo radi li console.log() kako treba. 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 čvor praćen imenom 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 izabere 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: Dodaj ( +) Oduzmi (-) Množenje (*) Deljenje (/) Vaš izbor: `, (izbor) => ( // ovde će se pojaviti više koda rl.close(); )); )); ));

Varijabli x je dodijeljen prvi broj, y drugi, a izbor je odabrana operacija. Sada naš program traži unos, ali ništa ne radi sa primljenim podacima.

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, a ako nisu, izaći iz programa:

If (!operations.validateNumbers(x, y)) ( console.log("Samo brojevi su dozvoljeni! Ponovo pokrenite program."); )

Ako je sve ispravno uneseno, sada morate pokrenuti odgovarajuću operaciju kreiranu ranije. Za obradu četiri moguća izbora, koristit ćemo naredbu switch i ispisati rezultat operacije. Ako je odabrana nepostojeća operacija, izvršit će se zadani blok, govoreći korisniku da pokuša ponovo:

If (!operations.validateNumbers(x, y)) ( console.log("Mogu se unositi samo brojevi! Ponovo pokrenite program."); ) else ( prekidač (izbor) ( slučaj "1": console.log(` Zbir $(x) i $(y) jednak je $(operations.add(x, y)).`); prekid; slučaj "2": console.log(`Razlika $(x) i $(y) jednaka $( operacije.subtract(x, y)).`); prekid; slučaj "3": console.log(`Proizvod $(x) i $(y) jednak je $(operations.multiply(x, y) ).`) ; prekid; slučaj "4": console.log(`Private $(x) i $(y) jednako $(operations.divide(x, y)).`); break; default: console.log ("Ponovo pokrenite program i odaberite broj između 1 i 4."); prekid; ) )

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

/** * Jednostavan Node.js kalkulator 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 Node.js kalkulator! 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: Dodaj ( +) Oduzmi (-) Množenje (*) Deljenje (/) Vaš izbor: `, (izbor) => ( if (!operations.validateNumbers(x, y)) ( console.log("Možete unositi samo brojeve! Molimo ponovo pokrenite program. "); ) else ( prekidač (izbor) ( slučaj "1": console.log(`Zbroj $(x) i $(y) jednak je $(operations.add(x, y)). `); break; case "2": console.log(`Razlika između $(x) i $(y) je $(operations.subtract(x, y)).`); break; case "3": console.log(`Proizvod $( x) i $(y) jednak je $(operations.multiply(x, y)).`); break; slučaj "4": console.log(`Private $(x) i $(y) je jednako $(operacije. divide(x, y)).`); break; default: console.log("Ponovo pokrenite program i odaberite broj između 1 i 4."); break; ) ) rl.close(); )); )) ; ));

Sada je naša aplikacija spremna. Hajde da na kraju proverimo njegov rad. Unesite 999 i 1 i odaberite operaciju oduzimanja:

$ node calc.js Unesite prvi broj: 999 Unesite drugi broj: 1 Vaš izbor: 2 Razlika između 999 i 1 je 998.

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



Učitavanje...
Top