LoginSignup
6
1

More than 5 years have passed since last update.

Protractorで爆速sendKeys

Last updated at Posted at 2017-12-21

こんにちは。Qiita見る歴3年くらいの @mumum です。
記事を書くのは初めてなので、なまあたたかく見てみてください。

はじめに

これはなに?

ここを見てくださっているかたは多分ご存じSeleniumのAngular(JS)向けフレームワークProtractorを使ったe2eUI自動テストに関する、コストパフォーマンス改善の記録をコードを交えて説明させていただきます。
最後まで読むと文字入力部分のテスト時間の短縮方法がわかります。

前提

テスト対象

AngularJSで書かれたソフトウェアのUI

テストツール・環境

Windowsで、Protractor上で書いたテストケースをchromedriverで実行しています。

テストフロー

テスト対象のUIにinput要素が10000個あるのでそれぞれに、1000キャラクタの文字列を入力していきます。

sendKeys遅い問題

実際に上記条件でテストを走らせると、各input要素への文字入力のところが異常に(手入力よりも)遅いことが確認できました。
文字入力の部分は、Protractorのフレームワークに沿って以下のように書いていました。

$("input要素セレクタ").sendKeys("1000キャラクタの文字列");

sendKeysの処理が遅いとあたりをつけ、何か回避策はないかと調べてみると、Stackoverflowに似たような問題に関する質問が出ていました。
そこでは、解決方法として、AngularJSをHackする方法を採用していましたが、そのほかの解決案としてクリップボードを活用してコピペする案も書かれていました。
ただ、コピペをするのはThis may require doing a bunch of fancy footwork, like using Flashということでリスク高いので採用はしないと書かれていました。

コピペで回避

しかしテストコードがテスト対象に強く依存するのは個人的に避けたかったので、今回は上でいうところのそのほかの解決案を採用することにしました。
幸い現在はブラウザネイティブでクリップボードにアクセス出来るAPIがあるので、それを使えば大丈夫ということで、コピペで回避することにしました。

実装

APIの仕様策定した人のブログによると、このAPI(document.execCommand())はユーザーによってトリガーされたイベントから呼ばれないといけないみたいなので、以下のフローでコード実装することにしました。

フロー

  1. 画面上に入力テキストを持たせるDOM($(#placeholder))作る
  2. $(#placeholder)にクリックイベント登録する
    1. $("#placeholder")のテキスト全選択
    2. document.execCommand("copy")
  3. $(#placeholder)に入力テキスト入れる
  4. $(#placeholder)をクリックさせてコピーとる
  5. $("input要素セレクタ")にフォーカス移して、ctrl+Vする

※直接DOMを弄るのはProtractorではできないので、browser.executeScript()を使いました。。

コード

async () => {
  await browser.executeScript(createDom);
  await browser.executeScript(pasteText, "1000キャラクタの入力テキスト");
  await $("placeholder").click();
  await $("input要素セレクタ").click();
  await browser.driver.actions.keyDown(Key.CONTROL).sendKeys("v").keyUp(Key.CONTROL).perform();
  await browser.executeScript(deleteDom);
}


function createDom() {
  const dom = document.createElement();
  dom.id = "placeholder";
  document.body.appendChild(dom);
  dom.addEventListener("click", clickEvent);
}
function clickEvent() {
  const dom = document.getElementById("placeholder");
  document.getSelection().selectAllChildren(dom);
  document.execCommand("copy");
}
function pasteText(pasteStr) {
  const dom = document.getElementById("placeholder");
  dom.textContent = pasteStr;
}
function deleteDom() {
  const dom = document.getElementById("placeholder");
  document.body.removeChild(dom);
}

結果

10000個のうち最初の100個のinput要素に対して、それぞれ1000キャラクタの文字列を入力していく処理に対してとった結果:

コピペ前 コピペ後
1.5時間 3分

98%の時間短縮になりました😎

おわりに

途中からほぼProtractorじゃ無くなっているじゃん。。とっても早くなりました。
コピーコマンドはユーザーがトリガーするイベントで実行される必要があるみたいですが、$.click()でいけました!>Protractorはユーザーでした。

それでは最後になりましたが、この記事が皆様のソフトウェアテスト時間短縮に役立ち、少しでも楽しくテストできるようになれば幸いです。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1