Tuesday, January 27, 2009

script/refactor

script/refactor という rails アプリケーションのリファクタリングを支援するスクリプトを書いてみました。

$ script/plugin install git://github.com/hiroshi/script-refactor.git

インストールすると、 script/refactor が生成されます。

例: user を person に変える。
$ script/refactor resource user person
Renamming files and directories:
git mv app/views/users app/views/people
git mv app/helpers/users_helper.rb app/helpers/people_helper.rb
git mv app/models/user.rb app/models/person.rb
git mv test/unit/user_test.rb test/unit/person_test.rb
git mv test/functional/users_controller_test.rb test/functional/people_controller_test.rb
git mv app/controllers/users_controller.rb app/controllers/people_controller.rb
git mv test/fixtures/users.yml test/fixtures/people.yml

Replacing class and variables:
user -> person
Users -> People
User -> Person
users -> people
pettern: /(\b|_)(user|Users|User|users)(\b|[_A-Z])/

./test/unit/person_test.rb:3: class UserTest < ActiveSupport::TestCase
./test/unit/person_test.rb:7: fixtures :users
./test/unit/person_test.rb:9: def test_should_create_user
./test/unit/person_test.rb:10: assert_difference 'User.count' do
...
./app/controllers/application.rb:18: current_user.group

NOTE: If you want to revert them:
git reset --hard


こんな感じにモデル、コントローラ、ヘルパー、テストのファイル名を変更して、コード中のクラス名、変数名もルールに従っているものは変更します。

適当に書いたスクリプトなので、特に置換する部分が思うような挙動にならない場合もあるかと思います。改善案やパッチをください。

Friday, January 23, 2009

My philosophy about testing

テストを含む開発の哲学については Rails 開発者の中でも様々あります。僕の場合、現状ではこんな感じなんですけど、みなさんどうですか?

テストの目的は2つあると考えます。
開発する最中に自分の書いているコードが正しいか確認するためのものと、コードを変更したときにその影響により過去に書いたコードが壊れないか確認するもの。

Rails アプリケーション開発の場合、前者は、基本的には、見た目の確認も行うため development mode でブラウザ確認で行います。
例外的に、レコードの作成、更新などで複雑な処理をする場合など、ブラウザでフォームに入力して、レコード作成、表示をするのに手間がかかったり、画面には現れないカラムの内容を確認したいときに、簡単な unit test を書いたりもします。

後者は一般的に回帰テスト(regression test)と呼ばれるもので、 Rails では functional test を中心に書いてゆきます。記述する精度は余裕やモチベーションによっても違うと思いますが、controller の各 action を実行して結果を簡単に確認して、 rcov による coverage 率が 100% に近づくようにします。

実装と平行、またはテスト駆動が望ましいとは思いますが、そうは言ってもね、たいていの場合は仕様がガッチリ決まっているわけではなく実験しながら実装することになるので、大きく変更する可能性があったり場合によっては捨ててしまうコードのテストに時間をかけるのはもったいないしモチベーションも上がらないので、実装がほぼ完了して次のタスクにとりかかる前にテストを書きます。
仕様決定権限がある人に確認してもらうこともある意味テストなので、極論ですけど、実装したものが仕様として望ましいかどうかのテストに合格してから実装の品質をテストしないと、「テストも全部書いてしまったので変更はできません」なんて本末転倒なことになるかと思います。

あとは、リリース後に不具合が見つかった場合、テストが甘かったわけなので、理想的には、その不具合を再現するテストを書いて、コードの修正でテストが通ることを確認して解決とします。