最初のAngularJSアプリチュートリアルパート2:足場、構築、テストのためのツール

公開: 2022-03-11

序章

AngularJSアプリケーションの開発を支援するために利用できる多くのツールがあるため、多くの人は、それが非常に複雑なフレームワークであるという印象を持っていますが、まったくそうではありません。 これが、このチュートリアルシリーズを始めた主な理由の1つです。

パート1では、AngularJSフレームワークの基本について説明し、最初のアプリケーションを作成することから始めました。 この投稿は初心者向けです。 経験豊富なAngularJS開発者であれば、成長するスタートアップで使用されているディレクティブやAngularJSのストーリーをわかりやすく説明することに興味があるかもしれません。

このチュートリアルでは、アプリケーションロジックレイヤーを脇に置き、スキャフォールディング、依存関係の管理、テスト用の準備(ユニットとエンドツーエンドの両方)など、適切なAngularJSプロジェクトのセットアップを実行する方法を学習します。 これは、Yeoman、Grunt、BowerのAngularJSツールを使用して行います。 次に、Karmaを使用してJasmineテストを作成および実行するプロセスを確認します。

Karma、Jasmine、Grunt、Bower、Yeoman…これらすべてのツールは何ですか?

AngularJSの足場を作り、AngularJSをテストし、アプリを適切に構築するのに役立つ開発ツールはたくさんあります。

JavaScriptを使用している場合は、Angularを初めて使用する場合でも、これらのツールの少なくともいくつかをすでに知っている可能性が高くなります。 ただし、共通のベースラインを確保するために、仮定を行うことは避けます。 これらのテクノロジーのそれぞれと、それが何に役立つかを簡単に確認しましょう。

  • Karma(以前はTestacularとして知られていました)は、GoogleのJavaScriptテストランナーであり、AngularJSをテストするための自然な選択です。 実際のブラウザー(電話/タブレットブラウザーを含む)でテストを実行できるようにするだけでなく、テストフレームワークに依存しません。 つまり、任意のテストフレームワーク(Jasmine、Mocha、QUnitなど)と組み合わせて使用​​できます。

  • 少なくともこの投稿では、ジャスミンが私たちが選択するテストフレームワークになります。 その構文は、RSpecを使用したことがある場合は、RSpecの構文と非常によく似ています。 (まだの場合でも、心配しないでください。このチュートリアルの後半で詳しく説明します。)

  • Gruntは、ミニファイ、コンパイル(またはビルド)、テスト、AngularJSアプリケーションのプレビューの設定など、いくつかの反復的なタスクを自動化するのに役立つタスクランナーです。

  • Bowerは、CSSフレームワーク、JavaScriptライブラリなど、すべてのアプリケーションの依存関係を見つけてインストールするのに役立つパッケージマネージャーです。 Railsバンドラーのようにgit上で実行され、依存関係を手動でダウンロードして更新する必要がありません。

  • Yeomanは、Grunt、Bower、およびスキャフォールディングツールYoの3つのコアコンポーネントを含むツールセットです。 Yoは、ジェネレーター(単なる足場テンプレート)を使用してボイラープレートコードを生成し、プロジェクトのGruntとBowerを自動的に構成します。 ほぼすべてのJavaScriptフレームワーク(Angular、Backbone、Emberなど)のジェネレーターを見つけることができますが、ここではAngularに焦点を当てているため、generator-angularプロジェクトを使用します。

では、どこから始めればよいのでしょうか。

まず、必要なツールをインストールする必要があります。

git、node.js、npmがまだインストールされていない場合は、先に進んでインストールしてください。

次に、コマンドラインに移動し、次のコマンドを実行してYeomanのツールをインストールします。

 npm install -g yo grunt-cli bower

ああ、忘れないでください。AngularJSジェネレーターを使用するので、それもインストールする必要があります。

 npm install -g generator-angular

OK、これで準備が整いました…

AngularJSアプリケーションをスキャフォールド/生成します

前回は、Angular-Seedプロジェクトからボイラープレートコードを手動で借用しました。 今回は、yo(generator-angularと組み合わせて)にそれを任せます。

新しいプロジェクトフォルダを作成し、そこに移動して実行するだけです。

 yo angular

BootstrapやCompassを含めるかどうかなど、いくつかのオプションが表示されます。 今のところ、Compassにはno 、Bootstrapにはyesとしましょう。 次に、含めるモジュール(リソース、Cookie、サニタイズ、ルーティング)についてプロンプトが表示されたら、 angular-route.jsのみを選択します。

これで、プロジェクトのスキャフォールドが作成され(1分かかる場合があります)、Karmaと統合され、すべてが事前構成されます。

注:ここでは、このチュートリアルのパート1で作成したアプリケーションで使用したモジュールにモジュールを制限していることに注意してください。 自分のプロジェクトでこれを行う場合、含める必要のあるモジュールを決定するのはあなた次第です。

ここで、Jasmineを使用するので、プロジェクトにkarma-jasmineアダプターを追加しましょう。

 npm install karma-jasmine --save-dev

Chromeインスタンスでテストを実行する場合は、 karma-chrome-launcherも追加しましょう。

 npm install karma-chrome-launcher --save-dev

OK、すべてを正しく実行すると、プロジェクトファイルツリーは次のようになります。

これらのAngularJSツールを使用したサンプルプロジェクトファイルツリーは次のようになります。

静的アプリケーションコードはapp/ディレクトリに入り、 test/ディレクトリにはテストが含まれます(うん、ご想像のとおりです!)。 ルートに表示されるファイルは、プロジェクト構成ファイルです。 それぞれについて学ぶべきことはたくさんありますが、今のところはデフォルトの構成のままにしておきます。 それでは、アプリを初めて実行してみましょう。これは、次のコマンドで簡単に実行できます。

 grunt serve

そして出来上がり! これで、アプリが目の前に表示されます。

BowerforAngularJSについて少し

本当に重要な部分(つまり、テスト)に入る前に、バウアーについてもう少し学ぶために少し時間を取ってみましょう。 前述のように、バウアーは私たちのパッケージマネージャーです。 プロジェクトにlibまたはプラグインを追加するには、 bower installコマンドを使用するだけです。 たとえば、 modernizrを含めるには、次のことを行う必要があります(もちろん、プロジェクトディレクトリ内)。

 bower install modernizr

ただし、これにより、 modernizrがプロジェクトの一部になりますが( app/bower_componentsディレクトリに配置されます)、必要に応じて、アプリケーションに含める(または含めるタイミングを管理する)責任があります。手動で追加されたライブラリを処理します。 これを行う1つの方法は、次の<script>タグをindex.htmlに追加することです。

 <script src="bower_components/modernizr/modernizr.js"></script>

または、 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

それでは、いくつかのテストを書いてみましょう。

では、パート1で中断したところから実際に再開し、AngularJSアプリのテストをいくつか作成します。

しかし、最初に、対処する必要のある小さな問題があります。generator-angularの開発者は、プロジェクトテンプレートをangular-seedプロジェクト(公式のAngularボイラープレート)に基づいていますが、何らかの理由で私は本当に理解していませんが、彼らは決定しましたappフォルダーの命名規則を変更します( cssstylesに、 jsscriptsに変更するなど)。

その結果、最初に作成したアプリには、生成したばかりのスキャフォールドと矛盾するパスが含まれるようになりました。 これを回避するには、ここからアプリコードをダウンロードし、この時点からそのバージョンで作業します(これは、最初に作成したアプリとほぼ同じですが、ジェネレーターの角度の命名に一致するようにパスが更新されています)。

アプリをダウンロードした後、 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()関数は、各テストの直前に実行されます。

ここで最も重要な(そして潜在的に混乱する)要素は、 httpMock変数でインスタンス化した$httpBackendサービスです。 このサービスは偽のバックエンドとして機能し、実際のサーバーが本番環境で行うのと同じように、テスト実行時にAPI呼び出しに応答します。 この場合、 expectJSONP()関数を使用して、指定されたURL(サーバーから情報を取得するために使用するものと同じ)へのJSONPリクエストをインターセプトするように設定し、代わりに、3つのドライバーを含む静的リストを返します。実サーバーの応答。 これにより、コントローラーから何が返されるかを確実に知ることができます。 したがって、 expect()関数を使用して、結果を期待される結果と比較できます。 それらが一致する場合、テストは合格します。

テストの実行は、次のコマンドで簡単に実行できます。

 grunt test

ドライバー詳細コントローラー( drivercontroller )のテストスイートは、今見たものとかなり似ているはずです。 演習として自分でそれを理解することをお勧めします(または、それがうまくいかない場合は、ここを見てください)。

エンドツーエンドのAngularJSテストはどうですか?

Angularチームは最近、Protractorと呼ばれるエンドツーエンドテスト用の新しいランナーを導入しました。 Webドライバーを使用してブラウザーで実行されているアプリケーションと対話し、デフォルトでJasmineテストフレームワークも使用するため、構文は単体テストの構文と非常に一貫性があります。

ただし、Protractorはかなり新しいツールであるため、Yeomanスタックおよびgenerator-angularとの統合には、かなりの量の構成作業が必要です。 そのことを念頭に置いて、このチュートリアルをできるだけシンプルに保つつもりで、将来の投稿をAngularJSでのエンドツーエンドのテストを徹底的にカバーすることに専念する予定です。

結論

チュートリアルシリーズのこの時点で、Angularアプリをyoでスキャフォールディングし、 bowerで依存関係を管理し、 karmaprotractorを使用していくつかのテストを作成/実行する方法を学びました。 ただし、このチュートリアルは、これらのAngularJSツールとプラクティスの紹介としてのみ意図されていることに注意してください。 ここでは、それらのいずれも詳細に分析しませんでした。

私たちの目標は、単にあなたがこの道を歩み始めるのを助けることでした。 ここから先に進んで、この素晴らしいフレームワークとツールスイートについてできる限りのことを学ぶのはあなた次第です。

補遺:著者からのいくつかの(重要な)メモ

このチュートリアルを読んだ後、 「待ってください。 実際にアプリのコーディングを開始する前に、これらすべてのことを行う必要はありませんか? これはこのチュートリアルの一部ではなかったのでしょうか?」

それに対する私の短い答えはノーです。 パート1で見たように、最初のAngularアプリをコーディングするために、これらすべてを実際に知る必要はありません。 むしろ、この投稿で説明したツールのほとんどは、開発ワークフローを最適化し、テスト駆動開発(TDD)を実践するのに役立つように設計されています。

そしてTDDについて言えば、TDDの最も基本的な概念は確かに健全なものです。 つまり、コードを作成する前にテストを作成します。 しかし、一部の人々はその概念を行き過ぎています。 TDDは開発手法であり、学習方法ではありません。 したがって、コードを書く前にテストを書くことは非常に理にかなっていますが、コーディング方法を学ぶ前にテストを書く方法を学ぶことは意味がありません。

個人的には、これが公式のAngularチュートリアルが非常に複雑に感じられ、フロントエンドのMVC/TDDの経験がない人にとっては従うことがほぼ不可能である主な理由だと思います。 それが、私がこのチュートリアルシリーズを始めた主な理由の1つです。

AngularJSの世界をナビゲートすることを学んでいる人たちへの私の個人的なアドバイスは、次のとおりです。 すべてを一度に学ぶ必要はありません(他の方法で言われているにもかかわらず!)。 他のフロントエンド/テストフレームワークでの以前の経験によっては、AngularJSを最初に理解するのはかなり難しい場合があります。 したがって、独自のシンプルなアプリを作成できるようになるまで、学ぶ必要のあることをすべて学び、フレームワークの基本に慣れたら、に最適な長期的な開発手法を選択して適用することに関心を持つことができます。君。

もちろん、それは私の謙虚な意見であり、誰もがそのアプローチに同意するわけではありません(そして、Angular開発チームはこれを公開すると私の後に雇われた殺人者を送るかもしれません)が、それは私のビジョンであり、それは多くの人々であると確信しています私に同意する人がいます。

関連: Angular 6チュートリアル:新しいパワーを備えた新機能