Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
横浜タネマキでGebと握手! #yokohamagroovy
Search
PoohSunny
July 30, 2016
Technology
0
390
横浜タネマキで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.1k
Make Work Visible in Agile2018 #LINE_DM
poohsunny
1
390
タウンワークをドライブさせるためになんちゃってアジャイルをやめた話 #devsumi #devsumiB / devsumi2018
poohsunny
30
45k
1 test 1 assert ?
poohsunny
0
370
XUTPから学ぶ記述性の高いユニットテスト 〜俺たちを助けるユニットテストへ〜 / xUTP in #xpjug
poohsunny
4
5.1k
XCUITestする時のTIPs 〜あなたを助けるXCUITestへ〜
poohsunny
0
3k
コードに思いが伝わる
poohsunny
0
250
The "yummy" licenses.
poohsunny
0
160
ブラウザテストをサクサク自動化するためのGeb実践入門 #jjug_ccc
poohsunny
21
6.9k
Other Decks in Technology
See All in Technology
Amazon Q Developerで.NET Frameworkプロジェクトをモダナイズしてみた
kenichirokimura
1
200
Amazon Route 53, 待ちに待った TLSAレコードのサポート開始
kenichinakamura
0
170
三菱電機で社内コミュニティを立ち上げた話
kurebayashi
1
360
デジタルアイデンティティ人材育成推進ワーキンググループ 翻訳サブワーキンググループ 活動報告 / 20250114-OIDF-J-EduWG-TranslationSWG
oidfj
0
540
Goで実践するBFP
hiroyaterui
1
120
2025年の挑戦 コーポレートエンジニアの技術広報/techpr5
nishiuma
0
150
あなたの知らないクラフトビールの世界
miura55
0
130
AWS re:Invent 2024 re:Cap Taipei (for Developer): New Launches that facilitate Developer Workflow and Continuous Innovation
dwchiang
0
170
Alignment and Autonomy in Cybozu - 300人の開発組織でアラインメントと自律性を両立させるアジャイルな組織運営 / RSGT2025
ama_ch
1
2.4k
AWSの生成AIサービス Amazon Bedrock入門!(2025年1月版)
minorun365
PRO
7
470
月間60万ユーザーを抱える 個人開発サービス「Walica」の 技術スタック変遷
miyachin
1
140
2024AWSで個人的にアツかったアップデート
nagisa53
1
110
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Gamification - CAS2011
davidbonilla
80
5.1k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Writing Fast Ruby
sferik
628
61k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Code Review Best Practice
trishagee
65
17k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Adopting Sorbet at Scale
ufuk
74
9.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
GraphQLとの向き合い方2022年版
quramy
44
13k
YesSQL, Process and Tooling at Scale
rocio
170
14k
Practical Orchestrator
shlominoach
186
10k
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Ͱָ͍͠ϒϥβΦʔτϝʔγϣϯΛʂ