( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

Rspecでfailするとデスメタルが流れるようにした

このような事があったので自動化した。
Mac限定。


こんな感じ。successだとレベルがアガる。

事前にbash-itunes というコマンドラインツールを入れておく。
iTunesを日本語で使ってる場合、patchを当てる必要がある。
こちらを山椒

コードはこれな。

class PlayItunesReporter
  attr_accessor :success_track, :failure_track
  def initialize(options = {})
    @success_track = options[:success]
    @failure_track = options[:failure]
  end

  def dump_summary(notification)
    return unless notification.examples.length > 0

    if notification.failed_examples.length == 0
      play!(success_track)
    else
      play!(failure_track)
    end
  end

  def play!(track)
    `itunes play "#{track}"`
  end
end


RSpec.configure do |config|

  itunes = PlayItunesReporter.new(success: "レベル・アップ", failure: 'Nemesis')
  config.reporter.register_listener itunes, :dump_summary
end

正直、曲は好きなの使えばいい。なんならこれでもいい

inspired by : コンパイル中に音楽を流せる sbt プラグインを作りました。 - tototoshi の日記

rspecの--tagオプションを利用して任意のコマンドライン引数をspec側に渡すという邪悪なhack

今まで、rspecコマンドでは任意の引数を渡すことはできなかったので、環境変数経由で引き渡すという方法をとっていた。
( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

MY_OPT1=true rspec spec/my_spec.rb

環境変数で渡すのはダルいのでなんとかしたいと思い、`--tag`オプション経由で値を渡すというダーティなhackを書いた。

仕掛けは、helper.rbなどで、以下のように`Rspec.world.filter_manager.incusions`から引数を切り出してクラス変数に保持しておくようなアレをホゲる。

helper.rb

class MyOptions
  class << self
    OPTION_KEYS = [:my_opt1, :my_opt2]
    attr_accessor :options
    def parse(world)
      @options = world.filter_manager.inclusions.slice(*OPTION_KEYS)
    end
  end
end

RSpec.configure do |config|

  # filterをonに
  config.filter_run :focus => true
  config.run_all_when_everything_filtered = true

  # --tagから独自の引数を切り出して保持しておく
  MyOptions.parse(RSpec.world)
end

あとは、`MyOptions.options[:my_opt1]`のように参照できる。

my_options_spec.rb

require File.join(File.dirname(__FILE__), 'helper')

describe "MyOptions" do
  subject { MyOptions.options }

  it { should include(:my_opt1) }
  it { should include(:my_opt2) }
end


実行すると、`--tag`経由で引数が渡っていることが確認できる。

$ rspec spec/my_options_spec.rb -t my_opt1 -t my_opt2
Run options: include {:focus=>true, :my_opt1=>true, :my_opt2=>true}

All examples were filtered out; ignoring {:focus=>true, :my_opt1=>true, :my_opt2=>true}

MyOptions
  should include :my_opt1
  should include :my_opt2

Top 2 slowest examples (0.0029 seconds, 100.0% of total time):
  MyOptions should include :my_opt1
    0.00205 seconds ./spec/my_options_spec.rb:6
  MyOptions should include :my_opt2
    0.00085 seconds ./spec/my_options_spec.rb:7

Finished in 0.0034 seconds
2 examples, 0 failures


`--tag`渡さないとfailする。

$ rspec spec/my_options_spec.rb
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}

MyOptions
  should include :my_opt1 (FAILED - 1)
  should include :my_opt2 (FAILED - 2)

Failures:

  1) MyOptions should include :my_opt1
     Failure/Error: it { should include(:my_opt1) }
       expected {} to include :my_opt1
       Diff:
       @@ -1,2 +1 @@
       -[:my_opt1]

     # ./spec/my_options_spec.rb:6:in `block (2 levels) in <top (required)>'

  2) MyOptions should include :my_opt2
     Failure/Error: it { should include(:my_opt2) }
       expected {} to include :my_opt2
       Diff:
       @@ -1,2 +1 @@
       -[:my_opt2]

     # ./spec/my_options_spec.rb:7:in `block (2 levels) in <top (required)>'

Top 2 slowest examples (0.00381 seconds, 100.0% of total time):
  MyOptions should include :my_opt1
    0.00282 seconds ./spec/my_options_spec.rb:6
  MyOptions should include :my_opt2
    0.00099 seconds ./spec/my_options_spec.rb:7

Finished in 0.00432 seconds
2 examples, 2 failures

Failed examples:

rspec ./spec/my_options_spec.rb:6 # MyOptions should include :my_opt1
rspec ./spec/my_options_spec.rb:7 # MyOptions should include :my_opt2

ちょっとの手間でRSpecの出力をキレイにするnamed_letをrubygems.orgに登録した

以前書いた、「 ちょっとの手間でRSpecの出力をキレイにするためにnamed_letというのを書いてみた - ゆろよろ日記」を、
ちゃんとしたGemにしてrubygems.orgに登録しました。


named_let | RubyGems.org | your community gem host
f:id:yuroyoro:20120225121036p:image:w640


ソースコードはGithubにあります。

yuroyoro/named_let · GitHub


ですが、ひとつ問題があります。このissueをご覧ください。


Issue #1: Very poor English!!!! · yuroyoro/named_let · GitHub


pull requestお待ちしております!!!!!

ちょっとの手間でRSpecの出力をキレイにするためにnamed_letというのを書いてみた

RSpecの話です。


RSpecは、テストコードがそのまま仕様を記述するドキュメントになる、というのが大きな利点の一つです。
しかし、rspecコマンドに-dオプションを渡して出力されるドキュメントは、必ずしも読める文章になっているとは限りません。


例として、以下のようなCanCanのspecを見てみます。

require 'spec_helper'
require "cancan/matchers"

describe Ability do
  context 'an user' do
    let(:user)          { Factory.create(:user) }

    let(:article)     { Factory.create(:article) }
    let(:own_article) { Factory.create(:article, :user => user) }

    subject { Ability.new(user) }

    it { should be_able_to(:read, article) }
    it { should be_able_to(:update, own_article) }
  end
end

Userは、ある記事をreadする権限を持っていて、自分が書いた記事はupdateすることができる、という記述です。
'should be_able_to(:read, article)'や' should be_able_to(:update, own_article) 'は、そのままの文章になってます。


では、これをrspec -dで実行してみます。


f:id:yuroyoro:20120110174348p:image:w640


アルェ?
'should be able to :read #

describe Ability do
  context 'an user' do
    let(:user)          { Factory.create(:user) }

    named_let(:article) { Factory.create(:article) }
    named_let(:own_article, "own article") { Factory.create(:article, :user => user) }

    subject { Ability.new(user) }

    it { should be_able_to(:read,  article) }
    it { should be_able_to(:update, own_article) }
  end
end


さっきのspecで、letで定義されていたarticleを、named_letを利用するように変更しました。named_letでは、第一引数のSymbolを表示の際に利用します。第二引数に別名を渡すことも出来ます。

    named_let(:article) { Factory.create(:article) }
    named_let(:own_article, "own article") { Factory.create(:article, :user => user) }


あらためて実行してみます。


f:id:yuroyoro:20120110174349p:image:w640


ちゃんと意図した文章になって出力されていますね。やったー。