ある程度の規模のプログラムを Ruby で書こうとおもうと、RSpec による BDD (Behavior Driven Development) は大事なんだな、っていうのがなんとなくわかってきた。
ディレクトリ構成やファイル構成はほぼ機械的に決まるので、じゃあ自動化しましょう、ということでこんなRakefileを書いた。
~/.anyrb/Rakefile:
#!/usr/bin/env ruby # vim: set ft=ruby require 'rubygems' require 'rake' require 'spec' require 'pathname' #require 'spec/rake/spectask' HOME = ENV['HOME'] || Pathname.new('~').expand_path APP = ENV['APP'] || Pathname.pwd.basename ANYRB_DIR = "#{HOME}/.anyrb" SPEC_DIR = "spec" PRODUCT_DIR = "lib" SPEC_FILES = FileList["#{SPEC_DIR}/**/*_spec.rb"] PRODUCT_FILES = SPEC_FILES.map {|f| f.sub(/^#{SPEC_DIR}\//, "#{PRODUCT_DIR}/").sub("_spec", "") } directory SPEC_DIR directory PRODUCT_DIR task :default => [:init] task :init => [SPEC_DIR, PRODUCT_DIR] do unless File.exist?(app_spec = "#{SPEC_DIR}/#{APP}_spec.rb") cp "#{ANYRB_DIR}/skeleton/spec.rb", app_spec end end task :generate => [:init, *PRODUCT_FILES] rule(/^#{PRODUCT_DIR}\/.+\.rb$/, => [proc {|t| t.sub(/^#{PRODUCT_DIR}\//, "#{SPEC_DIR}/").sub(/\.rb$/, "_spec.rb") }]) do |t| mkdir File.dirname(t.name) cp "#{ANYRB_DIR}/skeleton/product.rb", t.name end
% mkdir someapp % cd someapp % rake -f ~/.anyrb/Rakefile % ls ./ ../ Rakefile lib/ spec/ % ls spec/ ./ ../ someapp_spec.rb % rake generate -f ~/.anyrb/Rakefile % ls lib/ ./ ../ someapp.rb % touch spec/someapp_foobar_spec.rb % rake generate -f ~/.anyrb/Rakefile % ls lib/ ./ ../ someapp.rb someapp_foobar.rb
チュートリアルとしてはこんなかんじだろうか。-f オプションをいちいちつけるのはめんどくさいので、rake をラップするシェルスクリプトでも書いておくのがオススメ。
~/bin/anyrb:
#!/bin/sh rake -f ~/.anyrb/Rakefile "$@"
RSpecとRakeでガンガン開発しましょう。