Okay, here we go
describe VideoService, " when creating a video" do fixtures :companies, :sites, :video_formats, :publish_settings
before(:each) do @video = Video.new @video.company = companies(:test) @video.site = sites(:test) sites(:test).stub!(:formats).and_return [ video_formats(:flash) ]
@origin = mock_model(Origin, :process_source => true, :transcode_asset => true, :storage => "file") Origin.stub!(:find_transcoder).and_return @origin
@service = VideoService.new end
def create_video @service.create_video :video => @video, :signature => "abc123", :frame => 1, :storage => "file" end
it "should add a new video record" do lambda { create_video }.should change(Video, :count).by(1) end
it "should create two assets - one source and one transcoded" do lambda { create_video }.should change(Asset, :count).by(2) @video.source_asset.should be_source @video.should have(2).assets end
it "should create the main asset with the appropriate video format" do create_video @video.assets.find_by_video_format_id(video_formats(:flash).id).should_not be_blank end end
describe VideoService, " when creating a video" do fixtures :companies, :sites, :video_formats
before(:each) do @video = mock_model(Video, :save => true, :company_id => companies(:test).id, :site => sites(:test), :hook => nil) sites(:test).stub!(:formats).and_return [ video_formats(:flash) ]
@source_asset = mock_model(Asset, :video_id= => @video.id, :save => true) @transcode_asset = mock_model(Asset, :video_id= => @video.id, :save => true) Asset.stub!(:new).and_return @source_asset, @transcode_asset @video.stub!(:source_asset).and_return @source_asset
@source_origin = mock_model(Origin, :process_source => true, :transcode_asset => true, :storage => "file") @transcode_origin = mock_model(Origin, :transcode_asset => true, :storage => "file") Origin.stub!(:find_transcoder).and_return @source_origin, @transcode_origin
@service = VideoService.new end
def create_video @service.create_video :video => @video, :signature => "abc123", :frame => 1, :storage => "file" end
it "should find a transcoder" do Origin.should_receive(:find_transcoder).with(companies(:test).id, false, "file").and_return @source_origin create_video end
it "should process the source asset" do @source_origin.should_receive(:process_source).with("abc123", @source_asset, 1, "http://test.host:80/"\) create_video end
it "should find an origin for the transcode format" do Origin.should_receive(:find_transcoder).with(companies(:test).id, false, nil).and_return @transcode_origin create_video end
it "should transcode the new asset" do @transcode_origin.should_receive(:transcode_asset).with("abc123", @transcode_asset, "http://test.host:80/", "http://test.host:80/video_formats/#\{video\_formats\(:flash\)\.id\}\.xml"\) create_video end end
I created the VideoService to wrap the creation of a video in our system. At that stage in the code, there were a couple main parts - creating a new video record, creating a couple asset records, and notifying our transcode machines about the new assets.
The first example specifies the db behavior I want. That was my black-box test (you might say it's grey-box because I'm stubbing some stuff out, but that wasn't part of the original spec. It's just there so the spec can run - Origin makes a network call and it's easier to stub the whole thing out).
The second example is the white-box test, which verifies that the internals work. Certain origins should be found, they need to receive certain calls with a particular video, etc.
Now I'm not sure if people will like those specs but hopefully it
gives you an idea of how you can approach specifications from both
angles.
Pat