1

私の Rails 2 アプリは、flickrawライブラリを介して Flickr からの写真のスライドショーを表示します。私のコードは動作しますが、RSpec 単体テストを適切に記述する方法に行き詰まっています。

Slide私のアプリが flickraw から必要とするすべてをカプセル化するクラスがあります。モデル オブジェクトのように動作しますが、ActiveRecord は使用しません。それはあまり機能しません。面倒な作業のほとんどを flickraw に委任します。

テストを完了していないのは、現状では、Flickr からいくつかの写真 ID をハードコーディングする必要があり、写真セットを再配置したり新しい写真を追加したりするとテストが壊れてしまうからです。

したがって、私のいわゆる単体テストは統合テストに似ています。RSpec を使用してモックまたはスタブを作成する方法は理解していますが、flickraw ライブラリに対して行う方法がわかりません。 flickraw をスタブ化し、これを単体テストにするにはどうすればよいですか?

スライド.rb:

require 'flickraw'
FlickRaw.api_key = "xxx"
FlickRaw.shared_secret = "yyy"
flickr.auth.checkToken :auth_token => "zzz"
PHOTOSET_ID = 123123123

class Slide
  attr_accessor :id, :previous_id, :next_id, :url_square, :url_thumbnail, :url_small, :url_medium500,
                :url_medium640, :url_large, :url_original

  def self.last
    photoset = flickr.photosets.getPhotos(:photoset_id => PHOTOSET_ID)
    Slide.new(photoset.photo.last.id)
  end

  def self.first
    photoset = flickr.photosets.getPhotos(:photoset_id => PHOTOSET_ID)
    Slide.new(photoset.photo.first.id)
  end

  def self.find(id)
    Slide.new(id)
  end

  def initialize(id)
    self.id = id
    photo = flickr.photos.getInfo(:photo_id => id)
    context = flickr.photosets.getContext(:photoset_id => PHOTOSET_ID, :photo_id => id)
    sizes = flickr.photos.getSizes(:photo_id => id)

    self.previous_id = (context.prevphoto.id == 0) ? nil : context.prevphoto.id
    self.next_id = (context.nextphoto.id == 0) ? nil : context.nextphoto.id

    sizes.each do |size|
      if size.label == "Square"
        self.url_square = size.source
      elsif size.label == "Thumbnail"
        self.url_thumbnail = size.source
      elsif size.label == "Small"
        self.url_small = size.source
      elsif size.label == "Medium"
        self.url_medium500 = size.source
      elsif size.label == "Medium 640"
        self.url_medium640 = size.source
      elsif size.label == "Large"
        self.url_large = size.source
      elsif size.label == "Original"
        self.url_original = size.source
      end
    end
  end
end

slide_spec.rb:

require 'spec_helper'

describe Slide do
  before(:each) do
    first_photo_id = "444555666"
    @slide = Slide.new(first_photo_id)
  end

  describe "urls" do
    it "should generate the thumbnail url" do
      @slide.url_thumbnail.should match(/_t.jpg$/)
    end

    it "should generate the small url" do
      @slide.url_small.should match(/_m.jpg$/)
    end

    it "should generate the medium500 url" do
      @slide.url_medium500.should match(/.jpg$/)
    end

    it "should generate the medium640 url" do
      @slide.url_medium640.should match(/_z.jpg$/)
    end

    it "should generate the large url" do
      @slide.url_large.should match(/_b.jpg$/)
    end

    it "should generate the original url" do
      @slide.url_original.should match(/_o.jpg$/)
    end
  end

  describe "finding" do
    it "should find the correct last photo" do
      # ???
    end

    it "should find the correct first photo" do
      # ???
    end
  end

  describe "context" do
    it "should return the correct previous photo" do
      # ???
    end

    it "should return the correct next photo" do
      # ???
    end
  end
end
4

1 に答える 1

0

私が理解しているように、slide.stub!(:flickr).and_return を実行して、コンストラクター内にないものをすべてモックアウトできるはずです。ただし、コンストラクターが flickr api から大量にロードしているという事実を照会します。

スライドの実装を変更して、attr_accessors をロードする代わりに、flickr API から取得する実際のメソッドを使用できますか? クラスの外部 API を変更せずにこれを実行できるはずです。また、API 呼び出しの結果をインスタンス変数にキャッシュすることで速度を向上させることができます。

すべての作業をコンストラクターで実行したい場合は、flickr サービスを表す既定の引数を使用することをお勧めします。コンストラクタは次のようになります。

def initialize(id, flickr=flickr)
  … complicated setup code here…
end

このように、テストするときは、次のようにモック flickr オブジェクトを渡すだけです。

 flickr = mock(:flickr)
 @slide = Slide.new(image_id, flickr)

次に、新しい flickr オブジェクトに対して通常の rspec アサーションを記述できます (ここでも、外部 API を変更する必要はありません)。

于 2011-02-11T22:13:20.477 に答える