G*workshop 2011/11/22 Geb+Betamax
Upcoming SlideShare
Loading in...5
×
 

G*workshop 2011/11/22 Geb+Betamax

on

  • 5,042 views

 

Statistics

Views

Total Views
5,042
Views on SlideShare
3,231
Embed Views
1,811

Actions

Likes
3
Downloads
16
Comments
0

7 Embeds 1,811

http://d.hatena.ne.jp 1734
http://orangeclover.hatenablog.com 32
http://sns.labs.fujitsu.com 18
http://webcache.googleusercontent.com 15
http://a0.twimg.com 9
http://hatenatunnel.appspot.com 2
http://us-w1.rockmelt.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

G*workshop 2011/11/22 Geb+Betamax G*workshop 2011/11/22 Geb+Betamax Presentation Transcript

  • 入門Geb+Betamax 2011/11/22 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
  • 本日のお題 テスト自動化について Geb入門 Betamax入門 Geb+Spock+Betamaxでgrails test-app3
  • テスト自動化、しましょうか? Vモデル ここは未だに 人海戦術が 主流 ここはJUnitなどで わりかし自動化 できている http://ja.wikipedia.org/wiki/V%E3%83%A2%E3%83%87%E3%83%AB4
  • 自動化できれば・・・ テスト実行に伴う人的コストが不要になる  リファクタリングに取り組み易くなる  バグフィックスや機能修正によるリリース頻度を上 げられる  ミドルウェアやOSのFix適用に躊躇しなくてよくなる テストの品質を上げられる  手作業に完全ということはありえない  手作業は監査できない5
  • とはいえ・・・ 受け入れテスト(UAT)の完全自動化は大変  ならば、せめてスモークテストだけでも自動化を  人手によるテストやパフォーマンステストの前の関 門として、CIのプロセスに組み込んでみては? http://en.wikipedia.org/wiki/Smoke_testing6
  • Gebる前に: Seleniumの系譜 2004~ Selenium1 (Selenium RC) Selenium2 Selenium IDE 2009~ Selenium2 Selenium-Grid +WebDriver 2006~ 2011/07 WebDriver Selenium2.0リリース (Google) http://seleniumhq.org/docs/01_introducing_selenium.html#brief-history-of-the-selenium-project7
  • Selenium1とWebDriver Selenium1の課題  テスト・ドライバーがブラウザ上で稼働するため、ブラ ウザのサンドボックスの制限を受ける  原理的に対応が難しい機能がある  ファイルアップロードなど  Ajax対応 WebDriver  テスト・ドライバーがブラウザ外部で稼働するため上記 の制限を受けない  Headless Driver(HtmlUnit)に対応  詳細な比較については以下 http://www.asukaze.net/etc/webdriver/ 8
  • WebDriver: Java APIサンプルpublic class Selenium2Example { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); driver.get("http://www.google.com"); WebElement element = driver.findElement(By.name("q")); element.sendKeys("Cheese!"); element.submit(); System.out.println("Page title is: " + driver.getTitle()); (new WebDriverWait(driver, 10)) .until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return d.getTitle().toLowerCase().startsWith("cheese!"); } }); System.out.println("Page title is: " + driver.getTitle()); driver.quit(); }} 9
  • ちょっとめんどい10
  • そこでGeb(じぇぶ)ですよ http://www.gebish.org/ Groovyで構築されたWebDriverのラッパー  jQueryライクなNavigator APIを提供  Page Objectパターンによる構造化  WebDriver単体でも使えるが、より使いやすく  2011/11/22時点での最新バージョンは0.6.1  GitHub上の最新は0.7.0-SNAPSHOT 多様なテストフレームワークと統合可能  Spock,EasyB  JUnit3/4,TestNG  Cucumber(Cuke4Duke) 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() 12
  • 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) } }} 管理画面 13
  • Gebの例: はてなキーワード検索@Grapes([ @Grab("org.codehaus.geb:geb-core:0.6.1"), @Grab("org.seleniumhq.selenium:selenium-firefox-driver:2.12.0")])import geb.BrowserBrowser.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"} 14
  • GebとSpockのインテグレーション Gebと連携するSpockのテストケースとして以 下が提供される  geb.spock.GebSpec / GebReportingSpec browserインスタンスの注入  WebDriverのBrowserクラスの初期化が不要 evidence取得の自動化  GebReportingSpecを利用すると、テストケースのメ ソッド終了時にスクリーンショット(PNG)が自動取得 される15
  • Geb ドキュメント&サンプル The Book Of Geb  http://www.gebish.org/manual/current/  かなり詳しいドキュメント Gebソースコード  https://github.com/geb/geb Geb/Gradleサンプル  https://github.com/geb/geb-example-gradle16
  • ChromeDriver利用時の注意点 ChromeDriverを実行可能にしておくこと  http://code.google.com/p/selenium/wiki/ChromeDriver  バイナリをダウンロード  http://code.google.com/p/chromium/downloads/list  パスに追加 or システムプロパティ webdriver.chrome.drive を設定 17
  • GebReportingSpecの例class GoogleSpec extends GebReportingSpec { def "the first link should be wikipedia"() { when: to GoogleHomePage and: search.forTerm "wikipedia" then: at GoogleResultsPage and: firstResultLink.text() == "Wikipedia" when: firstResultLink.click() then: waitFor { at WikipediaPage } }} 18
  • GebSpec利用時の注意点 GebReportingSpecを利用する場合はレポート 出力先のディレクトリを指定しておく必要があ る  最も簡単なのはシステムプロパティを使うこと  groovy -Dgeb.build.reportsDir=/tempdir GebSpockReporting.groovy19
  • Gebについて詳しくは・・・ G*Magazine  http://grails.jp/g_mag_jp/  創刊号と第3号に、@bikisuke さんがGeb/Spock の技術情報を執筆 GitHub  https://github.com/kimukou/gradlestudy/tre e/master/geb-geb-example  @kimukou_26 さん作成サンプル20
  • Betamax http://robfletcher.github.com/betamax/ WebサービスのRecord/Playback Proxy  HTTPリクエスト/レスポンスをtapeに記録  tapeを利用してWebサービスをエミュレート JUnit/Spockとのインテグレーション vcr(Ruby)のクローン  https://www.relishapp.com/myronmarston/vcr  vcrのcassetと互換性あり?(未確認)21
  • Hello, Betamax <任意のディレクトリ> │ build.gradle └─src └─test └─groovy MySpec.groovy "gradle test"を実行すると、 src/test/resources/betamax/tapesにtapeが作成される 同じリクエストに対してはBetamaxがtapeを再生する  デフォルトではURLとHTTPメソッドの対で同一性を判定 22
  • build.gradleapply plugin: "groovy"repositories { mavenCentral()}dependencies { groovy("org.codehaus.groovy:groovy-all:1.8.4") testCompile("com.github.robfletcher:betamax:1.0") testCompile( "org.codehaus.groovy.modules.http-builder:http-builder:0.5.1") { exclude module: "groovy" exclude module: "httpclient" } testCompile("org.spockframework:spock-core:0.5-groovy-1.8") { exclude module: "groovy-all" }} 23
  • MySpec.groovyimport betamax.*import spock.lang.*import org.junit.*import groovyx.net.http.RESTClientimport org.apache.http.impl.conn.ProxySelectorRoutePlannerclass MySpec extends Specification { @Rule Recorder recorder = new Recorder() @Shared RESTClient http = new RESTClient() def setupSpec() { http.client.routePlanner = new ProxySelectorRoutePlanner( http.client.connectionManager.schemeRegistry, ProxySelector.default) } @Betamax(tape="my tape") def "various types of response data"() { when: def response = http.get(uri:"http://grails.org/") then: response.status == 200 }} 24
  • その他のサンプル 今のところまとまったドキュメント等はないの で、ソースコードからビルドして試すのがおす すめ  https://github.com/robfletcher/betamax  そろそろGitには慣れておいた方がいい ビルド時の注意点  SonaTypeのアカウント設定  テストが一部通らない・・・が無視してOK25
  • SonaTypeのアカウント設定 素直にビルドすると以下のエラーが  A problem occurred evaluating root project betamax. Cause: No such property: sonatypeUsername for class: org.gradle.api.internal.artifacts.publish.maven.deploy.groo vy.DefaultGroovyMavenDeployer  SonaTypeのアカウントなんて持ってないよママン! 以下で対処してください  gradle.propertiesを作成(値は空白で可) [gradle.properties] sonatypeUsername= sonatypePassword=26
  • テストが一部通らない 時刻の扱いに問題あり(Timezoneを考慮して いない)だが、テストケース側の問題なので無 視してOK  一応pull requestしたけど放置されてます。。。  他にもいくつか問題あり。ぜひパッチを!27
  • Grails + Geb + Betamax ソースのexamples/grails-betamax以下 ← 機能テスト(Spock+Geb+Betamax) ← tape(Twitter API呼出し) ← ユニットテスト(Spock+Betamax)28
  • tape YAMLでHTTPリクエスト/レスポンスを記録 !tape name: twitter success interactions: - recorded: 2011-08-31T13:12:42.293Z request: method: GET uri: http://search.twitter.com/search.json?q=betamax&rpp=10&page=1 headers: Accept: application/json Accept-Encoding: gzip,deflate Host: search.twitter.com Proxy-Connection: Keep-Alive response: status: 200 headers: Age: 0 Cache-Control: max-age=15, must-revalidate, max-age=300 Content-Encoding: gzip Content-Type: application/json;charset=utf-8 Date: Wed, 31 Aug 2011 13:12:42 GMT Expires: Wed, 31 Aug 2011 13:17:42 GMT Server: hi Vary: Accept-Encoding Via: 1.1 varnish X-Varnish: 2033991101 body: |- { "completed_in": 0.072,29 "max_id": 108888091493801987,
  • tapeの利用価値 Web APIにアクセスできない状況でもテストが できる  新幹線で移動することが多い人向け テストを高速化できる  いちいちサーバーにアクセスしなくてすむ テスト結果を安定化できる  サーバー側の変化からテストを分離できる レアケースに対するテストを容易にできる  TwitterのAPI呼出し制限に引っ掛かった場合など tapeを再利用(資産化)できる30
  • Betamaxはまり道 基本的にはRecorderと@Betamaxだけで いけるはず!  組合せによっていろいろ起こります。。。。  とりあえずGroovy-1.8/HTTPBuilderの組合せが おすすめ  素のURLクラスを使うと、 java.io.IOException: Premature EOF ???  400 Bad Request ??? 品質向上にご協力下さい"Please raise issues on Betamax’s GitHub issue tracker. Forks andpull requests are more than welcome." by Rob Fletcher31
  • ご静聴ありがとうございました32