rspecを勉強してみる

2013-06-02T00:00:00+00:00 rspec Ruby

まぁRailsとかでは書いたりもしてますけど、without Railsな環境とかっていうかRSpecももっと勉強しないとなっていう欲求にかられてゆる〜く勉強してみた

rspec --init

な感じで実行すると

.rspec
spec/spec_helper.rb

の2つが生成される。でRailsみたいにrake specみたいな感じでテスト実行出来るようにするとかには

require "rspec/core/rake_task"

#task :default => :spec

desc "run all"
RSpec::Core::RakeTask.new(:spec)

な感じで作れば良い模様。まーあとはテスト書くだけなんだけど、ついでにカバレッジレポートも出したいのでspec/spec_helper.rbとかに

require "simplecov"
SimpleCov.start

とか書いとく。でspec_helper自動で読み込む方式にしたい場合とかには、.rspec辺りに

--color
--format progress
-p # profile
--require spec_helper

な感じで書いとけば良い模様。さてこれからテスト書くんだが、テストする対象として

  • pow2ってメソッドを持ち、引数のInteger型を2倍にして返す
  • 引数がnilならArgumentError
  • 引数がIntegerじゃなければArgumentError
  • 引数が0以上じゃなければArgumentError

なクラスを定義する。まぁこれのテストを書く

require "sample"

describe Sample do
  describe "#pow2" do
    # 1回のみ
    before(:all) do
      puts "[BEFORE(all)]"
      @sample = Sample.new
    end

    # テスト毎
    before(:each) do
      puts "[BEFORE(each)]"
    end

    context "正常時" do
      subject {
        @sample.pow2(2)
      }

=begin
      # subjectは引数で指定出来る。その場合subjectでは無く、引数で指定した名の変数で確保される?
      subject(:n) {
        @sample.pow2(2)
      }

      it "argument is 2" do
        expect(n).to eq(4)
      end
=end

      it "argument is 2" do
        expect(subject).to eq(4)
      end
    end

    context "例外発生" do
      it "引数がnil" do
        expect { @sample.pow2(nil) }.to raise_error(
          ArgumentError,
          "argument is nil"
        )
      end

      it "引数がIntegerじゃない場合" do
        expect { @sample.pow2("2") }.to raise_error(
          ArgumentError,
          "argument isn`t an Integer"
        )
      end

      it "引数が0よりも大きくない場合" do
        expect { @sample.pow2(0) }.to raise_error(
          ArgumentError,
          "argument greater than zero"
        )
      end
    end

    context "mockしてみる" do
      it "mock return 1" do
        sample = mock("Sample")
        #sample.stub(:pow2) { 1 }
        sample.stub(:pow2 => 1)
        expect(sample.pow2(2)).to eq(1)
      end

      it "mock argument *2" do
        sample = mock("Sample")
        sample.should_receive(:pow2) do |*args|
          expect(args.size).to eq(2)
          expect(args[0]).to eq(3)

          args[0] * 2
        end

        expect(sample.pow2(3, 2)).to eq(6)
      end
    end
  end
end

ってな感じ。後述する参考に書いてるけど、今時なRSpecはshouldも使えるけどexpectを使うのが良いっていうか警告出なかったかなーっていう所があるので。んまぁ使い所で使い分ければ良いんじゃないかなーっと。あと、letっていうのもあるけどsubjectとの違いがよー分からんのでとりあえず今回はパス。さらにshared_contextっていうのもあるけど、今回要件が満たさないし後述する参考に詳しく書かれてるのでパス

とりまぁRspecの勉強はまだまだ続く的な感じで

参考

http://magazine.rubyist.net/?0035-RSpecInPractice

http://qiita.com/items/d880250adc8cdbe7a32f

https://github.com/rspec/rspec-expectations

Rails(OAuth)+Android SyncAdapter Eclipseの.factorypathでのAPT処理に関して