rspec-temp_dirとは?
rspecでいい感じに一時ディレクトリを作るためのgemです
なぜ作ったか?
テストで検証したい内容がメソッドの戻り値だとその戻り値をexpect
で検証するだけなのでテストが楽なのですが、ファイルを出力するようなメソッドだとファイルが書き込まれているか検証する必要があります。
テストで作ったファイルを毎回 after
で消すとテストコードが肥大化するので、「それなら最初から一時ディレクトリにファイルを書き出してやればファイル消す必要ないのでは?」という発想で作りました。
JUnitの TemporaryFolder にインスパイヤされています。
使い方
describe
や context
の中に include_context "uses temp dir"
を書くとテスト実行時に一時ディレクトリが作られて temp_dir
(String
版)と temp_dir_path
(Pathname
版)で取得できるようになります。
サンプルコード
require 'rspec/temp_dir'
describe "uses temp dir" do
include_context "uses temp dir"
it "should create temp_dir" do
expect(Pathname(temp_dir)).to be_exist
end
it "can create file in temp_dir" do
temp_file = "#{temp_dir}/temp.txt"
File.open(temp_file, "w") do |f|
f.write("foo")
end
expect(File.read(temp_file)).to eq "foo"
end
describe "#temp_dir_path" do
subject{ temp_dir_path }
it { should be_an_instance_of Pathname }
it { should be_exist }
end
end
実装
require
を除くとたったこれだけです 1
lib/rspec/temp_dir/uses_temp_dir.rb
RSpec.shared_context "uses temp dir" do
around do |example|
Dir.mktmpdir("rspec-") do |dir|
@temp_dir = dir
example.run
end
end
attr_reader :temp_dir
def temp_dir_path
Pathname(temp_dir)
end
end
Dir#mktmpdir
の「ブロック内から抜けると一時ディレクトリを削除する」という特徴を利用しています。
v0.0.4 -> v1.0.0
アドベントカレンダー執筆に際してv1.0.0にしました。
破壊的な変更は下記です。
RSpec 2系のサポートをやめた
- さすがにもう誰も2系使っていないよねということでサポートやめた
- 少なくとも自分の観測範囲では見ていない
- 2系と3系両方考慮するとコードが汚くなるのでやめたかった
- 2系だと
shared_context
はObject
に生えていて、 3系だとRSpec
に生えているため下記のように書くしかなかった
- 2系だと
lib/rspec/temp_dir/uses_temp_dir.rb
(RSpec.respond_to?(:shared_context) ? RSpec : Object).shared_context "uses temp dir" do
end
Ruby 1.9系のサポートをやめた
-
json gemが2系でRuby 2系未満を切り捨てて
bundle install
できなくなったため - json gem使っているのはdevelopment dependencyなので「Ruby 1.9系なら json 1系を使う」みたいなTravis CIの設定を書く(もしくは1.9自体Travisでビルドしない)という選択肢もあったけど、積極的にRuby 1.9系をサポートし続ける理由も特に思いつかなかったのでバッサリ
spec.required_ruby_version = ">= 2.0.0"
を書きました。