AngularJS-enhetstesting med Karma og Jasmine
โก Smart oppsummering
AngularJS-enhetstesting med Karma og Jasmine verifiserer kontrollere, direktiver og tjenester isolert. Karma kjรธrer spesifikasjoner i ekte nettlesere, Jasmine leverer pรฅstandssyntaksen, og angular-mocks injiserer avhengigheter uten en aktiv server.

En av de mest geniale funksjonene i AngularJS er Testing aspekt. Nรฅr utviklerne pรฅ Google Da de utviklet AngularJS, hadde de testing i tankene og sรธrget for at hele AngularJS-rammeverket var testbart.
I AngularJS utfรธres testing vanligvis ved hjelp av Karma (rammeverk). AngularJS-testing kan utfรธres uten Karma, men Karma-rammeverket har en sรฅ strรฅlende funksjonalitet for testing av AngularJS-kode at det er fornuftig รฅ bruke dette rammeverket.
- I AngularJS kan vi opptre Enhetstesting separat for kontrollere og direktiver.
- Vi kan ogsรฅ opptre ende-til-ende-testing av AngularJS, som testes fra et brukerperspektiv.
โ ๏ธ Versjonsmerknad: AngularJS (versjon 1.x) nรฅdde offisielt slutten av levetiden 31. desember 2021, og Protractor ble pensjonert i august 2023. Arbeidsflyten pรฅ denne siden er fortsatt gyldig for vedlikehold av eksisterende AngularJS 1.x-applikasjoner. Nye prosjekter bรธr bruke moderne Angular med en nรฅvรฆrende stรธttet lรธper.
Introduksjon og installasjon av Karma-rammeverket
Karma er en testing av automatiseringsverktรธy laget av AngularJS-teamet pรฅ GoogleDet fรธrste steget for รฅ bruke Karma er รฅ installere Karma. Karma installeres via npm (som er en pakkebehandler som brukes for enkel installasjon av moduler pรฅ en lokal maskin).
Installasjon av Karma
Installasjonen av Karma via npm gjรธres i en to-trinns prosess.
Trinn 1) Utfรธr linjen under fra kommandolinjen
npm install karma karma-chrome-launcher karma-jasmine --save-dev
hvori,
- npm er kommandolinjeverktรธyet for nodepakkebehandleren som brukes til รฅ installere tilpassede moduler pรฅ enhver maskin. Det leveres med node.js.
- Installasjonsparameteren instruerer npm-kommandolinjeverktรธyet om at installasjon er nรธdvendig.
- Det er 3 biblioteker som er spesifisert pรฅ kommandolinjen som kreves for รฅ jobbe med karma.
- karma er kjernebiblioteket som vil bli brukt til testformรฅl.
- karma-chrome-launcher er et eget bibliotek som gjรธr det mulig รฅ gjenkjenne karma-kommandoer av chrome-nettleseren.
- karma-jasmin โ Dette installerer jasmin som er et avhengig rammeverk for karma.
Trinn 2) Det neste trinnet er รฅ installere kommandolinjeverktรธyet karma. Dette er nรธdvendig for รฅ utfรธre karmalinjekommandoer. Karmalinjeverktรธyet vil bli brukt til รฅ initialisere karmamiljรธet for testing.
For รฅ installere kommandolinjeverktรธyet, kjรธr linjen nedenfor fra kommandolinjen
npm install -g karma-cli
- karma-cli brukes til รฅ installere kommandolinjegrensesnittet for karma, som skal brukes til รฅ skrive karma-kommandoene i kommandolinjegrensesnittet. -g-flagget installerer det globalt, slik at karma-kommandoen er tilgjengelig fra enhver mappe.
Konfigurasjon av Karma-rammeverket
Det neste trinnet er รฅ konfigurere karma som kan gjรธres via kommandoen
karma init
Etter at trinnet ovenfor er utfรธrt, vil karma lage en karma.conf.js-fil. Filen vil sannsynligvis se ut som kodebiten vist nedenfor
files: [ 'node_modules/angular/angular.js', 'node_modules/angular-mocks/angular-mocks.js', 'lib/app.js', 'tests/*.js' ]
Konfigurasjonsfilene ovenfor forteller karma runtime-motoren fรธlgende ting
- angular.js โ Dette forteller karma at applikasjonen din er avhengig av kjernemodulene i AngularJS.
- angular-mocks.js โ Dette forteller karma at den skal bruke enhetstestingsfunksjonaliteten for AngularJS fra angular-mocks.js-filen.
- Alle hovedapplikasjons- eller forretningslogikkfilene er til stede i lib-mappen til applikasjonen din.
- Testmappen vil inneholde alle enhetstestene.
๐ก Tips: Rekkefรธlgen i filarrayet har betydning. angular.js mรฅ lastes inn fรธr angular-mocks.js, og begge mรฅ lastes inn fรธr applikasjonskoden din, ellers er ikke injektoren tilgjengelig nรฅr spesifikasjonene kjรธrer.
For รฅ sjekke om karma fungerer, lag en fil som heter Sample.js, legg inn koden nedenfor og plasser den i testkatalogen.
describe('Sample test', function() { it('Condition is true', function() { expect('AngularJS').toBe('AngularJS'); }); });
Koden ovenfor har fรธlgende aspekter
- Beskriv-funksjonen brukes til รฅ gi en beskrivelse av testen. I vรฅrt tilfelle gir vi beskrivelsen "Sample test" til testen vรฅr.
- 'It'-funksjonen brukes til รฅ gi et navn til testen. I vรฅrt tilfelle oppgir vi navnet pรฅ testen vรฅr som "Betingelsen er sann". Navnet pรฅ testen mรฅ gi mening.
- Kombinasjonen av sรธkeordet 'forvent' og 'toBe' angir hva som er forventet og faktisk verdi av testresultatet. Hvis den faktiske og forventede verdien er den samme, vil testen bestรฅ, ellers mislykkes den.
Nรฅr du kjรธrer fรธlgende linje ved ledeteksten, vil den kjรธre testfilen ovenfor
karma start
Utgangen nedenfor er hentet fra IDE Webstorm hvor trinnene ovenfor ble utfรธrt.
- Utgangen kommer i Karma-utforskeren innenfor Webstorm. Dette vinduet viser utfรธrelsen av alle tester som er definert i karma-rammeverket.
- Her kan du se at beskrivelsen av testen som er utfรธrt vises som er "Sample test".
- Deretter kan du se at selve testen som har navnet "Condition is true" er utfรธrt.
- Merk at siden alle tester har det grรธnne "Ok"-ikonet ved siden av som symboliserer at alle tester bestรฅtt.
Hva er Jasmine i AngularJS-enhetstesting?
Karma bestemmer hvor tester kjรธres, mens Jasmine bestemmer hvordan de skrives. Jasmine er et atferdsdrevet spesifikasjonsrammeverk som leverer vokabularet som brukes i hvert eksempel pรฅ denne siden, og det er derfor karma-jasmine-adapteren er installert ved siden av lรธperen.
Jasmine bidrar med fire byggesteiner:
- beskrive(): Grupperer relaterte spesifikasjoner i en suite og godtar en lesbar beskrivelse av enheten som testes.
- den(): Deklarerer รฉn enkelt spesifikasjon. Navnet bรธr angi oppfรธrselen som verifiseres, i stedet for metoden som kalles.
- expect() med matchere: Sammenligner en faktisk verdi med en forventet. Vanlige samsvarsverdier inkluderer toBe, toEqual, toContain og toBeDefined.
- fรธrHver() og etterHver(): Kjรธr oppsett og nedbryting fรธr og etter hver spesifikasjon, noe som holder hver test uavhengig.
Jasmine tilbyr ogsรฅ spioner. En spion erstatter en ekte funksjon med en innspilt stand-in, slik at en kontroller kan testes uten รฅ kalle et live HTTP-endepunkt. Fordi Jasmine ikke trenger noe DOM og ikke noe eget assertion-bibliotek, er kombinasjonen av Karma og Jasmine fortsatt den enkleste mรฅten รฅ kjรธre AngularJS pรฅ. JavaSkriptenhetstester.
Tester AngularJS-kontrollere
Karma-testing-rammeverket har ogsรฅ funksjonalitet til รฅ teste kontrollere fra ende til annen. Dette inkluderer testing av $scope-objektet som brukes i kontrollere.
La oss se pรฅ et eksempel pรฅ hvordan vi kan oppnรฅ dette.
I vรฅrt eksempel,
Vi mรฅ fรธrst definere en kontroller. Denne kontrolleren vil utfรธre trinnene nedenfor
- Opprett en ID-variabel og tilordne verdien 5 til den.
- Tilordne ID-variabelen til $scope-objektet.
Testen vรฅr vil teste eksistensen av denne kontrolleren og ogsรฅ teste for รฅ se om ID-variabelen til $scope-objektet er satt til 5.
Fรธrst mรฅ vi sikre at fรธlgende forutsetning er pรฅ plass
Installer angular-mocks-biblioteket via npm. Dette kan gjรธres ved รฅ kjรธre linjen nedenfor i kommandolinjen.
npm install angular-mocks --save-dev
Neste er รฅ endre karma.conf.js-filen for รฅ sikre at de riktige filene er inkludert for testen. Segmentet nedenfor viser bare fildelen av karma.conf.js som mรฅ endres
files: ['lib/angular.js', 'lib/angular-mocks.js', 'lib/index.js', 'test/*.js']
- Parameteren 'filer' forteller i utgangspunktet Karma alle filene som kreves for รฅ kjรธre testene.
- Filene angular.js og angular-mocks.js er nรธdvendige for รฅ kjรธre AngularJS-enhetstester.
- index.js-filen kommer til รฅ inneholde vรฅr kode for kontrolleren
- Testmappen kommer til รฅ inneholde alle vรฅre AngularJS-tester
Nedenfor er AngularJS-koden vรฅr, som vil bli lagret som en Index.js-fil i testmappen til applikasjonen vรฅr.
Koden nedenfor gjรธr bare fรธlgende ting
- Lag en AngularJS-modul kalt sampleApp
- Lag en kontroller kalt AngularJSController
- Lag en variabel kalt ID, gi den en verdi pรฅ 5 og tilordne den til $scope-objektet
var sampleApp = angular.module('sampleApp', []); sampleApp.controller('AngularJSController', function($scope) { $scope.ID = 5; });
Nรฅr koden ovenfor er utfรธrt vellykket, vil neste trinn vรฆre รฅ lage en Testsak for รฅ sikre at koden er skrevet og utfรธrt pรฅ riktig mรฅte.
Koden for testen vรฅr vil vรฆre som vist nedenfor.
Koden vil vรฆre i en egen fil kalt ControllerTest.js, som vil bli plassert i testmappen. Koden nedenfor gjรธr bare fรธlgende viktige ting
- beforeEach-funksjonen โ Denne funksjonen brukes til รฅ laste inn AngularJS-modulen vรฅr kalt ยซsampleAppยป fรธr testkjรธringen. Merk at dette er navnet pรฅ modulen i en index.js-fil.
- $controller-objektet opprettes som et mockup-objekt for kontrolleren ยซAngularJSControllerยป som er definert i vรฅr index.js-fil. I alle typer enhetstesting representerer et mock-objekt et dummy-objekt som faktisk vil bli brukt til testingen. Dette mock-objektet vil faktisk simulere oppfรธrselen til kontrolleren vรฅr.
- beforeEach(inject(function(_$controller_) โ Dette brukes til รฅ injisere det falske objektet i testen vรฅr slik at det oppfรธrer seg som den faktiske kontrolleren.
- var $omfang = {}; Dette er et falskt objekt som opprettes for $scope-objektet.
- var controller = $controller('AngularJSController', { $scope: $scope }); โ Her sjekker vi om det finnes en kontroller med navnet 'AngularJSController'. Her tilordner vi ogsรฅ alle variabler fra $scope-objektet vรฅrt i kontrolleren vรฅr i Index.js-filen til $scope-objektet i testfilen vรฅr.
- Til slutt sammenligner vi $scope.ID med 5
describe('AngularJSController', function() { beforeEach(module('sampleApp')); var $controller; beforeEach(inject(function(_$controller_){ $controller = _$controller_; })); describe('$scope.ID', function() { it('Check the scope object', function() { var $scope = {}; var controller = $controller('AngularJSController', { $scope: $scope }); expect($scope.ID).toEqual(5); }); }); });
Testen ovenfor vil kjรธre i karma-nettleseren og gi samme bestรฅtt resultat som ble vist i forrige emne.
Testing av AngularJS-direktiver
Karma-testrammeverket har ogsรฅ funksjonalitet for รฅ teste tilpassede direktiver. Dette inkluderer malen.URL's som brukes i tilpassede direktiver.
La oss se pรฅ et eksempel pรฅ hvordan vi kan oppnรฅ dette.
I vรฅrt eksempel vil vi fรธrst definere et tilpasset direktiv som gjรธr fรธlgende
- Lag en AngularJS-modul kalt sampleApp
- Opprett en tilpasset direktiv med navnet โ guru99
- Lag en funksjon som returnerer en mal med en header-tag som viser teksten "This is AngularJS Testing."
var sampleApp = angular.module('sampleApp', []); sampleApp.directive('guru99', function () { return { restrict: 'E', replace: true, template: '<h1>This is AngularJS Testing</h1>' }; });
Nรฅr koden ovenfor er utfรธrt vellykket, vil neste trinn vรฆre รฅ lage en testcase for รฅ sikre at koden er skrevet og utfรธrt pรฅ riktig mรฅte. Koden for testen vรฅr vil vรฆre som vist nedenfor
Koden vil vรฆre i en egen fil kalt DirektivTest.js, som vil bli plassert i testmappen. Koden nedenfor gjรธr bare fรธlgende viktige ting
- beforeEach-funksjon โ Denne funksjonen brukes til รฅ laste inn AngularJS-modulen vรฅr kalt ยซsampleAppยป fรธr testkjรธringen.
- Tjenesten $compile brukes til รฅ kompilere direktivet. Denne tjenesten er obligatorisk og mรฅ deklareres slik at AngularJS kan bruke den til รฅ kompilere vรฅrt tilpassede direktiv.
- $rootScope er det primรฆre omfanget til enhver AngularJS-applikasjon. Vi har sett $scope-objektet til kontrolleren i tidligere kapitler. Vel, $scope-objektet er underobjektet til $rootScope-objektet. Grunnen til at dette er deklarert her, er fordi vi gjรธr en endring i en faktisk HTML-tag i DOM-en via vรฅrt tilpassede direktiv. Derfor mรฅ vi bruke $rootScope-tjenesten, som faktisk lytter eller vet nรฅr en endring skjer fra et HTML-dokument.
- var element = $kompilere(" โ)($rootScope) โ Dette brukes til รฅ sjekke om direktivet vรฅrt blir injisert som det skal. Direktivet er registrert med det lille bokstavnavnet guru99, sรฅ AngularJS matcher det lille elementet i markupen. Derfor brukes denne setningen til รฅ utfรธre den kontrollen.
- expect(element.html()).toContain(โDette er AngularJS-testingโ) โ Dette brukes til รฅ instruere expect-funksjonen om at den skal finne elementet (i vรฅrt tilfelle h1-taggen) slik at det inneholder innerHTML-teksten til โDette er AngularJS-testingโ.
describe('Unit testing directives', function() { var $compile, $rootScope; beforeEach(module('sampleApp')); beforeEach(inject(function(_$compile_, _$rootScope_){ $compile = _$compile_; $rootScope = _$rootScope_; })); it('Check the directive', function() { // Compile a piece of HTML containing the directive var element = $compile("<guru99></guru99>")($rootScope); $rootScope.$digest(); expect(element.html()).toContain("This is AngularJS Testing"); }); });
Testen ovenfor vil kjรธre i karma-nettleseren og gi samme bestรฅtt resultat som ble vist i forrige emne.
End-to-end-testing av AngularJS-applikasjoner
Rammeverket for karmatesting sammen med et rammeverk kalt Protractor har funksjonaliteten til รฅ teste en webapplikasjon fra ende til ende.
Sรฅ det er ikke bare testing av direktiver og kontrollere, men ogsรฅ testing av alt annet som kan vises pรฅ en HTML-side.
La oss se pรฅ et eksempel pรฅ hvordan vi kan oppnรฅ dette.
I vรฅrt eksempel nedenfor skal vi ha en AngularJS-applikasjon som lager en datatabell ved รฅ bruke ng-repeat-direktivet.
- Vi lager fรธrst en variabel kalt "tutorial" og tildeler den noen nรธkkelverdi-par i ett trinn. Hvert nรธkkel-verdi-par vil bli brukt som data nรฅr tabellen vises. Opplรฆringsvariabelen tilordnes deretter scope-objektet slik at det kan nรฅs fra vรฅrt syn.
- For hver rad med data i tabellen bruker vi ng-repeat-direktivet. Dette direktivet gรฅr gjennom hvert nรธkkelverdi-par i opplรฆringsomfangsobjektet ved รฅ bruke variabelen ptutor.
- Til slutt bruker vi tag sammen med nรธkkelverdiparene (ptutor.Name og ptutor.Description) for รฅ vise tabelldataene.
<table> <tr ng-repeat="ptutor in tutorial"> <td>{{ ptutor.Name }}</td> <td>{{ ptutor.Description }}</td> </tr> </table> </div> <script type="text/javascript"> var app = angular.module('DemoApp', []); app.controller('DemoController', function($scope) { $scope.tutorial = [ {Name: "Controllers", Description: "Controllers in action"}, {Name: "Models", Description: "Models and binding data"}, {Name: "Directives", Description: "Flexibility of Directives"} ]; });
Nรฅr koden ovenfor er utfรธrt vellykket, vil neste trinn vรฆre รฅ lage en testcase for รฅ sikre at koden er skrevet og utfรธrt pรฅ riktig mรฅte. Koden for testen vรฅr vil vรฆre som vist nedenfor
Testen vรฅr skal faktisk teste ng-repeat-direktivet og sikre at den inneholder 3 rader med data, slik den skal fra eksemplet ovenfor.
Fรธrst mรฅ vi sikre at fรธlgende forutsetning er pรฅ plass
Installer proffentractor-biblioteket via npm. Dette kan gjรธres ved รฅ kjรธre linjen nedenfor i kommandolinjen
npm install -g protractor
Koden for testen vรฅr vil vรฆre som vist nedenfor.
Koden vil vรฆre i en egen fil kalt CompleteTest.js , som vil bli plassert i testmappen. Koden nedenfor gjรธr bare fรธlgende viktige ting
- Nettleserfunksjonen leveres av proentractor-biblioteket og antar at AngularJS-applikasjonen vรฅr (med koden vist ovenfor) kjรธrer pรฅ nettstedet vรฅrt URL โ http://localhost:8080/Guru99 /
- var list = element.all(by.repeater('ptutor in tutorial')); -Denne kodelinjen henter faktisk ng-repeat-direktivet, som er fylt ut av koden 'ptutor in tutorial'. Elementet og by.repeater er spesielle nรธkkelord levert av pro-en.tractor-bibliotek som lar oss fรฅ detaljer om ng-repeat-direktivet.
- forventer(liste.antall()).toEqual(3); โ Til slutt bruker vi forventningsfunksjonen for รฅ se at vi faktisk fรฅr 3 elementer som fylles ut i tabellen vรฅr som et resultat av ng-repeat-direktivet.
describe('Unit testing end to end', function() { beforeEach(function() { browser.get('http://localhost:8080/Guru99/'); }); it('Check the ng directive', function() { var list = element.all(by.repeater('ptutor in tutorial')); expect(list.count()).toEqual(3); }); });
Testen ovenfor vil kjรธre i karma-nettleseren og gi samme bestรฅtt resultat som ble vist i forrige emne.
Karma vs. Jasmine vs. Protractor: Viktige forskjeller
De tre verktรธyene som brukes pรฅ denne siden blir ofte forvekslet fordi de vises i samme kommandolinje. Hvert av dem opptar et annet lag i teststakken, noe tabellen nedenfor viser tydelig.
| Parameter | Karma | Jasmine | Protractor |
| Kategori | Testlรธper | Spesifikasjonsrammeverk | Rammeverk for automatisering fra ende til ende |
| Hovedjobb | Starter nettlesere og rapporterer resultater | Gir beskrivelse, det og forventning | Kjรธrer en live-applikasjon i en ekte nettleser |
| Testnivรฅ | Enhet og integrering | Enhet og integrasjon | Ende til ende |
| Trenger en fungerende server | Nei | Nei | Ja |
| Konfigurasjonsfil | karma.conf.js | Ingen, den gรฅr inni en lรธper | fortractor.conf.js |
| Nรฅvรฆrende status | Utdatert, kun vedlikehold | Aktivt vedlikeholdt | Pensjonerte seg i august 2023 |
Kort sagt, Jasmine skriver testen, Karma utfรธrer den, og Protractor utvider den samme Jasmine-syntaksen til en fullstendig gjengitt side.
Beste praksis for AngularJS-enhetstesting
Et lite sett med vaner holder en AngularJS-pakke rask og pรฅlitelig etter hvert som applikasjonen vokser.
- Test รฉn enhet om gangen. Last bare inn modulen som testes i beforeEach, og simuler alle samarbeidspartnere slik at en feil peker mot รฉn enkelt fil.
- Ring aldri en ekte backend. Bruk $httpBackend-tjenesten fra angular-mocks for รฅ returnere ferdiglagde svar. Testene kjรธres deretter offline og gir identiske resultater pรฅ alle maskiner.
- Hold spesifikasjonsnavnene atferdsmessige. Et navn som ยซreturnerer 5 nรฅr kontrolleren initialiseresยป leses bedre i en rapport enn ยซtest1ยป.
- Skyll alltid nedbrytningssyklusen. Kall $rootScope.$digest() etter รฅ ha endret omfangsdata, ellers oppdateres aldri bindinger og overvรฅkere, og pรฅstander mislykkes av feil grunn.
- Mรฅl dekningen, men vurder den nรธye. Legg til karma-dekning for รฅ se uprรธvde grener. Hรธy dekning med svake pรฅstander skjuler fortsatt feil.
- Kjรธr pakken i kontinuerlig integrasjon. Bruk en headless Chrome launcher slik at de samme spesifikasjonene kjรธres pรฅ hver commit i stedet for bare pรฅ en utviklermaskin.
Ved รฅ bruke disse reglene blir eksemplene ovenfor omgjort fra isolerte demonstrasjoner til et regresjonssikkerhetsnett for en eldre AngularJS-kodebase. For et stรธrre bilde, se AngularJS-veiledning serien.

