Thucydidesをためす

Jenkins User Conferenceのタイムテーブルで存在を知って,ちょっと気になってたThucydidesを試したよ。
satta-2 : Jenkinsによる自動受け入れテストから継続的デリバリーまで


Thucydides,まず読めないw。ググってみたらギリシャの歴史家のお名前で「wikipedia:トゥキディデス」と読むらしい。作者は「Java Power Tools(asin:0596527934)」や「Jenkins: The Definitive Guide(asin:1449305350)」のJohn Smartさん。
GitHub - thucydides-webtests/thucydides: Thucydides is a tool that lets you use WebDriver-based unit or BDD tests to write more flexible and more reusable WebDriver-based tests, and also to generate documentation about your acceptance tests, including a narrative description of test, along with the corresponding screen shots, and also high-level summaries and aggregations of the test results
http://www.wakaleo.com/resources/thucydides-automated-testing-library
http://www.wakaleo.com/thucydides/


何やるツールかというと「ユーザ受入テスト(UAT)」をしてくれる。ざっと特徴を挙げると,

  • Mavenプラグインとして提供されていて,
  • JUnitのTestSuite的なモノ(Application)にユーザ要求を定義して,
  • ユーザ要求に対応するテストシナリオをeasyb(もしくはJUnit)で記述
  • テストシナリオ中の個々のテスト手順をStepsというクラスに定義し,
  • そのStepsからSeleniumのWebDriverを用いたWeb画面に相当するクラスを呼び出す。

って感じ(ワケワカラン)。「ユーザ受入テスト」だと範囲が広すぎてアレだけど,どうやらSelenium2(WebDriver)を利用して,もうちょっとユーザフレンドリなテストシナリオを書いて実行するテストツールと言った感じ。
特徴的な機能は,先ほどのStepsであるおまじない(@Stepアノテーションを付与)をすると,その時のブラウザのスクリーンショットを撮りながらテストを進めてくれる。当然,レポートにはそのスクリーンショットが添付される。


スゴそう&面白そうなんで試してみたんだけど,やっぱり大変w で,まあ仕事で使う事はないだろうなってのが今のところの結論。そうは言っても保守的な仕事環境じゃ難しいという意味なので,興味のある人はバトンを引き継いで欲しい。:-)

以下,備忘録を兼ねた簡単な使い方メモ。

プロジェクトの作り方

Mavenのプロジェクトとして作成する。UATはプロダクトコードとは独立して作成できるので,プロダクトコードのプロジェクトがどんな形態だとしても,こっちが影響受けることもない(し,向こうも同等)。

$ mvn archetype:generate


でプロジェクトを作成して,archetypeに"net.thucydides.thucydides-easyb-archetype"を選ぶ。いろいろ細かい事はこちらを参照のこと。
http://www.wakaleo.com/thucydides/_creating_a_new_thucydides_project.html

テストの構成

だいたいこんな構成で,Applicationってのが,TestSuite的というかテストの目次みたいなものになってる。


この @Feature ってのが,テストの括りみたいなもんんで,そん中の内部クラスに意味がある様子。というか,この内部クラスが,個々のテストシナリオに相当する。

public class Application {
    @Feature
    public class Search {
        public class SearchByKeyword {}
        public class SearchByKeyword_Ja {}
    }
    @Feature
    public class Search2 {
        public class SearchByBlogEntry {}
    }
}


テストシナリオの実体は別に記述する。JUnitかeasybか(他にもJBehaveも?)選べるみたい。とりあえず,easyb使ってみたけど,おまじないがいろいろあるみたいなので,素直にJUnit使っとけばよかったかなとも思わなくもなし。:-P

package com.mycompany

import com.mycompany.steps.BuildShokuninSteps
import com.mycompany.requirements.Application.Search2.SearchByBlogEntry

using "thucydides"

thucydides.uses_default_base_url "http://build-shokunin.org/"
thucydides.uses_steps_from BuildShokuninSteps
thucydides.tests_story SearchByBlogEntry

scenario "Looking up the keyword of 'JUC'", {
  given "BuildShokuninのトップページに訪れる", {
    build_shokunin.is_the_home_page()
  }
  when "キーワード 'JUC' でブログエントリを検索する", {
    build_shokunin.looks_for "JUC"
  }
}


'thucydides.uses_steps_from'とか'thucydides.tests_story'ってのがおまじないっぽい(あまり良くわかってない)。あと,scenario に日本語使ったらコケた。


テストシナリオ中に出てくる,

  build_shokunin.is_the_home_page()

なのがStepsクラス。たとえば,上記の実体は BuildShokuninSteps でJavaで書く。どうも,Stepsクラスから"Steps"を抜いて,キャメルケースをスネークケースに暗黙的に変換してるっぽい。なんで,

BuildShokuninSteps => build_shokunin

となるみたい(たぶん...。


そのStepsクラスはこんな感じ。

public class BuildShokuninSteps extends ScenarioSteps {
    public BuildShokuninSteps(Pages pages) {
        super(pages);
    }

    private BuildShokuninPage onBuildShokuninPage() {
        return getPages().currentPageAt(BuildShokuninPage.class);
    }

    @Step
    public void is_the_home_page() {
        onBuildShokuninPage().open();
    }

    @Step
    public void looks_for(String keyword) {
        onBuildShokuninPage().enter_keywords(keyword);
        onBuildShokuninPage().lookup_terms();
    }
}


見ての通り「手順」を記述してく。どうやら @Stepアノテーション に意味があるらしく,このアノテーションが付いたステップを実行するともれなくスクリーンショットを取ってくれるらしい。なので,ステップの内部処理(テストシナリオから直接呼ばれないメソッド)も @Stepアノテーション付けとくと,スクリーンショットの取得対象になる。


んで,ここではテストしたいWebページに相当するPageオブジェクトてのが必要になるらしく,それはそれで別途定義する(だんだんイヤになってきたw

@DefaultUrl("http://build-shokunin.org/")
public class BuildShokuninPage extends PageObject {
    @FindBy(id = "searchbox")
    private WebElement searchBox;

    @FindBy(name = "s")
    private WebElement searchButton;

    public BuildShokuninPage(WebDriver driver) {
        super(driver);
    }

    public void enter_keywords(String keyword) {
        element(searchBox).type(keyword);
    }

    public void lookup_terms() {
        element(searchButton).click();
    }
}


ここでやっとこSeleniumのWebDriverが登場する。つまり,テストしたいWebサイトのWebページ分のPageオブジェクトを用意して/それを意味ある操作にまとめたStepsクラスを作り/ユーザ要求に相当するテストシナリオから利用する,ようだ。


だれがどこを分担するのか分からんけど,これ使ってマジメにテストしようと思ったら,結構な苦労してPageオブジェクトを作る事になるんじゃ無かろうか?などと余計なことを考えてしまった。
逆にある程度,ルールまたは使うWebフレームワークが決まってしまえば,Pageオブジェクトを自動生成することはできそうな予感もする。
なので,Thucydidesを使う上での最大の障壁はPageオブジェクトの準備なのかなって思った次第。

テストの実行

これでテスト実行:

$ mvn test thucydides:aggregate


これでレポート作成(レポートは './target/site/thucydides'にできる):

$ mvn thucydides:thucydides


あとテストで使うブラウザはpom.xmlに指定する。

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <thucydides.version>0.7.10</thucydides.version>
    <webdriver.driver>iexplorer</webdriver.driver>
  </properties>

その他

残念な事が2つほど。1つは,テストケースに日本語使うとレポートで中途半端に文字化けする。もう1つは,スクリーンショットが途中までしか撮れない。どうもオートスクロールさせてページ全体のスクリーンショットを撮ろうとして,思い通りに行ってない感じ。テストで使ったのがIE6だったので,それが原因かも知れない...。


なんとか手軽にユーザ受入テストの自動化できないかなーと思うのだけれど,なかなかピタっとはまるモノはないねー。:-)
https://github.com/masanobuimai/thucydides-sample