08 Jun 2014, 14:26

Windows環境でJenkinsからRSpecを実行するメモ

やりたいこと

Windows環境で、RSpecを夜中に連続実行したい。

cronを利用してもいいけど、Better cronな Jenkinsを使う方法を調べた。

なぜcronでなくてJenkins?

<div class="outline-text-3" id="text-1-1">
  <p>
    Jenkinsを利用する利点は、
  </p>

  <ul class="org-ul">
    <li>
      cron書式で設定Ok <ul class="org-ul">
        <li>
          <a href="http://futurismo.biz/archives/1490">cronとwatchrを使ってJenkinsからオレオレリポジトリ監視してみる | Futurismo</a>
        </li>
      </ul>
    </li>

    <li>
      グラフィカルな結果レポート
    </li>
    <li>
      ログが残せる
    </li>
  </ul>

  <p>
    ところかな。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://hazi.jp/2012-12/2203/">邪道Jenkins(スライド) | Hazi.log</a>
    </li>
    <li>
      <a href="http://image.slidesharecdn.com/jenkins-130706091448-phpapp02/95/slide-1-638.jpg?cb=1373120272">すごい cron ? &#8211; Jenkins 試した</a>
    </li>
  </ul>
</div></p>

むかしも挑戦したけど

<div class="outline-text-3" id="text-1-2">
  <p>
    今回はRCではなくて、WebDriver.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://futurismo.biz/archives/292">Selenium RCで自分のPCからテストケースを実行する | Futurismo</a>
    </li>
  </ul>
</div></p>

Environment

<div class="outline-text-3" id="text-1-3">
  <ul class="org-ul">
    <li>
      Windows 7 64bit
    </li>
    <li>
      Jenkins
    </li>
    <li>
      Ruby 2.0 p353
    </li>
    <li>
      RSpec 3.0
    </li>
  </ul>
</div></p>

Jenkins

Jenkins インストール

<div class="outline-text-3" id="text-2-1">
  <p>
    公式サイトからwarファイルをダウンロード。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://jenkins-ci.org/">http://jenkins-ci.org/</a> <ul class="org-ul">
        <li>
          jenkins.war
        </li>
      </ul>
    </li>
  </ul>
</div></p>

Jenkins起動

<div class="outline-text-3" id="text-2-2">
  <p>
    ワンラインで終わり。jenkins ワー!
  </p>

  <div class="org-src-container">
    <pre class="src src-language">C:\Jenkins&gt;java -jar jenkins.war

  <p>
    localhost の port 8080がデフォルトなのでアクセスする。おじさんがいれば成功。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://localhost:8080/">http://localhost:8080/</a>
    </li>
  </ul>

  <p>
    ほかにも、windowsインストーラからインストールする方法もある。むかし挑戦した。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://futurismo.biz/archives/299">JenkinsをWindowsPCにインストールする | Futurismo</a>
    </li>
  </ul>

  <p>
    ハマった思い出があるので、今回は挑戦しない。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://futurismo.biz/archives/331">WindowsバッチファイルをJenkinsで起動したらネットにアクセスできない | Futurismo</a>
    </li>
  </ul>
</div></p>

RSpecを連続実行

cron実行

<div class="outline-text-3" id="text-3-1">
  <p>
    新規ジョブを作成 > フリースタイル・プロジェクトのビルド > ビルド・トリガ > 定期的に実行を選択。
  </p>

  <p>
    5分に1度実行。
  </p>

  <div class="org-src-container">
    <pre class="src src-language">*/5 * * * *

  <p>
    ビルド > Windowsバッチコマンドの実行を選択。入力欄にrspecの実行を記入。
  </p>

  <div class="org-src-container">
    <pre class="src src-language">rspec "C:\cygwin\home\TSUNEMICHI\repo\selenium\selenium_spec.rb"

  <p>
    手動でビルドを実行してみて、起動が成功すればOK.
  </p>

  <div class="org-src-container">
    <pre class="src src-language">C:\Users\TSUNEMICHI\.jenkins\jobs\selenium-rspec\workspace&gt;rspec "C:\cygwin\home\TSUNEMICHI\repo\selenium\selenium_spec.rb" 

.

Finished in 18.02 seconds (files took 1.68 seconds to load) 1 example, 0 failures Finished: SUCCESS

テスト出力

<div class="outline-text-3" id="text-3-2">
  <p>
    せっかくなので、テスト結果の視覚化を。 ci_reporterというgemをつかうことで、RSpecの実行結果をJUnit形式のxmlに変換できる。
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://github.com/nicksieger/ci_reporter/">nicksieger/ci_reporter</a>
    </li>
  </ul>

  <p>
    とのことだったが、rspec3は古いフォーマッタに対応していないとのことなので、今回は保留で。
  </p>

  <p>
    ほかにも、実行時間の視覚化もできるようだ。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://sue445.hatenablog.com/entry/2013/03/17/015836">Jenkinsにスローテストのグラフを表示する &#8211; くりにっき</a>
    </li>
  </ul>
</div></p>

Special Thanks

RSpec

<div class="outline-text-3" id="text-4-1">
  <p>
    selenium-webdriverで、なぞのエラーがでて苦しむ。手動パッチをあてた。
  </p>

  <p>
    invalid byte sequence in UTF-8 (ArgumentError)
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://gosyujin.github.io/2013/03/18/selenium-firefox-loaderror/">Selenium WebDriverでFirefoxがロードできなくなった &#8211; kk_Atakaの日記@GitHub Pages</a>
    </li>
    <li>
      <a href="http://seesaawiki.jp/w/kou1okada/d/Cygwin%20-%20Ruby-1.9.3p327%20-%20win32/registry">Cygwin &#8211; Ruby-1.9.3p327 &#8211; win32/registry &#8211; PIB</a>
    </li>
  </ul>
</div></p>

Jenkins

<div class="outline-text-3" id="text-4-2">
  <ul class="org-ul">
    <li>
      <a href="http://codezine.jp/article/detail/7505">「Selenium2」テスト徹底活用! Jenkinsによる自動実行とSelenium Grid2による複数環境でのテスト (1/6):CodeZine</a>
    </li>
    <li>
      <a href="http://ozzy2010.blogspot.jp/2012/05/5web-jenkins-x-selenium.html">ソフトウェアテスト: 5分でできるWebテスト自動化 &#8211; Jenkins x Selenium</a>
    </li>
  </ul>
</div></p>

29 Mar 2014, 13:45

RSpecのモックについて調べてみた

今日は、RSpecにおけるモックオブジェクト技法について調べてみました。

モックオブジェクト技法とは

モックオブジェクト技法とは、

  • オブジェクト同士のコラボレーションに注目したテスト方法。
  • オブジェクトの状態よりも、オブジェクト同士のやりとりに注目する。
  • インターフェースのテスト、シーケンス図のテストに注力した技法。

詳しくは、この本がいい。

RSpecにおけるテストダブル

基本は以下。double()メソッドでテストダブルオブジェクトを生成。

テストダブルとは、本物のオブジェクトの代役をするオブジェクト。 映画の俳優のスタントマン。

大抵の場合は、テスト対象のオブジェクトの引数としてオブジェクトが渡される。


   real_foo = Foo.new
   double_foo = double('foo')

   # real_fooをつかわないで、double_fooを渡す
   hoge = Hoge.new(double_foo)

記法には2種類ある。

  • should記法 should_recieve …
  • expect記法 allow/expect

expect記法の方が、より英語らしく感じる。文脈に応じて使い分ける。

スタブ

<div class="outline-text-3" id="text-2-1">
  <p>
    スタブメソッドを指定すると、 テストダブルオブジェクトのメソッドから好きな値を戻り値として得ることができる。
  </p>

  <pre><code>

allow(double_foo).to receive(:call).and_return(“Hello”) double_foo.stub(:call).and_return(“Hello”)

モック

<div class="outline-text-3" id="text-2-2">
  <p>
    スタブに検証機能をつけたものをモックという。検証機能とは、
  </p>

  <ul class="org-ul">
    <li>
      期待された引数で呼ばれたか?
    </li>
    <li>
      期待された回数呼ばれたか?
    </li>
    <li>
      期待された順番で呼ばれたか?
    </li>
  </ul>

  <p>
    などなどを検証する。この機能が、モックオブジェクト技法。 オブジェクト同士のやりとりに注力したテストがかける。
  </p>

  <p>
    期待された値で呼ばれたかは、with()メソッドで検証する。
  </p>

  <pre><code>

expect(double_foo).to recieve(:call).and_return(“Hello”) double_foo.should_recieve(:call).and_return(“Hello”)

リファレンスとか

<div class="outline-text-3" id="text-2-3">
  <p>
    機能が細かいので、詳しくは以下のリンクを参照。
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://relishapp.com/rspec/rspec-mocks/v/3-0/docs">RSpec Mocks 3.0 &#8211; RSpec Mocks &#8211; RSpec &#8211; Relish</a>
    </li>
  </ul>

  <p>
    自分は、この書籍を見ながら勉強している。
  </p>

  <div class='amazlink-box' style='text-align:left;padding-bottom:20px;font-size:small;/zoom: 1;overflow: hidden;'>
    <div class='amazlink-list' style='clear: both;'>
      <div class='amazlink-image' style='float:left;margin:0px 12px 1px 0px;'>
        <a href='http://www.amazon.co.jp/RSpec-Book-Professional-Ruby-Series/dp/4798121932%3FSubscriptionId%3DAKIAJDINZW45GEGLXQQQ%26tag%3Dsleephacker-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798121932' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51-3T735zLL._SL160_.jpg' style='border: none;' /></a>
      </div>

      <div class='amazlink-info' style='height:160; margin-bottom: 10px'>
        <div class='amazlink-name' style='margin-bottom:10px;line-height:120%'>
          <a href='http://www.amazon.co.jp/RSpec-Book-Professional-Ruby-Series/dp/4798121932%3FSubscriptionId%3DAKIAJDINZW45GEGLXQQQ%26tag%3Dsleephacker-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798121932' rel='nofollow' target='_blank'>The RSpec Book (Professional Ruby Series)</a>
        </div>

        <div class='amazlink-powered' style='font-size:80%;margin-top:5px;line-height:120%'>
          posted with <a href='http://amazlink.keizoku.com/' title='アマゾンアフィリエイトリンク作成ツール' target='_blank'>amazlink</a> at 14.03.29
        </div>

        <div class='amazlink-detail'>
          David Chelimsky
        </div>

        <div class='amazlink-sub-info' style='float: left;'>
          <div class='amazlink-link' style='margin-top: 5px'>
            <img src='http://amazlink.fuyu.gs/icon_amazon.png' width='18' /><a href='http://www.amazon.co.jp/RSpec-Book-Professional-Ruby-Series/dp/4798121932%3FSubscriptionId%3DAKIAJDINZW45GEGLXQQQ%26tag%3Dsleephacker-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798121932' rel='nofollow' target='_blank'>Amazon</a>
          </div>
        </div>
      </div>
    </div>
  </div>
</div></p>

実装例

以前書いたステートパターンの実装に対してテストコードを書いてみました。

その他所感

<div class="outline-text-2" id="text-4">
  <p>
    Mock系のツールは、GoogleMockとJMockをつかったことがあるけれども、 RSpecの記法はとてもシンプルなので、気に入った。
  </p>

  <p>
    JavaやC++だと、いちいちインタフェースを定義しないといけない。
  </p>

  <p>
    Rubyでは、それがないの
  </p></p>
</div></p>

22 Mar 2014, 09:40

RSpecのテスト結果をCSVで出力する

テスト項目表をExcelで作成する必要がある。

RSpecの実行結果をExcelにコピペするための楽な方法を考えてみたメモです。

RSpecのカスタムフォーマット

RSpecには、カスタムフォーマットという機能がある。

出力のフォーマットを自分でカスタマイズするための拡張ボイント。

この機能を利用して、CSVフォーマットでテスト結果を出力してみる。

前提条件

テスト項目表には、最低限以下のような項目を書く必要があると仮定する。

  • テスト番号
  • 大項目
  • 中項目
  • 小項目
  • 期待結果
  • 実施日

これらをRSpecのテストコードに埋め込む。

実装

メタデータをspecに埋め込む

<div class="outline-text-3" id="text-3-1">
  <p>
    RSpecのメタデータに、項目の情報を残す。デフォルトのメタデータは以下で見ることができる。
  </p>

  <pre><code>

it “テストです” do # すべての要素をみる example.metadata

# 特定の項目を見る
example.metadata[:description_args]

end

  <p>
    自分でメタデータを定義するには、 it &#8221; &#8220;, のあとに ハッシュ形式で書く。
  </p>

  <pre><code>

it “ほげほげであること” , :no => “1”, :date => “2014/03/22” do end

フォーマットスクリプトを作成する

<div class="outline-text-3" id="text-3-2">
  <p>
    フォーマットスクリプトは、デフォルトのフォーマッタを継承して作成する。
  </p>

  <p>
    必要なメソッドのみをカスタマイズする。
  </p>

  <ul class="org-ul">
    <li>
      initialise(output) はじめに呼ばれる
    </li>
    <li>
      example_started(example) サンプル開始時に呼ばれる
    </li>
    <li>
      example_passed(example) テスト成功時に呼ばれる
    </li>
    <li>
      example_passed(example) テスト失敗時に呼ばれる
    </li>
    <li>
      close() 最後に呼ばれる
    </li>
  </ul>

  <p>
    ほかにも、いろいろとメソッドがあるので、公式のドキュメント参照。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://rubydoc.info/gems/rspec-core/2.6.4/RSpec/Core/Formatters/DocumentationFormatter">Class: RSpec::Core::Formatters::DocumentationFormatter — Documentation for rspec-core (2.6.4)</a>
    </li>
  </ul>

  <p>
    今回は、Documentationフォーマットを継承する。
  </p>

  <pre><code>

def initialize(output) super(output) @results = Array.new end

def example_passed(example) super(example) result = createResult(example) result[:result] = “OK” @results << result end

def example_failed(example) super(example) result = createResult(example) result[:result] = “NG” @results << result end

def close output_csv() end

コマンド実行

<div class="outline-text-3" id="text-3-3">
  <p>
    コンソールから以下を叩く。
  </p>

  <pre><code>

rspec -I ../ -I . -r csv_formatter.rb csv_format_spec.rb -f CsvFormatter

  <p>
    -f のあとに自分がつくったフォーマッタのクラス名を渡す。
  </p>

  <p>
    -r のあとに自分がつくったスクリプトを渡す。
  </p></p>
</div></p>

コード

21 Feb 2014, 15:19

EmacsでRSpec環境をめちゃガチャパワーアップしたまとめ

はじめに

Emacs環境でのRSpec環境を強化しようと思った。

結果的にはEmacsうんぬんとあまり関係なく、 尻すぼみになってしまったけど、まあいいや。

これは前回の記事の続編。

環境

<div class="outline-text-3" id="text-1-1">
  <ul class="org-ul">
    <li>
      Emacs 24.3.1
    </li>
    <li>
      Ruby 2.1.0
    </li>
  </ul>

  <p>
    [toc]
  </p></p>
</div></p>

rspec-mode

まずは定番のrspec-modeを導入。

(require 'rspec-mode)
(eval-after-load 'rspec-mode
  '(rspec-install-snippets))

RSpec関係のショートカットを実行すると Could not determine the project root.とでてしまう。

以下を参考にして、空Rakefileを作成する。おまじないも書く。

(custom-set-variables '(rspec-use-rake-flag nil))
(custom-set-faces )

これでショートカットが動く。

C-c , v RSpec実行
C-c , s カ-ソルが当たっているサンプルを実行
C-c , t Specとソースを切り替える

rspecを実行したときのバッファが主張しすぎだと思う場合は、popwinで調整。

(push '("*rspec-compilation*" :regexp t) popwin:special-display-config)

yasnippet

rspec用の yasnippetを導入する。これで入力が楽になる。

git clone git@github.com:gary/yasnippets-rspec.git

とりあえず githubから落としてきて、ruby-modeのフォルダに突っ込んだ。 なんか、やりかたが違う気がするけど。。。

auto-test

保存時にRSpecを自動で動かすためのツール。

まずは、autotestを入れる。

gem install ZenTest

libにテスト対象コード、specにテストコードを入れる。 プロジェクトルートにautotestというディレクトリをつくり、 そのなかにdiscover.rbを作成。

プロジェクトルートで autotestを起動。テストを編集して、勝手にテストが走れば成功。

mkdir autotest
echo 'Autotest.add_discovery { "rspec2" }' > autotest/discover.rb
autotest

カラー表示

<div class="outline-text-4" id="text-4-0-1">
  <p>
    ~/.rspecをつくると、rspecがカラーになる。
  </p>

  <pre><code>/.rspec

–format nested –color

デスクトップ通知

<div class="outline-text-4" id="text-4-0-2">
  <p>
    autotest/discover.rbに以下を書くと、テストの成功時、失敗時のアクションが定義できる。
  </p>

  <pre><code>Autotest.add_hook :green do

end

Autotest.add_hook :red do end

  <p>
    たとえばLinux Mintだと、notify-sendコマンドを使えばデスクトップ通知が可能だ。notify-sendのインストールは以下の過去記事参照。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://futurismo.biz/archives/2160">GTDの規律に従い生産性Up!!3分後にデスクトップ通知と音を鳴らすワンラインスクリプト(Linux) | Futurismo</a>
    </li>
  </ul>

  <p>
    アイコンはフリー素材からひろった。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://www.iconarchive.com/">http://www.iconarchive.com/</a>
    </li>
  </ul>

  <pre><code>wget http://icons.iconarchive.com/icons/hopstarter/sleek-xp-basic/256/Close-2-icon.png

wget http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/256/Actions-dialog-ok-apply-icon.png

  <p>
    めっちゃくちゃいい感じに表示される!これはテンションアップ。
  </p>

  <pre><code>Autotest.add_discovery { "rspec2" }

Autotest.add_hook :green do system ‘notify-send -i ~/Pictures/tdd/Actions-dialog-ok-apply-icon.png OK’ end

Autotest.add_hook :red do system ‘notify-send -i ~/Pictures/tdd/Close-2-icon.png Error’ end

Emacsで動かす

<div class="outline-text-4" id="text-4-0-3">
  <p>
    autotestをEmacs上で動かす elispもある。
  </p>

  <pre><code>wget http://www.emacswiki.org/cgi-bin/emacs/download/autotest.el

  <p>
    だがしかし、自分の環境ではうまくうごかなかった。。。 emacs上でshellをたちあげて、autotestを実行すると同じことができる。
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://github.com/dchelimsky/rspec/wiki/autotest-integration">Autotest Integration · dchelimsky/rspec Wiki</a>
    </li>
    <li>
      <a href="http://tmtms.hatenablog.com/entry/20110101/rspec">RSpec で autotest &#8211; @tmtms のメモ</a>
    </li>
    <li>
      <a href="http://d.hatena.ne.jp/amacou/20080908/1220893836">autotest,RSpec,Emacsで快適テスト環境をつくる(あとGrowlも) &#8211; AorBorF</a>
    </li>
  </ul>
</div></p>

rspec-kickstarter

RSpecのテストコードを自動生成するツール。以下の記事を参照。

simplecov

RSpecと組み合わせてカバレッジをとるツール。

gem install simplecov 

spec_helper.rbに以下の2行を追加するだけ。すごくsimple!

require 'simplecov'
SimpleCov.start

ただし、autotestと一緒に利用すると、無限ループになるという悲しいことになった。注意。