Protractor-quick-guide

提供:Dev Guides
移動先:案内検索

分度器-はじめに

この章では、分度器の概要を説明します。ここでは、このテストフレームワークの起源と、このツールの動作、制限を選択する理由について説明します。

分度器とは何ですか?

Protractorは、AngularおよびAngularJSアプリケーション向けのオープンソースのエンドツーエンドのテストフレームワークです。 WebDriverの上にGoogleによって構築されました。 また、「Angular Scenario Runner」と呼ばれる既存のAngularJS E2Eテストフレームワークの代替としても機能します。

また、NodeJS、Selenium、Jasmine、WebDriver、Cucumber、Mochaなどの強力なテクノロジーを組み合わせたソリューションインテグレーターとしても機能します。 AngularJSアプリケーションのテストに加えて、通常のWebアプリケーションの自動回帰テストも作成します。 実際のブラウザを使用してテストを実行するため、実際のユーザーと同じようにアプリケーションをテストできます。

次の図は、分度器の簡単な概要を示します-

分度器の概要

上記の図では、私たちが持っていることに注意してください-

  • *分度器-前述のように、特に角型アプリ向けに設計されたWebDriver JSのラッパーです。
  • Jasmine -基本的には、JavaScriptコードをテストするための動作駆動型開発フレームワークです。 Jasmineで簡単にテストを書くことができます。
  • WebDriver JS -これは、selenium 2.0/WebDriverのNode JSバインディング実装です。
  • Selenium -ブラウザを自動化するだけです。

原点

前述したように、Protractorは、「Angular Scenario Runner」と呼ばれる既存のAngularJS E2Eテストフレームワークの代替品です。 基本的に、分度器の起源はシナリオランナーの終わりから始まります。 ここで生じる疑問は、なぜ分度器を構築する必要があるのか​​ということです。 これを理解するには、まずその前身であるシナリオランナーについて確認する必要があります。

分度器の開始

分度器の開発の主な貢献者であるジュリーラルフは、Google内の他のプロジェクトでAngular Scenario Runnerで次のような経験をしました。 これは、特にギャップを埋めるために、分度器を構築する動機になりました-

「シナリオランナーを使用してみましたが、テストに必要なことが実際にはできないことがわかりました。 ログインなどをテストする必要がありました。 ログインページはAngularページではなく、シナリオランナーはそれを処理できませんでした。 また、ポップアップや複数のウィンドウ、ブラウザの履歴のナビゲートなどのようなものには対処できませんでした。」

分度器の最大の利点は、Seleniumプロジェクトの成熟度であり、Angularプロジェクトで簡単に使用できるようにメソッドをまとめています。 Protractorの設計は、アプリケーションのWeb UI、バックエンドサービス、永続化レイヤーなどのすべてのレイヤーをテストするように構築されています。

分度器を使用する理由

ほぼすべてのアプリケーションが開発にJavaScriptを使用していることがわかっています。 JavaScriptのサイズが大きくなると、アプリケーション自体の数が増えるため、アプリケーションにとってテスターのタスクは難しくなり、複雑になります。 ほとんどの場合、AngularJSアプリケーションでWeb要素をキャプチャすることは非常に困難になり、JUnitまたはSelenium WebDriverを使用して、拡張HTML構文を使用してWebアプリケーションコンポーネントを表現します。

ここでの質問は、Selenium Web DriverがAngularJS Web要素を見つけることができない理由です。 その理由は、AngularJSアプリケーションがng-repeater、ng-controller、ng-modelなどの拡張HTML属性を持っているためです。 Seleniumロケーターには含まれていません。

ここでは、Seleniumの最上位にあるProtractorがAngularJS Webアプリケーションの拡張HTML要素を処理および制御できるため、Protractorの重要性が生まれます。 そのため、ほとんどのフレームワークは、AngularJSアプリケーションの単体テストの実行に焦点を当てていると言えます。Protractorは、アプリケーションの実際の機能のテストに使用されていました。

分度器の働き

テストフレームワークである分度器は、Seleniumと連動して、ブラウザーまたはモバイルデバイスで実行されているAngularJSアプリケーションとのユーザーの対話をシミュレートする自動テストインフラストラクチャを提供します。

分度器の動作は、次の手順の助けを借りて理解することができます-

  • *ステップ1 *-最初のステップでは、テストを作成する必要があります。 それはジャスミンまたはモカまたはキュウリの助けを借りて行うことができます。
  • *ステップ2 *-次に、分度器を使用して実行できるテストを実行する必要があります。 テストランナーとも呼ばれます。
  • *ステップ3 *-このステップでは、Seleniumサーバーがブラウザーの管理に役立ちます。
  • *ステップ4 *-最後に、ブラウザAPIはSelenium WebDriverの助けを借りて呼び出されます。

分度器の動作

利点

このオープンソースのエンドツーエンドのテストフレームワークには、次の利点があります-

  • オープンソースツールであるProtractorは、インストールとセットアップが非常に簡単です。
  • Jasmineフレームワークと連携してテストを作成します。
  • テスト駆動開発(TDD)をサポートします。
  • 自動待機が含まれているため、テストに待機とスリープを明示的に追加する必要はありません。
  • Selenium WebDriverのすべての利点を提供します。
  • 複数のブラウザーを介した並列テストをサポートします。
  • 自動同期の利点を提供します。
  • テスト速度が優れています。

制限事項

このオープンソースのエンドツーエンドのテストフレームワークには、次の制限があります-

  • WebDriver JSのラッパーであるため、ブラウザーの自動化で業種を明らかにしません。
  • JavaScriptの知識はJavaScriptでのみ使用できるため、ユーザーにとって不可欠です。
  • UI駆動のテストツールであるため、フロントエンドテストのみを提供します。

分度器-Javascriptテストの概念

JavaScriptの知識は分度器での作業に不可欠なので、この章ではJavaScriptテストの概念を詳細に理解しましょう。

JavaScriptのテストと自動化

JavaScriptは、最も人気のある動的に型付けされ解釈されたスクリプト言語ですが、最も難しいタスクはコードをテストすることです。 これは、JAVAやC ++などの他のコンパイル言語とは異なり、テスターがエラーを把握するのに役立つJavaScriptのコンパイル手順がないためです。 その上、ブラウザベースのテストには非常に時間がかかります。したがって、JavaScriptの自動テストをサポートするツールが必要です。

自動テストの概念

コードを改善するため、常にテストを作成することをお勧めします。手動テストの問題は、少し時間がかかり、エラーが発生しやすいことです。 手動テストのプロセスは、プロセスを繰り返し、テスト仕様を記述し、コードを変更し、ブラウザを数回更新する必要があるため、プログラマにとっても非常に退屈です。 また、手動テストは開発プロセスの速度も低下させます。

上記の理由により、これらのテストを自動化し、プログラマーがこれらの反復的で退屈な手順を取り除くのに役立つツールを用意することは常に有用です。 テストプロセスを自動化するには、開発者は何をすべきですか?

基本的に、開発者はCLI(コマンドラインインタープリター)または開発IDE(統合開発環境)でツールセットを実装できます。 その後、これらのテストは、開発者からの入力がなくても、個別のプロセスで継続的に実行されます。 JavaScriptの自動テストも新しいものではなく、Karma、Protractor、CasperJSなどの多くのツールがあります。 開発されています。

JavaScriptのテストの種類

目的に応じてさまざまなテストを行うことができます。 たとえば、一部のテストはプログラム内の関数の動作を確認するために作成され、他のテストはモジュールまたは機能のフローをテストするために作成されます。 したがって、次の2種類のテストがあります-

単体テスト

テストは、ユニットと呼ばれるプログラムの最小のテスト可能な部分で実行されます。 ユニットは基本的に、他の部分にそのユニットが依存することなく、単独でテストされます。 JavaScriptの場合、特定の動作を行う個々のメソッドまたは関数はコードの単位になることがあり、これらのコードの単位は孤立した方法でテストする必要があります。

ユニットテストの利点の1つは、ユニットが互いに独立しているため、ユニットのテストを任意の順序で実行できることです。 本当に重要な単体テストのもう1つの利点は、次のようにいつでもテストを実行できることです-

  • 開発プロセスの最初から。
  • モジュール/機能の開発が完了した後。
  • モジュール/機能を変更した後。
  • 既存のアプリケーションに新しい機能を追加した後。

JavaScriptアプリケーションの自動ユニットテストでは、Mocha、Jasmine、QUnitなどの多くのテストツールとフレームワークから選択できます。

エンドツーエンドのテスト

これは、最初から最後まで(一方の端から他方の端まで)アプリケーションのフローが設計どおりに正常に動作しているかどうかをテストするためのテスト方法論として定義できます。

エンドツーエンドテストは、機能/フローテストとも呼ばれます。 単体テストとは異なり、エンドツーエンドテストでは、個々のコンポーネントがアプリケーションとしてどのように連携するかをテストします。 これが、単体テストとエンドツーエンドテストの主な違いです。

たとえば、ユーザーが登録を完了するために有効な情報を提供する必要がある登録モジュールがある場合、その特定のモジュールのE2Eテストは次の手順に従ってテストを完了します-

  • 最初に、フォームまたはモジュールをロード/コンパイルします。
  • これで、フォームの要素のDOM(ドキュメントオブジェクトモデル)が取得されます。
  • 次に、送信ボタンのクリックイベントをトリガーして、ボタンが機能しているかどうかを確認します。
  • 次に、検証のために、入力フィールドから値を収集します。
  • 次に、入力フィールドを検証する必要があります。
  • テスト目的で、偽のAPIを呼び出してデータを保存します。

すべてのステップで独自の結果が得られ、予想される結果セットと比較されます。

ここで発生する問題は、この種のE2Eまたは機能テストは手動でも実行できるのに、なぜこれを自動化する必要があるのか​​ということです。 主な理由は、自動化によりこのテストプロセスが容易になるためです。 任意のアプリケーションと簡単に統合できる利用可能なツールのいくつかは、この目的のために、Selenium、PhantomJS、およびProtractorです。

テストツールとフレームワーク

Angularテスト用のさまざまなテストツールとフレームワークがあります。 以下は、いくつかの有名なツールとフレームワークです-

カルマ

Vojta Jinaによって作成されたKarmaは、テストランナーです。 もともと、このプロジェクトはTestacularと呼ばれていました。 これはテストフレームワークではありません。つまり、実際のブラウザーでJavaScriptユニットテストを簡単かつ自動的に実行することができます。 Karmaは、AngularJS用に構築されました。これは、Karmaの前に、WebベースのJavaScript開発者向けの自動テストツールがなかったためです。 一方、Karmaが提供する自動化により、開発者は簡単な1つのコマンドを実行して、テストスイート全体が成功したか失敗したかを判断できます。

Karmaを使用する長所

以下は、手動プロセスと比較してカルマを使用するいくつかの長所です-

  • 複数のブラウザーとデバイスでテストを自動化します。
  • ファイルのエラーを監視し、修正します。
  • オンラインサポートとドキュメントを提供します。
  • 継続的統合サーバーとの統合を容易にします。

Karmaを使用することの短所

以下は、カルマを使用するいくつかの短所です-

Karmaを使用する主な欠点は、構成と保守に追加のツールが必要なことです。

JasmineでKarmaテストランナーを使用している場合、1つの要素に複数のIDがある場合、CSSの設定に関する情報を見つけるためのドキュメントが少なくなります。

ジャスミン

JavaScriptコードをテストするための動作駆動型開発フレームワークであるJasmineは、Pivo​​tal Labsで開発されています。 Jasmineフレームワークの積極的な開発の前に、JsUnitという名前の同様の単体テストフレームワークも、組み込みのテストランナーを持つPivotal Labsによって開発されました。 ブラウザテストは、SpecRunnerlファイルを含めるか、コマンドラインテストランナーとして使用することにより、Jasmineテストで実行できます。 Karmaの有無にかかわらず使用できます。

ジャスミンを使用する長所

以下は、ジャスミンを使用するいくつかの長所です-

  • ブラウザ、プラットフォーム、言語に依存しないフレームワーク。
  • 行動駆動型開発とともにテスト駆動型開発(TDD)をサポートします。
  • Karmaとデフォルトで統合されています。
  • わかりやすい構文。
  • 追加の機能としてテストを支援するテストスパイ、偽物、およびパススルー機能を提供します。

ジャスミン使用の短所

以下は、ジャスミンを使用することの短所です-

  • テストの実行中はJasmineで使用可能なファイル監視機能がないため、テストは変更されるたびにユーザーが返す必要があります。

モカ

Node.jsアプリケーション用に作成されたMochaはテストフレームワークですが、ブラウザーのテストもサポートしています。 ジャスミンによく似ていますが、両者の主な違いは、テストフレームワークとしてスタンドアロンで実行できないため、Mochaにはプラグインとライブラリが必要なことです。 一方、Jasmineはスタンドアロンです。 ただし、MochaはJasmineよりも柔軟に使用できます。

モカを使用する長所

以下は、モカを使用するいくつかの長所です-

  • Mochaのインストールと構成は非常に簡単です。
  • ユーザーフレンドリーでシンプルなドキュメント。
  • 複数のノードプロジェクトを含むプラグインが含まれています。

モカを使用することの短所

以下は、モカを使用するいくつかの短所です-

  • アサーション、スパイなどのために個別のモジュールが必要です。
  • Karmaで使用するには、追加の構成も必要です。

QUnit

元々2008年にjQueryの一部としてJohn Resigによって開発されたQUintは、強力で使いやすいJavaScript単体テストスイートです。 一般的なJavaScriptコードをテストするために使用できます。 ブラウザでJavaScriptをテストすることに焦点を当てていますが、開発者が使用するのは非常に便利です。

QUnitを使用する長所

以下はQUnitを使用するいくつかの長所です-

  • インストールと設定が簡単。
  • ユーザーフレンドリーでシンプルなドキュメント。

QUnitを使用することの短所

以下はQUnitを使用することの短所です-

  • これは主にjQuery向けに開発されたため、他のフレームワークでの使用にはあまり適していません。

セレン

Seleniumは、もともと2004年にJason HugginsがThoughtWorksの内部ツールとして開発したもので、オープンソースのテスト自動化ツールです。 Seleniumは、「Seleniumはブラウザを自動化します。 それでおしまい!"。 ブラウザの自動化は、開発者が非常に簡単にブラウザと対話できることを意味します。

Seleniumを使用する長所

以下は、セレンを使用するいくつかの長所です-

  • 大規模な機能セットが含まれています。
  • 分散テストをサポートします。
  • Sauce Labsなどのサービスを通じてSaaSをサポートしています。
  • 簡単なドキュメントと豊富なリソースが用意されているので使いやすいです。

Seleniumを使用することの短所

以下は、セレンを使用するいくつかの短所です-

  • Seleniumを使用する主な欠点は、Seleniumを別のプロセスとして実行する必要があることです。
  • 開発者がいくつかの手順に従う必要があるため、構成は少し面倒です。

分度器-はじめに

前の章で、分度器の基本を学びました。 この章では、インストールと設定の方法を学びましょう。

前提条件

Protractorをコンピューターにインストールする前に、次の前提条件を満たす必要があります-

Node.js

分度器はNode.jsモジュールであるため、非常に重要な前提条件は、コンピューターにNode.jsをインストールする必要があることです。 Node.jsに付属のnpm(JavaScriptパッケージマネージャー)を使用して、Protractorパッケージをインストールします。

Node.jsをインストールするには、公式リンク(https://nodejs.org/en/download/)に従ってください。 Node.jsをインストールした後、コマンドプロンプトで以下に示すようにコマンド node --version および npm --version を記述することにより、Node.jsおよびnpmのバージョンを確認できます-

前提条件

クロム

Googleが構築したWebブラウザーであるGoogle Chromeは、Seleniumサーバーを必要とせずにProtractorでエンドツーエンドのテストを実行するために使用されます。 [[1]]

Selenium WebDriver for Chrome

このツールは、Protractor npmモジュールに付属しており、Webアプリケーションと対話することができます。

分度器のインストール

私たちのコンピューターにNode.jsをインストールした後、次のコマンドの助けを借りてProtractorをインストールできます-

npm install -g protractor

分度器が正常にインストールされたら、以下に示すように、コマンドプロンプトで protractor --version コマンドを記述して、そのバージョンを確認できます-

分度器のインストール

Chrome向けWebDriverのインストール

Protractorをインストールした後、Selenium WebDriver for Chromeをインストールする必要があります。 次のコマンドの助けを借りてインストールすることができます-

webdriver-manager update

上記のコマンドは、プロジェクトで使用される必要なChromeドライバーを含むSeleniumディレクトリを作成します。

インストールと構成の確認

Protractorのインストール後に、サンプルで提供されているconf.jsを少し変更することで、Protractorのインストールと構成を確認できます。 このconf.jsファイルは、ルートディレクトリ node_modules/Protractor/example にあります。

このため、最初に同じディレクトリにtestingconfig.jsという名前の新しいファイルを作成します。 node_modules/Protractor/example

次に、conf.jsファイルで、ソースファイル宣言パラメーターの下に、testingconfig.jsを記述します。

次に、すべてのファイルを保存して閉じ、コマンドプロンプトを開きます。 以下のスクリーンショットに示すように、conf.jsファイルを実行します。

以下に示すように出力が得られれば、分度器の設定とインストールは成功です-

構成分度器

上記の出力は、conf.jsファイルのソースファイル宣言パラメーターで空のファイルを提供したため、仕様がないことを示しています。 しかし、上記の出力から、分度器とWebDriverの両方が正常に実行されていることがわかります。

インストールと構成の問題

ProtractorおよびWebDriverをインストールおよび構成する際に、次の一般的な問題に遭遇する場合があります-

Seleniumが正しくインストールされていません

これは、WebDriverのインストール中の最も一般的な問題です。 この問題は、WebDriverを更新しない場合に発生します。 WebDriverを更新する必要があることに注意してください。更新しないと、Protractorのインストールを参照できません。

テストが見つかりません

もう1つの一般的な問題は、Protractorを実行した後、テストが見つからないことを示していることです。 このためには、相対パス、ファイル名、または拡張子が正しいことを確認する必要があります。 また、conf.jsファイルは構成ファイル自体から始まるため、非常に慎重に記述する必要があります。

分度器-分度器とSeleniumサーバー

前述のように、Protractorは、AngularおよびAngularJSアプリケーション向けのオープンソースのエンドツーエンドのテストフレームワークです。 Node.jsプログラムです。 一方、Seleniumは、Selenium Server、WebDriver API、およびWebDriverブラウザードライバーを含むブラウザー自動化フレームワークです。

セレンと分度器

ProtractorとSeleniumの組み合わせについて話す場合、ProtractorはSeleniumサーバーと連携して、自動化されたテストインフラストラクチャを提供できます。 インフラストラクチャは、ブラウザまたはモバイルデバイスで実行されている角度のあるアプリケーションとユーザーの対話をシミュレートできます。 次の図に示すように、ProtractorとSeleniumの組み合わせは、テスト、サーバー、ブラウザーの3つのパーティションに分割できます-

Seleniumを使用した分度器

Selenium WebDriverプロセス

上記の図で見たように、Selenium WebDriverを使用したテストには、次の3つのプロセスが含まれます-

  • テストスクリプト
  • サーバー
  • ブラウザ

このセクションでは、これら3つのプロセス間の通信について説明します。

テストスクリプトとサーバー間の通信

最初の2つのプロセス-テストスクリプトとサーバー間の通信は、Selenium Serverの動作に依存します。 つまり、Seleniumサーバーの実行方法は、テストスクリプトとサーバー間の通信プロセスに形を与えると言えます。

Seleniumサーバーは、スタンドアロンのSeleniumサーバー(selenium-server-standalone.jar)としてマシン上でローカルに実行することも、サービス(Sauce Labs)を介してリモートで実行することもできます。 スタンドアロンのSeleniumサーバーの場合、Node.jsとseleniumサーバーの間でhttp通信が行われます。

サーバーとブラウザー間の通信

サーバーがテストスクリプトから同じものを解釈した後、ブラウザーにコマンドを転送する責任があることはわかっています。 そのため、サーバーとブラウザにも通信メディアが必要であり、ここでは JSON WebDriver Wire Protocol を使用して通信を行います。 コマンドを解釈するために使用されるブラウザードライバーで拡張されたブラウザー。

Selenium WebDriverプロセスとその通信に関する上記の概念は、次の図の助けを借りて理解することができます-

Webドライバープロセス

Protractorでの作業中、最初のプロセスであるテストスクリプトはNode.jsを使用して実行されますが、ブラウザーでアクションを実行する前に、テスト対象のアプリケーションが安定していることを確認するための追加コマンドを送信します。

Selenium Serverのセットアップ

Selenium Serverは、テストスクリプトとブラウザードライバーの間ではプロキシサーバーのように動作します。 基本的に、コマンドをテストスクリプトからWebDriverに転送し、WebDriverからの応答をテストスクリプトに返します。 テストスクリプトの conf.js ファイルに含まれているSeleniumサーバーのセットアップには、次のオプションがあります-

スタンドアロンSeleniumサーバー

ローカルマシンでサーバーを実行する場合は、スタンドアロンのSeleniumサーバーをインストールする必要があります。 スタンドアロンのSeleniumサーバーをインストールするための前提条件は、JDK(Java Development Kit)です。 ローカルマシンにJDKをインストールする必要があります。 コマンドラインから次のコマンドを実行することで確認できます-

java -version

現在、手動で、またはテストスクリプトからSelenium Serverをインストールして起動するオプションがあります。

Seleniumサーバーを手動でインストールして起動する

Seleniumサーバーを手動でインストールして起動するには、Protractorに付属のWebDriver-Managerコマンドラインツールを使用する必要があります。 Seleniumサーバーをインストールして起動する手順は次のとおりです-

  • ステップ1 *-最初のステップは、SeleniumサーバーとChromeDriverをインストールすることです。 それは次のコマンドを実行する助けを借りて行うことができます-
webdriver-manager update
  • ステップ2 *-次に、サーバーを起動する必要があります。 それは次のコマンドを実行する助けを借りて行うことができます-
webdriver-manager start

ステップ3 *-最後に、設定ファイルのseleniumAddressを実行中のサーバーのアドレスに設定する必要があります。 デフォルトのアドレスは *http://localhost:4444/wd/hub です。

テストスクリプトからのSeleniumサーバーの起動

テストスクリプトからSeleniumサーバーを起動するには、設定ファイルで次のオプションを設定する必要があります-

  • * jarファイルの場所*-seleniumServerJarを設定して、構成ファイルでスタンドアロンSeleniumサーバーのjarファイルの場所を設定する必要があります。
  • ポートの指定-スタンドアロンのSelenium Serverの起動に使用するポートも指定する必要があります。 seleniumPortを設定することにより、構成ファイルで指定できます。 デフォルトのポートは4444です。
  • コマンドラインオプションの配列-サーバーに渡すコマンドラインオプションの配列も設定する必要があります。 seleniumArgsを設定することにより、構成ファイルで指定できます。 コマンドの配列の完全なリストが必要な場合は、*-help *フラグを使用してサーバーを起動します。

リモートSelenium Serverの使用

テストを実行する別のオプションは、Seleniumサーバーをリモートで使用することです。 サーバーをリモートで使用するための前提条件は、サーバーをホストするサービスを持つアカウントが必要であることです。 分度器での作業中に、サーバーをホストする次のサービスの組み込みサポートがあります-

TestObject

TestObjectをリモートSelenium Serverとして使用するには、TestObjectUser(TestObjectアカウントのユーザー名)およびtestobjectKey(TestObjectアカウントのAPIキー)を設定する必要があります。

BrowserStack

BrowserStackをリモートSelenium Serverとして使用するには、BrowserStackUser、BrowserStackアカウントのユーザー名、およびbrowserstackKey、BrowserStackアカウントのAPIキーを設定する必要があります。

ソースラボ

Sauce LabsをリモートSelenium Serverとして使用するには、sauce Labsアカウントのユーザー名であるsauceUserと、Sauce LabsアカウントのAPIキーであるSauceKeyを設定する必要があります。

コビトン

KobitonをリモートSelenium Serverとして使用するには、Kobitonアカウントのユーザー名であるkobitonUserと、KobitonアカウントのAPIキーであるkobitonKeyを設定する必要があります。

Selenium Serverを使用せずにブラウザードライバーに直接接続する

テストを実行するためのもう1つのオプションは、Seleniumサーバーを使用せずにブラウザードライバーに直接接続することです。 分度器は、Selenium Serverを使用せずに、設定ファイルでdirectConnect:trueを設定することにより、ChromeおよびFirefoxに対して直接テストできます。

ブラウザーのセットアップ

ブラウザーを構成およびセットアップする前に、どのブラウザーがProtractorでサポートされているかを知る必要があります。 以下は、分度器でサポートされているブラウザのリストです-

  • ChromeDriver
  • FirefoxDriver
  • SafariDriver
  • IEDriver
  • Appium-iOS/Safari
  • Appium-Android/Chrome
  • セレンドロイド
  • PhantomJS

ブラウザーの設定と構成については、ブラウザーのセットアップは構成ファイルの機能オブジェクト内で行われるため、Protractorの構成ファイルに移動する必要があります。

Chromeをセットアップする

Chromeブラウザを設定するには、機能オブジェクトを次のように設定する必要があります

capabilities: {
   'browserName': 'chrome'
}

chromeOptionsにネストされているChrome固有のオプションを追加することもできます。その完全なリストはhttps://sites.google.com/a/chromium.org/chromedriver/capabilitiesで確認できます。

たとえば、右上にFPS-counterを追加する場合は、構成ファイルで次のように実行できます-

capabilities: {
   'browserName': 'chrome',
   'chromeOptions': {
      'args': ['show-fps-counter=true']
   }
},

Firefoxのセットアップ

Firefoxブラウザを設定するには、次のように機能オブジェクトを設定する必要があります-

capabilities: {
   'browserName': 'firefox'
}

moz:firefoxOptionsオブジェクトにネストされているFirefox固有のオプションを追加することもできます。その完全なリストはhttps://github.com/mozilla/geckodriver#firefox-capabilitiesで確認できます。

たとえば、Firefoxでテストをセーフモードで実行する場合は、設定ファイルで次のように実行できます-

capabilities: {
   'browserName': 'firefox',
   'moz:firefoxOptions': {
     'args': ['—safe-mode']
   }
},

他のブラウザを設定する

ChromeまたはFirefox以外のブラウザをセットアップするには、https://docs.seleniumhq.org/download/から個別のバイナリをインストールする必要があります。

PhantonJSのセットアップ

実際、PhantomJSはクラッシュの問題があるためサポートされていません。 その代わりに、ヘッドレスChromeまたはヘッドレスFirefoxを使用することをお勧めします。 彼らは次のように設定することができます-

ヘッドレスChromeをセットアップするには、次のように-headlessフラグを指定してChromeを起動する必要があります-

capabilities: {
   'browserName': 'chrome',
   'chromeOptions': {
      'args': [“--headless”, “--disable-gpu”, “--window-size=800,600”]
   }
},

ヘッドレスFirefoxをセットアップするには、次のように –headless フラグを指定してFirefoxを起動する必要があります-

capabilities: {
   'browserName': 'firefox',
   'moz:firefoxOptions': {
      'args': [“--headless”]
   }
},

テスト用に複数のブラウザーをセットアップする

複数のブラウザに対してテストすることもできます。 このために、次のようにmultiCapabilities構成オプションを使用する必要があります-

multiCapabilities: [{
   'browserName': 'chrome'
},{
   'browserName': 'firefox'
}]

どのフレームワーク?

2つのBDD(動作駆動型開発)テストフレームワーク、JasmineとMochaがProtractorでサポートされています。 どちらのフレームワークもJavaScriptとNode.jsに基づいています。 テストの作成と管理に必要な構文、レポート、および足場は、これらのフレームワークによって提供されます。

次に、さまざまなフレームワークをインストールする方法を確認します-

ジャスミンフレームワーク

これは、分度器のデフォルトのテストフレームワークです。 Protractorをインストールすると、Jasmine 2.xバージョンがインストールされます。 個別にインストールする必要はありません。

Mochaフレームワーク

Mochaは、基本的にNode.jsで実行される別のJavaScriptテストフレームワークです。 テストフレームワークとしてMochaを使用するには、BDD(Behavior Driven Development)インターフェースとChaiアサーションをChai As Promiseedで使用する必要があります。 インストールは、次のコマンドの助けを借りて行うことができます-

npm install -g mocha
npm install chai
npm install chai-as-promised

ご覧のとおり、mochaのインストール中に-gオプションが使用されます。これは、-gオプションを使用してProtractorをグローバルにインストールしたためです。 インストール後、テストファイル内でChaiを要求して設定する必要があります。 それは次のように行うことができます-

var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
var expect = chai.expect;

この後、私たちはそのように約束としてチャイを使用することができます-

expect(myElement.getText()).to.eventually.equal('some text');

ここで、フレームワーク「mocha」を追加して、フレームワークプロパティを設定ファイルのmochaに設定する必要があります。 モカの「レポーター」や「遅い」などのオプションは、次のように設定ファイルに追加できます-

mochaOpts: {
   reporter: "spec", slow: 3000
}

キュウリフレームワーク

テストフレームワークとしてCucumberを使用するには、フレームワークオプション custom でProcutorと統合する必要があります。 インストールは、次のコマンドの助けを借りて行うことができます

npm install -g cucumber
npm install --save-dev protractor-cucumber-framework

ご覧のとおり、Cucumberのインストール中に-gオプションが使用されています。これは、Protractorをグローバルにインストールしたためです。 -gオプション付き。 次に、フレームワーク「custom」およびframeworkPath:「Protractor-cucumber-framework」をcucumberConf.jsという名前の構成ファイルに追加して、フレームワークプロパティを構成ファイルの custom に設定する必要があります。

以下に示すサンプルコードは、Protractorでキュウリ機能ファイルを実行するために使用できる基本的なcucumberConf.jsファイルです-

exports.config = {
   seleniumAddress: 'http://localhost:4444/wd/hub',

   baseUrl: 'https://angularjs.org/',

   capabilities: {
      browserName:'Firefox'
   },

   framework: 'custom',

   frameworkPath: require.resolve('protractor-cucumber-framework'),

   specs: [
      './cucumber/*.feature'
   ],

  //cucumber command line options
   cucumberOpts: {
      require: ['./cucumber/*.js'],
      tags: [],
      strict: true,
      format: ["pretty"],
      'dry-run': false,
      compiler: []
   },
   onPrepare: function () {
      browser.manage().window().maximize();
   }
};

分度器-最初のテストを書く

この章では、分度器で最初のテストを書く方法を理解しましょう。

分度器に必要なファイル

分度器を実行するには、次の2つのファイルが必要です-

仕様またはテストファイル

Protractorを実行するための重要なファイルの1つです。 このファイルには、実際のテストコードを記述します。 テストコードは、テストフレームワークの構文を使用して作成されます。

たとえば、 Jasmine フレームワークを使用している場合、 Jasmine の構文を使用してテストコードが記述されます。 このファイルには、テストのすべての機能フローとアサーションが含まれます。

簡単に言えば、このファイルには、アプリケーションと対話するためのロジックとロケーターが含まれていると言えます。

以下は、URLにナビゲートしてページタイトルを確認するテストケースを持つ単純なスクリプトTestSpecification.jsです-

//TestSpecification.js
describe('Protractor Demo', function() {
   it('to check the page title', function() {
      browser.ignoreSynchronization = true;
      browser.get('https://www.finddevguides.com/tutorialslibrary');
      browser.driver.getTitle().then(function(pageTitle) {
         expect(pageTitle).toEqual('Free Online Tutorials and Courses');
      });
   });
});

コードの説明

上記の仕様ファイルのコードは次のように説明することができます-

ブラウザ

これは、すべてのブラウザーレベルのコマンドを処理するために分度器によって作成されたグローバル変数です。 基本的に、WebDriverのインスタンスのラッパーです。 browser.get()は、特定のページを読み込むように分度器に指示する単純なSeleniumメソッドです。

  • describe および it -両方ともJasmineテストフレームワークの構文です。 '説明' は、テストケースのエンドツーエンドのフローを含めるために使用され、 'it' はテストシナリオの一部を含みます。 テストケースプログラムでは、複数の「it」ブロックを使用できます。
  • 期待-これは、Webページのタイトルをいくつかの事前定義されたデータと比較するアサーションです。
  • ignoreSynchronization -角度のないWebサイトをテストするときに使用されるブラウザーのタグです。 分度器は角度のあるWebサイトでのみ動作することを想定していますが、非角度のWebサイトで動作する場合は、このタグを*“ true” *に設定する必要があります。

構成ファイル

名前が示すように、このファイルはすべての分度器設定オプションの説明を提供します。 それは基本的に分度器に次のことを伝えます-

  • テストまたは仕様ファイルの場所
  • 選択するブラウザ
  • 使用するテストフレームワーク
  • Selenium Serverと話す場所

以下は、テストを行う単純なスクリプトconfig.jsです。

//config.js
exports.config = {
   directConnect: true,

  //Capabilities to be passed to the webdriver instance.
   capabilities: {
      'browserName': 'chrome'
   },

  //Framework to use. Jasmine is recommended.
   framework: 'jasmine',

  //Spec patterns are relative to the current working directory when
  //protractor is called.
   specs: ['TestSpecification.js'],

コードの説明

3つの基本的なパラメータを持つ上記の構成ファイルのコードは、次のように説明することができます-

機能パラメータ

このパラメーターは、ブラウザーの名前を指定するために使用されます。 それはconf.jsファイルの次のコードブロックで見ることができます-

exports.config = {
   directConnect: true,

  //Capabilities to be passed to the webdriver instance.
   capabilities: {
      'browserName': 'chrome'
},

上記のように、ここで指定されているブラウザの名前は「chrome」で、デフォルトでは分度器のブラウザです。 ブラウザの名前を変更することもできます。

フレームワークパラメーター

このパラメーターは、テストフレームワークの名前を指定するために使用されます。 それはconfig.jsファイルの次のコードブロックで見ることができます-

exports.config = {
   directConnect: true,

  //Framework to use. Jasmine is recommended.
   framework: 'jasmine',

ここでは、「ジャスミン」テストフレームワークを使用しています。

ソースファイル宣言パラメーター

このパラメーターは、ソースファイル宣言の名前を指定するために使用されます。 それはconf.jsファイルの次のコードブロックで見ることができます-

exports.config = {
   directConnect: true,
  //Spec patterns are relative to the current working
   directory when protractor is called.
   specs: ['TsetSpecification.js'],

上記のように、ここで指定されたソースファイル宣言の名前は 'TestSpecification.js' です。 この例では、 TestSpecification.js という名前の仕様ファイルを作成したためです。

コードの実行

Protractorを実行するために必要なファイルとそのコーディングについて基本的な理解を得たので、例を実行してみましょう。 この例を実行するには、次の手順に従います-

  • *ステップ1 *-まず、コマンドプロンプトを開きます。
  • ステップ2 *-次に、ファイルを保存したディレクトリ、つまりconfig.jsと *TestSpecification.js に移動する必要があります。
  • *ステップ3 *-ここで、コマンドProtrcator config.jsを実行してconfig.jsファイルを実行します。

以下に示すスクリーンショットは、例を実行するための上記の手順を説明します-

コードの実行

スクリーンショットでは、テストに合格したことがわかります。

ここで、非角形のWebサイトをテストしており、ignoreSynchronizationタグをtrueに設定していない場合、コードを実行した後、「ページ上にAngularが見つかりません」というエラーが表示されます。

それは次のスクリーンショットで見ることができます-

同期を無視

レポート生成

ここまで、テストケースを実行するために必要なファイルとそのコーディングについて説明しました。 分度器は、テストケースのレポートを生成することもできます。 この目的のために、Jasmineをサポートしています。 JunitXMLReporterを使用して、テスト実行レポートを自動的に生成できます。

しかし、その前に、次のコマンドの助けを借りてジャスミンレポーターをインストールする必要があります-

npm install -g jasmine-reporters

ご覧のとおり、Jasmine Reportersのインストール中に-gオプションが使用されています。これは、-gオプションを使用してProtractorをグローバルにインストールしたためです。

jasmine-reportersを正常にインストールした後、以前に使用したconfig.jsファイルに次のコードを追加する必要があります-

onPrepare: function(){//configure junit xml report

   var jasmineReporters = require('jasmine-reporters');
   jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
      consolidateAll: true,
      filePrefix: 'guitest-xmloutput',
      savePath: 'test/reports'
   }));

今、私たちの新しいconfig.jsファイルは次のようになります-

//An example configuration file.
exports.config = {
   directConnect: true,

  //Capabilities to be passed to the webdriver instance.
   capabilities: {
      'browserName': 'chrome'
   },

  //Framework to use. Jasmine is recommended.
   framework: 'jasmine',

  //Spec patterns are relative to the current working directory when
  //protractor is called.
   specs: ['TestSpecification.js'],
  //framework: "jasmine2",//must set it if you use JUnitXmlReporter

   onPrepare: function(){//configure junit xml report

      var jasmineReporters = require('jasmine-reporters');
      jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
         consolidateAll: true,
         filePrefix: 'guitest-xmloutput',
         savePath: 'reports'
      }));
   },
};

上記の設定ファイルを同じ方法で実行した後、以前に実行しました。 reports フォルダーのルートディレクトリの下にレポートを含むXMLファイルを生成します。 テストが成功した場合、レポートは次のようになります-

レポート生成

しかし、テストが失敗した場合、レポートは次のようになります-

レポート生成に失敗しました

分度器-コアAPIS

この章では、分度器の機能の鍵となるさまざまなコアAPIを理解できます。

分度器APIの重要性

分度器は、ウェブサイトの現在の状態を取得するために次のアクションを実行するために非常に重要なAPIの広い範囲を提供します-

  • テストするWebページのDOM要素を取得します。
  • DOM要素との対話。
  • それらにアクションを割り当てます。
  • 情報を共有します。

上記のタスクを実行するには、分度器APIを理解することが非常に重要です。

さまざまな分度器API

Protractorは、Node.jsのWebDriverバインディングであるSelenium-WebDriverのラッパーです。 分度器には、次のAPIがあります-

ブラウザ

これは、ナビゲーション、ページ全体の情報などのブラウザレベルのコマンドを処理するために使用されるWebDriverのインスタンスのラッパーです。 たとえば、browser.getメソッドはページをロードします。

素子

テストしているページのDOM要素を検索して対話するために使用されます。 この目的のために、要素を見つけるために1つのパラメーターが必要です。

ロケーター(by)

要素ロケーター戦略のコレクションです。 たとえば、CSSセレクタ、ID、またはng-modelでバインドされている他の属性によって要素を見つけることができます。

次に、これらのAPIとその機能について詳しく説明します。

ブラウザAPI

上記で説明したように、ブラウザレベルのコマンドを処理するためのWebDriverのインスタンスのラッパーです。 次のようにさまざまな機能を実行します-

機能とその説明

ProtractorBrowser APIの機能は次のとおりです。

*browser.angularAppRoot*

ブラウザAPIのこの関数は、Angularを検索する要素のCSSセレクターを設定します。 通常、この関数は「body」にありますが、ng-appの場合、ページのサブセクションにあります。サブ要素でもあります。

*browser.waitForAngularEnabled*

ブラウザAPIのこの関数は、trueまたはfalseに設定できます。 名前が示すように、この関数がfalseに設定されている場合、ProtractorはAngular $ httpおよび$ timeoutタスクが完了するのを待たずにブラウザーと対話します。 値を渡さずにwaitForAngularEnabled()を呼び出すことにより、現在の状態を変更せずに読み取ることもできます。

*browser.getProcessedConfig*

このブラウザーAPI機能の助けを借りて、現在実行中の仕様や機能など、処理された構成オブジェクトを取得できます。

*browser.forkNewDriverInstance*

名前が示すように、この関数は対話型テストで使用されるブラウザーの別のインスタンスを分岐します。 制御フローを有効または無効にして実行できます。 両方の場合の例を以下に示します-

例1

制御フローを有効にして* browser.forkNewDriverInstance()*を実行します-

var fork = browser.forkNewDriverInstance();
fork.get(‘page1’);

例2

制御フローを無効にして* browser.forkNewDriverInstance()*を実行します-

var fork = await browser.forkNewDriverInstance().ready;
await forked.get(‘page1’);
*browser.restart*

名前が示すように、ブラウザインスタンスを閉じて新しいインスタンスを作成することにより、ブラウザを再起動します。 制御フローを有効または無効にして実行することもできます。 両方の場合の例を以下に示します-

例1 *-制御フローを有効にして browser.restart()*を実行する-

browser.get(‘page1’);
browser.restart();
browser.get(‘page2’);

例2 *-制御フローを無効にして browser.forkNewDriverInstance()*を実行する-

await browser.get(‘page1’);
await browser.restart();
await browser.get(‘page2’);

browser.restartSync

browser.restart()関数に似ています。 唯一の違いは、新しいブラウザインスタンスに解決するプロミスを返すのではなく、新しいブラウザインスタンスを直接返すことです。 制御フローが有効になっている場合にのみ実行できます。

-制御フローを有効にして* browser.restartSync()*を実行する-

browser.get(‘page1’);
browser.restartSync();
browser.get(‘page2’);
*browser.useAllAngular2AppRoots*

名前が示すように、Angular2とのみ互換性があります。 要素を見つけるか、安定を待っている間、ページで利用可能なすべての角度のアプリを検索します。

*browser.waitForAngular*

このブラウザーAPI関数は、Angularがレンダリングを終了し、未処理の$ httpまたは$ timeout呼び出しがなくなるまで待機するようにWebDriverに指示します。

*browser.findElement*

名前が示すように、このブラウザーAPI関数は、要素を検索する前に、Angularがレンダリングを完了するのを待ちます。

*browser.isElementPresent*

名前が示すように、このブラウザーAPI関数は、要素がページに存在するかどうかをテストします。

*browser.addMockModule*

Protractor.getメソッドが呼び出されるたびに、Angularの前にロードするモジュールを追加します。

browser.addMockModule('modName', function() {
   angular.module('modName', []).value('foo', 'bar');
});
*browser.clearMockModules*

browser.addMockModuleとは異なり、登録済みのモックモジュールのリストをクリアします。

*browser.removeMockModule*

名前が示すように、レジスタモックモジュールを削除します。 例:browser.removeMockModule( ‘modName’);

*browser.getRegisteredMockModules*

browser.clearMockModuleの反対側で、登録済みのモックモジュールのリストを取得します。

*browser.get*

browser.get()を使用して、特定のWebアドレスにブラウザーを移動し、Angularのロードの前にそのページのモックモジュールをロードできます。

browser.get(url);
browser.get('http://localhost:3000');
//This will navigate to the localhost:3000 and will load mock module if needed
*browser.refresh*

名前が示すように、これは現在のページをリロードし、Angularの前にモックモジュールをロードします。

*browser.navigate*

名前が示すように、ナビゲーションメソッドをナビゲーションオブジェクトに戻し、それらが以前のように呼び出されるようにするために使用されます。 例:driver.navigate()。refresh()。

*browser.setLocation*

ページ内ナビゲーションを使用して別のページを参照するために使用します。

browser.get('url/ABC');
browser.setLocation('DEF');
expect(browser.getCurrentUrl())
   .toBe('url/DEF');

ABCからDEFページに移動します。

*browser.debugger*

名前が示すように、これは分度器のデバッグで使用する必要があります。 この関数は基本的に制御フローにタスクを追加して、テストを一時停止し、ブラウザーにヘルパー関数を挿入して、ブラウザーコンソールでデバッグできるようにします。

*browser.pause*

WebDriverテストのデバッグに使用されます。 テストで* browser.pause()*を使用して、制御フローのその時点から分度器デバッガーに入ることができます。

element(by.id('foo')).click();
browser.pause();
//Execution will stop before the next click action.
element(by.id('bar')).click();
*browser.controlFlowEnabled*

制御フローが有効かどうかを判断するために使用されます。

分度器-コアAPIS(続き…)

この章では、ProtractorのコアAPIをさらに学習しましょう。

Elements API

要素は、分度器によって公開されるグローバル関数の1つです。 この関数は、ロケータを取り、次を返します-

  • ElementFinder。ロケーターに基づいて単一の要素を検索します。
  • ElementArrayFinder。ロケーターに基づいて要素の配列を検索します。

上記の両方で、以下で説明するチェーン方式がサポートされています。

ElementArrayFinderの連鎖関数とその説明

以下はElementArrayFinderの機能です-

*element.all(locator).clone*

名前が示すように、この関数は要素の配列の浅いコピーを作成します。 ElementArrayFinder。

  • element.all(locator).all(locator)*

この関数は基本的に、空または子要素を含む新しいElementArrayFinderを返します。 次のように、複数の要素を配列として選択するために使用できます

element.all(locator).all(locator)
elementArr.all(by.css(‘.childselector’));
//it will return another ElementFindArray as child element based on child locator.
  • element.all(locator).filter(filterFn)*

名前が示すように、ElementArrayFinder内の各要素にフィルター関数を適用した後、フィルター関数を渡すすべての要素を含む新しいElementArrayFinderを返します。 基本的に2つの引数があり、1つはElementFinderで、2つ目はインデックスです。 ページオブジェクトでも使用できます。

見ます

<ul class = "items">
   <li class = "one">First</li>
   <li class = "two">Second</li>
   <li class = "three">Third</li>
</ul>

コード

element.all(by.css('.items li')).filter(function(elem, index) {
   return elem.getText().then(function(text) {
      return text === 'Third';
   });
}).first().click();
  • element.all(locator).get(index)*

これにより、インデックスによってElementArrayFinder内の要素を取得できます。 インデックスは0から始まり、負のインデックスがラップされることに注意してください。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

let list = element.all(by.css('.items li'));
expect(list.get(0).getText()).toBe('First');
expect(list.get(1).getText()).toBe('Second');
  • element.all(locator).first()*

名前が示すように、これはElementArrayFinderの最初の要素を取得します。 基になる要素は取得しません。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

let first = element.all(by.css('.items li')).first();
expect(first.getText()).toBe('First');
  • element.all(locator).last()*

名前が示すように、これはElementArrayFinderの最後の要素を取得します。 基になる要素は取得しません。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

let first = element.all(by.css('.items li')).last();
expect(last.getText()).toBe('Third');
  • element.all(locator).all(selector)*

$$への呼び出しが連鎖される可能性がある場合に、親内の要素の配列を見つけるために使用されます。

見ます

<div class = "parent">
   <ul>
      <li class = "one">First</li>
      <li class = "two">Second</li>
      <li class = "three">Third</li>
   </ul>
</div>

コード

let items = element(by.css('.parent')).$$('li');
  • element.all(locator).count()*

名前が示すように、これはElementArrayFinderによって表される要素の数をカウントします。 基になる要素は取得しません。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

let list = element.all(by.css('.items li'));
expect(list.count()).toBe(3);
  • element.all(locator).isPresent()*

ファインダーと要素を一致させます。 trueまたはfalseを返すことができます。 ファインダーに一致する要素が存在する場合はTrue、そうでない場合はFalse。

expect($('.item').isPresent()).toBeTruthy();
*element.all(locator).locator*

名前が示すように、最も関連性の高いロケーターを返します。

$('#ID1').locator();
//returns by.css('#ID1')
$('#ID1').$('#ID2').locator();
//returns by.css('#ID2')
$$('#ID1').filter(filterFn).get(0).click().locator();
//returns by.css('#ID1')
  • element.all(locator).then(thenFunction)*

ElementArrayFinderで表される要素を取得します。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

element.all(by.css('.items li')).then(function(arr) {
   expect(arr.length).toEqual(3);
});
  • element.all(locator).each(eachFunction)*

名前が示すように、ElementArrayFinderによって表される各ElementFinderで入力関数を呼び出します。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

element.all(by.css('.items li')).each(function(element, index) {
  //It will print First 0, Second 1 and Third 2.
   element.getText().then(function (text) {
      console.log(index, text);
   });
});
  • element.all(locator).map(mapFunction)*

名前が示すように、ElementArrayFinder内の各要素にマップ関数を適用します。 2つの引数があります。 最初はElementFinderで、2番目はインデックスです。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

let items = element.all(by.css('.items li')).map(function(elm, index) {
   return {
      index: index,
      text: elm.getText(),
      class: elm.getAttribute('class')
   };
});
expect(items).toEqual([
   {index: 0, text: 'First', class: 'one'},
   {index: 1, text: 'Second', class: 'two'},
   {index: 2, text: 'Third', class: 'three'}
]);
  • element.all(locator).reduce(reduceFn)*

名前が示すように、アキュムレーターとロケーターを使用して見つかったすべての要素に対して、reduce関数を適用します。 この関数は、すべての要素を単一の値に削減します。

見ます

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

コード

let value = element.all(by.css('.items li')).reduce(function(acc, elem) {
   return elem.getText().then(function(text) {
      return acc + text + ' ';
   });
}, '');

expect(value).toEqual('First Second Third ');
*element.all(locator).evaluate*

名前が示すように、入力が現在の基本要素のスコープ内にあるかどうかを評価します。

見ます

<span class = "foo">{{letiableInScope}}</span>

コード

let value =
element.all(by.css('.foo')).evaluate('letiableInScope');
*element.all(locator).allowAnimations*

名前が示すように、現在の基本要素でアニメーションを許可するかどうかを決定します。

element(by.css('body')).allowAnimations(false);

ElementFinderの連鎖機能とその説明

ElementFinderの連鎖機能とその説明-

*element(locator).clone*

名前が示すように、この関数はElementFinderの浅いコピーを作成します。

  • element(locator).getWebElement()*

このElementFinderによって表されるWebElementを返し、要素が存在しない場合はWebDriverエラーがスローされます。

見ます

<div class="parent">
   some text
</div>

コード

//All the four following expressions are equivalent.
$('.parent').getWebElement();
element(by.css('.parent')).getWebElement();
browser.driver.findElement(by.css('.parent'));
browser.findElement(by.css('.parent'));
  • element(locator).all(locator)*

親内の要素の配列を検索します。

見ます

<div class = "parent">
   <ul>
      <li class = "one">First</li>
      <li class = "two">Second</li>
      <li class = "three">Third</li>
   </ul>
</div>

コード

let items = element(by.css('.parent')).all(by.tagName('li'));
  • element(locator).element(locator)*

親内の要素を検索します。

見ます

<div class = "parent">
   <div class = "child">
      Child text
      <div>{{person.phone}}</div>
   </div>
</div>

コード

//Calls Chain 2 element.
let child = element(by.css('.parent')).
   element(by.css('.child'));
expect(child.getText()).toBe('Child text\n981-000-568');

//Calls Chain 3 element.
let triple = element(by.css('.parent')).
   element(by.css('.child')).
   element(by.binding('person.phone'));
expect(triple.getText()).toBe('981-000-568');
  • element(locator).all(selector)*

$$への呼び出しが連鎖される可能性がある場合、親内の要素の配列を見つけます。

見ます

<div class = "parent">
   <ul>
      <li class = "one">First</li>
      <li class = "two">Second</li>
      <li class = "three">Third</li>
   </ul>
</div>

コード

let items = element(by.css('.parent')).$$('li'));
  • element(locator)。$(locator)*

$への呼び出しが連鎖される可能性がある場合、親内の要素を検索します。

見ます

<div class = "parent">
   <div class = "child">
      Child text
      <div>{{person.phone}}</div>
  </div>
</div>

コード

//Calls Chain 2 element.
let child = element(by.css('.parent')).
   $('.child'));
expect(child.getText()).toBe('Child text\n981-000-568');

//Calls Chain 3 element.
let triple = element(by.css('.parent')).
   $('.child')).
   element(by.binding('person.phone'));
expect(triple.getText()).toBe('981-000-568');
  • element(locator).isPresent()*

要素がページに表示されるかどうかを決定します。

見ます

<span>{{person.name}}</span>

コード

expect(element(by.binding('person.name')).isPresent()).toBe(true);
//will check for the existence of element

expect(element(by.binding('notPresent')).isPresent()).toBe(false);
//will check for the non-existence of element
  • element(locator).isElementPresent()*

element(locator).isPresent()と同じです。 唯一の違いは、現在の要素ファインダーではなく、サブロケーターによって識別された要素が存在するかどうかをチェックすることです。

*element.all(locator).evaluate*

名前が示すように、入力が現在の基本要素のスコープ上にあるかどうかを評価します。

見ます

<span id = "foo">{{letiableInScope}}</span>

コード

let value = element(by.id('.foo')).evaluate('letiableInScope');
*element(locator).allowAnimations*

名前が示すように、現在の基本要素でアニメーションを許可するかどうかを決定します。

element(by.css('body')).allowAnimations(false);
*element(locator).equals*

名前が示すように、要素の同等性を比較します。

ロケーター(by)API

基本的に、バインディング、モデルなどによってAngularアプリケーションで要素を見つける方法を提供する要素ロケーター戦略のコレクションです。

関数とその説明

ProtractorLocators APIの機能は次のとおりです-

  • by.addLocator(locatorName、fuctionOrScript)*

ProtrcatorByのこのインスタンスにロケーターを追加し、さらにelement(by.locatorName(args))で使用できます。

見ます

<button ng-click = "doAddition()">Go!</button>

コード

//Adding the custom locator.
by.addLocator('buttonTextSimple', function(buttonText, opt_parentElement, opt_rootSelector) {
   var using = opt_parentElement || document,
   buttons = using.querySelectorAll('button');
   return Array.prototype.filter.call(buttons, function(button) {
      return button.textContent === buttonText;
   });
});
element(by.buttonTextSimple('Go!')).click();//Using the custom locator.
*by.binding*

名前が示すように、テキストバインディングによって要素を見つけます。 入力文字列を含む変数にバインドされた要素が返されるように、部分一致が行われます。

見ます

<span>{{person.name}}</span>
<span ng-bind = "person.email"></span>

コード

var span1 = element(by.binding('person.name'));
expect(span1.getText()).toBe('Foo');

var span2 = element(by.binding('person.email'));
expect(span2.getText()).toBe('[email protected]');
*by.exactbinding*

名前が示すように、正確なバインディングによって要素を見つけます。

見ます

<spangt;{{ person.name }}</spangt;
<span ng-bind = "person-email"gt;</spangt;
<spangt;{{person_phone|uppercase}}</span>

コード

expect(element(by.exactBinding('person.name')).isPresent()).toBe(true);
expect(element(by.exactBinding('person-email')).isPresent()).toBe(true);
expect(element(by.exactBinding('person')).isPresent()).toBe(false);
expect(element(by.exactBinding('person_phone')).isPresent()).toBe(true);
expect(element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true);
expect(element(by.exactBinding('phone')).isPresent()).toBe(false);
  • by.model(modelName)*

名前が示すように、ng-model式によって要素を見つけます。

見ます

<input type = "text" ng-model = "person.name">

コード

var input = element(by.model('person.name'));
input.sendKeys('123');
expect(input.getAttribute('value')).toBe('Foo123');
*by.buttonText*

名前が示すように、テキストでボタンを見つけます。

見ます

<button>Save</button>

コード

element(by.buttonText('Save'));
*by.partialButtonText*

名前が示すように、部分的なテキストでボタンを見つけます。

見ます

<button>Save my file</button>

コード

element(by.partialButtonText('Save'));
*by.repeater*

名前が示すように、ng-repeat内の要素を見つけます。

見ます

<div ng-repeat = "cat in pets">
   <span>{{cat.name}}</span>
   <span>{{cat.age}}</span>
<</div>
<div class = "book-img" ng-repeat-start="book in library">
   <span>{{$index}}</span>
</div>
<div class = "book-info" ng-repeat-end>
   <h4>{{book.name}}</h4>
   <p>{{book.blurb}}</p>
</div>

コード

var secondCat = element(by.repeater('cat in
pets').row(1));//It will return the DIV for the second cat.
var firstCatName = element(by.repeater('cat in pets').
   row(0).column('cat.name'));//It will return the SPAN for the first cat's name.
*by.exactRepeater*

名前が示すように、正確なリピーターによって要素を見つけます。

見ます

<li ng-repeat = "person in peopleWithRedHair"></li>
<li ng-repeat = "car in cars | orderBy:year"></li>

コード

expect(element(by.exactRepeater('person in
peopleWithRedHair')).isPresent())
   .toBe(true);
expect(element(by.exactRepeater('person in
people')).isPresent()).toBe(false);
expect(element(by.exactRepeater('car in cars')).isPresent()).toBe(true);
*by.cssContainingText*

名前が示すように、CSSによって、正確な文字列を含む要素を検索します

見ます

<ul>
<li class = "pet">Dog</li>
<li class = "pet">Cat</li>
</ul>

コード

var dog = element(by.cssContainingText('.pet', 'Dog'));
//It will return the li for the dog, but not for the cat.
  • by.options(optionsDescriptor)*

名前が示すように、ng-options式によって要素を見つけます。

見ます

<select ng-model = "color" ng-options = "c for c in colors">
   <option value = "0" selected = "selected">red</option>
   <option value = "1">green</option>
</select>

コード

var allOptions = element.all(by.options('c for c in colors'));
expect(allOptions.count()).toEqual(2);
var firstOption = allOptions.first();
expect(firstOption.getText()).toEqual('red');
  • by.deepCSS(selector)*

名前が示すように、シャドウDOM内でCSSセレクターによって要素を見つけます。

見ます

<div>
   <span id = "outerspan">
      <"shadow tree">
         <span id = "span1"></span>
      <"shadow tree">
      <span id = "span2"></span>
   </>
   </>
</div>

コード

var spans = element.all(by.deepCss('span'));
expect(spans.count()).toEqual(3);

分度器-オブジェクト

この章では、分度器のオブジェクトについて詳しく説明します。

ページオブジェクトとは

ページオブジェクトは、テストメンテナンスを強化し、コードの重複を減らすために、e2eテストを記述するために一般的になったデザインパターンです。 AUT(テスト対象のアプリケーション)のページへのインターフェイスとして機能するオブジェクト指向クラスとして定義できます。 ただし、ページオブジェクトを深く掘り下げる前に、自動UIテストの課題とその処理方法を理解する必要があります。

自動UIテストの課題

以下は、UIテストの自動化に関する一般的な課題です。

UIの変更

UIテストでの作業中に非常に一般的な問題は、UIで変更が発生することです。 たとえば、ほとんどの場合、ボタンやテキストボックスなどが発生します。 通常は変更され、UIテストの問題が発生します。

DSL(ドメイン固有言語)サポートの欠如

UIテストの別の問題は、DSLサポートの欠如です。 この問題により、テスト対象を理解することが非常に難しくなります。

多くの繰り返し/コードの重複

UIテストの次の一般的な問題は、繰り返しまたはコードの重複が多いことです。 それは次のコード行の助けを借りて理解することができます-

element(by.model(‘event.name’)).sendKeys(‘An Event’);
element(by.model(‘event.name’)).sendKeys(‘Module 3’);
element(by.model(‘event.name’));

厳しいメンテナンス

上記の課題により、メンテナンスの頭痛の種になります。 すべてのインスタンスを見つけて、新しい名前、セレクター、および他のコードに置き換える必要があるためです。 また、テストをリファクタリングと一致させるために多くの時間を費やす必要があります。

壊れたテスト

UIテストのもう1つの課題は、テストで多くの失敗が発生することです。

課題に対処する方法

UIテストのいくつかの一般的な課題を見てきました。 このような課題に対処する方法のいくつかは次のとおりです-

参照を手動で更新する

上記の課題を処理する最初のオプションは、参照を手動で更新することです。 このオプションの問題は、テストと同様にコードを手動で変更する必要があることです。 これは、1つまたは2つのテストファイルがある場合に実行できますが、プロジェクトに何百ものテストファイルがある場合はどうでしょうか。

ページオブジェクトの使用

上記の課題を処理する別のオプションは、ページオブジェクトを使用することです。 ページオブジェクトは基本的に、Angularテンプレートのプロパティをカプセル化する単純なJavaScriptです。 たとえば、次の仕様ファイルは、違いを理解するためにページオブジェクトなしとページオブジェクトを使用して記述されています-

ページオブジェクトなし

describe('angularjs homepage', function() {
   it('should greet the named user', function() {
      browser.get('http://www.angularjs.org');
      element(by.model('yourName')).sendKeys('Julie');
      var greeting = element(by.binding('yourName'));
      expect(greeting.getText()).toEqual('Hello Julie!');
   });
});

ページオブジェクト付き

ページオブジェクトを使用してコードを記述する場合、最初に行う必要があるのは、ページオブジェクトを作成することです。 したがって、上記の例のページオブジェクトは次のようになります-

var AngularHomepage = function() {
   var nameInput = element(by.model('yourName'));
   var greeting = element(by.binding('yourName'));

   this.get = function() {
      browser.get('http://www.angularjs.org');
   };

   this.setName = function(name) {
      nameInput.sendKeys(name);
   };

   this.getGreetingText = function() {
      return greeting.getText();
   };
};
module.exports = new AngularHomepage();

ページオブジェクトを使用してテストを整理する

上記の例では、UIテストの課題を処理するためにページオブジェクトを使用することを見てきました。 次に、それらを使用してテストを整理する方法について説明します。 そのためには、テストスクリプトの機能を変更せずにテストスクリプトを変更する必要があります。

この概念を理解するために、ページオブジェクトで上記の構成ファイルを使用します。 次のようにテストスクリプトを変更する必要があります-

var angularHomepage = require('./AngularHomepage');
describe('angularjs homepage', function() {
   it('should greet the named user', function() {
      angularHomepage.get();

      angularHomepage.setName('Julie');

      expect(angularHomepage.getGreetingText()).toEqual
      ('Hello Julie!');
   });
});

ここで、ページオブジェクトへのパスは仕様に関連することに注意してください。

同様に、テストスイートをさまざまなテストスイートに分離することもできます。 設定ファイルは次のように変更できます

exports.config = {
  //The address of a running selenium server.
   seleniumAddress: 'http://localhost:4444/wd/hub',

  //Capabilities to be passed to the webdriver instance.
   capabilities: {
      'browserName': 'chrome'
   },
  //Spec patterns are relative to the location of the spec file. They may
  //include glob patterns.
   suites: {
      homepage: 'tests/e2e/homepage/**/*Spec.js',
      search: ['tests/e2e/contact_search/**/*Spec.js',
         'tests/e2e/venue_search/**/*Spec.js']
   },

  //Options to be passed to Jasmine-node.
   jasmineNodeOpts: {
      showColors: true,//Use colors in the command line report.
   }
};

これで、実行中のテストスイートを簡単に切り替えることができます。 次のコマンドは、テストのホームページセクションのみを実行します-

protractor protractor.conf.js --suite homepage

同様に、次のコマンドを使用して特定のテストスイートを実行できます-

protractor protractor.conf.js --suite homepage,search

分度器-デバッグ

前章で分度器のすべての概念を見てきましたので、この章でデバッグの概念を詳細に理解しましょう。

前書き

エンドツーエンド(e2e)テストは、そのアプリケーションのエコシステム全体に依存するため、デバッグが非常に困難です。 これらはさまざまなアクションに依存していることがわかりました。特に、ログインなどの以前のアクションでは、許可に依存していると言うことができます。 e2eテストのデバッグにおけるもう1つの困難は、WebDriverへの依存性です。これは、オペレーティングシステムとブラウザが異なると動作が異なるためです。 最後に、e2eテストのデバッグも長いエラーメッセージを生成し、ブラウザー関連の問題を分離してプロセスエラーをテストすることを困難にします。

失敗の種類

テストスイートの失敗にはさまざまな理由がありますが、次のような有名な失敗タイプがあります-

WebDriverの障害

コマンドを完了できない場合、WebDriverによってエラーがスローされます。 たとえば、ブラウザが定義されたアドレスを取得できない、または期待どおりに要素が見つかりません。

WebDriverの予期しないエラー

Webドライバーマネージャーの更新に失敗すると、予期しないブラウザーとOS関連の障害が発生します。

Angularの分度器の故障

Protractor for Angularの失敗は、Protractorが期待どおりにライブラリでAngularを見つけられなかったときに発生します。

分度器のAngular2の障害

この種の障害では、構成にuseAllAngular2AppRootsパラメーターが見つからない場合、Protractorは失敗します。 これが発生するのは、これがないと、テストプロセスが1つの単一のルート要素を見ながら、プロセス内の複数の要素を期待するためです。

タイムアウトの分度器障害

この種の障害は、テスト仕様がループまたは長いプールにヒットし、時間内にデータを返さない場合に発生します。

期待失敗

最も一般的なテストの失敗の1つで、通常の期待失敗がどのようなものかを示します。

分度器でデバッグが重要なのはなぜですか?

テストケースを作成して失敗した場合、エラーが発生した正確な場所を見つけるのは非常に難しいため、それらのテストケースをデバッグする方法を知ることは非常に重要です。 Protractorを使用しているときに、コマンドラインで赤色のフォントで長いエラーが発生します。

テストの一時停止とデバッグ

分度器でデバッグする方法については、こちらで説明しています&miuns;

一時停止方法

一時停止メソッドを使用して分度器でテストケースをデバッグするのが最も簡単な方法の1つです。 テストコード&miuns;を一時停止する場所で次のコマンドを入力できます。

browser.pause();

実行中のコードが上記のコマンドをヒットすると、その時点で実行中のプログラムを一時停止します。 その後、私たちは好みに応じて次のコマンドを与えることができます-

前進するためのタイプC

コマンドが使い果たされるたびに、Cを入力して先に進む必要があります。 Cを入力しないと、テストは完全なコードを実行せず、Jasmineタイムアウトエラーのために失敗します。

対話モードに入るためにreplと入力します

インタラクティブモードの利点は、ブラウザにWebDriverコマンドを送信できることです。 対話モードに入る場合は、 repl と入力します。

テストを終了して続行するには、Ctrl-Cを入力します

一時停止状態からテストを終了し、停止した場所からテストを続行するには、Ctrl-Cを入力する必要があります。

この例では、 example_debug.js という名前の以下の仕様ファイルがあります。分度器はロケーター by.binding ( 'mmmm')で要素を識別しようとしますが、URL(https://angularjs.org/pageは指定されたロケーターを持つ要素はありません。

describe('Suite for protractor debugger',function(){
   it('Failing spec',function(){
      browser.get("http://angularjs.org");
      element(by.model('yourName')).sendKeys('Vijay');
        //Element doesn't exist
         var welcomeText =
         element(by.binding('mmmm')).getText();
         expect('Hello '+welcomeText+'!').toEqual('Hello Ram!')
   });
});

ここで、上記のテストを実行するには、テストを一時停止するbrowser.pause()コードを上記の仕様ファイルに追加する必要があります。 次のようになります-

describe('Suite for protractor debugger',function(){
   it('Failing spec',function(){
      browser.get("http://angularjs.org");
      browser.pause();
      element(by.model('yourName')).sendKeys('Vijay');
     //Element doesn't exist
      var welcomeText =
      element(by.binding('mmmm')).getText();
      expect('Hello '+welcomeText+'!').toEqual('Hello Ram!')
   });
});

ただし、実行する前に、構成ファイルでもいくつかの変更を行う必要があります。 前の章で example_configuration.js という名前の以前に使用した設定ファイルで次の変更を行っています-

//An example configuration file.
exports.config = {
   directConnect: true,

  //Capabilities to be passed to the webdriver instance.
   capabilities: {
      'browserName': 'chrome'
   },

  //Framework to use. Jasmine is recommended.
   framework: 'jasmine',

  //Spec patterns are relative to the current working directory when

  //protractor is called.
   specs: ['example_debug.js'],
      allScriptsTimeout: 999999,
      jasmineNodeOpts: {
      defaultTimeoutInterval: 999999
   },
   onPrepare: function () {
      browser.manage().window().maximize();
      browser.manage().timeouts().implicitlyWait(5000);
   }
};

今、次のコマンドを実行します-

protractor example_configuration.js

デバッガは上記のコマンドの後に起動します。

デバッガーメソッド

Protractorでテストメソッドをデバッグするために一時停止メソッドを使用するのは、少し高度な方法です。 テストコードを壊したい場所で次のコマンドを入力できます-

browser.debugger();

ノードデバッガーを使用してテストコードをデバッグします。 上記のコマンドを実行するには、テストプロジェクトの場所から開いた別のコマンドプロンプトに次のコマンドを入力する必要があります-

protractor debug protractor.conf.js

このメソッドでは、テストコードを続行するためにターミナルでCを入力する必要もあります。 ただし、pauseメソッドとは反対に、このメソッドでは1回だけ入力する必要があります。

この例では、上記で使用したb * example_debug.js という名前の同じ仕様ファイルを使用しています。 唯一の違いは、 browser.pause()の代わりに、テストコードを壊したい場所で browser.debugger()*を使用する必要があることです。 次のようになります-

describe('Suite for protractor debugger',function(){
   it('Failing spec',function(){
      browser.get("http://angularjs.org");
      browser.debugger();
      element(by.model('yourName')).sendKeys('Vijay');
     //Element doesn't exist
      var welcomeText = element(by.binding('mmmm')).getText();
      expect('Hello '+welcomeText+'!').toEqual('Hello Ram!')
   });
});

上記の例で使用したのと同じ構成ファイル example_configuration.js を使用しています。

次に、次のデバッグコマンドラインオプションを使用して分度器テストを実行します。

protractor debug example_configuration.js

デバッガは上記のコマンドの後に起動します。

分度器-分度器のスタイルガイド

この章では、分度器のスタイルガイドについて詳しく説明します。

前書き

スタイルガイドは、INGのフロントエンドエンジニア Carmen Popoviciu とGoogleのソフトウェアエンジニア Andres Dominguez という2人のソフトウェアエンジニアによって作成されました。 したがって、このスタイルガイドはCarmen PopoviciuおよびGoogleの分度器用スタイルガイドとも呼ばれます。

このスタイルガイドは、次の5つのキーポイントに分けることができます-

  • 一般的なルール
  • プロジェクト構造
  • ロケーター戦略
  • ページオブジェクト *テストスイート

一般的なルール

以下は、テストのために分度器を使用する際に注意する必要があるいくつかの一般的なルールです-

既にユニットテストされているものをエンドツーエンドでテストしないでください

これは、カルメンとアンドレスによって与えられた最初の一般的な規則です。 彼らは、すでにユニットテストされているコードに対してe2eテストを実行してはならないと提案しました。 その背後にある主な理由は、単体テストがe2eテストよりもはるかに高速であることです。 もう1つの理由は、時間を節約するために、テストの重複(ユニットテストとe2eテストの両方を実行しない)を避ける必要があることです。

1つの構成ファイルのみを使用する

推奨されるもう1つの重要な点は、1つの構成ファイルのみを使用する必要があることです。 テストする環境ごとに構成ファイルを作成しないでください。* grunt-protractor-coverage *を使用して、さまざまな環境をセットアップできます。

テストにロジックを使用しない

テストケースでIFステートメントまたはFORループを使用しないようにする必要があります。使用しない場合、テストは何もテストせずにパスするか、非常に遅く実行される可能性があります。

ファイルレベルでテストを独立させる

分度器は、共有が有効になっている場合、テストを並行して実行できます。 これらのファイルは、利用可能になると、さまざまなブラウザで実行されます。 CarmenとAndresは、分度器によって実行される順序が不明確であり、さらに単独でテストを実行するのが非常に簡単であるため、少なくともファイルレベルでテストを独立させることを推奨しました。

プロジェクト構造

分度器のスタイルガイドに関するもう1つの重要なポイントは、プロジェクトの構造です。 以下は、プロジェクト構造に関する推奨事項です-

賢明な構造でのe2eテストの模索

CarmenとAndresは、プロジェクトの構造に合った構造でe2eテストをグループ化することを推奨しました。 この推奨事項の背後にある理由は、ファイルの検索が容易になり、フォルダ構造がより読みやすくなることです。 このステップでは、e2eテストとユニットテストを分離します。 彼らは、次のような構造を避けることを推奨しました-

|-- project-folder
   |-- app
      |-- css
      |-- img
      |-- partials
         homel
         profilel
         contactsl
      |-- js
         |-- controllers
         |-- directives
         |-- services
         app.js
         ...
      indexl
   |-- test
      |-- unit
      |-- e2e
         home-page.js
         home-spec.js
         profile-page.js
         profile-spec.js
         contacts-page.js
         contacts-spec.js

一方、彼らは次のような構造を推奨しました-

|-- project-folder
   |-- app
      |-- css
      |-- img
      |-- partials
         homel
         profilel
         contactsl
      |-- js
         |-- controllers
         |-- directives
         |-- services
         app.js
         ...
      indexl
   |-- test
      |-- unit
      |-- e2e
         |-- page-objects
            home-page.js
            profile-page.js
            contacts-page.js
         home-spec.js
         profile-spec.js
         contacts-spec.js

ロケーター戦略

以下は、分度器をテストに使用する際に注意する必要のあるいくつかのロケーター戦略です-

XPATHを使用しない

これは、分度器スタイルガイドで推奨される最初のロケーター戦略です。 同じ理由は、マークアップが非常に簡単に変更される可能性があるため、XPathには多くのメンテナンスが必要だからです。 さらに、XPath式は最も遅く、デバッグが非常に困難です。

by.modelやby.bindingなどの分度器固有のロケーターを常に優先する

by.modelやby.bindingなどの分度器固有のロケーターは短く、具体的で読みやすいです。 それらの助けを借りて、ロケーターを書くことも非常に簡単です。

見ます

<ul class = "red">
   <li>{{color.name}}</li>
   <li>{{color.shade}}</li>
   <li>{{color.code}}</li>
</ul>

<div class = "details">
   <div class = "personal">
      <input ng-model = "person.name">
   </div>
</div>

上記のコードでは、次のことを避けることをお勧めします-

var nameElement = element.all(by.css('.red li')).get(0);
var personName = element(by.css('.details .personal input'));

一方、次を使用することをお勧めします-

var nameElement = element.all(by.css('.red li')).get(0);
var personName = element(by.css('.details .personal input'));
var nameElement = element(by.binding('color.name'));
var personName = element(by.model('person.name'));

分度器ロケーターを使用できない場合は、by.idおよびby.cssを使用することをお勧めします。

頻繁に変更されるテキストには、常にテキストロケーターを使用しないでください

ボタン、リンク、ラベルのテキストは時間とともに頻繁に変化するため、by.linkText、by.buttonText、by.cssContaningTextなどのテキストベースのロケーターを避ける必要があります。

ページオブジェクト

前に説明したように、ページオブジェクトはアプリケーションページの要素に関する情報をカプセル化するため、よりクリーンなテストケースを作成するのに役立ちます。 ページオブジェクトの非常に便利な利点は、複数のテストで再利用できることです。アプリケーションのテンプレートが変更された場合、ページオブジェクトを更新するだけで済みます。 以下は、テスト用の分度器を使用する際に注意する必要があるページオブジェクトの推奨事項です。

テスト対象のページと対話するには、ページオブジェクトを使用します

ページオブジェクトを使用してテスト中のページとやり取りすることをお勧めします。テスト中のページ上の要素に関する情報をカプセル化でき、また再利用できるためです。

ファイルごとに常に1ページのオブジェクトを宣言する

各ページオブジェクトを独自のファイルで定義する必要があります。これにより、コードがクリーンに保たれ、物の発見が容易になります。

ページの最後で、オブジェクトファイルは常に単一のmodule.exportsを使用します

1つのクラスのみをエクスポートする必要があるように、各ページオブジェクトで単一のクラスを宣言することをお勧めします。 たとえば、オブジェクトファイルの次の使用は避ける必要があります-

var UserProfilePage = function() {};
var UserSettingsPage = function() {};
module.exports = UserPropertiesPage;
module.exports = UserSettingsPage;

しかし、一方で、以下を使用することをお勧めします-

/* *@constructor*/
var UserPropertiesPage = function() {};

module.exports = UserPropertiesPage;

必要なすべてのモジュールを上部で宣言します

モジュールの依存関係を明確かつ見つけやすくするため、必要なすべてのモジュールをページオブジェクトの上部で宣言する必要があります。

テストスイートの開始時にすべてのページオブジェクトをインスタンス化する

テストスイートの最初にすべてのページオブジェクトをインスタンス化することをお勧めします。これにより、テストコードから依存関係が分離され、スイートのすべての仕様で依存関係が利用可能になります。

ページオブジェクトでexpect()を使用しないでください

ページオブジェクトでexpect()を使用しないでください。 すべてのアサーションはテストケースで行う必要があるため、ページオブジェクトでアサーションを作成しないでください。

もう1つの理由は、テストの読者がテストケースのみを読むことでアプリケーションの動作を理解できる必要があることです。