Tutorial Aplikasi AngularJS Pertama Anda Bagian 2: Alat untuk Perancah, Pembuatan, dan Pengujian
Diterbitkan: 2022-03-11pengantar
Dengan banyaknya alat yang tersedia untuk membantu dalam mengembangkan aplikasi AngularJS, banyak orang memiliki kesan bahwa ini adalah kerangka kerja yang sangat rumit, padahal sebenarnya tidak demikian. Itulah salah satu alasan utama saya memulai seri tutorial ini.
Di bagian pertama kami membahas dasar-dasar kerangka kerja AngularJS dan memulai dengan menulis aplikasi pertama kami. Posting ini dirancang untuk pemula. Jika Anda seorang pengembang AngularJS yang lebih berpengalaman, Anda mungkin lebih tertarik untuk mengungkap arahan atau kisah AngularJS yang digunakan pada startup yang sedang berkembang.
Dalam tutorial ini, kita akan mengesampingkan lapisan logika aplikasi dan mempelajari cara melakukan penyiapan proyek AngularJS yang tepat, termasuk perancah, manajemen ketergantungan, dan mempersiapkannya untuk pengujian (baik unit maupun ujung ke ujung). Kami akan melakukannya menggunakan alat AngularJS ini: Yeoman, Grunt, dan Bower. Kemudian, kita akan meninjau proses menulis dan menjalankan tes Jasmine menggunakan Karma.
Karma, Jasmine, Grunt, Bower, Yeoman… Apa saja alat-alat ini?
Jika Anda bekerja dengan JavaScript, kemungkinan besar Anda sudah mengetahui setidaknya beberapa alat ini, bahkan jika Anda baru mengenal Angular. Tetapi untuk membantu memastikan garis dasar yang sama, saya akan menghindari membuat asumsi apa pun. Mari kita tinjau secara singkat masing-masing teknologi ini dan apa kegunaannya:
Karma (sebelumnya dikenal sebagai Testacular) adalah test runner JavaScript Google dan pilihan alami untuk menguji AngularJS. Selain memungkinkan Anda untuk menjalankan pengujian pada browser nyata (termasuk browser ponsel/tablet), ini juga menguji framework agnostic ; yang berarti Anda dapat menggunakannya bersama dengan kerangka pengujian pilihan Anda (seperti Jasmine, Mocha, atau QUnit, antara lain).
Jasmine akan menjadi kerangka pengujian pilihan kami, setidaknya untuk posting ini. Sintaksnya sangat mirip dengan RSpec, jika Anda pernah menggunakannya. (Jika belum, jangan khawatir; kami akan memeriksanya lebih detail nanti dalam tutorial ini.)
Grunt adalah task runner yang membantu mengotomatiskan beberapa tugas berulang, seperti minifikasi, kompilasi (atau build), pengujian, dan pengaturan pratinjau aplikasi AngularJS Anda.
Bower adalah manajer paket yang membantu Anda menemukan dan menginstal semua dependensi aplikasi Anda, seperti kerangka kerja CSS, pustaka JavaScript, dan sebagainya. Ini berjalan di atas git, seperti bundler Rails, dan menghindari kebutuhan untuk mengunduh dan memperbarui dependensi secara manual.
Yeoman adalah toolset yang berisi 3 komponen inti: Grunt, Bower, dan alat scaffolding Yo. Yo menghasilkan kode boilerplate dengan bantuan generator (yang hanya merupakan template scaffolding) dan secara otomatis mengonfigurasi Grunt dan Bower untuk proyek Anda. Anda dapat menemukan generator untuk hampir semua kerangka kerja JavaScript (Angular, Backbone, Ember, dll.), tetapi karena kami berfokus di sini pada Angular, kami akan menggunakan proyek generator-angular.
Jadi dari mana kita mulai?
Nah, hal pertama yang harus kita lakukan adalah menginstal alat yang kita perlukan.
Jika Anda belum menginstal git, node.js, dan npm, lanjutkan dan instal.
Kemudian kita akan pergi ke baris perintah dan menjalankan perintah berikut untuk menginstal alat Yeoman:
npm install -g yo grunt-cli bower
Oh, dan jangan lupa, kita akan menggunakan generator AngularJS jadi Anda harus menginstalnya juga:
npm install -g generator-angular
Oke, sekarang kita siap untuk…
Scaffold/hasilkan aplikasi AngularJS kami
Terakhir kali, kami secara manual meminjam kode boilerplate kami dari proyek angular-seed. Kali ini, kami akan membiarkan yo (dalam hubungannya dengan generator-angular) melakukannya untuk kami.
Yang perlu kita lakukan adalah membuat folder proyek baru kita, navigasikan ke sana dan jalankan:
yo angular
Kami akan disajikan dengan beberapa opsi, seperti apakah akan menyertakan Bootstrap dan Kompas atau tidak. Untuk saat ini, katakan tidak pada Compass dan ya pada Bootstrap. Kemudian, ketika ditanya tentang modul mana yang akan disertakan (sumber daya, cookie, sanitasi, dan rute), kami hanya akan memilih angular-route.js
.
Scaffold proyek kita sekarang harus dibuat (mungkin butuh satu menit), terintegrasi dengan Karma dan semuanya sudah dikonfigurasi sebelumnya.
Catatan: Ingatlah bahwa kami membatasi modul di sini untuk modul yang kami gunakan dalam aplikasi yang kami buat di bagian pertama tutorial ini. Ketika Anda melakukan ini untuk proyek Anda sendiri, terserah Anda untuk menentukan modul mana yang perlu Anda sertakan.
Sekarang, karena kita akan menggunakan Jasmine, mari tambahkan adaptor karma-jasmine
ke proyek kita:
npm install karma-jasmine --save-dev
Jika kita ingin pengujian kita dijalankan pada instance Chrome, mari tambahkan juga karma-chrome-launcher
:
npm install karma-chrome-launcher --save-dev
Oke, jika kita melakukan semuanya dengan benar, pohon file proyek kita sekarang akan terlihat seperti ini:
Kode aplikasi statis kami masuk ke direktori app/
dan direktori test/
akan berisi (ya, Anda dapat menebaknya!) pengujian kami. File yang kita lihat di root adalah file konfigurasi proyek kita. Ada banyak yang harus dipelajari tentang masing-masing dari mereka, tetapi untuk saat ini kita hanya akan tetap menggunakan konfigurasi default. Jadi mari kita jalankan aplikasi kita untuk pertama kalinya, yang dapat kita lakukan hanya dengan perintah berikut:
grunt serve
Dan voila! Aplikasi kita sekarang akan muncul di depan kita!
Sedikit tentang Bower untuk AngularJS
Sebelum masuk ke bagian yang sangat penting (yaitu, pengujian), mari luangkan waktu sebentar untuk belajar lebih banyak tentang Bower. Seperti disebutkan sebelumnya, Bower adalah manajer paket kami. Menambahkan lib atau plugin ke proyek kami dapat dilakukan dengan menggunakan perintah bower install
. Misalnya, untuk memasukkan modernizr
, yang perlu kita lakukan adalah sebagai berikut (tentu saja dalam direktori proyek kita):
bower install modernizr
Perhatikan, meskipun ini membuat modernizr
menjadi bagian dari proyek kami (itu akan ditempatkan di direktori app/bower_components
), kami masih bertanggung jawab untuk memasukkannya ke dalam aplikasi kami (atau mengelola kapan harus disertakan) seperti yang kami perlukan hubungannya dengan lib yang ditambahkan secara manual. Salah satu cara untuk melakukannya adalah dengan menambahkan tag <script>
berikut ke index.html
kami :
<script src="bower_components/modernizr/modernizr.js"></script>
Atau, kita dapat menggunakan file bower.json
untuk mengelola dependensi kita. Setelah hati-hati mengikuti setiap langkah sampai sekarang, file bower.json
akan terlihat seperti ini:
{ "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" } }
Sintaksnya cukup jelas, tetapi informasi lebih lanjut tersedia di sini.
Kami kemudian dapat menambahkan dependensi baru tambahan yang kami inginkan, dan kemudian yang kami butuhkan hanyalah perintah berikut untuk menginstalnya:
bower install
Sekarang mari kita menulis beberapa tes!
Oke, sekarang saatnya untuk benar-benar melanjutkan dari bagian yang terakhir kita tinggalkan dan menulis beberapa tes untuk aplikasi AngularJS kita.
Tapi pertama-tama, ada sedikit masalah yang perlu kita atasi: Meskipun pengembang generator-angular mendasarkan template proyek mereka pada proyek angular-seed (yang merupakan boilerplate Angular resmi), untuk beberapa alasan saya tidak begitu mengerti, mereka memutuskan untuk mengubah konvensi penamaan folder app
(mengubah css
menjadi styles
, js
menjadi scripts
, dan seterusnya).

Akibatnya, aplikasi yang awalnya kami tulis sekarang memiliki jalur yang tidak konsisten dengan perancah yang baru saja kami buat. Untuk menyiasatinya, mari unduh kode aplikasi dari sini dan bekerja dengan versi itu mulai saat ini (sebagian besar aplikasi yang sama persis seperti yang kita tulis, tetapi dengan jalur yang diperbarui agar sesuai dengan penamaan sudut generator).
Setelah mengunduh aplikasi, navigasikan ke folder tests/spec/controllers
dan buat file bernama drivers.js
yang berisi berikut ini:
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"); }); });
Ini adalah test suite untuk driverscontroller
kami. Ini mungkin terlihat seperti banyak kode, tetapi sebagian besar sebenarnya hanyalah deklarasi data tiruan. Mari kita lihat sekilas elemen yang sangat penting:
- Metode
describe()
mendefinisikan rangkaian pengujian kami. - Setiap
it()
adalah spesifikasi pengujian yang tepat. - Setiap fungsi
beforeEach()
dijalankan tepat sebelum setiap pengujian.
Elemen terpenting (dan berpotensi membingungkan) di sini adalah layanan $httpBackend
yang kami buat pada variabel httpMock
. Layanan ini bertindak sebagai back-end palsu dan menanggapi panggilan API kami pada uji coba, seperti yang akan dilakukan server kami yang sebenarnya dalam produksi. Dalam hal ini, menggunakan fungsi expectJSONP()
, kami menyetelnya untuk mencegat permintaan JSONP apa pun ke URL yang diberikan (URL yang sama yang kami gunakan untuk mendapatkan info dari server) dan sebagai gantinya, mengembalikan daftar statis dengan tiga driver, meniru respon server nyata. Ini memungkinkan kita untuk mengetahui dengan pasti apa yang seharusnya kembali dari pengontrol. Oleh karena itu, kami dapat membandingkan hasil dengan yang diharapkan, menggunakan fungsi expect()
. Jika mereka cocok, tes akan lulus.
Menjalankan tes cukup dilakukan dengan perintah:
grunt test
Rangkaian uji untuk pengontrol detail driver ( drivercontroller
) harus cukup mirip dengan yang baru saja kita lihat. Saya sarankan Anda mencoba mencari tahu sendiri sebagai latihan (atau Anda bisa melihatnya di sini, jika Anda tidak sanggup).
Bagaimana dengan tes AngularJS ujung ke ujung?
Tim Angular baru-baru ini memperkenalkan pelari baru untuk pengujian ujung ke ujung yang disebut Busur Derajat. Ini menggunakan webdriver untuk berinteraksi dengan aplikasi yang berjalan di browser dan juga menggunakan kerangka pengujian Jasmine secara default, sehingga sintaksnya akan sangat konsisten dengan pengujian unit kami.
Karena Protractor adalah alat yang cukup baru, integrasinya dengan tumpukan Yeoman dan generator-angular
masih membutuhkan cukup banyak pekerjaan konfigurasi. Dengan mengingat hal itu, dan niat saya untuk membuat tutorial ini sesederhana mungkin, rencana saya adalah mendedikasikan posting mendatang secara eksklusif untuk mencakup pengujian ujung ke ujung di AngularJS secara mendalam.
Kesimpulan
Pada titik ini dalam seri tutorial, kita telah belajar cara membuat perancah aplikasi Angular kita dengan yo
, mengelola dependensinya dengan bower
, dan menulis/menjalankan beberapa tes menggunakan karma
dan protractor
. Namun, ingatlah bahwa tutorial ini dimaksudkan hanya sebagai pengantar alat dan praktik AngularJS ini; kami tidak menganalisis salah satu dari mereka di sini secara mendalam.
Tujuan kami hanyalah membantu Anda memulai jalan ini. Dari sini, terserah Anda untuk melanjutkan dan mempelajari semua yang Anda bisa tentang kerangka kerja dan rangkaian alat yang luar biasa ini.
Tambahan: Beberapa catatan (penting) dari penulis
Setelah membaca tutorial ini, beberapa orang mungkin bertanya, “Tunggu. Bukankah Anda seharusnya melakukan semua ini sebelum Anda benar-benar mulai mengkodekan aplikasi Anda? Bukankah ini seharusnya menjadi bagian pertama dari tutorial ini?”
Jawaban singkat saya untuk itu adalah tidak . Seperti yang kita lihat di bagian pertama, Anda sebenarnya tidak perlu mengetahui semua hal ini untuk mengkodekan aplikasi Angular pertama Anda. Sebaliknya, sebagian besar alat yang telah kita bahas dalam posting ini dirancang untuk membantu Anda mengoptimalkan alur kerja pengembangan dan mempraktikkan Pengembangan Berbasis Tes (TDD).
Dan berbicara tentang TDD, konsep paling dasar dari TDD tentu saja sangat bagus; yaitu, tulis tes Anda sebelum Anda menulis kode. Namun, beberapa orang menganggap konsep itu terlalu jauh. TDD adalah praktik pengembangan, bukan metode pembelajaran. Oleh karena itu, menulis tes Anda sebelum menulis kode Anda sangat masuk akal, sedangkan mempelajari cara menulis tes Anda sebelum mempelajari cara membuat kode tidak masuk akal.
Saya pribadi berpikir ini adalah alasan utama mengapa tutorial Angular resmi mungkin terasa sangat berbelit-belit dan hampir tidak mungkin diikuti oleh orang-orang yang tidak memiliki pengalaman MVC/TDD front-end sebelumnya. Itulah salah satu alasan utama mengapa saya memulai seri tutorial ini.
Saran pribadi saya untuk mereka yang belajar menavigasi dunia AngularJS adalah: Jangan terlalu keras pada diri sendiri. Anda tidak perlu mempelajari semuanya sekaligus (meskipun orang mengatakan sebaliknya!). Bergantung pada pengalaman Anda sebelumnya dengan kerangka kerja front-end/pengujian lainnya, AngularJS bisa sangat sulit untuk dipahami pada awalnya. Jadi, pelajari semua yang perlu Anda pelajari sampai Anda dapat menulis aplikasi sederhana Anda sendiri dan kemudian, setelah Anda merasa nyaman dengan dasar-dasar kerangka kerja, Anda dapat memusatkan perhatian pada memilih dan menerapkan praktik pengembangan jangka panjang yang paling sesuai untuk Anda. Anda.
Tentu saja, itu adalah pendapat saya yang sederhana dan tidak semua orang akan setuju dengan pendekatan itu (dan tim pengembang Angular mungkin mengirim pembunuh bayaran setelah saya setelah saya menerbitkan ini), tetapi itulah visi saya dan saya cukup yakin bahwa banyak orang di luar sana yang akan setuju dengan saya.