Rubyでファイルをコピーするとき、あまり同期/非同期を意識していなくて、テストでハマった時のお話。
あるテストを実行するときに設定ファイルのspec/necessary
が必要で、なければspec/example
からコピーして使うという状況でした。
Rakefileで書くとこんな感じ、
RSpec::Core::RakeTask.new('spec') do |t|
t.verbose = true
end
file 'spec/necessary' => 'spec/example' do |task|
CLEAN.exclude task.name
src_path = File.expand_path("../../#{task.prerequisites.first}", __FILE__)
dst_path = File.expand_path("../../#{task.name}", __FILE__)
dst_file = File.open(dst_path, 'w')
File.open(src_path) do |f|
f.each_line do |line|
dst_file.write line
end
end
end
Rake::Task[:spec].prerequisites << :'spec/necessary'
この書き方でテストが通らないので調べてみると、spec
タスクの実行時に'spec/necessary'が空の状態で存在していました。同期モードにしていなかったのが原因で、書き込みが終わる前にspec
タスクが実行されていると。
同期モードになるように修正したところ
file 'spec/necessary' => 'spec/example' do |task|
CLEAN.exclude task.name
src_path = File.expand_path("../../#{task.prerequisites.first}", __FILE__)
dst_path = File.expand_path("../../#{task.name}", __FILE__)
dst_file = File.open(dst_path, 'w')
+ dst_file.sync = true
File.open(src_path) do |f|
f.each_line do |line|
dst_file.write line
end
end
end
file 'spec/necessary' => 'spec/example' do |task|
CLEAN.exclude task.name
src_path = File.expand_path("../../#{task.prerequisites.first}", __FILE__)
dst_path = File.expand_path("../../#{task.name}", __FILE__)
+ File.open(dst_path, 'w') do |dest|
+ File.open(src_path).each do |source|
+ dest.write source
end
end
end
というレビューをもらいました。ブロックを渡せば、すぐに実行されるんだったなぁ。
時間を見つけて、Rubyのコードを読まないと・・・・