单元测试从base64字符串打印PNG的方法

时间:2014-05-15 23:43:45

标签: ruby testing rspec

我正在尝试测试以下方法,它给出了base64字符串,它会输出一个PNG:

def self.decode64_to_png(src)
    if (src.start_with? "data:image/png;base64")
      png = Base64.decode64(src['data:image/png;base64,'.length .. -1])
      png_logo_uuid = SecureRandom.urlsafe_base64(nil,false)
      if Rails.env.production?
        src = "#{Rails.root}/tmp/#{png_logo_uuid}.png" 
        File.open(src, 'wb') { |f| f.write(png) }
      else
        src = "#{Rails.root}/public/images/#{png_logo_uuid}.png" 
        File.open(src, 'wb') { |f| f.write(png) }
      end
      return src 
    end
  end

但我对测试很陌生,我正在试图找出在rspec中测试这个的最佳方法。我知道我应该先写测试,但我还在学习。基本上我想确保:

1 - 给定正确的base64字符串,创建一个图像并返回src 2 - 如果base64不正确,则返回nil。

这是我到目前为止所做的测试:

describe ".decode64_to_png" do
    it 'returns a path if the source is a correct base64 string' do
      File.stub(:open) { true }
      src = "data:image/png;base64,iVBORw0KGg"
      ImageManipulation.decode64_to_png(src).should_not be_nil
    end

    it 'returns nil if the source is not a correct base64 string' do
      File.stub(:open) { true }
      src = "asdasdasdata:image/png;base64,iVBORw0KGg"
      ImageManipulation.decode64_to_png(src).should be_nil
    end
  end

1 个答案:

答案 0 :(得分:1)

未测试

describe ".decode64_to_png" do
  let(:payload) { "iVBORw0KGg" }
  let(:uuid) { "uuid" }
  let(:file_args) { "#{Rails.root}/tmp/uuid.png" }

  context "when src is valid" do
    let(:src) { "data:image/png;base64,#{payload}" }
    before do
      Base64.should_receive(:decode64).with(payload)
      SecureRandom.should_receive(:urlsafe_base64).with(nil, false).and_return(uuid)
      Rails.stub_chain(:env, :production?) { true }
    end
    it "writes the image to a file" do
      File.should_receive(:open).with(file_args)
      ImageManipulation.decode64_to_png(src)
    end
    it "returns the file path" do
      File.stub(:open)
      ImageManipulation.decode64_to_png(src).should eq(file_args)
    end
  end

  context "when src is invalid" do
    let(:src) { "asdadasdada:data:image/png;base64,#{payload}" }
    it "does not write the image" do
      File.should_not_receive(:open)
      ImageManipulation.decode64_to_png(src)
    end
    it "returns nil" do
      ImageManipulation.decode64_to_png(src).should be_nil
    end
  end
end

测试副作用(即写入文件)似乎比返回值更重要;你应该测试两者。

请注意,最后一个示例失败,因为当输入无效时,方法返回输入,而不是返回nil。我认为该方法应该引发异常。

另请注意,这仅测试Rails.env.production?的代码路径为true。你最好完全从方法中移出它并将路径的根部分传递给方法,然后处理调用代码或初始化程序中环境之间的差异。

  

您将如何重写该功能,以便测试在所有方面都有意义   环境?

有几种方法;你可以添加一个Settings类,并在初始化时将图像文件夹路径粘贴在其中:

# lib/settings.rb
class Settings
  include Singleton
  attr_accessor :image_path
end

# config/initializers/settings.rb
case Rails.env
when "production"
  Settings.instance.image_path = "#{Rails.root}/tmp"
else
  Settings.instance.image_path = "#{Rails.root}/public/images"
end

替换

if Rails.env.production?
  src = "#{Rails.root}/tmp/#{png_logo_uuid}.png" 
  File.open(src, 'wb') { |f| f.write(png) }
else
  src = "#{Rails.root}/public/images/#{png_logo_uuid}.png" 
  File.open(src, 'wb') { |f| f.write(png) }
end

src = File.join(Settings.instance.image_path, "#{png_logo_uuid}.png")

添加到规范

Settings.stub_chain(:instance, image_path) { "#{Rails.root}/tmp" }

您还可以阅读YAML文件as described here中的值,或使用像simpleconfig这样的gem。