oinume journal

Scratchpad of what I learned

WebアプリケーションのE2EテストをGoで書く

これはGo Advent Calendar 2016の18日目の記事です。今回はGoでE2Eテストを行うためのライブラリagoutiについて書きます。

GoでE2Eテストを書く理由

WebアプリケーションのサーバーサイドをGoで書いている場合、GoでE2Eテストを書くメリットとして

  • JavaScriptが得意ではないエンジニア(自分)でもE2Eテストがガリガリかける
  • E2Eテスト実行時のカバレッジが取れる=サーバーのコードのどこを通ったかがわかる

があると思っている。特に2番めの理由が大事で、「E2Eテストを全部回した結果、サーバーのこの部分のコードは通っている」とわかるのはけっこう大きなメリットなのではないかと。どこがテストされている・いないを把握することで、「ここはE2Eテストだと難しいからユニットテストでカバーしよう」というような戦法が取りやすいと思う。

じゃあ具体的にGoでどうやってE2Eテストを書くのか、ということを次に説明する。

Go製WebDriverクライアントagouti

GoにはagoutiというSelenium WebDriverのクライアントがあるので、今回はこれを使う。agouti自体は単にWebブラウザを操作するライブラリなので、あわせてChromeDriverなどをインストールする必要がある。MacにChromeDriverをインストールするのはHomebrewでbrew install chromedriverしてインストールするのが楽で、それ以外のOSではChromeDriverのサイトからダウンロードしてすればOK。

一例として、下記のようなagoutiを使うGoのコードを書いて動かすと、Chromeが起動して https://ifconfig.co/ のページが表示されて5秒スリープする。

    webDriver := agouti.ChromeDriver() // ChromeDriverを使う
    if err := webDriver.Start(); err != nil {
        return err
    }
    defer webDriver.Stop()

    page, err := webDriver.NewPage()
    if err != nil {
        t.Error(err)
    }
    // Navigateで指定したURLにアクセスする
    if err := page.Navigate("https://ifconfig.co/"); err != nil {
        t.Error(err)
    }
    time.Sleep(5 * time.Second)

agoutiでWebアプリケーションをテストする

もう少し実践的な例として、フォームに入力された値を表示する簡単なWebアプリをテストするケースを考える。ディレクトリ構成は

  • cmd: サーバーの実行ファイル用
  • app: Webアプリケーションの本体
  • e2e: E2Eテスト置き場

という感じになっていて、全てのコードはgo-e2e-test-sampleのリポジトリに上げてある。

この、単にフォームで送信された名前を表示するだけのWebアプリケーションのコードはこんな感じ。

そして、E2Eテストのコードはこんな感じ。TestIndex/にアクセスしている。

ポイントとしては

  • testMainでサーバーとChromeDriverを起動
  • TestIndex関数内でwebDriver.NewPageでPageを生成し、Page.Navigateで起動したサーバーのURLにアクセス
  • Page.FindByXPathでHTMLの要素を検索してformをSubmit

というような流れになっている。なお、今回はXPathを使ってHTMLの要素を検索しているが、CSS Selectorを使うFindなんかもある。詳しくはgodocを見れば詳しく書いてある。

そして、このe2e_test.gogo testコマンドで実行すると、Chromeが立ち上がってテストが実行される。

$ go test -v ./e2e

カバレッジを取ってみる

では次にカバレッジを取って、どの部分がE2Eテストによって実行されているのかを調べてみる。go testの引数に-coverpkg-coverprofileをつけて実行する。

$ go test -v -cover -coverpkg=./app -coverprofile=cover.out ./e2e

これでcover.outにカバレッジのためのファイルができるので、go tool coverでHTMLとして表示してみる。

$ go tool cover  -html cover.out

ブラウザが立ち上がって下記のような画面が表示されるので、今回のE2Eテストで実行されているコードがひと目でわかる。

go_tool_cover_html

まとめ

  • agouti便利
  • go testでE2Eテストを実行できるようにしておくとgo tool coverなどのGoエコシステムがそのまま使える