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
410
横浜タネマキで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.4k
Make Work Visible in Agile2018 #LINE_DM
poohsunny
1
440
タウンワークをドライブさせるためになんちゃってアジャイルをやめた話 #devsumi #devsumiB / devsumi2018
poohsunny
30
46k
1 test 1 assert ?
poohsunny
0
440
XUTPから学ぶ記述性の高いユニットテスト 〜俺たちを助けるユニットテストへ〜 / xUTP in #xpjug
poohsunny
4
5.3k
XCUITestする時のTIPs 〜あなたを助けるXCUITestへ〜
poohsunny
0
3.1k
コードに思いが伝わる
poohsunny
0
310
The "yummy" licenses.
poohsunny
0
190
ブラウザテストをサクサク自動化するためのGeb実践入門 #jjug_ccc
poohsunny
21
7.1k
Other Decks in Technology
See All in Technology
ヘンリー会社紹介資料(エンジニア向け) / company deck for engineer
henryofficial
0
220
AI時代の開発を加速する組織づくり - ブログでは書けなかったリアル
hiro8ma
1
190
サイバーエージェント流クラウドコスト削減施策「みんなで金塊堀太郎」
kurochan
4
2.2k
20251007: What happens when multi-agent systems become larger? (CyberAgent, Inc)
ornew
1
510
CREが作る自己解決サイクルSlackワークフローに組み込んだAIによる社内ヘルプデスク改革 #cre_meetup
bengo4com
0
160
WEBサービスを成り立たせるAWSサービス
takano0131
1
200
NLPコロキウム20251022_超効率化への挑戦: LLM 1bit量子化のロードマップ
yumaichikawa
1
160
ソースを読むプロセスの例
sat
PRO
15
9.6k
ハノーファーメッセ2025で見た生成AI活用ユースケース.pdf
hamadakoji
0
280
私のMCPの使い方
tsubakimoto_s
0
120
混合雲環境整合異質工作流程工具運行關鍵業務 Job 的經驗分享
yaosiang
0
120
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
8.9k
Featured
See All Featured
Speed Design
sergeychernyshev
32
1.2k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
A Tale of Four Properties
chriscoyier
161
23k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
10
880
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.7k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
Writing Fast Ruby
sferik
629
62k
Keith and Marios Guide to Fast Websites
keithpitt
411
23k
How to Think Like a Performance Engineer
csswizardry
27
2.1k
KATA
mclloyd
PRO
32
15k
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Ͱָ͍͠ϒϥβΦʔτϝʔγϣϯΛʂ