読者です 読者をやめる 読者になる 読者になる

亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

Geb 公式チュートリアル読み解きシリーズ③: ページオブジェクトとモジュール #gebadvent

これは、Geb Advent Calendar 12/23 の記事です。

さて、前々回前回に続き、Gebの公式チュートリアル解説の続きです。

今回は、テストメソッドの中で使われているGebの機能、特にページオブジェクトについて見ていきましょう。

ページオブジェクト

ページオブジェクトとは

まずは、以下のコードを見てください。

when:
to GebishOrgHomePage
manualsMenu.links[0].click()

then:
at TheBookOfGebPage

これが、ページオブジェクトを利用したコードです。 一行ずつ見てみましょう。

まず、to GebishOrgHomePageGebishOrgHomePage へと移動します。

次に、 manualsMenu.links[0].click() で、リンクをクリックしているのですが、実はテストメソッドには manualsMenu の定義はありません。 実はto などでページ移動をした際には、そのページがもつ部品については、テストメソッドから直接アクセスできるようになっているのです。

最後のat TheBookOfGebPageアサーションの部分です。なんのアサーションをしているかというと、「TheBookOfGebPage にいまブラウザのページが表示されているかどうか」をアサーションしているのです。

このように、テストからは直接DOM要素を触るのではなく、「ページ」というオブジェクトを操作する形でテストを記述するのが、Gebの主要な書き方となります。

では、テストでこのように書くためには、どのように定義すればいいのでしょうか

ページオブジェクト定義の方法

その定義の部分が、以下になります。

class GebishOrgHomePage extends Page {

    static at = { title == "Geb - Very Groovy Browser Automation" }

    static content = {
        manualsMenu { $("#header-content ul li", 0).module(MenuModule) }
    }
}

Page を拡張したクラスとして定義することで、ページオブジェクトとして定義されているのですね。

ではまず、 to でページに移動するところはどうなっているのでしょう?こちらには、特にページの情報は書いていませんね・・・

実は、全ページに共通の baseUrlGebConfig.groovy に定義されています。

baseUrl = "http://gebish.org"

特にページ情報が書いていない場合は、 baseUrl のトップディレクトリに移動しますので、最初の to GebishOrgHomePage で遷移するのは、 baseUrl で定義されている http://gebish.org の部分となります。

では次に、manualsMenu.links[0].click() でアクセスされている manualsMenu についてです。 こちらについては、content プロパティの中に定義されていますね。

static content = {
    manualsMenu { $("#header-content ul li", 0).module(MenuModule) }
}

このように、content プロパティとして定義することで、ページが持つ部品を定義することができます。

.module(MenuModule) の部分は、MenuModule というモジュールオブジェクトとして定義するという意味ですが、これは後述します。

最後に at でのアサーションの部分です。こちらは対応するのは以下の部分になります。

static at = { title == "Geb - Very Groovy Browser Automation" }

at プロパティとして、そのページを表示した時に満たしておくべき条件を記述していきます。 例えば上記では、ページタイトルが "Geb - Very Groovy Browser Automation" なのかどうか、というのをそのページが満たすべき状態、としているのですね。

モジュールオブジェクト

ページオブジェクトがWebページそれぞれを抽象化したオブジェクトとなるのですが、メニューやヘッダー・フッターなど、ページをまたいで利用するような部品もあるでしょう。それらを共通化するために使われるのが、モジュールとなります。

この例では、manualsMenu { $("#header-content ul li", 0).module(MenuModule) } のようにメニュー部分をモジュールとして読み出しています。

こうすることで、テストメソッドから、manualsMenu.links[0].click() のように MenuModule が持つ links オブジェクトをりようすることができています。 では、どのようにモジュールオブジェクトを定義するのでしょうか。

定義の方法

モジュールの定義は以下のようになります。

class MenuModule extends Module {

    static content = {
        toggle { children("span") }
        links { $('.link-list li a') }
    }
}

Module クラスを拡張することで、モジュールオブジェクトとして利用できます。実は他の中身はページオブジェクトと大差はありません。 ここでは、 content プロパティを同様に定義しています。この中にある links を使っているのが、manualsMenu.links[0].click() の部分となります。

まとめ

ざっと見てきたように、このサンプルだけでも食べきれないくらい、Gebの面白い機能が詰まっています。 動く例題として、Gebの公式サンプルをしっかり読んでみるのは、Gebを使いこなす良い一歩になるのではと思います。

それでは、楽しいテストライフを!

Geb 公式チュートリアル読み解きシリーズ②: テストの書き方の基礎 #gebadvent

これは、Geb Advent Calendar 12/20 の記事です。

さて、前回書いた、Gebの公式チュートリアル解説の続きです。 今回は、テストメソッドの中身について、ざっと見ていきましょう。

見るべき場所は、geb-example-gradle/src/test/groovyディレクトリにある、以下のファイル群ですね。

  • GebishOrgHomePage.groovy
  • GebishOrgSpec.groovy
  • GebishOrgTest.groovy
  • MenuModule.groovy
  • TheBookOfGebPage.groovy

このファイル群をざっと分けると、

  • テストハーネスを利用したテスト本体
    • GebishOrgSpec.groovy (Spock)
    • GebishOrgTest.groovy (JUnit)
  • ページオブジェクト
    • GebishOrgHomePage.groovy
    • TheBookOfGebPage.groovy
  • モジュール
    • MenuModule.groovy

というような分類になります。 早速、それぞれを見てみましょう。

テストハーネス(フレームワーク

JUnit

まずは、JUnitを利用したテスト記述の部分です。 JUnitをGroovyから利用している状態ですね。

まず、最初の RunWith アノテーションで、実行するテストフレームワークを指定しています。 次に、 GebReportingTest を拡張したテストクラスを作成し、テストの記述を開始していますね。 あとは、通常の Test アノテーションを使っていけばいいわけです。

@RunWith(JUnit4)
class GebishOrgTest extends GebReportingTest {

    @Test
    void canGetToTheCurrentBookOfGeb() {
    }

}

この、 GebReportingTest は重要なテストクラスで、これを拡張することにより、各テストの最後でスクリーンショットを取るなど、Gebが提供する強力なレポート作成機能を利用することができます。

テストの中身自体は、以下のように assert 文で記述できますし、

 assert manualsMenu.links[0].text().endsWith("- CURRENT")

後ほど紹介するページオブジェクトの at アサーションも利用できます。

at TheBookOfGebPage

Spock

次は、Spockを利用したテスト記述です。 Gebを使うなら通常はこちらを利用することが多いですね。 Spockは、power assert をはじめ、強力なテスト記述能力をもったテストハーネスです。 詳しくは公式を色々眺めてみてください。

まずはフレーム部分から。

class GebishOrgSpec extends GebReportingSpec {

    def "can get to the current Book of Geb"() {
        when:

        and: 

        then:

        when:

        then:
    }
}

JUnitのようなアノテーションは不要で、 GebReportingSpec を拡張したクラスにメソッドを定義していくだけで、テスト記述として有効になっています。 あとは、Spockの特徴として、 given, when, thenステートメント利用した、振る舞い駆動的な書き方をしていきます。

あとは、アサーションとしては、

then: 
manualsMenu.links[0].text().endsWith("- CURRENT")

このように、 then の後に boolean を返す記述をすると、それだけでアサーションとみなしてくれます。

あとは、JUnitと同様、ページオブジェクトを利用した at アノテーションは勿論利用できます。

次回予告

本日はこれまで。 次回は、Gebのメイン機能であるページオブジェクトを中心に見ていきます!

小ネタ: Google SpreadSheetでコンテンツよりも高さの小さいセルを作る方法

Google Spreadsheet は地味に便利

神Excel にもなりかねない危険はあるものの、用法用量を守ればGoogle SpreadSheetはとても便利です。

何より素晴らしいのは、柔軟な共有気候ですね。この共同編集に慣れると、要件リストなんかをバーっと書いて行きたくなるんですよね。

地味に困るスプレッドシートの仕様

その時に、地味に困るのがGoogle SpreadSheetの仕様で、「内部コンテンツの高さより小さいセルは作れない」というものです。

例えば、以下のようなセルを作った場合。

f:id:posaunehm:20161219205951p:plain

残念ながら、この高さよりセルの高さを小さくすることはできません。 まぁ普通はそれで困りはしないのですが、、、中には概要的につらつらと書いておいて、詳細はセルの中身を見てね!みたいな感じで一覧性と詳細性を両立させたくなるんですよね。 *1

んで、これはもう決まった仕様のようで、2010年くらいから何人かが文句を言ってはいますが解消はされ無さそうです。

なぜか結合セルは特別扱い

とはいえ、やっぱり何とかはしたい。ではどうするか。 実は、この「コンテンツよりも小さいセルは作れない」という仕様、なぜか結合セルには適用されないのです。 従いまして、

f:id:posaunehm:20161219210418p:plain

この2つのセルを結合してやると・・・

f:id:posaunehm:20161219210519p:plain

このように、縦の高さを自在に変えることができます。

なんでこんな仕様なのかは謎なのですが、ちょっとした小ネタTipsでした。

*1:まぁそう考える時点でちょっとやばい気もするのですが・・・

(多分)全OS対応!Gebを3分でさくっと動かしてみよう。 #gebAdvent

まだ2日です(震え声)

というわけで、Geb Advent Calendar2日目です。

初日に、ざっと概要をまとめていただいたということで、今回は兎にも角にも動かしてみよう、というところから始めたいと思います!

用意するもの

  • Git(無くても何とかはなります)
  • JDK
  • お好きなCLIを叩ける端末
  • Firefox
  • Chrome

以上です!

Gebのようなシステムテストツールは、プログラマは勿論なのですが、テストエンジニアなどのちょっとプログラムの第一線ではない人も興味が有るところかと思います。 なので、まずさくっと動かして、「こんなことができるのか!」を実感していただければと思います。

幸いにして、Gebの公式サンプルは非常に充実しており、動かすまで後一歩のところまで既に仕立ててが済んでおります。

そんなわけで、やっていきましょう。

手順① ソースコードをもってくる

GitをCLIで叩ける人は、お好きなディレクトリでこちらを叩いちゃってくださいな。

git clone https://github.com/geb/geb-example-gradle.git

だめな人は、githubからダウンロードしてもOK。

手順② 実行

こちらもCLI叩ける人は、

cd geb-example-gradle
./gradlew test

こちらもわかんない人は、gradlew.batWindowsの人) gradlewWindows以外)を叩いてください。

うまく行けば、色んなものが諸々ダウンロードされて、ブラウザが立ち上がってテストが開始されるはずです。

テストも既に書かれており、Book of Gebのページの簡単なテストを行うようになっております。

手順③ 結果を確認

build/reports ディレクトリに、結果がHTMLとして格納されています。 たとえば、Chromeのテスト結果が見たければ、 build/reports/chromeTest/tests/index.html にテスト結果が格納されています。

f:id:posaunehm:20161203212055p:plain

また、build/reports/chromeTest/geb/GebishOrgSpec/001-001-can get to the current Book of Geb-end.html にはスクリーンショットがきちんと取られているのも確認できると思います。

(多分)次回予告

さて、ではこのサンプルの中で何が行われているのかを、次のAdvent Calendarで解説したいと思います。


追記

Windowではテストの開始はできますが、テスト自体は失敗しました(Windows 10 にて)。

Macのウィンドウ切り替えアプリ Contexts がすごくよい。あと、Microsoft MVP 更新しました。

Macのアプリ紹介とMS MVPの更新を同時にやるとか一体何やってるんですかね僕。

さて、とはいえ、Contextsです。

Contexts

Macは割とウィンドウ切り替えがうざい

Mac使っていて、意外と不便に感じるのが、「Alt + Tab」がないことです。 いや、まぁ本当のProgrammerなら (Emacs | Vim) の外から出ないで開発するんでしょうけれど、私はIDE大好き人間でして、、、必然ウィンドウ切り替えが頻発するのです。

あとは、やっぱりフルスクリーン派なので。 するとMacでWindowの切り替えをどうするかというと、

  1. 4本指横スワイプで切り替え
  2. 4本指上スワイプでWindow一覧出して切り替え
  3. Comamnd + Tab で切り替え

の3択なのですが、それぞれ問題があります。

  • 1 は遠くのウィンドウに移る時に、どこいったんだっけ!?と迷います
  • 2 は一覧開くのがまどろっこしい上に、なんだか超絶重いことが多いです
  • 3 は切り替えは早いのですが、なんと切り替えがアプリ単位で、ウィンドウ指定できないのです

Contextは求めていたもの

Contextの何がいいって、まず 3 をウィンドウ単位にしてくれる、というのが基本機能としてあります。 まずはこれ、これで十分。

だけれど、なんと他にも機能があります。

トラックパッドの上端をなぞると、、、

f:id:posaunehm:20161008111823p:plain

同じく一覧を出してくれます。この操作感が思いの外気持ちよく、割と使ってしまいます。

基本的にはテキストですけれど、スライド作っているときとかはトラックパッドにも手は伸びてますからね。

そんなこんなでContextsオススメです。

それからそれから

Microsoft MVP for Visual Studio and Development Technology 、再受賞させていただきました。 今年もシアトルにはいけないのですが、来年にはなんとか行きたい。そんな気分です。

2016年、今年もよろしくおねがいしまーす!

さて、あけおめです。

しばらくBlog書いていないので、なんか、感覚がつかめていませんが。。。

とりあえず、今年の目標でも書いておこうかなぁ。 その前に、去年を振り返るか。

2015年を振り返って

いやぁ、転職してしまいましたねぇ。。。自分でもこうなるなんてびっくりです。就活の時は、「一生勤められる会社を!」みたいな思考だったんですけどね。 やっぱり、外の勉強会に言って、もっと楽しい現場の話を聞いていると、ウズウズしちゃうんですねぇ。

転職して8ヶ月、なんだかんだで楽しくやってます。これまでやったこと無いことばかりで、やっぱ大変ですけどね!

2016年に向けて

やっぱり、僕フロント中心の設計が好きみたいです。というわけで、Fluxというか、モダンなWeb開発は何とかマスターしていきたいなーと思っています。

あとは、そろそろ、ぜんぜん違う言語を身に着けたいですね。Goとか、Rustとか、Elixirとか。

それから、ちょっと読書の年にはしたい。 かなり、危機感はあったりします。知識をもっと貯めねば。貯金がまだあるうちに。

おし、がんばろ。

今年もよろしくお願いします。

大きすぎるDiff、縮まったDiff、縮まないDiff

これは、 DevLOVE Advent Calendar 6日目の記事です。 id:itow_ponde さんから、受け取ります。

f:id:posaunehm:20151206235021j:plain (町で見つけた本当のAdvent)

さて、今回のテーマは「Diff」です。違いじゃなくて、「Diff」というのが、なんともDevLOVEらしいですねw

大きすぎるDiff

さて、思い返せば、もう恐らく5~6年前になりますか。僕が勉強会に出始めたのは。

その当時は、登壇している人々って、とんでもなく遠くに感じたものです。 言ってしまえば、「アイドルとそのファン」みたいな感じです。

自分が、登壇するとか、主催するとか、そっち側に行くとは思っても見ませんでした。 このまま、普通のエンジニアとして過ごしていくんだろーなー、と。

縮まったDiff

転機は最初の勉強会参加から1年後くらいに、突然やって来ました。 @toshiotm と(京都人同士なのに)岡山で出会い、勉強会を主催する意気投合をしたのです。

それは、「アジャイルサムライ京都道場」となり、「京都アジャイル勉強会」となって、今に至っています。 勉強会をしていく中で、 XP祭り関西やら、Agile Tour Osakaやら、システムテスト自動化カンファレンスやら、様々なイベントで登壇やスタッフなど前面に立つようになりました。

大きな舞台の前にも、何度か立ってきましたが、そこには支えてくれる仲間たちが、必ずいました。 周りのみんなに助けられて、時にはおだてられ、ノセられて、ちょっとずつ住む世界が変わってきました。

縮まらないDiff

そして、前に立つようになって分かったこと。それは、より具体的な差となって横たわる、すごい人々僕との間のDiffでした。

そこに足りないのは、技術的なスキルもあれば、人間的な大きさもあれば、実践してきた経験もある、というように見えています。 この差を、今度は埋めていかねばなりません。

大変です、大変ですけれど。

どうやって埋めればいいのか、のが見えていいないわけではありません。

バイナリレベルのDiffから、行単位のDiffが見えるくらいまで、見え方は変わってきてるんじゃないかと思ってます。

この見え方の違いそのものも、過去と今のDiffですね。 来年このDiffがどうなっているのか、楽しみです。