İlk AngularJS Uygulaması Eğitimi Bölüm 2: İskele, İnşa ve Test Araçları
Yayınlanan: 2022-03-11Tanıtım
AngularJS uygulamalarını geliştirmeye yardımcı olacak birçok araçla, birçok insan bunun son derece karmaşık bir çerçeve olduğu izlenimine sahip, ki bu hiç de öyle değil. Bu eğitim serisine başlamamın ana nedenlerinden biri de bu.
Birinci bölümde, AngularJS çerçevesinin temellerini ele aldık ve ilk uygulamamızı yazarak başladık. Bu yazı yeni başlayanlar için tasarlanmıştır. Daha deneyimli bir AngularJS geliştiricisiyseniz, büyüyen bir startup'ta kullanımda olan yönergeleri veya AngularJS'nin hikayesini açığa çıkarmakla daha çok ilgilenebilirsiniz.
Bu öğreticide, uygulama mantığı katmanını bir kenara koyacağız ve iskele, bağımlılık yönetimi dahil olmak üzere uygun AngularJS proje kurulumunu nasıl gerçekleştireceğimizi ve test için hazırlamayı öğreneceğiz (hem ünite hem de uçtan uca). Bunu şu AngularJS araçlarını kullanarak yapacağız: Yeoman, Grunt ve Bower. Ardından, Karma kullanarak Jasmine testleri yazma ve çalıştırma sürecini gözden geçireceğiz.
Karma, Jasmine, Grunt, Bower, Yeoman… Bütün bu araçlar nelerdir?
JavaScript ile çalışıyorsanız, Angular'da yeni olsanız bile, bu araçlardan en azından bazılarını zaten biliyorsunuzdur. Ancak ortak bir temel sağlamaya yardımcı olmak için herhangi bir varsayımda bulunmaktan kaçınacağım. Bu teknolojilerin her birini ve ne işe yaradığını kısaca gözden geçirelim:
Karma (önceden Testacular olarak bilinir) Google'ın JavaScript test çalıştırıcısıdır ve AngularJS'yi test etmek için doğal seçimdir. Testlerinizi gerçek tarayıcılarda (telefon/tablet tarayıcıları dahil) çalıştırmanıza izin vermesinin yanı sıra, test çerçevesi agnostiktir ; bu, onu seçtiğiniz herhangi bir test çerçevesiyle (diğerlerinin yanı sıra Jasmine, Mocha veya QUnit gibi) birlikte kullanabileceğiniz anlamına gelir.
Jasmine, en azından bu yazı için tercih ettiğimiz test çerçevemiz olacak. Sözdizimi, bununla daha önce çalıştıysanız, RSpec'inkine oldukça benzer. (Yapmadıysanız endişelenmeyin; bu eğitimde daha sonra daha ayrıntılı olarak kontrol edeceğiz.)
Grunt, küçültme, derleme (veya derleme), test etme ve AngularJS uygulamanızın önizlemesini ayarlama gibi birçok tekrarlayan görevi otomatikleştirmeye yardımcı olan bir görev çalıştırıcıdır.
Bower, CSS çerçeveleri, JavaScript kitaplıkları vb. gibi tüm uygulama bağımlılıklarınızı bulmanıza ve yüklemenize yardımcı olan bir paket yöneticisidir. Rails paketleyici gibi git üzerinden çalışır ve bağımlılıkları manuel olarak indirme ve güncelleme ihtiyacını ortadan kaldırır.
Yeoman, 3 temel bileşen içeren bir araç setidir: Grunt, Bower ve iskele aracı Yo. Yo, oluşturucuların (sadece iskele şablonlarıdır) yardımıyla ortak kod oluşturur ve projeniz için Grunt ve Bower'ı otomatik olarak yapılandırır. Hemen hemen her JavaScript çerçevesi (Angular, Backbone, Ember, vb.) için oluşturucular bulabilirsiniz, ancak burada Angular'a odaklandığımız için jeneratör-angular projesini kullanacağız.
Peki, nereden başlıyoruz?
Pekala, yapmamız gereken ilk şey, ihtiyaç duyacağımız araçları kurmak.
Git, node.js ve npm zaten kurulu değilse, devam edin ve kurun.
Ardından komut satırına gideceğiz ve Yeoman'ın araçlarını yüklemek için aşağıdaki komutu çalıştıracağız:
npm install -g yo grunt-cli bower
Oh, ve unutmayın, AngularJS oluşturucusunu kullanacağız, bu yüzden onu da yüklemeniz gerekecek:
npm install -g generator-angular
Tamam, şimdi hazırız…
AngularJS uygulamamızı iskele/oluşturma
Geçen sefer, angular-seed projesinden standart kodumuzu manuel olarak ödünç aldık. Bu sefer, sizin (jeneratör-açısal ile bağlantılı olarak) bunu bizim için yapmanıza izin vereceğiz.
Tek yapmamız gereken yeni proje klasörümüzü oluşturmak, ona gitmek ve çalıştırmak:
yo angular
Bootstrap ve Compass'ı dahil edip etmeme gibi bazı seçeneklerle karşılaşacağız. Şimdilik Compass'a hayır , Bootstrap'a evet diyelim. Ardından, hangi modüllerin dahil edileceği sorulduğunda (kaynak, tanımlama bilgileri, sterilize etme ve yönlendirme), yalnızca angular-route.js
öğesini seçeceğiz.
Proje iskelemiz şimdi oluşturulmalı (bir dakika sürebilir), Karma ile entegre ve önceden yapılandırılmış olmalıdır.
Not: Buradaki modülleri, bu öğreticinin birinci bölümünde oluşturduğumuz uygulamada kullandığımız modüllerle sınırladığımızı unutmayın. Bunu kendi projeniz için yaptığınızda, dahil etmeniz gereken modülleri belirlemek size kalmış olacaktır.
Şimdi Jasmine kullanacağımıza göre karma-jasmine
adaptörünü projemize ekleyelim:
npm install karma-jasmine --save-dev
Testlerimizin bir Chrome örneğinde yürütülmesini istiyorsak, karma-chrome-launcher
da ekleyelim:
npm install karma-chrome-launcher --save-dev
Tamam, her şeyi doğru yaptıysak, şimdi proje dosya ağacımız şu şekilde görünmelidir:
Statik uygulama kodumuz app/
dizinine girer ve test/
dizini testlerimizi içerecektir (evet, tahmin ettiniz!). Root üzerinde gördüğümüz dosyalar proje konfigürasyon dosyalarımızdır. Her biri hakkında öğrenilecek çok şey var, ancak şimdilik sadece varsayılan konfigürasyona bağlı kalacağız. Şimdi aşağıdaki komutla basitçe yapabileceğimiz uygulamamızı ilk kez çalıştıralım:
grunt serve
Ve işte! Uygulamamız artık önümüze çıkmalı!
AngularJS için Bower hakkında biraz
Gerçekten önemli kısma (yani teste) geçmeden önce, Bower hakkında biraz daha bilgi edinmek için bir dakikanızı ayıralım. Daha önce de belirtildiği gibi, Bower paket yöneticimizdir. Projemize bir lib veya eklenti eklemek, basitçe bower install
komutu kullanılarak yapılabilir. Örneğin, modernizr
dahil etmek için tek yapmamız gereken şudur (elbette proje dizinimizin içinde):
bower install modernizr
Bununla birlikte, bu, modernizr
projemizin bir parçası yapsa da ( app/bower_components
dizininde bulunacaktır), ihtiyaç duyduğumuz şekilde onu uygulamamıza dahil etmekten (veya ne zaman dahil edileceğini yönetmekten) hala sorumluyuz. manuel olarak eklenen herhangi bir lib ile yapmak için. Bunu yapmanın bir yolu, aşağıdaki <script>
etiketini index.html
eklemektir:
<script src="bower_components/modernizr/modernizr.js"></script>
Alternatif olarak, bağımlılıklarımızı yönetmek için bower.json
dosyasını kullanabiliriz. Şimdiye kadarki her adımı dikkatlice takip ettikten sonra, bower.json
dosyası şöyle görünmelidir:
{ "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" } }
Sözdizimi oldukça açıklayıcıdır, ancak burada daha fazla bilgi mevcuttur.
Daha sonra istediğimiz yeni bağımlılıkları ekleyebiliriz ve ardından bunları yüklemek için tek ihtiyacımız olan aşağıdaki komuttur:
bower install
Şimdi bazı testler yazalım!
Tamam, şimdi birinci bölümde kaldığımız yerden devam etme ve AngularJS uygulamamız için bazı testler yazma zamanı.
Ama önce, ele almamız gereken küçük bir sorun var: Generator-angular geliştiricileri proje şablonlarını angular-seed projesine (resmi Angular kazan plakasıdır) dayandırsalar da, nedense gerçekten anlamıyorum, karar verdiler. app
klasörü adlandırma kurallarını değiştirmek için ( css
styles
, js
scripts
vb. olarak değiştirmek).

Sonuç olarak, orijinal olarak yazdığımız uygulama şimdi, az önce oluşturduğumuz iskele ile tutarsız olan yollara sahip. Bunu aşmak için, buradan uygulama kodunu indirelim ve bu noktadan itibaren bu sürümle çalışalım (çoğunlukla orijinal olarak yazdığımız uygulamanın aynısıdır, ancak yollar üretici-açısal adlandırmayla eşleşecek şekilde güncellenmiştir).
Uygulamayı indirdikten sonra, tests/spec/controllers
klasörüne gidin ve aşağıdakileri içeren drivers.js
adlı bir dosya oluşturun:
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"); }); });
Bu, sürücü denetleyicimiz için test driverscontroller
. Çok fazla kod gibi görünebilir, ancak çoğu aslında sadece sahte veri bildirimidir. Gerçekten önemli unsurlara hızlıca bir göz atalım:
-
describe()
yöntemi, test takımımızı tanımlar. - Her
it()
uygun bir test özelliğidir. - Her
beforeEach()
işlevi, testlerin her birinin hemen öncesinde yürütülür.
Buradaki en önemli (ve potansiyel olarak kafa karıştırıcı) öğe, httpMock
değişkeninde somutlaştırdığımız $httpBackend
hizmetidir. Bu hizmet, sahte bir arka uç görevi görür ve tıpkı gerçek sunucumuzun üretimde yapacağı gibi, test çalıştırmalarında API çağrılarımıza yanıt verir. Bu durumda, expectJSONP()
işlevini kullanarak, onu verilen URL'ye (sunucudan bilgi almak için kullandığımızla aynı) herhangi bir JSONP isteğini engelleyecek ve bunun yerine, gerçek sunucu yanıtı. Bu, kontrolörden neyin geri gelmesi gerektiğini kesin olarak bilmemizi sağlar. Bu nedenle, expect()
işlevini kullanarak sonuçları beklenenlerle karşılaştırabiliriz. Eşleşirlerse, test geçer.
Testleri çalıştırmak basitçe şu komutla yapılır:
grunt test
Sürücü ayrıntıları denetleyicisi ( drivercontroller
) için test paketi, az önce gördüğümüze oldukça benzer olmalıdır. Bunu bir egzersiz olarak kendi başınıza çözmeyi denemenizi tavsiye ederim (ya da bilmiyorsanız buraya bir göz atabilirsiniz).
Uçtan uca AngularJS testleri ne olacak?
Angular ekibi kısa süre önce, Protractor adlı uçtan uca testler için yeni bir koşucu tanıttı. Tarayıcıda çalışan uygulama ile etkileşim kurmak için web sürücüsünü kullanır ve ayrıca varsayılan olarak Jasmine test çerçevesini kullanır, bu nedenle sözdizimi birim testlerimizinkiyle oldukça tutarlı olacaktır.
İletki oldukça yeni bir araç olduğundan, Yeoman yığını ve oluşturucu generator-angular
ile entegrasyon hala oldukça fazla yapılandırma çalışması gerektiriyor. Bunu göz önünde bulundurarak ve bu öğreticiyi olabildiğince basit tutma niyetimle, planım gelecekteki bir gönderiyi yalnızca AngularJS'de uçtan uca testleri derinlemesine ele almaya adamak.
Çözüm
Eğitim serisinin bu noktasında, Angular uygulamamızı yo
ile nasıl kuracağımızı, bağımlılıklarını bower
ile nasıl yöneteceğimizi ve karma
ve protractor
kullanarak bazı testler yazmayı/çalıştırmayı öğrendik. Ancak, bu öğreticinin yalnızca bu AngularJS araçlarına ve uygulamalarına bir giriş niteliğinde olduğunu unutmayın; Hiçbirini burada derinlemesine analiz etmedik.
Amacımız sadece bu yola başlamanıza yardımcı olmaktı. Buradan, devam etmek ve bu harika çerçeve ve araç takımı hakkında öğrenebileceğiniz her şeyi öğrenmek size kalmış.
Ek: Yazardan bazı (önemli) notlar
Bu öğreticiyi okuduktan sonra, bazı insanlar “Bekle. Uygulamanızı kodlamaya başlamadan önce tüm bunları yapmanız gerekmiyor mu? Bunun bu eğitimin bir parçası olması gerekmez miydi?”
Buna kısa cevabım hayır . Birinci bölümde gördüğümüz gibi, aslında ilk Angular uygulamanızı kodlamak için tüm bunları bilmenize gerek yok. Bunun yerine, bu gönderide tartıştığımız araçların çoğu, geliştirme iş akışınızı optimize etmenize ve Test Odaklı Geliştirme (TDD) uygulamanıza yardımcı olmak için tasarlanmıştır.
Ve TDD'den bahsetmişken, TDD'nin en temel konsepti kesinlikle sağlam bir kavramdır; yani, kodunuzu yazmadan önce testlerinizi yazın. Yine de bazı insanlar bu kavramı çok ileri götürüyor. TDD bir öğrenme yöntemi değil , bir geliştirme uygulamasıdır. Buna göre, testlerinizi kodunuzu yazmadan önce yazmak çok mantıklıyken, kodlamayı öğrenmeden önce testlerinizi nasıl yazacağınızı öğrenmek pek mantıklı değil.
Şahsen, resmi Angular öğreticilerinin bu kadar karmaşık hissetmesinin ve daha önce ön uç MVC/TDD deneyimi olmayan kişiler için takip etmenin neredeyse imkansız olmasının ana nedeninin bu olduğunu düşünüyorum. Bu eğitim serisine başlamamın ana nedenlerinden biri de bu.
AngularJS dünyasında gezinmeyi öğrenenler için kişisel tavsiyem şudur: Kendinize fazla yüklenmeyin. Her şeyi bir anda öğrenmenize gerek yok (insanlar size aksini söylese de!). Diğer ön uç/test çerçeveleriyle olan önceki deneyiminize bağlı olarak, AngularJS'yi başlangıçta anlamak oldukça zor olabilir. Bu nedenle, kendi basit uygulamalarınızı yazabilecek duruma gelene kadar öğrenmeniz gereken her şeyi öğrenin ve ardından, çerçevenin temelleri konusunda rahat olduğunuzda, sizin için en iyi olan uzun vadeli geliştirme uygulamalarını seçme ve uygulama ile ilgilenebilirsiniz. sen.
Tabii ki, bu benim alçakgönüllü görüşüm ve herkes bu yaklaşımı kabul etmeyecek (ve Angular geliştirici ekibi bunu yayınladıktan sonra benden sonra kiralık bir katil gönderebilir), ancak bu benim vizyonum ve eminim ki bu birçok insan orada benimle aynı fikirde olacak.