rubyでライブラリなどを書くとき、Rakefileと相対パスのrequireを使ってクラスの取得やテストをやりやすくする
+---+ lib | +-+ some_module | +-+-- a_processor | | +-- order.rb | | +-- item.rb | +-- b_processor | | +-- order.rb | | +-- item.rb | +-- composer.rb # composerは a_processor, b_processor 以下のクラスを必要とする +---+ test # ここから一括で回せるようにしたい +-+ some_module +-+-- a_processor | +-- order_test.rb | +-- item_test.rb +-- b_processor | +-- order_test.rb | +-- item_test.rb +-- composer_test.rb
といった構成のライブラリを作るとして、composer
書いたり、 地味にテストを自動実行できるようにどうしたら良いか調べるのがめんどくさかったのでメモ。
追加分
+---+ lib | +-+ some_module | +-+-- a_processor | | +-- order.rb | | +-- item.rb | +-- b_processor | | +-- order.rb | | +-- item.rb | +-- composer.rb | +-- a_processor.rb ** 追加 | +-- b_processor.rb ** 追加 +---+ test + Rakefile ** 追加 +-+ some_module +-+-- a_processor | +-- order_test.rb | +-- item_test.rb +-- b_processor | +-- order_test.rb | +-- item_test.rb +-- composer_test.rb
それっぽく他パッケージにあるクラスを全て読み込む
比較的苦しくない抑えどころに近いんですが、そのパッケージのクラスを丸ごと読み込んでくれるファイル用意して、それを require
すると楽そう。
# a_processor.rb require "#{File.dirname(__FILE__)}/a_processor/order.rb" require "#{File.dirname(__FILE__)}/a_processor/item.rb"
ただ、明示的にクラスの指定どうこうする必要がない場合は、 Dir
クラスなどを使って each で回すと良さそう。
# a_processor.rb をなくしてbuilder.rb 冒頭で Dir.glob("#{File.dirname(__FILE__)}/a_processor/*").each do |file| require file end
test以下のディレクトリのファイル全てをコマンド一つで実行する
今回は test
ディレクトリ以下で rake test
で全部実行できればよかったので、下記のような Rakefile
を test
直下に置く。
Rakefile
はおいたところで Rakefile
に書いたタスクが rake xxx
(xxxなしだと task :default
に定義したものが使われる)実行されるようになるので、書いてから、普通はトップディレクトリにおいて、 ./**/*_test.rb
-> ./test/**/*_test.rb
にしたほうがいいかとも思った。
# Rakefile # coding: UTF-8 require 'rake/testtask' task :default => [:test] Rake::TestTask.new do |test| test.test_files = Dir['./**/*_test.rb'] test.verbose = false end
なお、テストファイルで本番用のファイルを要求するときは、そのライブラリ用のベースクラス的なのを用意して、そこで require
しておくと楽。
# base_test.rb require 'test/unit' Dir.glob("#{File.dirname(__FILE__)}/a_processor/*").each do |file| require file end Dir.glob("#{File.dirname(__FILE__)}/b_processor/*").each do |file| require file end Dir.glob("#{File.dirname(__FILE__)}/**.rb").each do |file| require file end class SomeModule::BaseTest < Test::Unit::TestCase include SomeModule ... # 他のテスト用クラスは require "#{File.dirname(__FILE__)}/path/to/base_test.rb" class SomeModule::SomeTest < SomeModule::BaseTest