開発部の栗田です。End-to-Endテストの効率化をテーマにプレゼンを行いましたので概要を紹介させて頂きます。
繰り返しのテストを自動化してくれるSelenium WebDriver。(以下WebDriverと呼びます)
過去長い時間マニュアルテストをしていた私には、夢の様なツールで大好きです。
スモークテストを自動化して、随分助けて頂きました。
しかし確認作業を全部自動化出来るかというと、実はそうでは無いようです。値の検証は得意で動作テストは概ね自動化できそうですが、「見た目の不具合(レイアウトバグ)」を見つけるのは苦手だと思います。
レイアウト確認をマニュアルで行おうとすると、確認に至るまでの操作もマニュアルで行う事になります。そうなると、動作確認を自動化するするメリットが減ってしまいそうです。
そんな苦手分野を克服する方法の紹介です。
<目的は時間の削減、自動化は方法、半自動でも時間を削減できる>
自動化を始めた頃、私は自動化が目的になっていた時期がありました。完全な自動化が難しいと理解した頃、目的が叶えられないと錯覚した事もありました。でも重要なのは時間の節約ですね。
自動テストの目的は時間の節約です。
こんな振り返りをするのは今回紹介する、今回ご紹介する方法が、全自動ではなく半自動を目指したものだからです。
全自動は夢としてとっておいて、まずは半自動でテスト時間を短縮したいと思います。
<概要>
WEBエレメント単位で画像抽出、それをドット単位で比較して、見た目の変化を見つける方法です。
WebDriverはスクリーンキャプチャ*を撮影する事、エレメントの座標とサイズを得る事ができますが、これらを使いつつ実現します。
*厳密には IEDriver と FirefoxDriver はdocument 全体の画像キャプチャを返しますが、ChromeDriver はスクリーン範囲のみのキャプチャを返します。document 全体に統一してほしいところです。
<全画面スクリーンショットの撮影 + 画像の自動比較 + 目視確認>
まずは、部分画像ではなく「全画面(ドキュメント)画像比較」をした場合の確認です。
良いところ:
- 動作テストに、全画面スクリーンショット撮影の処理を加えておけば、レイアウト確認は画像を見るだけでテストを完結出来ます。これだけでも、レイアウト確認に必要だった操作手順を省略する事ができます。
- また、画像一致の確認を自動的に行う事で、目視確認するものは変化のあった画像だけに絞る事が出来ます。
悪いところ:
- 画像に少しの変更があるだけで目視確認が必要になりますが、例えば共通UIのフッターの文言が変更されるだけで、全部の画像確認が必要になってしまいます。
- 大きなストレージが必要になります。確認の度に全画面の画像を保存するのは、いかにも無駄が多そうです。プロジェクトによっては現実的な容量を超えるかも知れません。
- 全画面を比較対象とすると、自動であっても多少は時間が掛かります。
使用するメソッドなど:
- 画像の撮影は、WebDriverのget_screenshot_as_fileメソッドなどで可能です。
# python code
driver.get_screenshot_as_file(‘tmp_full.png’)
- 画像の比較は、ドットデータを配列変換する任意の画像ライブラリで実現可能です。(私はPython の scipy.misc.imread を使用しています)
# python code
from scipy.misc import imread
test_img = imread(“/validation/0001.png”,1) # rgb を格納した配列を得られる
latest_img = imread(“/latest/0001.png”,1)
bools = test_img == latest_img
bools.all()
その他:
- 画像の確認と更新は、それ用にWEBページなどを用意しておくと効率的です。差異のある部分を強調表示するViewを用意すれば、ヒューマンエラーを軽減できると思います。
<エレメント単位のスクリーンショットを撮影 + 画像の自動比較 + 目視確認>
本題の「WEBエレメント単位で画像比較」したらどうなるかの考察です。
全画面撮影ではノイズが多い事、データ量が多い事が問題でした。これらを回避しています。
良いところ(前項に加えて):
- 比較する画像範囲を絞った事で、ノイズとなるケースが大幅に削減されます。
- 必要なストレージ容量が大幅に削減されます。下記は仮の数値ですが現実的な容量に収まりそうです。
A) 確認項目数 = 10000
B) 環境数 = 6
C) 1画像の平均容量 = 200KB
D) 不一致となる場合の画像数の割合 (仮に5%) = 500
(A + D) * B * C = 必要な容量
(10000+500) * 6 * 200KB = 約 12 GB
※数値は仮のものです。
使用するメソッドなど(前項に加えて):
- エレメントの位置とサイズの情報は、WebElement の location と size で取得可能です。
- javascriptのgetBoundingClientRect メソッドでも、取得可能です。リクエストの往復回数を減らせるので、お勧めです。driver.execute_script メソッドで js を実行して確認できます。(確認環境 IE10, Chrome 28, Firefox 22.0 on windows7)
/* javascript code */
var e = document.querySelector(css_string);
var bc_rect = e.getBoundingClientRect();
bc_rect.left; // left座標を取得できます。ほか座標も同様に取得できます。
- エレメント画像の切り抜きは、一般的な画像ライブラリで出来ると思います。(私はPython の PIL を使っています)
# python code
from PIL import Image
img = Image.open(‘/tmp/0001.png’)
rect_info = [left, top, right, bottom] # 各座標を格納した配列
cropped_img = img.crop(rect_info)
cropped_img.save(“/latest/0001.png”, “PNG”)
部分画像としたことで、目視確認数、データ量の問題を大解決しています。
後記の「確認されている事象」で、ノイズとなるケースを紹介しています。プロジェクトによってはノイズ量が多くなるかも知れません。御参考まで御覧頂ければと思います。
<その他のメリット>
画像比較をベースとした自動化を行うと、次のようなメリットも期待できます。
- 不具合があった場合、取得済みの画像を添付すれば、バグレポートの文章量を削減できる。
- 複雑な確認内容を画像比較とすれば、テストスクリプトをシンプルに出来そう。
<確認されている事象>
次のケースではWEBエレメントのStyleに変化が無い場合でも、画像が微妙に変化する事が確認されています。
確認対象 : IE10, Chrome 28, Firefox 22.0 on windows7
エレメントの位置とサイズ情報の取得方法 : WebElement の location と size
発生状況 : 確認対象のWEBエレメントのposition (top, left ) に float 単位で変化した場合
事象1:エレメントのposition(top, left)が1ドットずれるケースがある。(確認した3環境で発生)
事象2:エレメント中のブロック要素などが1ドットずれるケースがある。(確認した3環境で発生)
事象3:フォントのアンチエリアスの掛かり方が変化する。(IE10で発生)
事象1と2について
各ドットの確認時に上下左右1ドットのずれを許容する事で回避できました。(IE10については事象3により未確認です)*
*1ドット幅のborderなどは無視されるはずですので、どちらのメリットを取るかは判断が必要です。
事象3について
ClearType フォントと sub-pixel フォントが原因のようです。簡単なテストでは、9割程度が不一致となりました。
(テスト内容:top, left をそれぞれ0.0から0.9まで変更した切り抜き画像(10 * 10 = 100画像)を、それぞれを他99画像と比較)
ClearTypeの設定をオフにしましたが、あまり改善は見られないようです。(9割→8割5分程度)
sub-pixelについては、調べた範囲では解除方法が提供されておらず、別の方法を検討中です。
<まとめ>
今回紹介した部分画像比較の方法は、前述の通りテスト時間の短縮を目的としたものです。
ノイズが多くなる場合も、テストプロセスは自動化できる為、テスト時間の削減が期待できるほか、
「その他のメリット」で紹介した点も合わせると、総合的にテストを効率化できる方法になっていると思います。
自動テストの出来る事は、他にもいろいろ有りそうです。
また、折を見てご紹介したいと思います。
最近のコメント