tdc20111031_groovy_geb
TRANSCRIPT
Groovy/Geb 入門
2011/10/31 @TDC 勉強会 ( 番外編 ) JJUG 幹事 / JGGUG サポートスタッフ 須江 信洋
http://twitter.com/nobusue http://d.hatena.ne.jp/nobusue
※ 資料の内容は個人としての意見・見解を述べたものであり、所属する企業・組織が内容を保証するものではありません。
自己紹介 須江 信洋(すえ のぶひろ)
Twitter: @nobusue http://www.facebook.com/profile.php?
id=732337788 かれこれ 10 年位、 JavaEE 関連の仕事をしてま
す G*(Groovy 関連技術 ) との関わり
Groovy コミュニティ (JGGUG) サポートスタッフ 「プログラミング GROOVY 」執筆チーム 「 Groovy イン・アクション」翻訳チーム Groovy で作った Bot 飼ってます (@hatena_groovy)
2
3
Groovy とは
JVM 上で稼動するスクリプト言語Java を拡張し、改良
既存の Java コード≒ Groovy のコード記述量削減、「本質的なこと」に集中できる
例 ) LL 的なリスト / マップリテラル 例 ) 過剰な例外処理の撲滅、リソース開放の自動化
Java との親和性が高いJava のクラス= Groovy のクラスJava のオブジェクト= Groovy のオブジェクト
詳しく知りたい方はこちらへ↓http://d.hatena.ne.jp/uehaj/20110126/1296003293
スクリプトの配布を楽にする :Grape Grape(@Grab) で、 maven リポジトリから jar を
自動取得 Groovy-1.6 からの新機能( 1.7 でさらに改善) 内部では Apache Ivy を利用
4
@Grab(group = 'org.twitter4j', module='twitter4j-core', version='[2.1,)')
import twitter4j.*Twitter twitter =
TwitterFactory.getInstance("<scrname>","<pass>")twitter.updateStatus(args[0])
Twitter4j を使った Twitter クライアントこのファイルだけで動きます!!( 要 Groovy-1.7 以上 )
先進的ビルドとテスト
高生産性 FW
組み込み
Java をカイゼン
Groovy は単なる言語ではない!Groovy のエコシステム
5
Grails GriffonGaelyk
Gant
Gradle
Spock
Geb
GPars(JSR166y)
Groovy++
Maven3
Jenkins(Hudson)
FreeMind
GSQL
JavaFX2.0
SwingBuilder
MarkupBuilder(XML/HTML)
テスト自動化できてますか? V モデル
6
http://ja.wikipedia.org/wiki/V%E3%83%A2%E3%83%87%E3%83%AB
ここは JUnit などでわりかし自動化できている
ここは未だに人海戦術が主流
Continuous Delivery UAT まで自動化することで道が拓ける
7
http://www.amazon.co.jp/dp/0321601912
Selenium の系譜
8
Selenium1(Selenium RC)
2004~
Selenium IDE
Selenium-Grid
WebDriver(Google)
2006~
Selenium2
Selenium2+WebDriver
2009~
2011/07Selenium2.0 リリース
http://seleniumhq.org/docs/01_introducing_selenium.html#brief-history-of-the-selenium-project
Selenium1 と WebDriver Selenium1 の課題
テスト・ドライバーがブラウザ上で稼働するため、ブラウザのサンドボックスの制限を受ける
原理的に対応が難しい機能がある ファイルアップロードなど Ajax 対応
WebDriver テスト・ドライバーがブラウザ外部で稼働するため上記
の制限を受けない Headless Driver(HtmlUnit) に対応 詳細な比較については以下 http://www.asukaze.net/
etc/webdriver/
9
Geb( じぇぶ ) とは
Groovy で構築された WebDriver のラッパー jQuery ライクな Navigator API を提供 Page Object パターンによる構造化 2011/10 時点での最新バージョンは 0.6
多様なテストフレームワークと統合可能 Spock,EasyB JUnit3/4,TestNG Cucumber(Cuke4Duke)
10
http://www.gebish.org/
jQuery-like Navigator API
11
// CSS 3 selectors$("div.some-class p:first[title='something']") // Find via index and/or attribute matching$("h1", 2, class: "heading")$("p", name: "description")$("ul.things li", 2) // 'text' is special attribute for the element text content$("h1", text: "All about Geb") // Use builtin matchers and regular expressions$("p", text: contains("Geb"))$("input", value: ~/\d{3,}-\d{3,}-\d{3,}/) // Chaining$("div").find(".b")$("div").filter(".c").parents()$("p.c").siblings()
Page Object パターン
12
class LoginPage extends Page { static url = "http://myapp.com/login" static at = { heading.text() == "Please Login" } static content = { heading { $("h1") } loginForm { $("form.login") } loginButton(to: AdminPage) { loginForm.login() } }}
class AdminPage extends Page { static at = { heading.text() == "Admin Section" } static content = { heading { $("h1") } }}
Browser.drive { to LoginPage assert at(LoginPage) loginForm.with { username = "admin" password = "password" } loginButton.click() assert at(AdminPage)}
ログイン画面
管理画面
テスト
Geb の例 : はてなキーワード検索
13
@Grapes([ @Grab("org.codehaus.geb:geb-core:latest.release"), @Grab("org.seleniumhq.selenium:selenium-firefox-driver:latest.release")])import geb.Browser
Browser.drive { go "http://d.hatena.ne.jp/keyword/" assert title == " はてなキーワード - 話題の言葉がわかる、みんなで編集するキーワード " $("form.header-search").word = "Groovy" $("form.header-search").find("input", name:"submit").click()
assert title == " はてな検索 : Groovy"}
Spock( すぽっく ) とは
Groovy で構築された BDD フレームワーク Groovy の動的型を活用した DSL を提供 Power Assert で問題箇所を容易に特定可能 可読性の高いテストケース データ・ドリブン・テストにより多数のテストパターン
をコンパクトに記述可能 テストケースは JUnit から実行可能
14
http://code.google.com/p/spock/
Power Assert
15
def a = 1def b = 2def c = 3
assert (a+b)*c == 5
途中結果や、どこで fail したかまで教えてくれる。assertEquals() とかを組み合わせる必要ナシ。
可読性の高いテストケース
16
def "subscribers receive published events at least once"() { when: publisher.send(event) then: (1.._) * subscriber.receive(event) where: event << ["started", "paused", "stopped"]}
def "length of Spock's and his friends' names"() { expect: name.size() == length
where: name | length "Spock" | 5 "Kirk" | 4 "Scotty" | 6}
Geb と Spock のインテグレーション Geb と連携する Spock のテストケースとして以下
が提供される geb.spock.GebSpec / GebReportingSpec
browser インスタンスの注入 WebDriver の Browser クラスの初期化が不要
エビデンス取得の自動化 GebReportingSpec を利用すると、テストケースのメ
ソッド終了時にスクリーンショット (PNG) が自動取得される
17
GebReportingSpec の例
18
@Grab("org.codehaus.geb:geb-spock:0.6.0")@Grab("org.spockframework:spock-core:0.5-groovy-1.8")@GrabExclude("org.codehaus.groovy:groovy-all")@Grab("org.seleniumhq.selenium:selenium-firefox-driver:latest.release")import geb.spock.GebReportingSpec
class FunctionalReportingSpec extends GebReportingSpec { def "Hatena Keyword Search Top"() { when: go "http://d.hatena.ne.jp/keyword/" then: title == " はてなキーワード - 話題の言葉がわかる、みんなで編集するキーワード " } def "Hatena Keyword Search Result"() { when: $("form.header-search").word = "Groovy" $("form.header-search").find("input", name:"submit").click() then: assert title == " はてな検索 : Groovy" }}
GebSpec 利用時の注意点 Spock-0.5(2011/10 時点 ) では Groovy の @Grab
を利用する場合は、依存関係の兼ね合いで以下が必要 @GrabExclude("org.codehaus.groovy:groovy-
all") GebReportingSpec を利用する場合はレポート出力先のディレクトリを指定しておく必要がある 最も簡単なのはシステムプロパティを使うこと groovy -Dgeb.build.reportsDir=/tempdir
GebSpockReporting.groovy
19
JGGUG からのお知らせ G* ワークショップ
だいたい月 1回のペースで G* 関連の勉強会を実施しています
次回は 11/22予定、 Geb の詳しい話を予定 詳細は http://www.jggug.org/ で
G*Magazine http://grails.jp/g_mag_jp/ JGGUG が発行している電子雑誌です。 創刊号と第 3号に、 @bikisuke さんが Geb/Spock の
技術情報を執筆されています。
20
ご静聴ありがとうございました
21