Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

開発者による現実的な自動化テスト及びRubyのテストツールについて

社内勉強会で使った資料。開発者自身が行う自動化テストについての考え方と、実際に使っているテストツール(Cucumber, Capybara, PhantomJS等)について解説しました。

前半は開発者自身が書く自動化テストコードについての考え方、後半は具体的なテストコードの例を紹介しました。

前半については、テストの話題で一般的に言われている常識に真っ向から反抗しております。「カバレッジは気にしない」「単体テストより統合テスト優先」「テストファースト無視」など、一般的な常識からすると無茶苦茶なことを言っているようですが、リアルな開発の現場で、テストを有効に行うための現実論を述べています。

また、後半ではRubyを使ったテスト環境としてCucumber+Capybara+Poltergeist+PhantomJSの組み合わせを紹介し、Test::Unit, Rspec, Cucumberで同じテストを行う時のコードの違いや、Cucumber+Capybaraの組み合わせを使う際の柔軟性のあるステップ定義などを述べました。

なお、今回のスライドで使用したデモのソースコードはGitHubにアップしています。ご自由に活用ください。
https://github.com/takaaki-kasai/cucumber-demo/tree/master

  • Login to see the comments

開発者による現実的な自動化テスト及びRubyのテストツールについて

  1. 1. 開発者による現実的な自動化テスト
 及びRubyのテストツールについて Takaaki Kasai 2015.03.12
  2. 2. テストそのものの話
  3. 3. テストを自動化してますか?
  4. 4. なぜテストの自動化が必要なのか • ここでいうテストとは開発者が自ら書くテストコードのこと • リグレッションテストの労力と時間を大幅に削減できる • 以前書いたコードを壊していないことが保証できる
 (少なくともテストコードの仕様上は) • 開発者自身の心の安寧が得られる ← 重要
 (余計なことを考えず今眼の前にあるコードに集中できる) • リファクタリングが躊躇なくできる
 (壊したらどうしよう・・・なんて心配が不要になる)
  5. 5. そもそも「テストコードを書く」文化がない場合は? • 「勝手にやりましょう」 • 人間、目の前で見せられるまで納得しない
 → いきなり「テストを書く時間をとらせてくれ」よりも
   勝手にやってしまって、効果を見せた方が話が早い やっちまえ!
  6. 6. テストを書くのは品質の保証のため? • 開発者自身が品質保証のためにやるのは大変 • あくまで
 「リグレッションテストの手間と時間の削減」
 「開発者の精神的安定と効率と集中力向上」
 「リファクタリングによるコードの洗練」
 のためにやるという考え方 ← 今回の話はこれ • 完全なテストはいらない
 → 過去のコードを壊していないか確認できればいい テストは過去のコードをチェックする センサーみたいなもの
  7. 7. カバレッジ⃝⃝%なんて目指さない • ぶっちゃけ、異常系なしで正常系だけでもいい
 
 そもそも、新しいコードを追加して過去のコードを壊すとき は、正常系が壊れることが多い。異常系の細かい部分が一箇 所だけ壊れることを確認するよりも、正常系だけの確認をし たほうが圧倒的に効率がいい。 • テストを書く目的が品質保証ではなく「開発者自身のため」 であるからこその割り切り
 (テストケースを細かく完璧に書く時間がない・・・・) • ということで、カバレッジは気にしない。
  8. 8. 単体テストより統合テスト • テストを書く目的が過去のコードを壊していないかの確認な ので、統合テストだけでも目的は果たせる • もちろん単体テストはないよりあったほうがいい。書く時間 があれば。 • 時間が足りない時は、とりあえず先に実装を終わらせて後か ら統合テストだけ書く 「時間は作るもの」 なんて言うけど限界ある
  9. 9. TDDじゃないの? • テスト駆動は確かに「理想」
 → だけど、いちいちやってる時間あるか? • 全てをテストファーストにするのはあきらめる
 → 正直、UIまで含めてテストファーストはキツイ
 → そこまで秀才じゃないッス • 「雪だるま式」という考え方もある
 → 雪だるまは、最初に「核」になる部分を
   こねくり回して作って、それから転がして大きくする。
   同じように、最初はテストを書かずに「核」を作って、
   それからテスト駆動のサイクルを回す。
  10. 10. ツールの話
  11. 11. 現在の自動テスト環境 • Cucumber • Capybara • Poltergeist • PhantomJS どういうこと? Poltergeist
  12. 12. Poltergeist Cucumber Capybara PhantomJS 処理の流れ 自然言語 →コード への変換 Webアプリの テスト向けDSL PhantomJS用 ドライバ ヘッドレス ブラウザ
  13. 13. Cucumberって? • テストコード記述ツールの進化
 Test::Unit → RSpec → Cucumber • Test::Unit
 Rubyのソースコードそのもの • RSpec
 ソースコードに自然言語による説明がつけられる • Cucumber
 自然言語によるテスト仕様記述とソースコードを分離
  14. 14. サンプルアプリケーション Hello! ボタンを押すと Hello, World!! と表示するだけ test_rack_app.rb config.ru 実行コマンド $ rackup -o 0.0.0.0
  15. 15. Test::Unit • Rubyのソースコードそのもの • メソッド定義がテストの単位(先頭に test_ をつける) • アサーション用のメソッドが用意されている(assert_*)
  16. 16. Test::Unit(コード例) test_unit.rb
  17. 17. Test::Unit(実行例:成功時)
  18. 18. Test::Unit(実行例:失敗時)
  19. 19. • ソースコードに自然言語による説明がつけられる • ブロックでテストの単位を表す • より柔軟なアサーション: expect(*).to ∼ RSpec
  20. 20. RSpec(コード例) rspec_spec.rb
  21. 21. RSpec(実行例:成功時)
  22. 22. RSpec(実行例:失敗時)
  23. 23. • 自然言語によるテスト仕様記述とソースコードを分離 • featureファイル: テスト仕様記述
 → gherkin(ガーキン)という言語、ほぼ自然言語で書ける • step定義ファイル: ソースコード
 → featureをrubyのコードに翻訳 Cucumber
  24. 24. Cucumber(コード例 1/2) features/hello.feature
  25. 25. Cucumber(コード例 2/2) features/step_definitions/hello_steps.rb features/support/env.rb cucumber.yml
  26. 26. Cucumber(実行例:成功時)
  27. 27. Cucumber(実行例:失敗時)
  28. 28. テストコードをもっと便利に • Webアプリケーションでよく使う動作や確認
 例えば・・・・
 ・フォーム内要素への入力
 ・HTMLの特定のタグ内に文字列があることを確認
 ・ボタンをクリック
 → 楽にテストを記述したい! • そこで、Capybara
 Webアプリのテスト向けDSLが っている
 CSSセレクタやXPathが使える
 HTMLの特定要素の属性やテキストの比較がラクにできる
  29. 29. Capybara+Cucumber(コード例) features/step_definitions/hello_steps.rb features/hello.feature features/support/env.rb
  30. 30. Capybara+Cucumber(実行例: 失敗時) CSSセレクタで比較の範囲を絞ったので、エラーが分かりやすくなった → もちろん、自力でHTMLを解析して比較すれば同様のことは   できるけど、しんどい。Capybaraを使えばラク。
  31. 31. ステップ定義に柔軟性をもたせる step定義ファイル(抜粋) → CSSセレクタをfeatureファイル側に含めると、   stepの汎用性がぐっと高まる featureファイル(抜粋)
  32. 32. 柔軟なステップ定義の例をもう少し step定義ファイル(抜粋) featureファイル(抜粋)
  33. 33. さらにJavascirptもテストしたい • 統合テストであるからには、JSも含んだ動作を検証したい
 → JSのみの単体テストじゃなくて、ページ遷移なども
   含めて自動でテストしたい • Seleniumって選択肢もあるけど、重い・扱いにくい • そこで「ヘッドレスブラウザ」を使う
 → 最近よく使われるのが PhantomJS 「コマンド一発打って待ってれば 全部完了」が理想ですね
  34. 34. ヘッドレスブラウザ PhantomJS • 中身はWebKit
 正確には QtWebKit • 公式サイトにあるビルド済みバイナリを使うのが吉
 → 自力でビルとすると30分以上かかる可能性大
 → 2ヶ月程前にメジャーバージョンアップ(2.0)したが、
   2.0のビルド済みバイナリは未提供(2015.03.12現在)
 → なので、バージョン1系列の過去のバイナリを使う
 https://code.google.com/p/phantomjs/downloads/list • たまにクラッシュします(笑)さすがにWebKitを完全に動かすのは簡単じゃないっぽい
 落ちた部分だけ再度テストを実行しましょう。
  35. 35. PhantomJSを使うには • Capybaraは、アプリケーションにアクセスしに行く部分のモ ジュール(=ドライバ)を選択できる
 ※デフォルトではRack::Test • CapybaraからPhantomJSを使うためには、
 ドライバとしてPoltergeistを使う features/support/env.rb 追記 追記 左記の設定で、 シナリオの直前に @javascript と記述(タグ)をつけた シナリオはPoltergeistド ライバ経由でPhantomJS を使うようになる
  36. 36. AJAXをテストする features/support/wait_for_ajax.rb step定義ファイル(抜粋) featureファイル(抜粋)
  37. 37. リモートサーバをテストする features/support/env.rb(抜粋) 基本的にはこれだけ • ステップ定義は変わらない
  38. 38. ステップに長いデータを渡す step定義ファイル(抜粋) featureファイル(抜粋) →単に長い文字列を渡すためだけじゃなくて、 rubyのコードを書いてevalしたり、 JSONとして評価したり色々できる この部分がステップの 最後の引数になる
  39. 39. データの初期化はどうする? • env.rbに書く
 テスト実行前のフックに登録する
 データへのアクセスが意外と面倒だったりする • アプリ内にテスト専用コントローラを用意する
 アプリ内部からデータにアクセスするので色々ラク
 テストコードを実行するマシンとテスト環境用データがある マシンが分離している場合にも使える
 もちろん本番環境からは除外するし、テスト環境限定で動く ようにしておく
 例:http://hostname/test/init-data にアクセスすると初期 化実行
  40. 40. Capybara+Cucumber+PhantomJS 実際の例&デモ
  41. 41. ありがとうございました

×