С многото налични инструменти за подпомагане на развитието Ъглов JS приложения, много хора имат впечатлението, че това е изключително сложна рамка, което съвсем не е така. Това е една от основните причини да започна тази поредица с уроци.
В част първа ние разгледахме основите на рамката AngularJS и започнахме, като написахме първото си приложение. Тази публикация е предназначена за начинаещи. Ако сте повече опитен разработчик на AngularJS , може да ви интересува повече демистифициращи директиви или история на AngularJS се използва при нарастващ стартъп .
В този урок ще оставим настрана логическия слой на приложението и ще се научим как да провеждаме правилната настройка на проекта на AngularJS, включително скеле, управление на зависимостите и подготовката му за тестване (както единица, така и от край до край). Ще направим това, като използваме тези инструменти на AngularJS: Yeoman, Grunt и Bower. След това ще прегледаме процеса на писане и провеждане на тестове за жасмин с помощта на Карма.
Ако работите с JavaScript, е много вероятно вече да знаете поне някои от тези инструменти, дори и да сте нови Ъглова . Но за да се гарантира обща изходна линия, ще избегна да правя каквито и да било предположения. Нека да разгледаме накратко всяка от тези технологии и за какво е полезна:
Карма (известен преди като Testacular) е тестовият бегач на Google за JavaScript и естественият избор за тестване на AngularJS. Освен че ви позволява да провеждате тестовете си на реални браузъри (включително браузъри за телефони / таблети), това също е така тест агностик ; което означава, че можете да го използвате заедно с всякакви тестова рамка по ваш избор (като Жасмин, Мока , или QUnit , наред с други).
Жасмин ще бъде избраната от нас тестова рамка, поне за тази публикация. Синтаксисът му е доста подобен на този на RSpec , ако някога сте работили с това. (Ако не сте, не се притеснявайте; ще го разгледаме по-подробно по-късно в този урок.)
Земя е бегач на задачи, който помага за автоматизиране на няколко повтарящи се задачи, като например минификация , компилация (или компилация), тестване и настройка на визуализация на вашето приложение AngularJS.
Бауър е мениджър на пакети, който ви помага да намерите и инсталирате всички зависимости на приложението си, като CSS рамки, JavaScript библиотеки и т.н. Той прегазва git, подобно на Комплект за релси и избягва необходимостта от ръчно изтегляне и актуализиране на зависимости.
Йеоман е набор от инструменти, съдържащ 3 основни компонента: Grunt, Bower и инструмента за скеле Аз . Yo генерира шаблонния код с помощта на генератори (които са просто шаблони за скеле) и автоматично конфигурира Grunt и Bower за вашия проект. Можете да намерите генератори за почти всяка рамка на JavaScript (Angular, Backbone, Ember и др.), Но тъй като тук се фокусираме върху Angular, ще използваме генератор-ъглови проект.
Е, първото нещо, което ще трябва да направим, е да инсталираме инструментите, от които ще се нуждаем.
кой c език да науча
Ако нямате отивам , node.js , и над морското равнище вече инсталирани, продължете и ги инсталирайте.
След това ще отидем в командния ред и ще изпълним следната команда, за да инсталираме инструментите на Yeoman:
npm install -g yo grunt-cli bower
О, и не забравяйте, ще използваме генератора AngularJS, така че ще трябва да го инсталирате и:
npm install -g generator-angular
Добре, сега сме готови да ...
Последен път , ние ръчно заимствахме нашия шаблонния код от ъглово семе проект. Този път ще оставим йо (заедно с ъглово генератор) да направи това вместо нас.
Всичко, което трябва да направим, е да създадем нашата нова папка на проекта, да отидем до нея и да стартираме:
yo angular
Ще ни бъдат представени някои опции, като например дали да включим или не Bootstrap и Компас . Засега, да кажем не до Компас и да до Bootstrap. След това, когато бъдете подканени кои модули да включите (ресурс, бисквитки, дезинфекция и маршрут), ще изберем само angular-route.js
Нашето скеле на проекта вече трябва да бъде създадено (може да отнеме минута), интегрирано с Karma и всички предварително конфигурирани.
Забележка: Имайте предвид, че тук ограничаваме модулите до тези, които използвахме в приложението, което вградихме част първа от този урок. Когато правите това за собствения си проект, от вас зависи да определите кои модули ще трябва да включите.
Сега, тъй като ще използваме Жасмин, нека добавим karma-jasmine
адаптер към нашия проект:
npm install karma-jasmine --save-dev
В случай, че искаме тестовете ни да бъдат изпълнени на екземпляр на Chrome, нека добавим и karma-chrome-launcher
:
npm install karma-chrome-launcher --save-dev
Добре, ако направихме всичко както трябва, нашето файлово дърво на проекта сега трябва да изглежда така:
Нашият статичен код за приложение отива в app/
директория и test/
директория ще съдържа (да, познахте!) нашите тестове. Файловете, които виждаме в корена, са нашите конфигурационни файлове на проекта. Може да се научи много за всеки един от тях, но засега просто ще се придържаме към конфигурацията по подразбиране. Така че нека стартираме нашето приложение за първи път, което можем да направим просто със следната команда:
grunt serve
И вуаля! Нашето приложение сега трябва да изскочи пред нас!
Преди да влезем в наистина важната част (т.е. тестването), нека отделим малко време, за да научим малко повече за това Бауър . Както споменахме по-рано, Bower е нашият мениджър на пакети. Добавянето на lib или плъгин към нашия проект може просто да се извърши с помощта на bower install
команда. Например, за да включим modernizr
, всичко, което трябва да направим, е следното (в нашата директория на проекта, разбира се):
bower install modernizr
Имайте предвид обаче, че макар това да прави modernizr
част от нашия проект (той ще се намира в директорията app/bower_components
), ние все още носим отговорност за включването му в нашето приложение (или управление, когато трябва да бъде включено), както би трябвало да направим с всеки ръчно добавен lib. Един от начините да направите това е просто да добавите следния етикет към нашия index.html
:
bower.json
Като алтернатива можем да използваме bower.json
файл за управление на нашите зависимости. След внимателно проследяване на всяка стъпка досега, { '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' } }
файлът трябва да изглежда така:
bower install
Синтаксисът е доста обяснителен, но има повече информация тук .
След това можем да добавим всякакви допълнителни нови зависимости, които искаме, и тогава всичко, от което се нуждаем, е следната команда за тяхното инсталиране:
app
Добре, сега е време действително да продължим оттам, откъдето сме спрели част първа и напишете няколко теста за нашето приложение AngularJS.
Но първо, има малък проблем, който трябва да разрешим: Въпреки че разработчиците на генератор-ъглови базират своя шаблон на проект на ъглово семе проект (който е официалният ъглов шаблон), по някаква причина наистина не разбирам, те решиха да променят css
конвенции за именуване на папки (промяна styles
на js
, scripts
на tests/spec/controllers
и т.н.).
В резултат на това приложението, което първоначално написахме, вече има пътища, които не съответстват на скелето, което току-що генерирахме. За да заобиколим това, нека изтеглим кода на приложението от тук и работи с тази версия от този момент нататък (това е предимно точно същото приложение, което първоначално написахме, но с пътищата, актуализирани, за да съответстват на ъгълното именуване на генератора).
След като изтеглите приложението, отворете drivers.js
папка и създайте файл с име 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'); }); });
съдържащи следното:
driverscontroller
Това е тестовият пакет за нашите describe()
. Може да изглежда като много код, но по-голямата част от него всъщност е просто фалшива декларация за данни. Нека да разгледаме набързо наистина важните елементи:
it()
метод дефинира нашия тестов пакет.beforeEach()
е подходяща спецификация за тест.$httpBackend
функция се изпълнява точно преди всеки от тестовете.Най-важният (и потенциално объркващ) елемент тук е httpMock
услуга, която създадохме на expectJSONP()
променлива. Тази услуга действа като фалшив back-end и реагира на нашите API извиквания при тестовите пускове, точно както действителният ни сървър би направил в производството. В този случай, използвайки expect()
функция, ние го настройваме да прихваща всякакви JSONP заявки към дадения URL (същият, който използваме за получаване на информацията от сървъра) и вместо това връщаме статичен списък с три драйвера, имитиращи истинския отговор на сървъра. Това ни позволява да знаем със сигурност какво трябва да се върне от контролера. Следователно можем да сравним резултатите с очакваните, използвайки grunt test
функция. Ако те съвпадат, тестът ще премине.
Изпълнението на тестовете се извършва просто с командата:
drivercontroller
Тестовият пакет за контролера с подробности за драйвера (generator-angular
) трябва да бъде доста подобен на този, който току-що видяхме. Препоръчвам ви да се опитате да го разберете сами като упражнение (или можете просто да погледнете тук , ако не сте до него).
Екипът на Angular наскоро представи нов бегач за тестове от край до край, наречен Транспортир . Използва уеб драйвер за да взаимодейства с приложението, изпълнявано в браузъра, а също така използва рамката за тестване на Jasmine по подразбиране, така че синтаксисът ще бъде в съответствие с този на нашите модулни тестове.
Тъй като Protractor е доста нов инструмент, това е интеграция със стека на Yeoman и yo
все още изисква доста работа по конфигурирането. Имайки предвид това и намерението ми да направя този урок възможно най-опростен, моят план е да посветя бъдеща публикация изключително на задълбочено обхващане на тестване от край до край в AngularJS.
На този етап от поредицата с уроци научихме как да скелираме нашето Angular приложение с bower
, да управляваме неговите зависимости с karma
и да напишем / стартираме някои тестове, използвайки protractor
и
|_+_|. Имайте предвид обаче, че този урок е предназначен само като въведение в тези инструменти и практики на AngularJS; не анализирахме нито един от тях тук в дълбочина.
Нашата цел е просто да ви помогнем да започнете по този път. Оттук нататък зависи да продължите и да научите всичко, което можете за тази невероятна рамка и набор от инструменти.
След като прочетат този урок, някои хора могат да попитат, 'Изчакайте. Не трябва ли да правите всички тези неща, преди действително да започнете да кодирате приложението си? Не трябваше ли това да е част от този урок? '
Моят кратък отговор на това е не . Както видяхме в част първа, всъщност не е нужно да знаете всички тези неща, за да кодирате първото си приложение Angular. По-скоро повечето от инструментите, които обсъдихме в тази публикация, са създадени, за да ви помогнат да оптимизирате работния процес на разработката си и да практикувате разработено чрез тест (TDD).
И като говорим за TDD, най-основната концепция за TDD със сигурност е една здрава; а именно, напишете тестовете си, преди да напишете кода си. Някои хора обаче приемат тази концепция твърде далеч. TDD е практика за развитие, не метод на обучение. Съответно, писане вашите тестове, преди да напишете кода си, имат много смисъл, докато научавайки как да напишете тестовете си, преди да научите как да кодирате не.
Аз лично смятам, че това е основната причина официалните уроци по Angular да се чувстват толкова объркани и да са почти невъзможни за проследяване за хора без предишен MVC / TDD опит. Това е една от основните причини, поради които започнах тази поредица с уроци.
Моят личен съвет за тези, които се учат да се ориентират в света AngularJS е: Не бъдете прекалено твърди към себе си. Не е нужно да научите всичко наведнъж (въпреки че хората ви казват друго!). В зависимост от предишния ви опит с други фронт-енд / тестови рамки, AngularJS може да бъде доста трудно да се разбере първоначално. Така че научете всичко, което трябва да научите, докато не можете да напишете свои собствени прости приложения и след това, след като се запознаете с основите на рамката, можете да се занимавате с избора и прилагането на дългосрочните практики за развитие, които работят най-добре за Вие.
Разбира се, това е моето скромно мнение и не всеки ще се съгласи с този подход (и екипът на Angular dev може да изпрати нает убиец след мен, след като публикувам това), но това е моята визия и съм почти сигурен, че има много хора там, който ще се съгласи с мен.
Свързани: Урок за ъглови 6: Нови функции с нова мощност