ProtractorのE2Eテストで「Timed out waiting for asynchronous Angular tasks to finish after 11 seconds」エラーでハマった話
どうも!大阪オフィスの西村祐二です。
AngularにはE2EテストのフレームワークとしてProtractorが同梱されています。
それを使ってテストを書くときにハマったところと、その対応策を紹介していこうと思います。
今回、「Timed out waiting for asynchronous Angular tasks to finish after 11 seconds」というエラーに遭遇したので、その対応策を紹介します。
テストシナリオ
ページのpタグの値を取得してテストするという簡単なものです。
テストの目的はルーティングとして、「/」にアクセスすると、未ログインの場合はログインコンポーネントのログインページが表示されることをテストしたかったという意図があります。
環境
Angular CLI: 6.0.8 Node: 8.11.3 OS: darwin x64 Angular: 6.0.9
テストファイル
テスト対象のページ
ただ、pタグが記載されているだけです。「/」にアクセスするとこのコンポーネントが呼ばれるようにルーティングしています。
<p>test</p>
E2Eテストのディレクトリ構成
e2e ├── protractor.conf.js ├── src │ └── login │ ├── login.e2e-spec.ts │ └── login.po.ts └── tsconfig.e2e.json
login.po.ts
ページオブジェクトを取得する処理を記載しています。
ここでは「/」のときのページを取得するメソッドと、pタグのテキストを返すメソッドを定義しています。
import { browser, element, by } from 'protractor'; export class LoginPage { navigateTo() { return browser.get('/'); } getPageTitleText() { return element(by.css('p')).getText(); } }
login.e2e-spec.ts
ページオブジェクトから取得した値が正しいかどうかのテストを記載しています。
pタグの値が「test」となっていれば、OKというテストです。
import { LoginPage } from './login.po'; describe('toppage', () => { let page: LoginPage; beforeEach(() => { page = new LoginPage(); }); it('p_tag value test', () => { page.navigateTo(); expect(page.getPageTitleText()).toEqual('test'); }); });
Protractorを使ってテスト
下記コマンドで、E2Eテストを実行してみましょう。
$ ng e2e
エラー内容
下記のようなエラーとなりました。タイムアウトしているということで、テストのタイミングをルーティングするまでに待つ処理を挟んでみたりしましたが、どれも違いました。
************************************************** * Failures * ************************************************** 1) top page test - Failed: Timed out waiting for asynchronous Angular tasks to finish after 11 seconds. This may be because the current page is not an Angular application. Please see the FAQfor more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular While waiting for element with locator - Locator: By(css selector, p) Executed 1 of 1 spec (1 FAILED) in 13 secs. [17:25:16] I/launcher - 0 instance(s) of WebDriver still running [17:25:16] I/launcher - chrome #01 failed 1 test(s) [17:25:16] I/launcher - overall: 1 failed spec(s) [17:25:16] E/launcher - Process exited with error code 1 An unexpected error occured: undefined
対処法
エラーの原因として、Angularの$http
と$timeout
を待ってくれるwaitForAngularEnabledがデフォルトでTrueとなっていることが原因でした。
これをFalse
にしてやります。
そうすることでエラーが解消します。
import { browser, element, by } from 'protractor'; export class LoginPage { navigateTo() { browser.waitForAngularEnabled(false); return browser.get('/'); } getPageTitleText() { return element(by.css('p')).getText(); } }
再度、テストしてみます。
$ ng e2e
下記のようなログが出力されました。うまくいきましたね。
[17:36:29] I/update - chromedriver: chromedriver_2.40 up to date (node:99068) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. [17:36:30] I/launcher - Running 1 instances of WebDriver [17:36:30] I/direct - Using ChromeDriver directly... Jasmine started toppage ✓ p_tag value test Executed 1 of 1 spec SUCCESS in 1 sec. [17:36:33] I/launcher - 0 instance(s) of WebDriver still running [17:36:33] I/launcher - chrome #01 passed
本当にテストできているか確認するために、login.e2e-spec.ts
のtoEqual
を「testt
」に変えて再度テストしてみます。
************************************************** * Failures * ************************************************** 1) toppage p_tag value test - Expected 'test' to equal 'testt'. Executed 1 of 1 spec (1 FAILED) in 2 secs. [17:38:33] I/launcher - 0 instance(s) of WebDriver still running [17:38:33] I/launcher - chrome #01 failed 1 test(s) [17:38:33] I/launcher - overall: 1 failed spec(s) [17:38:33] E/launcher - Process exited with error code 1 An unexpected error occured: undefined
想定どおりにテストが失敗していることがわかりますね。
グローバルに設定を反映させる
余談ですが、protractor.conf.js
に設定を記載することでテストファイル全体にbrowser.waitForAngularEnabled(false);
を設定することもできます。
// Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts const { SpecReporter } = require('jasmine-spec-reporter'); exports.config = { allScriptsTimeout: 11000, specs: [ './src/**/*.e2e-spec.ts' ], capabilities: { 'browserName': 'chrome' }, directConnect: true, baseUrl: 'http://localhost:4200/', framework: 'jasmine', jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000, print: function() {} }, onPrepare() { require('ts-node').register({ project: require('path').join(__dirname, './tsconfig.e2e.json') }); browser.waitForAngularEnabled(false); jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); } };
さいごに
いかがだったでしょうか。
ProtractorでE2Eテストを書くときに遭遇した、「Timed out waiting for asynchronous Angular tasks to finish after 11 seconds」というエラーの対処法を紹介しました。
どんどんテストを書いてノウハウを共有していきましょう。
誰かの参考になれば幸いです。