Med de mange verktøyene som er tilgjengelige for å hjelpe deg med å utvikle AngularJS applikasjoner, har mange inntrykk av at det er et ekstremt komplisert rammeverk, som slett ikke er tilfelle. Det er en av hovedgrunnene til at jeg startet denne opplæringsserien.
I del en vi dekket det grunnleggende i AngularJS-rammeverket og startet med å skrive vår første søknad. Dette innlegget er designet for nybegynnere. Hvis du er en mer erfaren AngularJS-utvikler , er du kanskje mer interessert i avmystifiserende direktiver eller en historie om AngularJS i bruk ved en voksende oppstart .
I denne opplæringen skal vi legge til side applikasjonslogikklaget og lære å gjennomføre riktig AngularJS-prosjektoppsett, inkludert stillas, avhengighetsadministrasjon og forberede det for testing (både enhet og ende-til-ende). Vi gjør dette ved hjelp av disse AngularJS-verktøyene: Yeoman, Grunt og Bower. Deretter vil vi gjennomgå prosessen med å skrive og kjøre Jasmine-tester ved hjelp av Karma.
Hvis du jobber med JavaScript, er det svært sannsynlig at du allerede kjenner til i det minste noen av disse verktøyene, selv om du ikke har begynt noe med det Vinklet . Men for å sikre en felles grunnlinje, vil jeg unngå å ta noen antakelser. La oss kort gjennomgå hver av disse teknologiene og hva den er nyttig for:
Karma (tidligere kjent som Testacular) er Googles JavaScript-testløper og det naturlige valget for å teste AngularJS. I tillegg til at du kan kjøre testene dine på ekte nettlesere (inkludert telefon- / nettbrettlesere), er det også det test rammeverk agnostiker ; som betyr at du kan bruke den sammen med noen testrammeverk etter eget valg (for eksempel Jasmine, Mokka , eller QUnit , blant andre).
Jasmin vil være vårt testrammeverk, i det minste for dette innlegget. Syntaksen er ganske lik den for RSpec , hvis du noen gang har jobbet med det. (Hvis du ikke har det, ikke bekymre deg; vi vil sjekke det ut nærmere senere i denne opplæringen.)
Bakke er en oppgaveløper som hjelper med å automatisere flere repeterende oppgaver, for eksempel minifisering , kompilering (eller bygging), testing og konfigurering av en forhåndsvisning av AngularJS-applikasjonen.
Bower er en pakkebehandling som hjelper deg med å finne og installere alle applikasjonsavhengighetene dine, for eksempel CSS-rammer, JavaScript-biblioteker og så videre. Det går over git, omtrent som Rails bundler , og unngår behovet for å laste ned og oppdatere avhengigheter manuelt.
Yeoman er et verktøysett som inneholder 3 kjernekomponenter: Grunt, Bower og stillasverktøyet Jeg . Yo genererer kokeplatekode ved hjelp av generatorer (som bare er stillasmaler) og konfigurerer automatisk Grunt og Bower for prosjektet ditt. Du kan finne generatorer for nesten alle JavaScript-rammeverk (Angular, Backbone, Ember, etc.), men siden vi her fokuserer på Angular, vil vi bruke generator-vinkel prosjekt.
Vel, det første vi trenger å gjøre er å installere verktøyene vi trenger.
Hvis du ikke har det gå , node.js , og over havnivå installert allerede, fortsett og installer dem.
Deretter går vi til kommandolinjen og kjører følgende kommando for å installere verktøyene til Yeoman:
npm install -g yo grunt-cli bower
Å, og ikke glem, vi skal bruke AngularJS-generatoren, så du må installere den også:
npm install -g generator-angular
OK, nå er vi klare til ...
Sist , lånte vi kildeplatekoden vår manuelt fra vinkelfrø prosjekt. Denne gangen lar vi deg (i forbindelse med generator-vinkel) gjøre det for oss.
Alt vi trenger å gjøre er å lage vår nye prosjektmappe, navigere til den og kjøre:
yo angular
Vi vil bli presentert for noen alternativer, for eksempel om de skal inkluderes eller ikke Støvelhempe og Kompass . For nå, la oss si Nei til Kompass og ja til Bootstrap. Når vi blir bedt om hvilke moduler som skal inkluderes (ressurs, informasjonskapsler, desinfiser og rute), velger vi bare angular-route.js
Prosjektstillaset vårt skal nå opprettes (det kan ta et øyeblikk), integrert med Karma og alt forhåndskonfigurert.
Merk: Husk at vi begrenser modulene her til de vi brukte i applikasjonen vi bygde inn del en av denne opplæringen. Når du gjør dette for ditt eget prosjekt, vil det være opp til deg å bestemme hvilke moduler du må inkludere.
Nå, siden vi skal bruke Jasmine, la oss legge til karma-jasmine
adapter til prosjektet vårt:
npm install karma-jasmine --save-dev
I tilfelle vi vil at testene våre skal utføres på en Chrome-forekomst, la oss også legge til karma-chrome-launcher
:
npm install karma-chrome-launcher --save-dev
OK, hvis vi gjorde alt riktig, burde prosjektfiltret vårt nå se slik ut:
Den statiske applikasjonskoden vår går inn i app/
katalog og test/
katalogen vil inneholde (yup, du gjettet det!) testene våre. Filene vi ser på roten er prosjektkonfigurasjonsfilene våre. Det er mye å lære om hver enkelt av dem, men foreløpig holder vi oss til standardkonfigurasjonen. Så la oss kjøre appen vår for første gang, som vi bare kan gjøre med følgende kommando:
grunt serve
Og voila! Appen vår skal nå dukke opp foran oss!
Før vi går inn i den virkelig viktige delen (dvs. testingen), la oss ta et øyeblikk å lære litt mer om Bower . Som nevnt tidligere, er Bower vår pakkesjef. Å legge til en lib eller plugin til prosjektet vårt kan ganske enkelt gjøres ved hjelp av bower install
kommando. For eksempel, for å inkludere modernizr
er alt vi trenger å gjøre følgende (i prosjektkatalogen vår, selvfølgelig):
bower install modernizr
Vær imidlertid oppmerksom på at mens dette gjør modernizr
en del av prosjektet vårt (det vil være i katalogen app/bower_components
), Vi er fortsatt ansvarlige for å inkludere det i søknaden vår (eller administrere når det skal inkluderes) som vi trenger å gjøre med en hvilken som helst manuelt lagt til lib. En måte å gjøre dette på er å bare legge til følgende merke i index.html
:
bower.json
Alternativt kan vi bruke bower.json
fil for å administrere våre avhengigheter. Etter å ha fulgt hvert trinn nøye til nå, { 'name': 'F1FeederApp', 'version': '0.0.0', 'dependencies': { 'angular': '1.2.15', 'json3': '~3.2.6', 'es5-shim': '~2.1.0', 'jquery': '~1.11.0', 'bootstrap': '~3.0.3', 'angular-route': '1.2.15' }, 'devDependencies': { 'angular-mocks': '1.2.15', 'angular-scenario': '1.2.15' } }
filen skal se slik ut:
bower install
Syntaksen er ganske selvforklarende, men mer informasjon er tilgjengelig her .
Vi kan da legge til eventuelle nye avhengigheter vi ønsker, og alt vi trenger er følgende kommando for å installere dem:
app
OK, nå er det på tide å faktisk hente fra der vi slapp del en og skriv noen tester for AngularJS-appen vår.
Men først er det et lite problem vi må løse: Selv om utviklerne av generator-vinkel baserte prosjektmalen sin på vinkelfrø prosjektet (som er den offisielle Angular boilerplate), av en eller annen grunn forstår jeg ikke helt, bestemte de seg for å endre css
konvensjoner om navngivning av mapper (endre styles
til js
, scripts
til tests/spec/controllers
, og så videre).
Som et resultat har appen vi opprinnelig skrev nå stier som ikke er i samsvar med stillaset vi nettopp genererte. For å komme deg rundt dette, la oss laste ned appkoden fra her og jobbe med den versjonen fra dette tidspunktet (det er for det meste nøyaktig den samme appen vi opprinnelig skrev, men med banene oppdatert for å matche generator-vinkelnavnet).
Etter nedlasting av appen, naviger til drivers.js
mappe og opprett en fil med navnet describe('Controller: driversController', function () { // First, we load the app's module beforeEach(module('F1FeederApp')); // Then we create some variables we're going to use var driversController, scope; beforeEach(inject(function ($controller, $rootScope, $httpBackend) { // Here, we create a mock scope variable, to replace the actual $scope variable // the controller would take as parameter scope = $rootScope.$new(); // Then we create an $httpBackend instance. I'll talk about it below. httpMock = $httpBackend; // Here, we set the httpBackend standard reponse to the URL the controller is // supposed to retrieve from the API httpMock.expectJSONP( 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK').respond( {'MRData': {'StandingsTable': {'StandingsLists' : [{'DriverStandings':[ { 'Driver': { 'givenName': 'Sebastian', 'familyName': 'Vettel' }, 'points': '397', 'nationality': 'German', 'Constructors': [ {'name': 'Red Bull'} ] }, { 'Driver': { 'givenName': 'Fernando', 'familyName': 'Alonso' }, 'points': '242', 'nationality': 'Spanish', 'Constructors': [ {'name': 'Ferrari'} ] }, { 'Driver': { 'givenName': 'Mark', 'familyName': 'Webber' }, 'points': '199', 'nationality': 'Australian', 'Constructors': [ {'name': 'Red Bull'} ] } ]}]}}} ); // Here, we actually initialize our controller, passing our new mock scope as parameter driversController = $controller('driversController', { $scope: scope }); // Then we flush the httpBackend to resolve the fake http call httpMock.flush(); })); // Now, for the actual test, let's check if the driversList is actually retrieving // the mock driver array it('should return a list with three drivers', function () { expect(scope.driversList.length).toBe(3); }); // Let's also make a second test checking if the drivers attributes match against // the expected values it('should retrieve the family names of the drivers', function () { expect(scope.driversList[0].Driver.familyName).toBe('Vettel'); expect(scope.driversList[1].Driver.familyName).toBe('Alonso'); expect(scope.driversList[2].Driver.familyName).toBe('Webber'); }); });
inneholder følgende:
driverscontroller
Dette er testpakken for describe()
. Det kan se ut som mye kode, men det meste er faktisk bare mock-datadeklarasjon. La oss se raskt på de virkelig viktige elementene:
it()
metoden definerer vår testpakke.beforeEach()
er en skikkelig testspesifikasjon.$httpBackend
funksjonen utføres rett før hver av testene.Det viktigste (og potensielt forvirrende) elementet her er httpMock
tjenesten som vi instanserte på expectJSONP()
variabel. Denne tjenesten fungerer som en falsk backend og svarer på API-anropene våre på testkjøring, akkurat som vår faktiske server ville gjort i produksjonen. I dette tilfellet bruker du expect()
funksjon, setter vi den til å fange opp JSONP-forespørsler til den angitte URL-en (den samme vi bruker for å få informasjonen fra serveren), og i stedet returnere en statisk liste med tre drivere, som etterligner den virkelige serverresponsen. Dette gjør det mulig for oss å vite sikkert hva som skal komme tilbake fra kontrolleren. Vi kan derfor sammenligne resultatene med de forventede ved å bruke grunt test
funksjon. Hvis de stemmer overens, vil testen bestå.
Å kjøre testene gjøres ganske enkelt med kommandoen:
drivercontroller
Testpakken for driverinformasjonskontrolleren (generator-angular
) skal være ganske lik den vi nettopp så. Jeg anbefaler at du prøver å finne ut av det selv som en øvelse (eller du kan bare ta en titt her , hvis du ikke er i stand til det).
Angular-teamet introduserte nylig en ny løper for end-to-end tester kalt Vinkelmåler . Det bruker webdriver for å samhandle med applikasjonen som kjører i nettleseren, og den bruker også Jasmine-testrammeverket som standard, slik at syntaksen vil være veldig konsistent med den for enhetstestene våre.
Siden Protractor er et ganske nytt verktøy, er det imidlertid integrering med Yeoman-stakken og yo
krever fortsatt en god del konfigurasjonsarbeid. Med det i tankene, og min intensjon om å holde denne opplæringen så enkel som mulig, er planen min å dedikere et fremtidig innlegg utelukkende til å dekke end-to-end-testing i AngularJS i dybden.
På dette punktet i opplæringsserien har vi lært hvordan vi kan stillas Angular-appen vår med bower
, administrere avhengighetene med karma
, og skrive / kjøre noen tester med protractor
og
|_+_|. Vær imidlertid oppmerksom på at denne opplæringen kun er ment som en introduksjon til disse AngularJS-verktøyene og praksisene; vi analyserte ingen av dem her i stor dybde.
Målet vårt har rett og slett vært å hjelpe deg i gang på denne veien. Herfra er det opp til deg å fortsette og lære alt du kan om dette fantastiske rammeverket og pakken med verktøy.
Etter å ha lest denne veiledningen kan noen spørre: 'Vente. Skal du ikke gjøre alt dette før du faktisk begynner å kode appen din? Burde ikke dette ha vært en del av denne veiledningen? '
Mitt korte svar på det er Nei . Som vi så i del en, trenger du ikke å vite alt dette for å kode din første Angular-app. Snarere er de fleste verktøyene vi har diskutert i dette innlegget designet for å hjelpe deg med å optimalisere arbeidsflyten din og øve deg på testdrevet utvikling (TDD).
Og når vi snakker om TDD, er det mest grunnleggende konseptet med TDD absolutt en lyd; nemlig skriv testene dine før du skriver koden. Noen mennesker tar imidlertid konseptet altfor langt. TDD er en utviklingspraksis, ikke en læringsmetode. Tilsvarende, skriving testene dine før du skriver koden gir mye mening, mens lære hvordan å skrive testene dine før du lærer å kode, gjør det ikke.
Jeg personlig synes dette er hovedårsaken til at de offisielle Angular-opplæringene kan føles så kronglete og kan være nesten umulige å følge for folk uten tidligere MVC / TDD-opplevelse på fronten. Det er en av hovedgrunnene til at jeg startet denne opplæringsserien.
Mitt personlige råd til de som lærer å navigere i AngularJS-verdenen er: Ikke vær for hard mot deg selv. Du trenger ikke å lære alt på en gang (til tross for at folk forteller deg noe annet!). Avhengig av din tidligere erfaring med andre front-end / test-rammer, kan AngularJS være ganske vanskelig å forstå i utgangspunktet. Så lær alt du trenger å lære til du er i stand til å skrive dine egne enkle apper, og så, når du er komfortabel med det grunnleggende i rammeverket, kan du bekymre deg for å velge og bruke de langsiktige utviklingsrutinene som fungerer best for du.
Selvfølgelig er det min ydmyke mening, og ikke alle er enige i den tilnærmingen (og Angular dev-teamet kan sende en leidemorder etter meg når jeg først publiserer dette), men det er min visjon, og jeg er ganske sikker på at det er mange mennesker der ute som vil være enig med meg.
I slekt: Angular 6 Tutorial: Nye funksjoner med ny kraft