SlideShare a Scribd company logo
AWSで実現するSeleniumテスト高速術



           Fumiaki Inoue
           Shanon Inc. / QA Manager
           Jenkinsユーザ・カンファレンス2012東京
自己紹介



 井上 史彰
   1981年生まれ 30歳


 仕事
   株式会社 シャノン
   開発エンジニア → 開発マネージャー → QAマネージャー


 開発言語
   Perl
アジェンダ



 製品紹介
   システムの構成
   開発体制
   各種メトリクス


 自動テスト強化での様々な課題
   Jenkins, Selenium, AWS の組み合わせではまった点など


 まとめ




                                       3
4
BtoBマーケティングを支援するWebアプリケーション
2006年3月頃リリース



                       5
導入企業




       http://www.shanon.co.jp/case/




                    6
構成

     構成
      Apache, FastCGI, Postgresql




     言語
      Perl


     機能数
      約400 – 500機能 + API


     関連アプリ数
      内部的には約10個のアプリケーションがAPI連携して動作


                                    7
開発体制



 Scrum
   スプリント期間は1ヶ月
   7人くらいのチームが2つ
   開発 : QA = 2 : 1


 毎月4週目にバージョンアップ
   前月に開発した機能をリリース




                     8
シャノンの自動テストツール



 Selenium
   テストスイート数: 270, テストケース数: 約3500
   FirefoxのIDEで作成/メンテナンス。一部スクリプトも


 独自テストツール
   API, CSV/XLS, HTMLテンプレート変数, メールテンプレート変数


 Jmeter

 AppScan


                                    9
Seleniumのテストスイート数




                    10
全テスト実行時間の合計




              11
自動テストの機能カバー率




               12
自動テストの機能カバー率




               13
バージョンアップ後のデグレードバグ数




                     14
Seleniumテストでの様々な課題




                     15
ゴール?


 機能を追加しつつも不具合を最小限に!!




 POINT
 ・価値を生み出すことに集中
 ・ソフトウェアの規模拡大につれてテスト工数は増加
 ・自動化できるところはしっかり自動化する
 ・品質向上させるためにユーザー感覚でブラウザを操作するSeleniumは効果的



                                    16
Seleniumテスト実行環境



       クライアント側    サーバー側


                          https://aaa.mp.
                          jp



                          https://bbb.mp
                          .jp



                          https://ccc.mp.
                          jp




                                17
Seleniumテスト実行の流れ



 データの初期化(サーバー側)
   関連アプリのデータを初期化
   設定や各種データの登録


 テスト実行(クライアント側)
   ブラウザ起動、画面操作、レポート出力




                        18
課題1

テストの定期実行と結果の見える化




               19
Jenkinsの導入



  いつテストが実行されたか分からない
     テスト実行にはWindowsPCにログインして手動で実行
     誰かが使ってると他の人は使えない → 取り合いに


  テストが成功したか分からない
     テスト結果もPCにログインして結果のレポートを確認する必要があった




 POINT
 ・最新ののソースコードでテストが実行され、早く開発にフィードバックすることが大事!
  Jenkinsを導入したことで、毎日定期的にテストを実行することが可能に



                                         20
課題2

テストの安定化




          21
テストケースの量産




            22
Seleniumはなぜ安定しない?


How to Lose Races and Win at Selenium

Selenium tests often fail because they’re too fast.
Where a user might wait for a page to load
for a few seconds and then click on a link,
Selenium will interact with a page at the speed of code,
before the page is ready.

The way to fix this is to have Selenium repeat its actions
and assertions until they work.
If you don’t, Selenium races your browser.


http://sauceio.com/index.php/2011/04/how-to-lose-races-and-win-at-selenium/




                                                                              23
spin asserts


 def spin_assert(self, msg, assertion):
   for i in xrange(60):
      try:
          self.assertTrue(assertion())
          return
      except Exception, e:
          pass
      sleep(1)
   self.fail(msg)




  POINT
  ・HTMLスイートを直接SeleniumRCサーバー内で実行する方法だと安定しない



                                          24
Exporting the Test for Junit



   テストスイートをチェックアウト
      リポジトリからHTMLスイートをチェックアウト


   Junit形式にエクスポート
      Seleniumにあるエクスポート機能を利用
      Rhinoを使ってJavaのコードから呼び出す
      (今だったらnode.jsでもいいかも)


   Javaテストケースのコンパイル

   テスト実行、レポート出力

                                25
レポートの拡張


   エラー発生時の画面キャプチャ




                Junit Attachments プラグインでもできるみたい


                            26
レポートの拡張


   実行時の変数表示




   レスポンス時間表示
           startCommand("verifyTextNotPresent","NG", "", "n");
           assertFalse(selenium.isTextPresent("NG"));
           endCommand("verifyTextNotPresent", "NG", "", "n");

           startCommand("verifyTextNotPresent","ERROR", "", "n");
           assertFalse(selenium.isTextPresent("ERROR"));
           endCommand("verifyTextNotPresent", "ERROR", "", "n");




                                                27
WebDriver/Selenium2



       private static WebDriver getDriver(String driverName) {
        if (Strings.equals(driverName, "firefox")) {
             return new FirefoxDriver();
        } else if (Strings.equals(driverName, "chrome")) {
             return new ChromeDriver();
        } else if (Strings.equals(driverName, "ie")) {
             return new InternetExplorerDriver();
        } else if (Strings.equals(driverName, "safari")) {
             return new SafariDriver();
        }
       }

       WebDriver driver = getDriver(args[0]);
       driver.get("http://www.google.com");




                                                             28
各種プラットフォーム/ブラウザでのテスト


                         Windows   Linux        Mac

   Internet Explorer 6              -           -
   Internet Explorer 7              -           -
   Internet Explorer 8              -           -
   Internet Explorer 9              -           -
   Firefox 3.x                                  -
   Firefox Latest                   -
   Chrome Latest                    -
   Safari


POINT
・Javascriptなどブラウザに依存することの確認を行うテストケースを実行


                                           29
課題3

テスト実行の長時間化




             30
実行の長時間化




    すべてのテスト1時間くらいで実行したい
     1台で同時に5個のテストケースを、さらに10台にすると可能?


                                      31
テストの並列実行



 単純にクライアント、サーバーの台数を増加
   サーバーは社内には置けなかったからAWSへ
   ある程度短縮できたが、、、




                           32
アンチパターン



  テスト実行ノードを指定
   [実行するノードを制限]でノード名を直接指定
   → 複数台使用しても負荷を分散できない
   → サーバーごとに偏りが出てしまう


  テスト実行開始時間の指定
   [定期的に実行]で開始時間をずらして指定していた
   → 実行がかぶると負荷が高くなり不安定に
   → テスト待ち時間の無駄




                              33
対応方針



  テスト実行ノード
   実行ノードの直指定は止める
   テスト実行時にどこかのノードで実行されるか決める


  全テストジョブを同時刻に実行開始
   実行待ちの時間をなくす
   slaveの[同時ビルド数]で負荷を調整




                              34
変更後の構成イメージ

           クライアント側           サーバー側
            クライア             サーバー
            ントA              A




            クライア             サーバー
            ントB              B




POINT
・すべてのビルドが1つのキューで管理され、順番にどこかのスレーブで実行される
・AWSインスタンスは自動ON/OFF
 ビルドキューに溜まっているビルド数に応じて自動で起動/終了する



                                     35
ラベル

 slaveのラベル設定
      slaveにはラベル(タグ)を複数設定できる
      テストジョブの[実行するノードを制限]でラベル式を設定
      → 指定したラベルのどこかのslaveでテストが実行される

            クライアント側            サーバー側
              クライア              サーバー
              ントA               A




              クライア              サーバー
              ントB               B




サーバー側とクライアント側で負荷のバランスがうまくいかずテストが安定しない。。
 サーバー側とクライアント側を1:1にしないといけない?


                                       36
AWSインスタンス


アプリケーションとクライアントを1インスタンスに
  AWSの1つのインスタンスに
  ・フロントサーバー
  ・アプリケーションサーバー            クライアント&
                           サーバー
  ・データベース               クライアント&サー
                        バーA
  ・SeleniumRC+Firefox


                        クライアント&サー
                        バーB




ちょうどよいAWSのインスタンスタイプがなかった
 CPU, メモリ, コスト。。。


                                     37
AWS側のアプリ, Seleniumクライアントのスケール

           クライアント側          サーバー側
             クライア            サーバー
             ントA             A




             クライア            サーバー
             ントB             B




 POINT
 ・クライアント側とサーバー側が 1 : 1 でうまくスケールするようにしないと、、


                                    38
解決すべき課題



 クライアントのPCをどうするか?
   社内の余ってるPCを使う?
   Saucelab (http://saucelabs.com)
    - Seleniumテストをクラウドで(従量課金)
    - Sauce OnDemand というJenkinsプラグイン
    - 各種ブラウザに対応
    - アプリケーションが社内にあるような場合でも利用できる
    - 動画でのテストレポート


 キューの仕組みをどうするか?
   Pluginで使えそうなものはないか?




                                 39
Clouds

  お名前.com
            メリット                      デメリット

  コストパフォーマンス良い              スケールしない
  (常時稼動させる場合はAWSの1/10ぐらい違   毎回手動でセットアップ
  う)


                            クラスタ構成ができない

                            FWが無いのでiptablesでセキュリティ確保しなけ
                            ればならない


  AWS
            メリット                      デメリット

  APIによるスケーラブルなサーバ管理        常時稼動させるには割高
  (イメージ管理、バックアップ 等)         (リザーブドインスタンスも有るが、インスタン
                            スタイプが固定されてしまう)

  負荷に応じてスケールアップができる         従量課金なので月額利用料の予測が必要
  (機能増につれてメモリも増加するが、
  AWSならボタン一つで対応可能)




                                          40
スペック比較



                          AWS                      お名前.com
                     (ミディアムインスタンス)                (KVM 2GB)

 CPU                2 ECU(2 ECU × 1仮想コア)    3コア


 メモリ                3.75 GB                 2GB

 IO速度               36.5 MB/s               133 MB/s
 (ddコマンドによる簡易測定 )



 Disk容量             8GB~                    200GB~

 月額利用料                            ¥10,775                     ¥1,153




                                                   41
Jenkinsプラグイン




自分のやりたいことが
プラグインとして用意されてなかったら?

- 自社サービスに特有のことを設定可能にしたい
- テスト結果の集計処理をカスタマイズしたい

自分でプラグインを書いてJenkinsを拡張しましょう!




                               付録B プラグインの開発
                                   池田 尚史



                                  42
Jenkins plugin作成


slaveで種別(クライアント側, サーバ側)を設定




テストジョブでも(クライアント側, サーバー側)のどっ
  ちで実行するかを設定



キューに溜まったビルド数に応じてAWSをON/OFF

テスト終了後にAWSの特定インスタンスに復元
                       43
ビルドをキューへ登録



 hudson.model.Queue.QueueDecisionHandler
   ジョブが実行できるかのチェックするときにフック

   - ジョブの設定を確認
   - 実行中または既にキューに入っていないかの確認
   - その他チェック

   → 特に問題なければビルドキューに入れる




                                44
キューの実行可否



 hudson.model.queue.QueueTaskDispatcher
   ノードがタスクを実行できるかをチェックするときにフック

   -   ジョブの設定を確認
   -   ノードの設定を確認
   -   ノードのステータスを確認(online/offline)
   -   各ノードで実行中の本数を確認
   -   上流のジョブ(初期化処理など)がどのノードで実行されたか




                                 45
AWSのON/OFF



  キューの状態を定期的に監視するジョブを作成
    それぞれのノードで
    - 実行できる本数+いくつか以上の待ちがあると準備済みのインスタンス
       を起動
    - ノードが余っていると終了

    AWSのAPIをコールするスクリプトを作成




                              46
アプリケーションの初期化と復元


アプリケーションで使用するすべてのデータを
削除、初期化、ダンプ、復元するスクリプトを作成

 どのテストジョブでどんな処理が必要かをspreadsheetで設定
  - ドメイン名
  - データベース名
  - 初期化時に使用するダンプファイル
  - 実行するテストスイート名




                                     47
Seleniumテストの実行フロー

              Jenkins
                                  1. テスト
                                  ジョブの実
                                  行


      2. 設定情報取得(perl)                 2. 設定情報取得(perl)

      3. テストケースチェックアウト                3. テストケースチェックアウト

      4. セレニウムテストケースの                 4. セレニウムテストケースの
         エクスポート(java)                    エクスポート(java)

      jUnit                           jUnit
                        5. テスト実                     5. テスト実
                        行                           行


                        6. ブラウザ                         6. ブラウザ
                        起動                              起動
                           コマンド                            コマンド
                        実行                              実行




                                                            48
課題4

任意のブランチでのテスト




               49
Parameterized Trigger Plugin



   ビルドのパラメータ化
     テストジョブを[パラメータ付きジョブ]として設定
     パラメータでテスト実行環境を指定できるように


   Trigger parameterized build on other projects
     上流のテストジョブで指定したパラメータ値を
     下流のジョブに渡す



   ビルドの実行



                                      50
複数ブランチでのテスト実行

            Jenkins




  HEAD



 V.2.60.0



 V.2.59.0

                      51
最後に




      52
新しく製品の自動テストを作るとしたら?



 Seleniumテスト
   - IDEかプログラムかは製品/機能によって使い分ける
    ユニットテストとの切り分けも大事
    すべてをSeleniumだけでカバーすることはできない
   - 1機能に対して1テストケースにして15分以内に抑える
   - 最初からパラレル実行できる構成を意識
     テストケース間が依存しないように
     a. パラレルで実行すれば短時間で終了できる
     b. 変更の際にメンテナンスしやすい
     c. テストケースが失敗してもペナルティが少ない




               http://sauceio.com/index.php/2011/02/speed-up-your-selenium-tests/


                                                        53
まとめ



 価値のあるソフトウェアをより早く提供
      自動化された継続的なビルド、テスト、デプロイは非常に重要


 Jenkinsは強力な味方
      まだ使っていない人はさっそく始めましょう




                               54
We're Hiring!

inoue@shanon.co.jp




                     55
プラチナスポンサー




メディアスポンサー



シルバースポンサー

            56
ありがとうございました




              57

More Related Content

Awsで実現するseleniumテスト高速術