Upgrade to Pro — share decks privately, control downloads, hide ads and more …

テストを自動化するのをやめ、自動テストを作ろう

 テストを自動化するのをやめ、自動テストを作ろう

July Tech Festa 2020 TrackB https://jtf2020.peatix.com/

tsuemura

July 25, 2020
Tweet

More Decks by tsuemura

Other Decks in Technology

Transcript

  1. テストを⾃動化するのをやめ、
    ⾃動テストを作ろう
    Takuya Suemura @ Autify, Inc.

    View Slide

  2. 末村 拓也 (すえむら たくや)
    Twitter: @tsueeemura
    Autify テスト⾃動化スペシャリスト
    開発者 兼 サポート 兼 エバンジェリスト
    現場猫 → 底辺PHPer → QAエンジニア → 現職
    CodeceptJS コントリビュータ
    SoftwareDesign誌 6〜8⽉号『はじめよう,⾼速
    E2Eテスト』

    View Slide

  3. Autifyについて
    WebアプリのE2Eテスト⾃動化の
    ためのツール
    AIによるシナリオの⾃動修復
    (セルフヒーリング)
    リアルデバイス & Dockerコンテ
    ナでの実⾏に対応
    コーディング不要で
    誰でもすぐ使える
    https://autify.com

    View Slide

  4. 今⽇のテーマ

    View Slide

  5. テスト⾃動化

    View Slide

  6. テスト⾃動化をやめて、
    ⾃動テストを作ろう

    View Slide

  7. テスト⾃動化 ≠ ⾃動テスト

    View Slide

  8. テスト⾃動化の成果物 ≠ ⾃動テスト

    View Slide

  9. ⼿動テストを素朴に⾃動化しても、
    ⾃動テストにはならない

    View Slide

  10. 今⽇話すこと
    なぜテスト⾃動化は失敗しやすいのか
    ⼿動テストと、その⾃動化、そして⾃動テストはどう違うのか
    ⾃動テストとはどうあるべきか
    ⼿動テストの⾃動化に価値はないのか
    とくに断りがない限りはE2Eテストについての⾔及です
    (E2Eテスト: システム全てを統合した状態で主にUIからやるテスト)

    View Slide

  11. なぜテスト⾃動化は
    失敗しやすいのか

    View Slide

  12. 本題に⼊る前にコンテキストの説明
    E2Eテストとは
    テスト⾃動化とは

    View Slide

  13. E2Eテストとは
    ビルド済みのアプリケーションに対して
    Webブラウザやモバイル端末から
    主にGUIを通してテストを実⾏すること
    システムテストと呼ばれたりもする
    QA(品質管理)とかテスターとかが⼿動でポチポチやることが多い
    ⼿動のものを「⼿動テスト」、⾃動のものを「E2Eテスト」と呼んだりする⼈
    もいるが、今回は実⾏⼿段を問わず全てE2Eテストと呼称する

    View Slide

  14. よくある開発の流れ
    ローカルで開発
    プルリクエストを出す
    メインブランチにマージ
    ステージングサーバにデプロイ
    E2Eテスト
    問題がなければ本番にリリース

    View Slide

  15. テスト⾃動化とは
    主に⼿動で⾏ってきたE2Eテストを⾃動化すること
    Selenium, Puppeteer, Cypress, TestCafe, Appiumなどを使う
    主に省⼒化や⾼頻度化が⽬的
    副次的に実⾏者によるバラツキの削減などもある
    テスト⼿順は⼿動テストのものを流⽤する
    開発の流れそのものは変えない

    View Slide

  16. Checking vs Exploring

    View Slide

  17. Checking vs Exploring

    View Slide

  18. テスト⾃動化が失敗する(機能しなくなる)よくあるパターン
    ⼿動で頑張ってたテストを⾃動化してみたはいいが……︖
    突然動かなくなる (メンテナンスコストが⾼い)
    アプリケーションは動いてるがテストは落ちる
    不安定で成功したり失敗したりする
    思ったより効果が出ない (費⽤対効果が⼩さい)
    テストしてないところでばかりバグが出る
    早期発⾒に繋がらない

    View Slide

  19. ⼿動テストを⾃動化するとたくさんの観点が失われる
    # ログインページ
    ## ログインできる
    1. URL /login にアクセスする
    2. ユーザー名に takuya と⼊⼒する
    3. パスワードに insecure と⼊⼒する
    4. ログインボタン をクリックする
    5. ホーム画⾯ が表⽰されることを確認

    View Slide

  20. describe('ログインページ', () => {
    it('ログインできる', () => {
    browser.get('/login') // URL /login にアクセスする
    $('#username').setValue('takuya') // ユーザー名に takuya と⼊⼒する
    $('#password').setValue('insecure') // パスワードに insecure と⼊⼒する
    $('a.btn.btn-primary').click() // ログインボタン をクリックする
    assert.equal(browser.url, '/home') // ホーム画⾯が表⽰されることを確認
    })
    })
    ロケータ(要素探索のキー)がセマンティックじゃなくなった
    ユーザー名を⼊れるフィールドっぽいやつ → #username
    ログインボタンっぽいやつ → a.btn.btn-primary
    アサーション(検証)が弱くなった
    ホーム画⾯っぽいページ → /home というURLである

    View Slide

  21. assert.ok(
    $('a[href="https://yahoo.co.jp"]')
    .isExisting()
    )
    CSSが読み込まれてないけど
    Aタグが存在するからヨシ︕

    View Slide

  22. なぜ⾃動化したテストだけが「腐る」のか︖
    実はユニットテストでも同じことは起きている
    違いは開発サイクル
    ユニットテストは「開発の中で」実⾏・修正される
    ⾃動化したテストは「開発が終わってから」実⾏・修正される
    もともと⼿動テストがそういう流れでやってたことの名残
    リリース直前にテストが壊れているのが分かった場合、壊れたままリリースする
    ことがある
    結果、メンテナンスが後回しになってしまう
    これが「腐る」の正体
    実⾏頻度が⾼く、開発中も実⾏されるようになると、テストは腐りにくくなる

    View Slide

  23. 単純に頻度を⾼めればいいのか︖
    頻度を⾼める(例えば1回/⽇→10回/⽇)にしても問題は解決しない
    回数ではなく実⾏環境の幅を増やさないといけない
    例えば、もともとステージングだけで実⾏していたなら、それを開発環境や
    CI環境でも実⾏できるようにする
    ⼿動テストを単純に⾃動化しても、 前提条件 や 事前準備 は⾃動化されない
    特定の環境に依存したテストケースになってしまう
    環境や特定のテストデータに依存している限り、開発サイクルに寄せることはで
    きない
    依存している前提条件をクリアにし、どの環境でも実⾏できるテストにする

    View Slide

  24. (まとめ)テスト⾃動化が失敗してしまう理由
    開発サイクルの中でテストが実⾏・メンテナンスされていない
    テストコードのアップデートが遅れ、製品に問題はないのに「E2Eテストだけ
    失敗する」になりがち
    実⾏タイミングが遅く、バグの早期発⾒に繋がらない
    観点が不明瞭なままテストコードに落とし込んでしまう
    「ホーム画⾯が表⽰されることを確認」→「URLが /home であることを確
    認」のような不正確な翻訳が⽣まれる
    ⼈間がテストする場合にくらべ発⾒が少なくなってしまう

    View Slide

  25. テスト⾃動化と
    ⾃動テストの
    違いとは︖

    View Slide

  26. ⾃動テストの⼀般的なイメージ
    コードで書かれる
    xUnitとかRSpecとか
    TDD・リファクタリング
    安全な開発のためにやるもの
    (なんとなく)QAとかテスターがやるやつとはちょっと違う

    View Slide

  27. ⾃動テストと型検査、Linter
    ⾃動テスト: アプリケーションが期待した動きをしないとリリースできない
    型検査: 型に不整合があるとビルドが通らない
    Linter: 不適切な書き⽅をすると警告が出る
    それぞれの対応する領域に対して強制⼒を持つ

    View Slide

  28. アプリケーションと⾃動テストの関係
    どちらもプロダクトの⼀部
    どちらも仕様を具現化したもの
    アプリケーションはそれ単体では意味をなさない
    誰かに使われてはじめて価値を⽣み出す
    アプリケーションは振る舞いを具現化したもの
    ⾃動テストは使い⽅を具現化したもの
    ⾃動テストはアプリケーションを束縛する
    アプリケーションの特定の挙動に依存することでその挙動を束縛する
    互いにコードとして書かれ、実⾏可能な形で記述されていることで強制⼒を
    発揮する

    View Slide

  29. ⾃動テストとは
    プロダクトの⼀部であり、同時に開発される
    開発サイクルの中で実装される
    (テストフェーズの⾃動化ではない)
    アプリケーションの挙動に強く依存し、
    アプリケーションをより強固にする
    静的解析などと同様に頻繁に実⾏され、
    仕様からの逸脱を常に防ぐ

    View Slide

  30. 素朴なテスト⾃動化は部分的な変化のみをもたらす
    - ⼿動テスト テスト⾃動化 ⾃動テスト
    開発サイクル 開発とは別 開発とは別 開発と同時
    頻度 少 少 多
    実⾏⼿順 あいまい・暗黙的 厳密・具体的 厳密・具体的
    検証⽅法 発⾒的 保証的 保証的
    太字は⾃動化によって変わってしまうもの
    ⾚字は⾃動化しても残り続けるもの

    View Slide

  31. おれたちが本当に
    欲しかったものは︖

    View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. テスト⾃動化の動機
    ⼈間からの脱却
    単純作業からの解放
    リソース不⾜の解決
    属⼈化防⽌
    検証作業のバラツキを減らす
    ⾼速化・⾼頻度化
    リリーススピードの向上
    いつでもテスト
    リファクタリング
    上司のご意向

    View Slide

  38. (再掲)⼿動テストとテスト⾃動化、そして⾃動テストの違い
    - ⼿動テスト テスト⾃動化 ⾃動テスト
    開発サイクル 開発とは別 開発とは別 開発と同時
    頻度 少 少 多
    実⾏⼿順 あいまい・暗黙的 厳密・具体的 厳密・具体的
    検証⽅法 発⾒的 保証的 保証的
    太字は⾃動化によって変わってしまうもの
    ⾚字は⾃動化しても残り続けるもの

    View Slide

  39. なぜテスト⾃動化では
    ⾼速・⾼頻度が
    実現されないのか

    View Slide

  40. ⾼頻度化に向けて(1) シナリオの最適化
    ⼿動テスト向けに最適化された状態
    あるテストで作られたデータを別のテストで再利⽤している
    「新規作成」のシナリオで作ったデータを「更新」で再利⽤
    特定の環境にしか存在しないテスト⽤データを使っている

    View Slide

  41. ⾼頻度化に向けて(1) シナリオの最適化
    ⾃動テスト向けに最適化する
    ⽬的︓CIでの実⾏や並列実⾏との相性を良くする
    常に新しいデータを作成する
    GUIではなくAPIやコマンドで作成する
    実⾏が他のテストに影響しないようにする
    例えば、テストデータの作成時にランダムな(重複しない)⽂字列を使う
    環境依存の箇所を排除する
    環境変数を使う

    View Slide

  42. ⼿動テスト最適化
    機能1
    機能2
    機能3
    ログイン
    機能1
    ログイン
    機能2
    ログイン
    機能3
    機能1の
    データ作成
    機能1, 2の
    データ作成
    ログイン
    ログアウト
    ログイン
    ログアウト
    ⾃動テスト最適化
    テスト⽤の
    ユーザー作成
    事前準備
    実⾏
    事後処理
    機能1の
    データ作成
    テストデータの
    削除

    View Slide

  43. ⾃動テストらしいテスト⾃動化
    開発中も含めさまざまな環境でテストされている
    ⾼頻度(理想はコミットorプッシュごと)に実⾏され不具合を防ぐ
    安定性が⾼い
    他のテストシナリオからの影響を受けない
    何度も、同時に実⾏されても問題ない(冪等性がある)
    テストシナリオが短く保たれている
    テスト観点以外の操作はAPIやコマンド(サーバサイドスクリプト)で⾏う

    View Slide

  44. HAPPY END! (?)

    View Slide

  45. ⾼頻度は実現できたが、⼈間からは脱却できたか︖
    ⼈間からの脱却 ← こっちがまだ
    単純作業からの解放
    リソース不⾜の解決
    属⼈化防⽌
    検証作業のバラツキを減らす
    ⾼速化・⾼頻度化
    リリーススピードの向上
    いつでもテスト
    リファクタリング
    上司のご意向

    View Slide

  46. 参考: テスト⾃動化の8原則
    1. ⼿動テストはなくならない
    2. ⼿動でおこなって効果のないテストを⾃動化しても無駄である
    3. ⾃動テストは書いたことしかテストしない
    4. テスト⾃動化の効⽤はコスト削減だけではない
    5. ⾃動テストシステムの開発は継続的におこなうものである
    6. ⾃動化検討はプロジェクト初期から
    7. ⾃動テストで新種のバグが⾒つかることは稀である
    8. テスト結果分析という新たなタスクが⽣まれる
    https://sites.google.com/site/testautomationresearch/test_automation_principle

    View Slide

  47. 参考: テスト⾃動化の8原則
    3. ⾃動テストは書いたことしかテストしない
    ⼈間による⼿動テストは、テストケースの記述に対して驚くほど広範な要素を暗
    黙的にテストしている。これに対し、操作、合否判定を厳密に記述する必要があ
    る⾃動テストにおいては、おのずと視野は「記述された様に」限定される。ユー
    ザ名とパスワードを⼊⼒してログインする、といったテストが⾃動化されていた
    として、その⾃動テストは仮にログイン画⾯に表⽰されているロゴが競合他社の
    ものであったとしても、それに気づくことはない。
    (太字は発表者によるもの)
    https://sites.google.com/site/testautomationresearch/test_automation_principle

    View Slide

  48. アサーション地獄もまた「素朴な⾃動化」の⼀つ

    View Slide

  49. 再掲
    assert.ok(
    $('a[href="https://yahoo.co.jp"]')
    .isExisting()
    )
    CSSが読み込まれてないけど
    Aタグが存在するからヨシ︕

    View Slide

  50. 参考: テスト⾃動化の8原則
    7. ⾃動テストで新種のバグが⾒つかることは稀である
    運⽤に乗った⾃動テストは基本的に「枯れた」テストケースを対象とするため、
    ほとんどの種類のバグはテストケースを枯らす過程、あるいは⾃動テストを実装
    する過程で既に⼈間によって発⾒されているはずである。 多くの運⽤に乗った⾃
    動テストの意義は「⼀度動いたはずの機能がうっかり壊れる」ことを最速で発⾒
    することにある。 ただし、⼿順が同じでデータの種類が膨⼤なテストを⾃動化す
    る場合、ファジング、テストパターンを有機的に⽣成できるAPIレイヤのテスト、
    ブラウザやRDBなどのバージョンアップの影響を受けていないことを確認するテ
    ストなど、いくつかの例外もある。
    (太字は発表者によるもの)

    View Slide

  51. (再掲)テスト⾃動化が失敗するよくあるパターン
    ⼿動で頑張ってたテストを⾃動化してみたはいいが……︖
    突然動かなくなる (メンテナンスコストが⾼い)
    アプリケーションは動いてるがテストは落ちる
    不安定で成功したり失敗したりする
    思ったより効果が出ない (費⽤対効果が⼩さい)
    テストしてないところでばかりバグが出る
    早期発⾒に繋がらない

    View Slide

  52. 開発サイクル寄りのかっちりしたテストとは
    別のアプローチが必要

    View Slide

  53. ふんわり

    View Slide

  54. 「ふんわり ≒ ⼿動テストよりの」⾃動テスト
    - ⼿動(ふんわり)テスト テスト⾃動化 ⾃動(かっちり)テスト
    開発サイクル 開発とは別 開発とは別 開発と同時
    頻度 少 少 多
    実⾏⼿順 あいまい・暗黙的 厳密・具体的 厳密・具体的
    検証⽅法 発⾒的 保証的 保証的

    View Slide

  55. 「ふんわり」が必要な理由
    「かっちり」では⾒落としてしまうものがある
    環境依存のデータに依存するものを検知できない
    例)⼤量の関連データを持ったユーザーのみ正常に動作しない
    アサーションを書いてないものを検知できない
    明らかにおかしいけど⼿順書に書かれてないからヨシ︕
    特にレイアウト崩れとかは弱い
    全部 getComputedStyle でやっちゃう︖

    View Slide

  56. 「ふんわり」が必要な理由
    「かっちり」はそもそもE2Eらしくない
    かっちりしたテストで検証するのはクリーンで焦点を絞ったテスト
    E2Eはそもそもダーティでリアルな状況下でのテストが⽬的のはず
    ステージングや本番にしかないデータ
    ブラウザやデバイスなどの実⾏環境
    リアルな環境で「正しそうに」動くことを確認するものが欲しい

    View Slide

  57. 「ふんわり ≒ ⼿動テストより」
    の⾃動テストは実現可能か︖

    View Slide

  58. ふんわりしたロケータ
    かっちりテストとは異なり、開発サイクルの中でメンテされるとは限らないので
    ふんわり≒宣⾔的なロケーティングが必要
    // これはよくない
    $('#username').click()
    // これは次善の策
    $('[data-test=username]').click()
    // こう書けると良さそう
    $('ユーザー名').click()

    View Slide

  59. ふんわりしたロケータ(1) セマンティックロケータ
    ⽂⾔や構造による「意味のある」ロケータ
    #username ではなく ユーザー名 のように表⽰されている⽂⾔で指定
    例えばinputならラベルやプレースホルダを使う
    xxという⽂⾔を持つモーダルの中のyyというボタン のようなUI構造で指定
    // CodeceptJSでは⽂⾔や構造による指定をサポートしている
    I.click('ユーザー名')
    // 「本当に送信しますか︖」という⽂⾔のあるモーダルの中から
    within(locate('.modal'.withText('送信先は間違いありませんか︖'), () => {
    // 「はい」と「送信」をクリック
    I.click('はい')
    I.click('送信')
    })

    View Slide

  60. ID: not matched
    class: matched
    alter text: matched
    coodinate: not matched
    image source: matched
    .... Confidence: 80%
    ふんわりしたロケータ(2)
    AIによる要素探索
    (マルチロケータ、
    セルフヒーリング)
    複数のロケータで複合的に探索
    ⾒つかった要素の特徴でシナリ
    オをアップデート
    開発サイクルとテストのサ
    イクルのズレを吸収

    View Slide

  61. ふんわりした検証
    アサーション地獄を回避したい
    全ての検証項⽬を地道に定義するのはメンテナンス地獄にも繋がる
    ⼈間がパッと⾒て分かるレベルのエラーを(定義せずに)回避したい
    表⽰されるべきものが表⽰されていない
    レイアウトが崩れている

    View Slide

  62. ふんわりした検証
    画像⽐較(ビジュアルリグレッション)
    テスト実⾏ごとのスクリーンショットを⽐較する
    スタイル崩れなどの検出に有効
    ⽐較から除外する箇所の定義が別途必要
    広告
    検索結果
    撮影時の座標がズレると全てが終わる
    位置ずれ補正
    Awesome Visual Regression Testing: 画像⽐較テストツールのリンク集
    https://github.com/mojoaxel/awesome-regression-testing_

    View Slide

  63. ふんわりした検証
    その他考えうる施策
    ページパフォーマンス、エラー監視
    デッドリンク検知
    ⾃然⾔語解析
    テキストの意味が⼤幅に変わっていないか
    ⽂法の誤り
    etc...

    View Slide

  64. かっちりとふんわり
    どっちがいいの︖

    View Slide

  65. テストを「網のように」考える
    バグはなるべく上層でキャッチするようにしつつ、下にも網を広げる
    ユニットテスト
    統合テスト
    APIテスト
    UIコンポーネントテスト
    かっちりしたE2Eテスト
    ふんわりしたE2Eテスト
    ⼿動での探索的テスト

    View Slide

  66. テストタイプによる使い分け例
    かっちりテスト向け
    機能テスト
    回帰テスト
    ふんわりテスト向け
    互換性(クロスブラウザ・マルチデバイス)テスト
    ユースケーステスト
    スモークテスト

    View Slide

  67. 今⽇伝えたかったこと
    ⼿動テストを素朴に⾃動化しても、⾃動テストにはならない
    素朴なテスト⾃動化はどっちつかずのものになってしまう
    新規バグは⾒つからず、そのくせメンテ⼯数はガッツリ持っていく
    ⾃動テストらしい具体性をもったかっちりした⾃動テストと、⼿動テストのよう
    にファジーなふんわりした⾃動テストというアプローチがある
    テスト⾃動化をゴールにするのではなく、エントリーポイントとして使い、さら
    に発展させてほしい

    View Slide

  68. Enjoy Testing!
    spatial.chatの H1 で僕と握⼿︕

    View Slide