$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
横浜タネマキでGebと握手! #yokohamagroovy
Search
PoohSunny
July 30, 2016
Technology
0
420
横浜タネマキでGebと握手! #yokohamagroovy
Yokohama.groovy #42でのGebのハンズオンの資料です。
PoohSunny
July 30, 2016
Tweet
Share
More Decks by PoohSunny
See All by PoohSunny
ドレイファスモデルの紹介 / introduce Dreyfus model
poohsunny
1
1.5k
Make Work Visible in Agile2018 #LINE_DM
poohsunny
1
460
タウンワークをドライブさせるためになんちゃってアジャイルをやめた話 #devsumi #devsumiB / devsumi2018
poohsunny
30
47k
1 test 1 assert ?
poohsunny
0
460
XUTPから学ぶ記述性の高いユニットテスト 〜俺たちを助けるユニットテストへ〜 / xUTP in #xpjug
poohsunny
4
5.3k
XCUITestする時のTIPs 〜あなたを助けるXCUITestへ〜
poohsunny
0
3.1k
コードに思いが伝わる
poohsunny
0
330
The "yummy" licenses.
poohsunny
0
210
ブラウザテストをサクサク自動化するためのGeb実践入門 #jjug_ccc
poohsunny
21
7.1k
Other Decks in Technology
See All in Technology
AgentCore BrowserとClaude Codeスキルを活用した 『初手AI』を実現する業務自動化AIエージェント基盤
ruzia
7
1.4k
オープンソースKeycloakのMCP認可サーバの仕様の対応状況 / 20251219 OpenID BizDay #18 LT Keycloak
oidfj
0
160
事業の財務責任に向き合うリクルートデータプラットフォームのFinOps
recruitengineers
PRO
2
190
Oracle Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
1
400
Lookerで実現するセキュアな外部データ提供
zozotech
PRO
0
200
日本の AI 開発と世界の潮流 / GenAI Development in Japan
hariby
1
360
2025-12-18_AI駆動開発推進プロジェクト運営について / AIDD-Promotion project management
yayoi_dd
0
150
ActiveJobUpdates
igaiga
1
310
20251218_AIを活用した開発生産性向上の全社的な取り組みの進め方について / How to proceed with company-wide initiatives to improve development productivity using AI
yayoi_dd
0
650
会社紹介資料 / Sansan Company Profile
sansan33
PRO
11
390k
20251219 OpenIDファウンデーション・ジャパン紹介 / OpenID Foundation Japan Intro
oidfj
0
490
AgentCoreとStrandsで社内d払いナレッジボットを作った話
motojimayu
1
870
Featured
See All Featured
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Bash Introduction
62gerente
615
210k
How to Talk to Developers About Accessibility
jct
1
84
Prompt Engineering for Job Search
mfonobong
0
120
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
0
210
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
170
YesSQL, Process and Tooling at Scale
rocio
174
15k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
43
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
210
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
80
Transcript
ԣλωϚΩͰ GebͱѲखʂ @PoohSunny Yokohama.groovy #42 #yokohamagroovy
@PoohSunny { work: "σΟϕϩούʔ" geb: "very minor contributor" community: [
"TDDBC", "Agile Samurai Base Camp", "ຊSeleniumϢʔβʔίϛϡχςΟ" "Yokohama.groovy" <- NEW! ] }
None
ࠓͷςʔϚ
͐͡Ϳ
ϒϥβΦʔτϝʔγϣϯ πʔϧ LicenseApache License, Version 2.0 ͦΖͦΖ1.0.0ͳͣʂʂ ݱࡏͷ࠷৽όʔδϣϯ0.13.1
GebΛͬͯΈΑ͏ʂ
ͪΐͬͱ͚ͩલஔ͖ GebͷϦ
؆ܿͳهड़1 import geb.Browser Browser.drive { go "http://myapp.com/login" assert $("h1").text() ==
"Please Login" $("form.login").with { username = "admin" password = "password" login().click() } assert $("h1").text() == "Admin Section" } 1 http://www.gebish.org/
Seleniumͩͱ...
Gebͩͱ!2 2 http://www.slideshare.net/youtaroutakahashi/what-makes-geb-groovy
࣮ࡍͬͯΈ·͠ΐ ͏ɻ
࠷ॳʹ͏ϓϩδΣΫτ GebͷϗʔϜϖʔδʹΞΫηε͢Δͷ ͪ͜ΒΛΫϩʔϯ͍ͯͩ͘͠͞ https://github.com/PoohSunny/geb-hands-on-project
͍ͬͯΔπʔϧ Gradle: λεΫϥϯφʔͱͯ͠ Spock: ςετϥϯφʔͱͯ͠ ࣮ࡍͷςετSpockͷςετͱͯ͠هड़ GebSpecɺ͋Δ͍GebReportingSpecΛܧঝ class GebishOrgSpec extends
GebReportingSpec { Reportingͱ͍͍ͭͯΔΫϥε → ҙͷλΠϛϯάɾऴྃ࣌ʹΩϟϓνϟ͕औΕ·͢ɻ
ϓϩδΣΫτͷσΟϨΫτϦ ߏ root |-- src | `-- test | |--
groovy | | `- xxxSpecs.groovy | `-- resources | `-- GebConfig.groovy `-- build.gradle
build.gradle ґଘؔͷఆٛ3 dependencies { // ུ // ඞཁͳυϥΠόΛͦΕͧΕґଘؔʹՃ testCompile "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion"
testCompile("com.codeborne:phantomjsdriver:1.2.1") { // phantomjs driver pulls in a different selenium version transitive = false } } 3 ͳͥɺWebDriverΛͦΕͧΕґଘؔʹՃ͢Δͷ͔ʹ͍ͭͯɺhttps://groups.google.com/d/ msg/geb-user/Og40o5mXK-4/tga5H2zuRRYJ
ͱΓ͋͑ͣಈ͔ͯ͠ΈΑ͏ ԼهͷίϚϯυΛ࣮ߦͯ͠ɺϒϥβ ্ཱ͕͕ͪΔʁ ./gradlew test
ಈ͍ͨʂ Ͱίέͨʂ
গ͠ղઆ ͍ͬͯΔAPI // ҾͰࢦఆ͞Ε͍ͯΔURLʹભҠ go "XXX" // ϖʔδͷλΠτϧΛνΣοΫ title ==
"Very Groovy Browser Automation!"
APIʹ͍ͭͯ པΔͳΒެࣜυΩϡϝϯτ http://www.gebish.org/manual/current/ αϯϓϧ͕ଟ͍͔ΒӳޠͰ͖ͬͱେৎʂ
࿅श མͪͨςετΛͯ͠ΈΑ͏ ࣍ͷϖʔδʹղ͕͋Γ·͢ɻ
ղ // λΠτϧͷظ͕ؒҧͬͯͨʂ title == "Very Groovy Browser Automation"
࿅शͦͷ2 ԼهͷॲཧΛՃͯ͠Έ·͠ΐ͏ɻ • ϗʔϜϖʔδ͔ΒɺϚχϡΞϧͷϦϯΫΛΫ ϦοΫ • ϚχϡΞϧϖʔδʢThe book of Gebʣ͕දࣔ
͞ΕΔ͔ΛνΣοΫ • step-2ͬͯϒϥϯνʹɺҰ෦ຒ·ͬͯΔςετ ͕͋ΔͷͰɺͦΕΛຒΊͯΒ͏ͱ͍͍͔ͱɻ • ώϯτ͕ཉ͍͠ਓ࣍ͷϖʔδ
͔͜͜Βώϯτ
jQueryͬΆ͍API4 $("div") // ࠷ॳʹݟ͔ͭͬͨ div ཁૉ $("div", name: "main") //
<div name="main"></div> $("div", 1, name: "main") // ೋ൪ͷ<div name="main"></div> 4 http://www.gebish.org/manual/current/#the-jquery-ish-navigator-api
͜Μͳॻ͖ํՄ $("#user-name") // user-name ͱ͍͏id͕ࢦఆ͞Ε͍ͯΔཁૉ $(".btn") // btn ͱ͍͏class͕ࢦఆ͞Ε͍ͯΔཁૉ ཁૉΛ୳͢ͷChrome
Developer tool + jQueryͰͬͯɺͦΕΛGebʹίϐ ϖ͢Δͱ͔Α͘Γ·͢ νʔϜͰهड़͕όϥόϥͩͱ͘͜͠ͳΔͷͰɺܾΊ͓ͯ͘ͱྑ͍Ͱ͢
click manualsMenu.links[0].click() ϖʔδΦϒδΣΫτͷఆٛͷํ͍Ζ͍Ζ content { // to: ͜ͷΤϨϝϯτ͕ΫϦοΫ͞Εͨͱ͖ʹConfirmPageΛ͢ // toWait:
࣍ͷϖʔδͷatνΣοΫ͕trueʹͳΔ·Ͱͭ button(to: ConfirmPage, toWait: true) { $('button#save') } }
interact()5 ෳࡶͳૢ࡞Λ͢Δͱ͖ʹ ྫ͑υϥοά & υϩοϓ interact { clickAndHold($('#draggable')) moveByOffset(150, 200)
release() } 5 http://www.gebish.org/manual/current/#interact-closures
ώϯτ͜͜·Ͱ ͪͳΈʹ͑ step-2- answer ϒϥϯνʹ͋Γ·͢ɻ
Ͱ͖ͨ͠ͷͷ ͋Μ·Γ͖Ε͍Ͱͳ͍
Կ͕͍͚ͳ͍ʁ interact { // ఆ͕͍ٛ moveToElement($("#header-content ul li", 0).children("span")) }
// ఆٛͷॏෳ $("#header-content ul li", 0).$('.link-list li a')[0].click()
Ͳ͏վળ͢Δʁ
هड़γϯϓϧΛ৺͕͚Δ ਂ͗͢ΔΤϨϝϯτऔಘ $("#id").find(".class-a").find("td").find(".class-b")
هड़γϯϓϧΛ৺͕͚Δ ఆٛ͘ // ్தʹࢦఆͰ͖ͦ͏ͳattributeΛ୳͢ $("#user-td").find(".class-b") // ΤϨϝϯτΛׂ͢Δ userTd { $("#id").find(".class-a").find("td")
} column { userTd.find(".class-b") }
ϖʔδΦϒδΣΫτύλʔϯ ͷར༻ ར༻͢ΔίϯςϯπͷϝϯςφϯεੑΛ্͛ɺ࠶ ར༻͘͢͢͠ΔͨΊͷσβΠϯύλʔϯ6 6 http://www.seleniumhq.org/docs/06testdesign_considerations.jsp#page-object-design-pattern
GebͷϖʔδΦϒδΣΫτʹ ͍ͭͯৄ͘͠
GebͷϖʔδΦϒδΣΫτ PageΫϥεΛܧঝ class GebishOrgHomePage extends Page { static at =
{ title == "Sample page" } static content = { header { $("#header") } manualsMenu { module MenuModule, $("#header", 0) } } }
࠶ར༻ՄೳͳύʔπModuleʹ import geb.Module class MenuModule extends Module { static content
= { toggle { children("span") } links { $('.link-list li a') } } }
Page url at content
url7 to()ϝιουͰݺΜͩ࣌ʹભҠ͢ΔઌΛઃఆ class PageWithUrl extends Page { static url =
"example" } ૬ରύεͰهड़͢Δͱ͖ɺbaseUrlͷઃఆ͕ඞཁ8 8 http://www.gebish.org/manual/current/#base-url 7 http://www.gebish.org/manual/current/#page-urls
at9 at()ϝιουར༻࣌ʹ͜ͷϖʔδͷΞαʔτ͕ߦΘΕΔ to()ϝιουͰϖʔδભҠͨ͠ͱ͖atνΣοΫ͕Δ class PageWithAtChecker extends Page { static at
= { $("h1").text() == "Example" } } 9 http://www.gebish.org/manual/current/#at-checker
content ϖʔδͷཁૉΛهड़ class PageWithDiv extends Page { static content =
{ theDiv { $('div', id: 'a') } } }
Page, Moduleઐ༻ͷσΟϨΫτϦ ʹஔ͠·͠ΐ͏ root |-- src | `-- test |
|-- groovy | | |-- pages | | |-- modules | | `- xxxSpecs.groovy | `-- resources | `-- GebConfig.groovy `-- build.gradle
࿅श ϖʔδΦϒδΣΫτΛͬͯ վળͯ͠ΈΑ͏ʂ
࿅श ࠓͷςετɺ؆ܿͰͳ͍هड़ॏෳΛ͓࣋ͬͯ Γɺ·ͨมߋʹऑ͍ߏʹͳ͍ͬͯ·͢ɻ͜ΕΒ ͷΛղܾ͢Δ͘ςετίʔυΛϦϑΝΫλ Ϧϯά͍ͯͩ͘͠͞ɻ ΩʔϫʔυɿϖʔδΦϒδΣΫτύλʔϯɺ؆ܿ ͳهड़ɺϞδϡʔϧԽ step-3ͱ͍͏ϒϥϯνʹϖʔδΦϒδΣΫτͷ ܗΛ࡞ͬͨͷ͕͋Γ·͢ɻ
͔͜͜Β՝Λ Δ্Ͱͷώϯτ
ϖʔδΦϒδΣΫτͷఆٛͷํ͍Ζ͍Ζ content { // to: ͜ͷΤϨϝϯτ͕ΫϦοΫ͞Εͨͱ͖ʹConfirmPageΛ͢ // toWait: ࣍ͷϖʔδͷatνΣοΫ͕trueʹͳΔ·Ͱͭ button(to:
ConfirmPage, toWait: true) { $('button#save') } }
Θ͔Γ͍͢هड़Λ ͜ͷϘλϯͲ͜ͷϘλϯʁ to LoginPage login("user", "password") clickListButton()
Θ͔Γ͍͢هड़Λ SpockͷػೳΛ׆༻ given: "user is at Top page" to LoginPage
login("user", "password") at TopPage when: "user clicks list button" listButton.click() then: "user moves to List page" at ListPage
ॻ͖ํόϥόϥ // A͞Μ go "http://myapp.com/login" $("form.login").with { username = "admin"
password = "password" login().click() } // B͞Μ to LoginPage username = "admin" password = "password" loginButton.click() // C͞Μ to LoginPage login("admin", password)
ॻ͖ํͷ౷Ұ ·ͣϖʔδΦϒδΣΫτԽ ·ͱ·ͬͨॲཧϝιουͱͯ͠ఆٛ͢Δ
ϝιουͷཻόϥόϥ // A͞Μ to HomePage menuLinks[0].click() // B͞Μ to HomePage
manualLink.click() // C͞Μ to HomePage showManual()
ͳͥɺͳʹΛ ςετ͍ͨ͠ͷ͔ʹґଘ10 తΛࢥ͍ग़͢ νʔϜͰٞ͢Δ 10 http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
՝ʹ٧·ͬͨΒ ్தܦա͕Լهϒϥϯνʹ͋ Γ·͢ɻ https://github.com/yokohamagroovy/ geb-hands-on-project/tree/step3-hints
࠷ऴܗ ຊՈͷαϯϓϧϓϩδΣΫτ ʹ͍ۙͷʹͳΔͣɻ https://github.com/geb/geb-example- gradle ɾϖʔδɺϞδϡʔϧͷύοέʔδϯά ɾϖʔδΦϒδΣΫτͷϝιουͷΓग़͠ํɺ໋໊ҙਤతʹมߋͯ͠·͢
͓͠·͍ GebͰָ͍͠ϒϥβΦʔτϝʔγϣϯΛʂ