桐生あんずです

日常やプログラミングについて書いています。

Railsのminitestで画像アップロードのテストをする際にpublic/system以下に余分なディレクトリを生成しないようにする

桐生あんずです。
以前に以下の記事で、
kiryuanzu.hatenablog.com
paperclipで画像アップロードをした際の画像テストのやり方を紹介しました。
ただ、このままの状態だと、テストするたびにpublic/system以下にディレクトリが生成されてしまう現象を確認しました。
このような何層にも連なる画像コピーファイルのディレクトリが生まれて、テストするたびに更新されています。
f:id:kiryuanzu:20180130133022p:plain
テストする際に大きな問題はないかもしれませんが、余分なディレクトリが毎回生成されるのは邪魔なので、生成されない方法を考えたいと思います。

どこかに手がかりはないかな〜と思ってpaperclipの公式リファレンスを見ることにしました。
github.com
Testingの章を探っていくと、似たような問題に言及している記述が。

Integration Tests

Using integration tests with FactoryBot may save multiple copies of your test files within the app. To avoid this, specify a custom path in the config/environments/test.rb like so:

Paperclip::Attachment.default_options[:path] = "#{Rails.root}/spec/test_files/:class/:id_partition/:style.:extension"
Then, make sure to delete that directory after the test suite runs by adding this to spec_helper.rb.

config.after(:suite) do
  FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
end

ここでは、FactroyBotを利用した際にテストファイルのコピーが発生するのでそれを避けるためにコピーファイルを指定のディレクトリに生成したのちにテストが終わったらファイルを削除する記述のやり方を教えてくれているようです。
rspecによる書き方ですが、minitestの構文に書き換えて同じことをやってみたらなんとかなりそうですね。

Railsテスティングガイドを見ていくと
Rails テスティングガイド | Rails ガイド

 # 各テストの実行直後に呼び出される
  def teardown
    # @article変数は実際にはテストの実行のたびに直前で初期化されるので
    # ここで値をnilにする意味は実際にはないのですが、
    # teardownメソッドの動作を理解いただくためにこのようにしています
    @article = nil
  end

teardownを使うことで各テストの実行直後にメソッドを呼び出すことができることがわかりました。

なので、config/enviroments/test.rbに

 Paperclip::Attachment.default_options[:path] = "#{Rails.root}/minitest/test_files/:class/:id_partition/:style.:extension"

と記述してminitestのディレクトリにコピーを生成するようにし、
テストを実行するファイルに

def teardown
   FileUtils.rm_rf(Dir["#{Rails.root}/minitest/test_files/"])
end

と記述し、指定したファイルをテストの度に消すようにしました。(FileUtilsはrubyのメソッドでファイルを消したり、他にも様々なことができるメソッドです)

そのように記述することで、無事不要なディレクトリが生成されることはなくなりました。いい話。