PuppeteerとJestを使用してNode.jsでエンドツーエンドのテストを作成する方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
エンドツーエンドテスト(略して e2e )は、アプリケーションのライフサイクル全体を本番環境のようなシナリオでユーザーの観点からテストするプロセスです。 このプロセスには通常、通常のユーザーと同じようにアプリケーションのインターフェイスを自動的にナビゲートするスクリプトを展開し、その過程で特定の機能と動作をテストすることが含まれます。 Node.js 開発では、 Chrome API PuppeteerとJavaScriptテストフレームワークJestを組み合わせて使用して、e2eテストを自動化できます。 、バグを修正して新しい機能を追加するときに、アプリケーションのユーザーインターフェイス(UI)が引き続き機能していることを確認できます。
このチュートリアルでは、サンプルWebページのアカウント作成およびログイン機能が意図したとおりに機能することを検証するe2eテストを作成します。 最初に、基本的なPuppeteerスクリプトを記述してブラウザーを開き、テストWebページに移動します。次に、ブラウザーとページインスタンスをグローバルに使用できるようにするプリセットを構成します。 次に、 GitHubのDigitalOceanCommunityリポジトリからmock-authサンプルアプリケーションのクローンを作成し、アプリケーションをローカルで提供します。 このサンプルアプリケーションは、アカウントを作成してそのアカウントにログインするためのインターフェイスをユーザーに提供します。 最後に、アカウント作成フォームとログインフォームに入力するようにPuppeteerスクリプトを調整し、送信ボタンをクリックしてから、Jestで単体テストを記述して、スクリプトが期待どおりに機能することを検証します。
警告:ウェブスクレイピングの倫理と合法性は複雑であり、絶えず進化しています。 また、場所、データの場所、および問題のWebサイトによっても異なります。 このチュートリアルでは、スクレーパーアプリケーションをテストするために特別に設計されたローカルで提供されるサンプルアプリケーションをスクレイプします。 他のドメインをスクレイピングすることは、このチュートリアルの範囲外です。
前提条件
このガイドを開始する前に、次のものが必要です。
- Node.jsバージョン
14.16.0
以降がコンピューターにインストールされています。 これをmacOSまたはUbuntu20.04にインストールするには、 Node.jsをインストールし、macOSまたはオプション2にローカル開発環境を作成する方法—NodeSourceを使用したAptでのNode.jsのインストールの手順に従います。 Ubuntu20.04にNode.jsをインストールする方法のPPAセクション。 - ChromeWebブラウザがインストールされているローカルデスクトップ環境。 このチュートリアルで使用されているPuppeteerスクリプトはヘッドレスモードで実行されないため、テストを実行するにはデスクトップ環境が必要です。
- Puppeteerとそれが提供するAPIにある程度精通している。 Node.jsとPuppeteerを使用してWebサイトをスクレイプする方法に従って、Puppeteerの使用方法を学ぶことができます。
- Jestで単体テストを作成した経験もあります。 このトピックの詳細については、Jestの公式ドキュメントを確認してください。
ステップ1—テストプログラムを開始する
このステップでは、Node.jsテストプログラム用のディレクトリを作成し、必要な依存関係をインストールします。 このチュートリアルでは、3つの依存関係を使用します。これらの依存関係は、Node.jsのデフォルトのパッケージマネージャーであるnpmを使用してインストールします。 これらの依存関係により、JestとPuppeteerを一緒に使用できるようになります。
まず、このプロジェクトのフォルダーを作成し、そのフォルダーに移動します。 このチュートリアルでは、プロジェクトの名前としてend-to-end-test-tutorial
を使用します。
mkdir end-to-end-test-tutorial cd end-to-end-test-tutorial
以降のすべてのコマンドは、このディレクトリで実行します。
これで、ディレクトリ内のnpmを初期化して、依存関係を追跡できるようになります。 次のコマンドを使用して、プロジェクトのnpmを初期化します。
npm init
このコマンドは、一連のプロンプトを表示します。 すべてのプロンプトでENTER
を押すか、パーソナライズされた説明を追加できます。 必ずENTER
を押し、entry point:
およびtest command:
の入力を求められたら、デフォルト値のままにしておきます。 または、-y
フラグをnpm
に渡すと、すべてのデフォルト値が送信されます。
これらのプロンプトに入力すると、package.json
ファイルが作成され、プロジェクトの依存関係といくつかの追加のメタデータが管理されます。
次に、ファイルを保存するように求められます。 yes
と入力し、ENTER
を押します。 npmは、この出力をpackage.json
ファイルとして保存します。
これで、依存関係をインストールできます。 このチュートリアルに必要な3つの依存関係は次のとおりです。
jest
:ユニットテストライブラリ。puppeteer
:ChromeDevtoolsプロトコルを介した高レベルの抽象化API。- jest-puppeteer :PuppeteerでJestを適切にセットアップするのに役立つパッケージ。
npmを使用してこれらの依存関係をインストールします。
npm install --save jest puppeteer jest-puppeteer
このコマンドを実行すると、Jest、Puppeteer、互換性のあるバージョンのChromiumブラウザー、およびjest-puppeteer
ライブラリがインストールされます。
注: Linuxマシンでは、Puppeteerに追加の依存関係が必要になる場合があります。 Ubuntu 20.04を使用している場合は、PuppeteerのトラブルシューティングドキュメントのUNIXセクションでChromeヘッドレス内のDebianDependenciesドロップダウンが起動しないことを確認してください。 次のコマンドを使用して、不足している依存関係を見つけることもできます。
ldd ~/end-to-end-test-tutorial/node_modules/puppeteer/.local-chromium/linux-970485/chrome-linux/chrome | grep not
このコマンドでは、プロジェクトのChromeのインストールでldd
を使用してプログラムの依存関係を検索し、結果をgrep
にパイプして、not
という単語を含むすべての依存関係を検索します。 。 これにより、インストールされていない依存関係が表示されます。 chrome
モジュールへの個々のパスは異なる場合があることに注意してください。
必要な依存関係がインストールされると、package.json
ファイルのdependencies
の一部としてそれらが含まれます。 これを確認するには、お好みのテキストエディタで開きます。
nano package.json
これにより、次のようなファイルが表示されます。
end-to-end-test-tutorial / package.json
{ "name": "end-to-end-test-tutorial", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "jest": "^27.5.1", "jest-puppeteer": "^6.1.0", "puppeteer": "^13.5.0" } }
これにより、依存関係がインストールされたことを確認できます。
テストプログラムを開始し、依存関係を設定したら、次にそれを構成し、最初のPuppeteerスクリプトを追加して、すべてが正しく設定されていることを確認します。
ステップ2—テストプログラムの構成
Webサイトを手動でテストする方法は、ブラウザーを使用してWebページを閲覧し、ボタンをクリックし、ページをスクロールして、各インタラクションで正しいページとテキストがレンダリングされていることを確認することです。 これらは、自動化されたエンドツーエンドテストの作成に関連する手順と同じです。ブラウザはプログラムでWebページを開き、インターフェイスをナビゲートします。テストライブラリは、ブラウザがWebページから期待される動作または出力を取得したことを表明します。 このステップでは、Node.jsアプリケーションでこれらの手順を実行するようにJestとPuppeteerを構成し、www.google.com
にアクセスするPuppeteerスクリプトを使用して構成をテストします。
まず、テストアプリケーションに構造を与えるためにいくつかのフォルダを作成します。
mkdir actions mkdir logs mkdir specs mkdir utils
actions
フォルダーには、ローカルWebページをクロールするPuppeteerスクリプトが保持され、specs
にはテスト自体が保持され、utils
には模擬クレデンシャル生成などのヘルパーファイルが保持されます。 このチュートリアルでは使用されていませんが、テストの結果を保持するためにlogs
フォルダーを作成することをお勧めします。
これらのディレクトリを作成したら、お好みのエディタでjest.config.js
ファイルを作成して開きます。
nano jest.config.js
次の構成をファイルに追加します。
end-to-end-test-tutorial / jest.config.js
module.exports = { preset: 'jest-puppeteer', roots: [ 'specs' ], };
これはJest構成ファイルであり、インストールしたjest-puppeteer
ライブラリのpreset
構成を使用するようにJestに指示するように設定されています。 また、このチュートリアルの後半で作成するテストスクリプトの場所としてspecs
フォルダーを指定します。
ファイルを保存して終了します。 次に、ルートディレクトリから、jest-puppeteer.config.js
ファイルを作成して開きます。
nano jest-puppeteer.config.js
次の構成をファイルに追加します。
end-to-end-test-tutorial / jest-puppeteer.config.js
module.exports = { launch: { headless: false, args: [ "--window-size=1366,768" ], }, browser: 'chromium', }
これらの構成は、Webページをテストするためにブラウザーを開く方法を定義します。 headless
は、ブラウザがインターフェイスの有無にかかわらず実行されるかどうかを決定します。 この場合、デスクトップ環境でウィンドウを開くようにPuppeteerを構成しています。 args
は、関連するPuppeteer引数をブラウザインスタンスに渡すために使用されます。 この場合、これを使用して、開いているブラウザのウィンドウサイズを指定します。 最後に、browser
は使用するブラウザを指定します。 このチュートリアルでは、これはChromiumですが、 puppeteer-firefox がインストールされている場合は、Firefoxである可能性があります。
ファイルを保存して終了します。
specs
フォルダーをすべてのテストを保持するフォルダーとして設定し、そのフォルダーに基本的なテストファイルを作成します。
specs
フォルダーに移動し、users.test.js
ファイルを作成します。 users.test.js
ファイルを開き、次のコードを追加して、アプリケーションの機能をテストします。
end-to-end-test-tutorial / spec / users.test.js
jest.setTimeout(60000) describe('Basic authentication e2e tests', () => { beforeAll( async () => { // Set a definite size for the page viewport so view is consistent across browsers await page.setViewport( { width: 1366, height: 768, deviceScaleFactor: 1 } ); await page.goto('https://www.google.com'); await page.waitFor(5000); } ); it( 'Should be truthy', async () => { expect( true ).toBeTruthy(); }) });
このコードでは、最初にsetTimeout()
メソッドを使用してJestのデフォルトのタイムアウトを60秒に設定します。 Jestのデフォルトのタイムアウトは5秒で、テストに合格または不合格になる必要があります。そうでない場合、テストはエラーを返します。 ブラウザの操作は実行に5秒以上かかることが多いため、時間の経過に対応するために60秒に設定します。
次に、describe
ブロックは、describe
キーワードを使用して、関連するテストを相互にグループ化します。 その中で、beforeAll
スクリプトを使用すると、このブロック内のすべてのテストの前に特定のコードを実行できます。 これは、このテストブロックに対してローカルであるが、含まれるすべてのテストに対してグローバルである変数のようなコードを保持します。 ここでは、ブラウザで開いたページのビューポートをjest-puppeteer.config.js
で指定したブラウザのサイズに設定するために使用しています。 次に、page
オブジェクトを使用してwww.google.com に移動し、5秒間待機します。これにより、ページが読み込まれた後、ブラウザが閉じる前にページが表示されます。 page
オブジェクトは、すべてのテストスイートでグローバルに使用できます。
次に、作成したスクリプトが機能することを検証するための模擬テストを作成しました。 ブール値true
が真の値であるかどうかをチェックします。これは、すべてが正しく機能している場合は常に当てはまります。
ファイルを保存して終了します。
ここで、テストを実行して、期待どおりに機能するかどうかを確認する方法が必要です。 次のコードブロックに示すように、package.json
ファイルを開き、scripts
セクションを変更します。
end-to-end-test-tutorial / package.json
{ "name": "Doe's-e2e-test", "version": "1.0.0", "description": "An end to end test", "main": "index.js", "scripts": { "e2e": "jest" }, "keywords": [], "author": "John Doe", "license": "MIT" }
これにより、キーワードe2e
がjest
コマンドを呼び出してテストを実行します。 ファイルが保存されたら、次のコマンドを使用して、ターミナルでe2eテストを実行します。
npm run e2e
このコマンドを実行すると、新しいブラウザウィンドウが開き、Googleに移動して、コンソールに次の出力を出力します。
Output > jest PASS specs/users.test.js (13.772s) Basic authentication e2e tests √ Should be truthy (3ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 14.221s, estimated 16s Ran all test suites.
これは、PuppeteerとJestの両方が正しく機能していることを示しています。 これで、Webページのテストを作成する準備が整いました。 ただし、最初に、テストするインターフェイスを使用できるようにサンプルWebページを設定します。
ステップ3—サンプルWebインターフェイスの実行
このステップでは、 DigitalOcean Community GitHubリポジトリからサンプルアプリケーションのクローンを作成し、LiveServer開発サーバーを使用してローカルで実行します。 これにより、Node.jsアプリケーションでテストするためのユーザーインターフェイスが提供されます。
注:このチュートリアルでは、このサンプルUIをユーザーの観点からのみ検査します。 ユーザーインターフェイスを構築するために必要な開発は、このチュートリアルの範囲を超えています。 UIログイン認証ページの開発に興味がある場合は、Reactアプリケーションにログイン認証を追加する方法チュートリアルを確認してください。
まず、新しいターミナルを開き、テストアプリケーションの外部で次のgitコマンドを実行します。
git clone https://github.com/do-community/mock-auth.git
これにより、DigitalOceanリポジトリからユーザーインターフェイスのクローンが作成されます。 このコードには、模擬認証インターフェースを作成する HTML 、 CSS 、およびJavaScriptが含まれています。
次に、次のコマンドを使用してLiveServerをグローバルにインストールします。
npm install -g live-server
注: Ubuntu 20.04などの一部のシステムでは、npmパッケージをグローバルにインストールすると、アクセス許可エラーが発生し、インストールが中断される可能性があります。 sudo
をnpm install
と一緒に使用しないことはセキュリティのベストプラクティスであるため、代わりにnpmのデフォルトディレクトリを変更することでこれを解決できます。 EACCES
エラーが発生した場合は、公式のnpmドキュメントのの指示に従ってください。
Live Serverは、ライブリロード機能を備えた軽量の開発サーバーです。 静的なHTMLページを取得し、localhost
で利用できるようにします。
次に、mock-auth
サンプルインターフェイスに移動します。
cd mock-auth
次に、次のコマンドを使用して、ローカル開発サーバーでアプリケーションを起動します。
live-server
デフォルトのブラウザでhttp://127.0.0.1:8080
のWebページが開き、次の画像として表示されます。
これは、テストプログラムが対話するUIです。 ログインボタンをクリックすると、ブラウザはユーザー名とパスワードのフィールドを含むログインフォームをロードします。 アカウントの作成ボタンを選択すると、アカウントの作成フォームが表示され、フルネーム、ユーザー名、パスワードのフィールドが表示されます。 次の手順では、これらの各インターフェイスをナビゲートするテストを作成し、アカウントの作成とログインが期待どおりに機能することを確認します。
ステップ4—アカウント作成のテスト
Webサイトでアカウントを作成する場合、最も一般的な動作は、Webサイトが、名前と新しく作成したアカウントに関するいくつかの関連情報が記載されたウェルカムページに移動することです。 このステップでは、サンプルWebアプリケーションのアカウント作成ページがこのように機能することを検証します。 これを行うには、actions
フォルダーにスクリプトを記述してインターフェイスをナビゲートし、そのアクションを使用して機能を検証するテストを記述します。
まず、テストプログラムが含まれているターミナルに戻り、サンプルWebアプリケーションのアカウントの作成ページをクロールするスクリプトを作成します。 このチュートリアルでは、このファイルにcreateAccount.js
という名前を付けます。
nano actions/createAccount.js
このファイルを開いたら、次のコードを追加します。
エンドツーエンドテストチュートリアル/actions/createAccount.js
const chalk = require( 'chalk' ); class createAccount { constructor( page ) { this.url = "http://127.0.0.1:8080/" this.page = page; this.signupBtn = '#signup'; this.signupBody = '#signupBody'; this.fullnameField = '#fullname'; this.usernameField = '#username'; this.passwordField = '#password'; this.loginPageBtn = '#loginBtn'; this.signupPageBtn = '#signupBtn'; } } module.exports = ( page ) => new createAccount( page );
このスニペットは、最初にchalk
モジュールをインポートします。このモジュールは、後でターミナルでエラーメッセージをフォーマットするために使用されます。 これは必須ではありませんが、エラー報告が読みやすくなります。 次に、createAccount
というクラスを作成します。 コンストラクターはpage
パラメーターを受け取り、サンプルWebアプリケーションのホームページURLを設定し、プログラムがDOM[X229Xで対話するHTML要素へのID参照としてオブジェクトのプロパティを設定します。 ]。 最後に、コードは関数をエクスポートして、createAccount
クラスの新しいインスタンスを作成します。
次に、signup
メソッドをcreateAccount
クラスに追加します。これは、ページでさまざまなアクションを実行するのに役立ちます。 次の強調表示されたコードをファイルに追加します。
エンドツーエンドテストチュートリアル/actions/createAccount.js
... this.signupPageBtn = '#signupBtn'; } async signup( fullname, username, password ) { try { await this.page.goto( this.url ); await this.page.waitFor( this.signupBtn ); await this.page.click( this.signupBtn ); // Wait for the signupBody on the signup page to load await this.page.waitFor( this.signupBody ); // Type the login credentials into the input fields await this.page.type( this.fullnameField, fullname ); await this.page.waitFor( 1000 ); await this.page.type( this.usernameField, username ); await this.page.waitFor( 1000 ); await this.page.type( this.passwordField, password ); await this.page.waitFor( 1000 ); // Click then create account button await this.page.click( this.signupPageBtn ); // Wait for homepage to load await this.page.waitFor( '#firstname' ); await this.page.waitFor( 2000 ); const firstname = await this.page.$eval( '#homeBody #firstname', el => el.textContent ); return firstname; } catch ( err ) { console.log( chalk.red( 'ERROR => ', err ) ); } } } module.exports = ( page ) => new createAccount( page );
ここでは、signup
メソッドを非同期キーワードとして宣言しています。 この関数は、 try ... catch ブロックを使用して、WebアプリケーションのURLに移動し、インターフェースをナビゲートします。 page
オブジェクトで使用されるメソッドのいくつかは次のとおりです。
page.goto(url)
:ブラウザを指定されたURLに移動します。page.waitFor(milliseconds or element)
:指定されたミリ秒の間、または要素がロードされるまで、ページ上の他のアクションを遅らせます。page.click(selector)
:ページ上の要素をクリックします。page.type(selector, text)
:指定された入力フィールドにテキストを入力します。page.$eval(selector, callback(element))
:要素を選択し、その要素に対してコールバック関数を実行します。
これらの方法では、signup
関数は最初にページをベースURLにナビゲートし、次にサインアップボタンがロードされるのを待ちます。 次に、このボタンをクリックして、サインアップフォームの本文が読み込まれるのを待ちます。 フルネーム、ユーザー名、パスワードをそれぞれのフィールドに1秒間隔で入力します。 次に、サインアップボタンをクリックして、ウェルカムページが読み込まれるのを待ちます。 page.$eval()
メソッドは、このメソッドから返されるウェルカムページに表示される名前をフェッチするために使用されます。
ファイルを保存して終了します。
次に、アカウントの作成が期待どおりに機能することを検証するためのテストを作成します。 ただし、先に進む前に、新しいアカウントを作成するためのクレデンシャルを決定する必要があります。 このために、新しいモジュールを作成します。
credentials.js
ファイルをutils
フォルダーに作成します。
nano utils/credentials.js
次のコードをファイルに追加します。
end-to-end-test-tutorial / utils / credentials.js
module.exports = ( user ) => { let username = `${user}-${Math.random()}` let password = `${Math.random()}`; // Make sure both usernames and passwords are strings username = String( username ); password = String( password ); const fullname = "John Doe" let credential = { fullname, username, password }; return credential; }
このコードは、ランダムなユーザー名、パスワード、およびハードコードされたフルネームを生成し、生成された資格情報をJSONオブジェクトとして返します。 ハードコードされた名前を任意の名前に変更できますが、多くの場合、アカウントを作成するときの一意のエンティティはユーザー名です。
保存してcredentials.js
を終了します。
次に、specs
フォルダーに移動し、エディターでusers.test.js
ファイルを開きます。 ここに示すようにコードを変更します。
end-to-end-test-tutorial / specs / users.test.js
let credentials = require( '../utils/credentials' ); jest.setTimeout(60000); describe('Basic authentication e2e tests', () => { let credential; beforeAll( async () => { // Set a definite site for the page viewport so view is consistent across browsers await page.setViewport( { width: 1366, height: 768, deviceScaleFactor: 1 } ); credential = credentials( 'User' ); await page.goto('https://www.google.com'); await page.waitFor(5000); } ); it( 'Should be truthy', async () => { expect( true ).toBeTruthy(); }) } );
ここでは、前に作成したcredentials
モジュールをインポートし、そのブロック内のすべてのテストでグローバルに使用できるcredential
変数を作成し、beforeAll
を使用して生成された資格情報をその変数に割り当てました。このブロックのすべてのテストの前に実行されるブロック。
これで、次のようにコードを変更することで、実際に検証を行うテストを作成できます。
end-to-end-test-tutorial / specs / users.test.js
let credentials = require( '../utils/credentials' ); let createAccount = require( '../actions/createAccount' ); jest.setTimeout(60000); describe('Basic authentication e2e tests', () => { let credential; beforeAll( async () => { // Set a definite site for the page viewport so view is consistent across browsers await page.setViewport( { width: 1366, height: 768, deviceScaleFactor: 1 } ); credential = credentials( 'User' ); createAccount = await createAccount( page ); } ); it( 'Should be able to create an account', async () => { const firstname = await createAccount.signup( credential.fullname, credential.username, credential.password ); page.waitFor( 1000 ); expect( credential.fullname ).toContain( firstname ); }) } );
これで、createAccount
モジュールをインポートし、signup
メソッドを呼び出して、プログラムがインターフェイスをナビゲートした後、ウェルカムページにfullname
を表示しました。 次に、コードは、このfullname
がテストメソッドが呼び出される前に生成されたfullname
と同じであることを表明します。
スクリプトを保存し、コマンドnpm run e2e
を使用して実行します。
npm run e2e
Chromeブラウザが開き、生成されたクレデンシャルを使用してアカウントが自動的に作成されます。 テストが終了すると、次の出力がコンソールに記録されます。
Output> jest PASS specs/users.test.js (28.881s) Basic authentication e2e tests √ Should be able to create an account (26273ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 29.087s Ran all test suites.
このスクリプトにより、アカウント作成プロセスが検証されました。
このステップでは、サンプルWebアプリケーションをクロールし、アカウントを自動的に作成するスクリプトを作成しました。 次に、クローラースクリプトの単体テストを作成することにより、プロセスが期待どおりに機能することを確認しました。 次のステップでは、ログイン機能についても同じことを行います。
ステップ5—ログインプロセスのテスト
このステップでは、ログイン機能が正常に機能することを表明します。 この手順は、アカウントの作成手順と似ています。最初にWebクローラースクリプトを作成してログインページをナビゲートし、次に単体テストを記述して、機能が期待どおりに機能していることを確認します。
まず、お好みのエディターでloginAccount.js
ファイルを作成して開きます。
nano actions/loginAccount.js
次に、次のコードを追加して、ログインページをトラバースします。
エンドツーエンドテストチュートリアル/アクション/loginAccount.js
const chalk = require( 'chalk' ); class LoginAccount { constructor( page ) { this.url = "http://127.0.0.1:8080/" this.page = page; this.loginBtn = '#login'; this.loginBody = '#loginBody'; this.usernameField = '#username'; this.passwordField = '#password'; this.loginPageBtn = '#loginBtn'; } async login( username, password ) { try { await this.page.goto( this.url ); await this.page.waitFor( this.loginBtn ); await this.page.click( this.loginBtn ); // Wait for the loginBody on the login page to load await this.page.waitFor( this.loginBody ); // Type the login credentials into the input fields await this.page.type( this.usernameField, username ); await this.page.waitFor( 1000 ); await this.page.type( this.passwordField, password ); await this.page.waitFor( 1000 ); await this.page.click( this.loginPageBtn ); // Wait for homepage to load await this.page.waitFor( '#firstname' ); await this.page.waitFor( 2000 ); const firstname = await this.page.$eval( '#homeBody #firstname', el => el.textContent ); return firstname; } catch ( err ) { console.log( chalk.red( 'ERROR => ', err ) ); } } } module.exports = ( page ) => new LoginAccount( page );
このコードは、createAccount.js
ファイルに似ています。 まず、LoginAccount
クラスを作成し、page
オブジェクトをパラメーターとして受け取る関数をエクスポートしました。 コンストラクターには、DOMで対話するためのいくつかのHTML要素へのID参照が含まれています。
LoginAccount
クラスには、username
およびpassword
をパラメーターとして受け取り、ページでさまざまなアクションを実行するのに役立つ非同期login
メソッドがあります。 コードは最初にサンプルWebアプリケーションのURLに移動し、次にログインページをロードするボタンをクリックします。 ログインページが読み込まれると、login
メソッドに渡されたユーザー名とパスワードをフォームに入力し、ログインボタンをクリックして送信します。 ログインが成功すると、ウェルカムページが読み込まれ、単体テストに渡す名が返されます。
ファイルを保存して終了します。
次に、users.test.js
ファイルを再度開き、次のように変更します。
end-to-end-test-tutorial / specs / users.test.js
let credentials = require( '../utils/credentials' ); let createAccount = require( '../actions/createAccount' ); let loginAccount = require( '../actions/loginAccount' ); jest.setTimeout(60000); describe('Basic authentication e2e tests', () => { let credential; beforeAll( async () => { // Set a definite site for the page viewport so view is consistent across browsers await page.setViewport( { width: 1366, height: 768, deviceScaleFactor: 1 } ); credential = credentials( 'User' ); createAccount = await createAccount( page ); loginAccount = await loginAccount( page ); } ); it( 'Should be able to create an account', async () => { const firstname = await createAccount.signup( credential.fullname, credential.username, credential.password ); page.waitFor( 1000 ); expect( credential.fullname ).toContain( firstname ); }) it( 'Should be able to log in after a successful account creation', async () => { const firstname = await loginAccount.login( credential.username, credential.password ); page.waitFor( 1000 ); expect( credential.fullname ).toContain( firstname ); } ); } );
このコードでは、page
のWebクローラー関数と呼ばれるloginAccount
モジュールをインポートし、Loginページの名前が合格した場合に合格する新しいテストアサーションを作成しました生成された資格情報に含まれています。
ファイルを保存し、ターミナルからnpm run e2e
を実行します。
npm run e2e
Webクローラーはブラウザーを開き、 Login ページに移動して資格情報を入力すると、テストスクリプトが実行され、Webクローラーがウェルカムページに到達したかどうかが確認されます。
以下が端末に記録されます。
Output> jest PASS specs/users.test.js (48.96s) Basic authentication e2e tests √ Should be able to create an account (21534ms) √ Should be able to log in after a successful account creation (12899ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 52.426s Ran all test suites.
これは、ログインが成功するためのテストが期待どおりに合格したことを示しています。 ただし、テストはまだ完了していません。 プログラムは、失敗したログイン試行を処理できる必要があります。
間違ったユーザー名とパスワードの組み合わせが指定された場合、アラートプロンプトがポップアップし、無効なユーザー名またはパスワードが入力されましたというメッセージが表示されます。 アラートボックスメッセージをテストするには、page
オブジェクトでdialog
イベントをリッスンできます。 警告ボックスの存在は、ログインが失敗したことを示しています。
これを実装するには、次のようにusers.test.js
スクリプトを変更します。
end-to-end-test-tutorial / specs / users.test.js
let credentials = require( '../utils/credentials' ); let createAccount = require( '../actions/createAccount' ); let loginAccount = require( '../actions/loginAccount' ); jest.setTimeout(60000); describe('Basic authentication e2e tests', () => { let credential; beforeAll( async () => { // Set a definite site for the page viewport so view is consistent across browsers await page.setViewport( { width: 1366, height: 768, deviceScaleFactor: 1 } ); credential = credentials( 'User' ); createAccount = await createAccount( page ); loginAccount = await loginAccount( page ); } ); it( 'Should be able to create an account', async () => { const firstname = await createAccount.signup( credential.fullname, credential.username, credential.password ); page.waitFor( 1000 ); expect( credential.fullname ).toContain( firstname ); }) it( 'Should be able to log in after a successful account creation', async () => { const firstname = await loginAccount.login( credential.username, credential.password ); page.waitFor( 1000 ); expect( credential.fullname ).toContain( firstname ); } ); it( 'Should not login on wrong credentials', async () => { try { page.on( 'dialog', dialog => { expect( dialog.message() ).toBe( 'Invalid username or password inputted' ); dialog.accept(); }); await page.goto( 'http://127.0.0.1:8080/login.html' ); await page.type( '#username', 'username' ); await page.type( '#password', 'password' ); await page.click( '#loginBtn' ); await page.waitFor(5000) //Wait for the dialog to accept the prompt before proceeding } catch(err){ console.log("An error occured while trying to login => ", err) } }) } );
このコードでは、ページの操作を実行する前に、最初にdialog
イベントのイベントリスナーを設定する新しいアサーションを追加しました。 dialog
イベントをリッスンする前にWebクローラーがボタンをクリックすると、イベントがバブルされる前にdialog
がポップアップ表示されます。
次に、コードはlogin.html
ページに移動し、資格情報としてusername
とpassword
を入力します。 これらのクレデンシャルは、アカウントの作成時に入力したクレデンシャルと一致しないため、エラーが発生し、アサーションが待機しているダイアログボックスがトリガーされます。 最後に、最後に5秒の遅延を追加したことに注意してください。 これは、jest-puppeteer
がページを閉じる前に、dialog
イベントがダイアログを受け入れるようにするためです。 実行できるテストがなくなると、ページは閉じられます。
users.test.js
ファイルを保存して、テストを実行します。
npm run e2e
次に、すべてのテストに合格することを確認します。
Output PASS specs/users.test.js (25.736 s) Basic authentication e2e tests ✓ Should be able to create an account (11987 ms) ✓ Should be able to log in after a successful account creation (8196 ms) ✓ Should not login on wrong credentials (5168 ms) Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total Snapshots: 0 total Time: 25.826 s, estimated 27 s Ran all test suites.
これは、サンプルWebアプリケーションが期待どおりに機能していることを示しています。
結論
このチュートリアルでは、PuppeteerとJestを使用して、アカウント作成とログイン機能を備えたサンプルWebアプリケーションの自動テストを作成しました。 PuppeteerとJestが連携するように構成してから、WebアプリケーションUIをナビゲートし、検出したHTML要素の値を返すスクリプトを作成しました。 最後に、これらの値が、テストしていたアクションの期待値と一致するかどうかをテストしました。
エンドツーエンドのテストは、UIをテストするための便利な方法であるだけではありません。 また、これを使用して、Webアプリケーションの他の主要な機能が期待どおりに機能することを確認することもできます。 たとえば、デバイスエミュレーションとネットワークスロットリングを使用して、複数のデバイス間でパフォーマンステストを実行できます。 エンドツーエンドテストの詳細については、PuppeteerおよびJestの公式ドキュメントを確認してください。