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
Groovyとは
JVM上で稼動するスクリプト言語
Javaを拡張し、改良
  既存のJavaコード≒Groovyのコード
  記述量削減、「本質的なこと」に集中できる
    例) LL的なリスト/マップリテラル
    例) 過剰な例外処理の撲滅、リソース開放の自動化

Javaとの親和性が高い
  Javaのクラス=Groovyのクラス
  Javaのオブジェクト=Groovyのオブジェクト

 詳しく知りたい方はこちらへ↓
  http://d.hatena.ne.jp/uehaj/20110126/1296003293

                                       3
スクリプトの配布を楽にする:Grape
   Grape(@Grab)で、mavenリポジトリからjarを自動取
    得
       Groovy-1.6からの新機能(1.7でさらに改善)
       内部ではApache Ivyを利用
       @Grab(
          group = 'org.twitter4j', module='twitter4j-core',
          version='[2.1,)')
       import twitter4j.*
       Twitter twitter =
          TwitterFactory.getInstance("<scrname>","<pass>")
       twitter.updateStatus(args[0])
                Twitter4jを使ったTwitterクライア
                ント
                このファイルだけで動きます!!
    4
                (要Groovy-1.7以上)
Groovyは単なる言語ではない!
                Groovyのエコシステム
    Javaをカイゼン                 高生産性FW

      GSQL         Grails      Gaelyk   Griffon
SwingBuilder
                                         組み込み
MarkupBuilder                            Jenkins
 (XML/HTML)                             (Hudson)

        ビルドとテスト
                             先進的         Maven3
                             GPars
     Gant       Spock       (JSR166y)   FreeMind

    Gradle       Geb        Groovy++    JavaFX2.0
5
テスト自動化できてますか?
       Vモデル

                                                           ここは未だに
                                                           人海戦術が
                                                           主流



                                                     ここはJUnitなどで
                                                     わりかし自動化
                                                     できている




        http://ja.wikipedia.org/wiki/V%E3%83%A2%E3%83%87%E3%83%AB
    6
Continuous Delivery
       UATまで自動化することで道が拓ける




                      http://www.amazon.co.jp/dp/0321601912


    7
Seleniumの系譜
            2004~
        Selenium1
      (Selenium RC)                         Selenium2


            Selenium IDE
                                                                                 2009~

                                                                        Selenium2
            Selenium-Grid                                               +WebDriver

                                2006~
                                                                           2011/07
                             WebDriver
                             (Google)
                                                                           Selenium2.0リリース

    http://seleniumhq.org/docs/01_introducing_selenium.html#brief-history-of-the-selenium-project

8
Selenium1とWebDriver
       Selenium1の課題
           テスト・ドライバーがブラウザ上で稼働するため、ブラ
            ウザのサンドボックスの制限を受ける
           原理的に対応が難しい機能がある
               ファイルアップロードなど
               Ajax対応
       WebDriver
           テスト・ドライバーがブラウザ外部で稼働するため上記
            の制限を受けない
           Headless Driver(HtmlUnit)に対応
           詳細な比較については以下
            http://www.asukaze.net/etc/webdriver/

    9
Geb(じぇぶ)とは

                               http://www.gebish.org/

    Groovyで構築されたWebDriverのラッパー
        jQueryライクなNavigator APIを提供
        Page Objectパターンによる構造化
        2011/10時点での最新バージョンは0.6
    多様なテストフレームワークと統合可能
        Spock,EasyB
        JUnit3/4,TestNG
        Cucumber(Cuke4Duke)


    10
jQuery-like Navigator API
// 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()

  11
Page Objectパターン
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() }
   }
}                                                         Browser.drive {          テスト
                                                            to LoginPage
                                                            assert at(LoginPage)
                                                            loginForm.with {
                                                               username = "admin"
class AdminPage extends Page {                                 password = "password"
   static at = { heading.text() == "Admin Section" }        }
   static content = {                                       loginButton.click()
      heading { $("h1") }                                   assert at(AdminPage)
   }                                                      }
}                                                    管理画面

     12
Gebの例: はてなキーワード検索
@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"
}

    13
Spock(すぽっく)とは
                    http://code.google.com/p/spock/


    Groovyで構築されたBDDフレームワーク
        Groovyの動的型を活用したDSLを提供
        Power Assertで問題箇所を容易に特定可能
        可読性の高いテストケース
        データ・ドリブン・テストにより多数のテストパターン
         をコンパクトに記述可能
        テストケースはJUnitから実行可能




    14
Power Assert
def a = 1
def b = 2
def c = 3

assert (a+b)*c == 5




       途中結果や、どこでfailしたかまで教えてく
       れる。
       assertEquals()とかを組み合わせる必要ナシ。


  15
可読性の高いテストケース
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
}
    16
GebとSpockのインテグレーション
    Gebと連携するSpockのテストケースとして以下が
     提供される
        geb.spock.GebSpec / GebReportingSpec
    browserインスタンスの注入
        WebDriverのBrowserクラスの初期化が不要
    エビデンス取得の自動化
        GebReportingSpecを利用すると、テストケースのメソッ
         ド終了時にスクリーンショット(PNG)が自動取得される




    17
GebReportingSpecの例
@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"
    }
}

    18
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

TDC20111031_Groovy_Geb

  • 1.
    Groovy/Geb入門 2011/10/31 @TDC勉強会(番外編) JJUG幹事/ JGGUGサポートスタッフ 須江 信洋 http://twitter.com/nobusue http://d.hatena.ne.jp/nobusue ※資料の内容は個人としての意見・見解を述べたものであり、 所属する企業・組織が内容を保証するものではありません。
  • 2.
    自己紹介  須江 信洋(すえ のぶひろ)  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 3
  • 4.
    スクリプトの配布を楽にする:Grape  Grape(@Grab)で、mavenリポジトリからjarを自動取 得  Groovy-1.6からの新機能(1.7でさらに改善)  内部ではApache Ivyを利用 @Grab( group = 'org.twitter4j', module='twitter4j-core', version='[2.1,)') import twitter4j.* Twitter twitter = TwitterFactory.getInstance("<scrname>","<pass>") twitter.updateStatus(args[0]) Twitter4jを使ったTwitterクライア ント このファイルだけで動きます!! 4 (要Groovy-1.7以上)
  • 5.
    Groovyは単なる言語ではない! Groovyのエコシステム Javaをカイゼン 高生産性FW GSQL Grails Gaelyk Griffon SwingBuilder 組み込み MarkupBuilder Jenkins (XML/HTML) (Hudson) ビルドとテスト 先進的 Maven3 GPars Gant Spock (JSR166y) FreeMind Gradle Geb Groovy++ JavaFX2.0 5
  • 6.
    テスト自動化できてますか?  Vモデル ここは未だに 人海戦術が 主流 ここはJUnitなどで わりかし自動化 できている http://ja.wikipedia.org/wiki/V%E3%83%A2%E3%83%87%E3%83%AB 6
  • 7.
    Continuous Delivery  UATまで自動化することで道が拓ける http://www.amazon.co.jp/dp/0321601912 7
  • 8.
    Seleniumの系譜 2004~ Selenium1 (Selenium RC) Selenium2 Selenium IDE 2009~ Selenium2 Selenium-Grid +WebDriver 2006~ 2011/07 WebDriver (Google) Selenium2.0リリース http://seleniumhq.org/docs/01_introducing_selenium.html#brief-history-of-the-selenium-project 8
  • 9.
    Selenium1とWebDriver  Selenium1の課題  テスト・ドライバーがブラウザ上で稼働するため、ブラ ウザのサンドボックスの制限を受ける  原理的に対応が難しい機能がある  ファイルアップロードなど  Ajax対応  WebDriver  テスト・ドライバーがブラウザ外部で稼働するため上記 の制限を受けない  Headless Driver(HtmlUnit)に対応  詳細な比較については以下 http://www.asukaze.net/etc/webdriver/ 9
  • 10.
    Geb(じぇぶ)とは http://www.gebish.org/  Groovyで構築されたWebDriverのラッパー  jQueryライクなNavigator APIを提供  Page Objectパターンによる構造化  2011/10時点での最新バージョンは0.6  多様なテストフレームワークと統合可能  Spock,EasyB  JUnit3/4,TestNG  Cucumber(Cuke4Duke) 10
  • 11.
    jQuery-like Navigator API //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() 11
  • 12.
    Page Objectパターン class LoginPageextends 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() } } } Browser.drive { テスト to LoginPage assert at(LoginPage) loginForm.with { username = "admin" class AdminPage extends Page { password = "password" static at = { heading.text() == "Admin Section" } } static content = { loginButton.click() heading { $("h1") } assert at(AdminPage) } } } 管理画面 12
  • 13.
    Gebの例: はてなキーワード検索 @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" } 13
  • 14.
    Spock(すぽっく)とは http://code.google.com/p/spock/  Groovyで構築されたBDDフレームワーク  Groovyの動的型を活用したDSLを提供  Power Assertで問題箇所を容易に特定可能  可読性の高いテストケース  データ・ドリブン・テストにより多数のテストパターン をコンパクトに記述可能  テストケースはJUnitから実行可能 14
  • 15.
    Power Assert def a= 1 def b = 2 def c = 3 assert (a+b)*c == 5 途中結果や、どこでfailしたかまで教えてく れる。 assertEquals()とかを組み合わせる必要ナシ。 15
  • 16.
    可読性の高いテストケース def "subscribers receivepublished 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 } 16
  • 17.
    GebとSpockのインテグレーション  Gebと連携するSpockのテストケースとして以下が 提供される  geb.spock.GebSpec / GebReportingSpec  browserインスタンスの注入  WebDriverのBrowserクラスの初期化が不要  エビデンス取得の自動化  GebReportingSpecを利用すると、テストケースのメソッ ド終了時にスクリーンショット(PNG)が自動取得される 17
  • 18.
    GebReportingSpecの例 @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 FunctionalReportingSpecextends 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" } } 18
  • 19.
    GebSpec利用時の注意点  Spock-0.5(2011/10時点)ではGroovyの@Grabを利用 する場合は、依存関係の兼ね合いで以下が必要  @GrabExclude("org.codehaus.groovy:groovy-all")  GebReportingSpecを利用する場合はレポート出力先 のディレクトリを指定しておく必要がある  最も簡単なのはシステムプロパティを使うこと  groovy -Dgeb.build.reportsDir=/tempdir GebSpockReporting.groovy 19
  • 20.
    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.