Hatena::Grouprubyist

うんたらかんたらRuby RSSフィード

2010-04-13autospecの結果をgrowlで通知

autospecの結果をgrowlで通知

| autospecの結果をgrowlで通知 - うんたらかんたらRuby を含むブックマーク はてなブックマーク - autospecの結果をgrowlで通知 - うんたらかんたらRuby

インストール

growl

こちらからGrowl


autotest-growl

ZenTestからautotest及びautotest用のモジュールが

それぞれ別gemになった模様。

(ZenTest入れてない人は、gem install ZenTestで入れてください。)

$ sudo gem install autotest-growl

In order to use autotest-growl, the following line has to be added to your
~/.autotest file:

require 'autotest/growl'

Make sure the notification service installed on your computer:

http://growl.info (Growl for Mac OS X)
http://growlforwindows.com (Growl for Windows)
http://www.galago-project.org (libnotify for Linux)

If Growl notifications are not always displayed, take a look at the README
for assistance.

For more information, feedback and bug submissions, please visit:

http://www.bitcetera.com/products/autotest-growl

If you like this gem, please consider to recommend me on Working with
Rails, thank you!

http://workingwithrails.com/recommendation/new/person/11706-sven-schwyn

+-------------------------------------------------------------------------+
| UPGRADING USERS please take a look at the README now for important news |
| related to modified dependencies since 0.1.x and Rails compatibility.   |
+-------------------------------------------------------------------------+

上記は、インストール時に表示されるメッセージですが

なんとwindowsgrowlも開発されているというメッセージが。

近々使ってみたいと思います。


設定

メッセージ通り

~/.autotestを作成し下記を保存します。

require 'autotest/growl'


稼働確認

#~/.autotest
require 'autotest/growl'

autotest(autospec)を実行。

f:id:rochefort:20100413080951p:image

f:id:rochefort:20100413080952p:image

こ、これは楽しい。


画像は

下記に格納されています。

/opt/local/lib/ruby/gems/1.8/gems/autotest-growl-0.2.3/img/ruby


あと.autotestのsampleは下記。

/opt/local/lib/ruby/gems/1.8/gems/ZenTest-4.3.1/example_dot_autotest.rb


補足

以前は、growlnotify が必要なようでしたが

現在は無しでも動きます。(素晴らしい!)

(探せば結構情報がありますが、旧バージョンの情報が多いようです。)

masashi_fujimasashi_fuji2010/11/03 13:07autotest + growlに関しては古い記事が多くて混乱していましたが、この記事のおかげですんなりと環境構築できました。ありがとうございました。

rochefortrochefort2010/11/03 16:15お役に立ててよかったです。
ruby / rails 周りは進化が早いですからね〜。readmeやらdocumentは必ず読むようにしてます。

2010-04-12autospecでテストを自動化

autospecでテストを自動化

| autospecでテストを自動化 - うんたらかんたらRuby を含むブックマーク はてなブックマーク - autospecでテストを自動化 - うんたらかんたらRuby

zen testのautotestという機能を使うと

テストコードを修正して保存する度に

自動的にテストが実行されます。


↓の実演動画内で稼働していて、便利そうだなと思ったので

使ってみました。

(growlでの通知はまた次回)

簡単で便利で最高です。

スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby - Rubyist


install

$ sudo gem install ZenTest


autospec

rspec入れるとついてくるautospecコマンドを実行すれば

自動でテストされるようになります。


$ autospec
loading autotest/rspec
/opt/local/bin/ruby /Users/rochefort/.gem/ruby/1.8/gems/rspec-1.3.0/bin/spec --autospec /Users/rochefort/work/ruby/rspec/bowling/spec/game_spec.rb 
.........

Finished in 0.020817 seconds

9 examples, 0 failures

rspecのオプションは

spec.optsに書いておけばOKです。

#spec.opts
--colour
--format specdoc

spec/game_spec.rbを更新する度に、テストが自動実行される

$ autospec
loading autotest/rspec
/opt/local/bin/ruby /Users/rochefort/.gem/ruby/1.8/gems/rspec-1.3.0/bin/spec --autospec /Users/rochefort/work/ruby/rspec/bowling/spec/game_spec.rb -O spec/spec.opts 

Game すべてガターの場合
- スコアは0点

Game すべて1ピンの場合
- スコアは20点

Game ストライクの場合
- スコアは24点

Game パーフェクトゲーム場合
- スコアは300点

Game Game スペアの場合
- スコアは21点

Game Uncle Bobの受け入れゲームの場合
- スコアは133点

Game 10フレーム目の場合 1投目がストライクの場合
- スコアは17点

Game 10フレーム目の場合 2投目がストライクの場合
- スコアは14点

Game 10フレーム目の場合 スペアの場合
- スコアは14点

Finished in 0.024603 seconds

9 examples, 0 failures

終了は

ctrl + C を2回

トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100412

2010-04-11RE: スはスペックのス~RSpecによるテスト駆動開発の実演

RE: スはスペックのス~RSpecによるテスト駆動開発の実演

| RE: スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby を含むブックマーク はてなブックマーク - RE: スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby

20110216追記

すいません、修正後ソースが見えなくなってました。



前回の続き(スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby - Rubyist)。

テストコードをリファクタリングしてみた。

余談だけど、gitで随時コミットするのがいいと思った。


describeのnest

全てGameに対するテストなのでnestしてみた。

対象を説明する時は describe, 状況を説明する時は context。


beforeを一纏め

#修正前抜粋
  context "すべてガターの場合" do 
    before do
      @game = Game.new
      20.times { roll_gutter }
    end

    it "スコアは0点" do
      @game.score.should == 0
    end
  end

beforeセクションは、Game.newが重複しまくっているので

これを一纏めに。

beforeセクションの内容は、テストの準備という位置づけの方が

いいような気がする(あとでもう少し調べる)ので

各beforeセクションで実行しているテスト条件の設定をitセクションへ移動してみた。


subjectを設定

#修正前
@game.score.should == 0

全テストで比較する対象が@game.scoreなので

subjectを設定

#修正後
  subject{ @game.score }


  should == 0

contextをさらにnest

(ここは余計かも)group化した方が見やすいかもと思ったので

10フレーム目の3つのテストを

contextで更にnestしてみた。

#修正後
  context "10フレーム目の場合" do
    context "1投目がストライクの場合" do
      it "スコアは17点" do
        18.times { roll_gutter }
        roll_strike
        @game.roll(3)
        @game.roll(4) # 17
        should == 17
      end
    end

    context "2投目がストライクの場合" do
      it "スコアは14点" do
        19.times { roll_gutter }
        roll_strike
        @game.roll(4) # 14
        should == 14
      end
    end

    context "スペアの場合" do
      it "スコアは14点" do
        18.times { roll_gutter }
        roll_spare
        @game.roll(4) # 14
        @game.score.should == 14
      end
    end
  end

修正前全部

require File.expand_path(File.dirname(__FILE__) + "/../game.rb")
#[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6] => 133

describe Game, "すべてガターの場合" do
  before do
    @game = Game.new
    20.times { roll_gutter }
  end

  it "スコアは0点" do
    @game.score.should == 0
  end
end

describe Game, "すべて1ピンの場合" do
  before do
    @game = Game.new
    20.times { @game.roll(1) }
  end

  it "スコアは20点" do
    @game.score.should == 20
  end
end

describe Game, "ストライクの場合" do
  before do
    @game = Game.new
    roll_strike
    @game.roll(3)
    @game.roll(4)
    18.times { roll_gutter }
  end

  it "スコアは24点" do
    @game.score.should == 24
  end
end

describe Game, "パーフェクトゲーム場合" do
  before do
    @game = Game.new
    12.times { roll_strike }
  end

  it "スコアは300点" do
    @game.score.should == 300
  end
end

describe Game, "スペアの場合" do
  before do
    @game = Game.new
    roll_spare
    @game.roll(4)
    @game.roll(3) # 21
    16.times { roll_gutter }
  end

  it "スコアは21点" do
    @game.score.should == 21
  end
end

#[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6] => 133
describe Game, "Uncle Bobの受け入れゲームの場合" do
  before do
    @game = Game.new
    [1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6].each {|pin| @game.roll pin}
  end

  it "スコアは133点" do
    @game.score.should == 133
  end
end

describe Game, "10フレーム目の1投目がストライクの場合" do
  before do
    @game = Game.new
    18.times { roll_gutter }
    roll_strike
    @game.roll(3)
    @game.roll(4) # 17
  end

  it "スコアは17点" do
    @game.score.should == 17
  end
end

describe Game, "10フレーム目の2投目がストライクの場合" do
  before do
    @game = Game.new
    19.times { roll_gutter }
    roll_strike
    @game.roll(4) # 14
  end

  it "スコアは14点" do
    @game.score.should == 14
  end
end

describe Game, "10フレーム目でスペアの場合" do
  before do
    @game = Game.new
    18.times { roll_gutter }
    roll_spare
    @game.roll(4) # 14
  end

  it "スコアは14点" do
    @game.score.should == 14
  end
end

private
def roll_gutter
  @game.roll(0)
end

def roll_strike
  @game.roll(10)
end

def roll_spare
  @game.roll(5)
  @game.roll(5)
end

修正後全部

多少見やすくなったかな。

require File.expand_path(File.dirname(__FILE__) + "/../game.rb")
#require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
#[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6] => 133

describe Game do
  before do
    @game = Game.new
  end

  subject{ @game.score }

  context "すべてガターの場合" do
    it "スコアは0点" do
      20.times { roll_gutter }
      should == 0
    end
  end

  context "すべて1ピンの場合" do
    it "スコアは20点" do
      20.times { @game.roll(1) }
      should == 20
    end
  end

  context "ストライクの場合" do
    it "スコアは24点" do
      roll_strike
      @game.roll(3)
      @game.roll(4)
      18.times { roll_gutter }
      should == 24
    end
  end

  context "パーフェクトゲーム場合" do
    it "スコアは300点" do
      12.times { roll_strike }
      should == 300
    end
  end

  context Game, "スペアの場合" do
    it "スコアは21点" do
      roll_spare
      @game.roll(4)
      @game.roll(3) # 21
      16.times { roll_gutter }
      should == 21
    end
  end

  #[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6] => 133
  context "Uncle Bobの受け入れゲームの場合" do
    it "スコアは133点" do
      [1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6].each {|pin| @game.roll pin}
      should == 133
    end
  end

  context "10フレーム目の場合" do
    context "1投目がストライクの場合" do
      it "スコアは17点" do
        18.times { roll_gutter }
        roll_strike
        @game.roll(3)
        @game.roll(4) # 17
        should == 17
      end
    end

    context "2投目がストライクの場合" do
      it "スコアは14点" do
        19.times { roll_gutter }
        roll_strike
        @game.roll(4) # 14
        should == 14
      end
    end

    context "スペアの場合" do
      it "スコアは14点" do
        18.times { roll_gutter }
        roll_spare
        @game.roll(4) # 14
        @game.score.should == 14
      end
    end
  end
end

private
def roll_gutter
  @game.roll(0)
end

def roll_strike
  @game.roll(10)
end

def roll_spare
  @game.roll(5)
  @game.roll(5)
end


テスト結果

spec -c -fs spec/game_spec.rb

Game すべてガターの場合
- スコアは0点

Game すべて1ピンの場合
- スコアは20点

Game ストライクの場合
- スコアは24点

Game パーフェクトゲーム場合
- スコアは300点

Game Game スペアの場合
- スコアは21点

Game Uncle Bobの受け入れゲームの場合
- スコアは133点

Game 10フレーム目の場合 1投目がストライクの場合
- スコアは17点

Game 10フレーム目の場合 2投目がストライクの場合
- スコアは14点

Game 10フレーム目の場合 スペアの場合
- スコアは14点

Finished in 0.007972 seconds

9 examples, 0 failures

kakutanikakutani2010/04/14 15:25動画を丁寧に観ていただけて嬉しいです。ありがとうございます。あれは2年前のセッションなのと入門的な内容なので、いまやるならもうちょっと違う書き方がありそうですね。subjectとかnested contextはすでに使われているので、ちょっと違う感じでまとめてみました。 http://gist.github.com/365496 こっちのほうが読みやすいというつもりは無いのですが、共通処理の括り出しかたの一例として参考になれば幸いです。実行結果はこんな感じです。さいきんは --format は s よりも n がおすすめです。 http://gist.github.com/365501

rochefortrochefort2010/04/14 23:41おおお、角谷さんコメントありがとうございます!
しかもテストまで書き直してくださったなんて。
ブロック渡してテストするなんて、全く思いつきませんでした。
これはすっきりですね。
--format n もいいです。
t_wadaさんやmoroさんやるびまの記事を拝見して、最近rspec始めたところなので本当に勉強になります。

kakutanikakutani2010/04/15 01:03書き直しとか滅相もないです。ありがたいなあ、と思ったので自分でもちょっとやってみただけなので。ブロック渡し云々も、id:rochefort のリファクタした後のコードを見て「なんか他にないかなー」と無理矢理考えたところでもあるので、あんまり間に受けないでください(いつもこう書いてるわけではないです!)。 自分の日記にも感想を書いてみました: http://kakutani.com/20100414.html#p03

トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100411

2010-04-10スはスペックのス~RSpecによるテスト駆動開発の実演

スはスペックのス~RSpecによるテスト駆動開発の実演

| スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby を含むブックマーク はてなブックマーク - スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby

スはスペックのス~RSpecによるテスト駆動開発の実演~ - 角谷信太郎 (1/3)‐ニコニコ動画(9)

スはスペックのス~RSpecによるテスト駆動開発の実演~ - 角谷信太郎 (2/3)‐ニコニコ動画(9)

スはスペックのス~RSpecによるテスト駆動開発の実演~ - 角谷信太郎 (3/3)‐ニコニコ動画(9)

を見ながらテストしてみた。

スライドはこちら。S is for Spec


追記

RE: スはスペックのス~RSpecによるテスト駆動開発の実演 - うんたらかんたらRuby - Rubyist


追記その2

autospecの結果をgrowlで通知 - うんたらかんたらRuby - Rubyist


感想

凄くいい動画・資料でした。

いやぁ、いい時代だ。


1本目は、TDDについての解説です。

2、3本目はボーリングのスコア算出プログラムの実演です。

1本目で解説した内容をテストを書くという「プロセス」を通して実演しています。

この「プロセス」がいいし、TDDって素晴らしいと思えます。


動画自体は1.5時間くらいあって長いし、

実演部は随時止めながら手動かしたので

全部で2時間ちょっとくらいかかりましたが

見る価値、やる価値は十分ありました。


一応ソース

#spec/game_spec.rb
require File.expand_path(File.dirname(__FILE__) + "/../game.rb")
#require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
#[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6] => 133

describe Game, "すべてガターの場合" do
  before do
    @game = Game.new
    20.times { roll_gutter }
  end

  it "スコアは0点" do
    @game.score.should == 0
  end
end

describe Game, "すべて1ピンの場合" do
  before do
    @game = Game.new
    20.times { @game.roll(1) }
  end

  it "スコアは20点" do
    @game.score.should == 20
  end
end

describe Game, "ストライクの場合" do
  before do
    @game = Game.new
    roll_strike
    @game.roll(3)
    @game.roll(4)
    18.times { roll_gutter }
  end

  it "スコアは24点" do
    @game.score.should == 24
  end
end

describe Game, "パーフェクトゲーム場合" do
  before do
    @game = Game.new
    12.times { roll_strike }
  end

  it "スコアは300点" do
    @game.score.should == 300
  end
end

describe Game, "スペアの場合" do
  before do
    @game = Game.new
    roll_spare
    @game.roll(4)
    @game.roll(3) # 21
    16.times { roll_gutter }
  end

  it "スコアは21点" do
    @game.score.should == 21
  end
end

#[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6] => 133
describe Game, "Uncle Bobの受け入れゲームの場合" do
  before do
    @game = Game.new
    [1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6].each {|pin| @game.roll pin}
  end

  it "スコアは133点" do
    @game.score.should == 133
  end
end

private
def roll_gutter
  @game.roll(0)
end

def roll_strike
  @game.roll(10)
end

def roll_spare
  @game.roll(5)
  @game.roll(5)
end
#game.rb
class Game
  FRAMES_OF_A_GAEME = 10
  def initialize
    @rolls = []
  end

  def roll(pins)
    @rolls << pins
  end
  
  def score
    roll_idx = 0
    score = 0
    FRAMES_OF_A_GAEME.times do |frame|
      if strike?(roll_idx)
        # strike
        score += strike_bounus(roll_idx)
        roll_idx += 1
      elsif spare?(roll_idx)
        # spare
        score += spare_bounus(roll_idx)
        roll_idx += 2
      else
        score += score_of_frame(roll_idx)
        roll_idx += 2        
      end
    end
    score
  end

  private
  def strike?(roll_idx)
    @rolls[roll_idx] == 10
  end
  
  def spare?(roll_idx)
    @rolls[roll_idx] + @rolls[roll_idx + 1] == 10
  end
  
  def score_of_frame(roll_idx)
    @rolls[roll_idx] + @rolls[roll_idx + 1]
  end
  
  def strike_bounus(roll_idx)
    10 + @rolls[roll_idx + 1] + @rolls[roll_idx + 2]
  end
  
  def spare_bounus(roll_idx)
    10 + @rolls[roll_idx + 2]
  end
end

10フレーム目が特殊な気がするので

追加で書いてみた。

describe Game, "10フレーム目の1投目がストライクの場合" do
  before do
    @game = Game.new
    18.times { roll_gutter }
    roll_strike
    @game.roll(3)
    @game.roll(4) # 17
  end

  it "スコアは17点" do
    @game.score.should == 17
  end
end

describe Game, "10フレーム目の2投目がストライクの場合" do
  before do
    @game = Game.new
    19.times { roll_gutter }
    roll_strike
    @game.roll(4) # 14
  end

  it "スコアは14点" do
    @game.score.should == 14
  end
end

describe Game, "10フレーム目でスペアの場合" do
  before do
    @game = Game.new
    18.times { roll_gutter }
    roll_spare
    @game.roll(4) # 14
  end

  it "スコアは14点" do
    @game.score.should == 14
  end
end

あとで

テスト自体は、もう少しきれいになるので、修正しよう。

autotestについて調べよう。


以下、自分用メモ

1つのゴール

"clean code that works"

動作するきれいなコード

1つのテーマ

"The translation of a feeling into a test is a common theme of TDD."

感情をテストにすることが、TDDのテーマである。

不安だ

何かがおかしい

これでいい

退屈だ

→テストを構造化する

→書くのを止める


2つの主張

設計の技法

開発の進め方

2つのルール

テストに失敗した時だけコードを書く

重複を取り除く

3つのモード

Red

Green

Refactoring

3つの技法

"Fake It"

いんちき

"Triangulate"

三角測量

"Obvious implementation"

ふつうに実装する

4つのモード

Think+3つのモード

2010-04-04RSpec入門

RSpec入門

| RSpec入門 - うんたらかんたらRuby を含むブックマーク はてなブックマーク - RSpec入門 - うんたらかんたらRuby

t-wadaさんのRSpecの記事を読んでやってみた。

RSpec の入門とその一歩先へ - t-wadaの日記

RSpec の入門とその一歩先へ、第2イテレーション - t-wadaの日記


個人的には

特に第2イテレーションが参考になりました。

    • share_examples_for it_should_behave_like
    • describeのnest
    • 対象を説明する時は describe, 状況を説明する時は context
トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100404