Read Perfect Software

投稿者 okkez 2010-06-25 15:06:00 GMT

読んだ。

ワインバーグの最新作なのかな。ジュンク堂で偶然見かけて、購入。

ソフトウェアのテストにまつわる誤解、誤謬、詐欺に関する本。 具体的なソフトウェアテストの技術や知見を知りたい人は別の本を読めばいいと思う。 例えばこの辺。(もちろん本書にも参考文献はいくつもあげられている。)

本文で紹介されている人々の会話も面白いし、実際にありそうな感じだった。いくつかは、自分自身も経験がある内容だった。

で、どういう人がこの本を読むべきかと言うと、ソフトウェア開発に直接、間接に関わるすべての人々が読むべきだと思った。 開発者は、自分の行動やテストに対する考え方や振る舞いを振り返りながら。 テストエンジニアは、開発者から本書にあるような扱いを受けたことがないか振り返りながら。 マネージャは、自分のチームの開発者とテストエンジニアが上手くいっているか気にしながら。あるいは、部下の報告を無視したり、 曲解したり、勘違いしていないか振り返りながら。 その他の人々は、いつか自分が当事者になるかもしれないのだから、当事者になったときのために。

カテゴリ ,  | コメントなし | トラックバックなし

Working Effectively with Legacy Code

投稿者 okkez 2010-06-13 13:39:00 GMT

「レガシーコード改善ガイド」の読書会に行ってきた。今回で最終回だった。 全体的に著者の経験に基づいた実用的なテクニックが多かった。

著者の「テストコードが無いコード」== 「レガシーコード」という考え方には同意できる。 本書では、そういったレガシーコードに対するシチュエーション別の考え方が多数紹介されている。 難を言えば、サンプルコードに C++ と Java が節ごとに切り替わって、少し戸惑うことがあった。 「レガシーコード」 == 「テストコードが無いコード」に悩んでいる人は読んでみるといいと思う。

合わせて読みたい

カテゴリ ,  | コメントなし | トラックバックなし

Rails の generator gem のテスト方法

投稿者 okkez 2009-12-18 14:39:00 GMT

自分で Rails の generator gem のテストを書いてみたんだけど、どうもしっくり来ない。

参考にしたのはここ。

作ってた engines はこれ。

やりたかったことは以下のとおり。

  • Rails Engines なので基本的には Rails アプリケーションとしてテストしたい
  • generator は engines として使うときに必要なファイルを生成するためのものなので独立してテストしたい
  • rake test でちゃんとテスト出来れば OK

で、冒頭の Rails Guides を参考にテストを書いてみたけどちゃんと動かなかったので Rails のソースを読んでみた。 読んでみて分かったのは以下のこと。

  • Rails::Generator::Scripts::Generate#run でファイルを生成する先は指定できる
  • けど、generator をどこから探してくるかは指定できない
  • RAILS_ROOT が定義されていると RAILS_ROOT/lib/generators や RAILS_ROOT/vendor/generators などから探してくれる
  • 他には既にインストール済みの generator からも探してくれる
  • RAILS_ROOT/generators は見てくれない

作っているのは engines gem なのだから RAILS_ROOT/generators も見てほしいんだけど、それはやってないらしいので、ここでは RAILS_ROOT/lib/generators に symlink を張ることにした。 一応、これでちゃんと動いているみたいなのだけど、setup で symlink 作成して teardown で symlink を削除したりしてるのがちょっと気持ち悪い。

Rails Guides にも書いてあったとおり generator を提供している多くの Gem は generator 自体のテストは書いていない。(cucumber や rspec を参考にしたかったんだけど書いてなかった。)

もう一回やりたかったことをまとめるとこうなる。

  • Rails Engines なので基本的には Rails アプリケーションとしてテストしたい
  • generator は engines として使うときに必要なファイルを生成するためのものなので独立してテストしたい
  • 既存の generator を読み込まずにテストしたい (開発中の Gem と同名の Gem が入っていてもいいように)
  • rake test でちゃんとテスト出来れば OK

あ、コードは github に全部上がっているので見てください。

みんな generator のテストはあんまり書かないものなのかなぁ?

カテゴリ ,  | タグ ,  | コメントなし | トラックバックなし

Rails Engines なプラグインを書いてみた

投稿者 okkez 2009-12-18 14:38:00 GMT

Rails Engines なプラグインを書いてみたら、いくつかハマったポイントがあったので未来の自分のために記録しておく。

  1. スタイルシートや画像などが読めない
  2. マイグレーションファイルをどうしよう
  3. プラグインがロードできない
  4. Engine 側で使っている Gem を rake gems などで扱いたい

大体この四つくらいかと。それ以外は普通にアプリケーションを作れば OK

スタイルシートや画像などが読めない

これは簡単で、本家でも解説されてた。 Rake タスクを作ってコピーするだけ。

マイグレーションファイルをどうしよう

これも簡単。本家では、プラグイン側のマイグレーションを実行する方法がまだ無いから仕方ないと書かれていた。 Rake タスクを作ってコピーすればいい。タイムスタンプなマイグレーションを使っている場合はこれで問題ないはず。

プラグインがロードできない

これは調べるのに時間がかかったけど分かってみれば簡単だった。 plugin_root/init.rb や plugin_root/rails/init.rb では Rails::Initializer.run のブロックパラメータの config が見える ので(正確には違うけど)それ経由で以下のようにしておくとよいみたい。

plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
config.plugin_paths << File.join(plugin_root, 'vendor/plugins')

Engine 側で使っている Gem を rake gems などで扱いたい

プラグインと同様、init.rb 内で config.gem すれば良い。

カテゴリ ,  | タグ ,  | コメントなし | トラックバックなし

Hikifarm on Rack

投稿者 okkez 2009-11-25 12:48:00 GMT

Hikifarm on Rack の対応をしてみました。

  • https://svn.sourceforge.jp/svnroot/hiki/hiki/branches/rack

やっと Hikifarm on Rack を実装出来たので rack ブランチにコミットしてみました。 まだ足りない部分はいくつかありますが、余裕のある人は試してみてください。 コードやファイル名についてもコメントをください。

使い方

  • misc/hikifarm/hikifarm_conf.rb を Hiki のインストールディレクトリにコピーする
  • hikifarm_conf.rb を環境に応じて書き換える
  • 必要っぽいディレクトリを作成しておく
  • 以下のコマンドを実行する
 $ rackup hikifarm.ru

注意

  • Hikifarm, Hiki ともにデフォルトで UTF-8 で動作します
  • 古い misc/hikifarm/index.cgi は変更してませんが使えないと思います

主な変更点

  • misc/hikifarm/index.cgi から hiki/farm.rb, hiki/farm/{config,dispatcher,manager,page,wiki}.rb に分離
  • Hikifarm の内部的にコードを整理した
  • Hiki::Config.new に hikiconf.rb のパスを指定できるようにした
  • UTF-8 化

TODO (把握してるものだけ)

  • Hikifarm の RSS 出力
  • 複数の wiki を作成したときの動作確認
  • attach の動作確認を行う
  • テストを書く
  • リファクタリング

カテゴリ ,  | タグ ,  | コメントなし | トラックバックなし

Rails の fixtures の書き方を整理してみる

投稿者 okkez 2009-08-26 12:45:00 GMT

ほとんど以下に書いてあるけど、最近 fixtures の整理をしてるので書いてみる。

  • http://railsapi.com/doc/rails-v2.3.3.1/files/activerecord/lib/active_record/fixtures_rb.html

CSV とか single file とか色々あるけれどここでは YAML fixtures について書きます。

ラベルで参照する

pirates.yml
### in pirates.yml reginald: id: 1 name: Reginald the Pirate monkey_id: 1 ### in monkeys.yml george: id: 1 name: George the Monkey pirate_id: 1

上記のようなものが以下のように書けます。

  ### in pirates.yml

  reginald:
    name: Reginald the Pirate
    monkey: george

  ### in monkeys.yml

  george:
    name: George the Monkey
    pirate: reginald

polymorphic belongs_to

今日一番の収穫がこれ。

  ### in fruit.rb
  class Fruit < ActiveRecord::Base
    belongs_to :eater, :polymorphic => true
  end

  ### in fruits.yml

  apple:
    id: 1
    name: apple
    eater_id: 1
    eater_type: Monkey

こんな風に書いていたのが、こう書けます。

  ### in fruits.yml
  apple:
    eater: george (Monkey)

今、修正している Rails アプリではポリモーフィック関連をたくさん使っているのでこれはすごく便利です。

belongs_to 応用

こんなモデル定義がある場合にはちょっと変わった書き方ができます。

# in expense.rb
class Expense < ActiveRecord::Base
  has_many :expense_details
end
# in expense_detail.rb
class ExpenseDetail < ActiveRecord::Base
  belongs_to :header, :class_name => 'Expense', :foreign_key => 'expense_id'
end

普通は belongs_to :expense と書きますが、上のように書くことで header と書けるようになります。

### expenses.yml
hawaii:
  title: hawaii trip!

### expense_details.yml
chocorate:
  name: chocorate
  header: hawaii

nested set を使っているとき

nested set を使っている時はこう書けます。

### menus.yml
root:
  name: root
  parent_id:
menu_1:
  name: menu_1
  parent_id: <%= Fixtures.identify(:root) %>

$LABEL

$LABEL を使うと上の menus.yml がこうなります。

### menus.yml
root:
  name: $LABEL
  parent_id:
menu_1:
  name: $LABEL
  parent_id: <%= Fixtures.identify(:root) %>

他にもまだまだ便利な書き方はたくさんありそうです。

カテゴリ ,  | タグ  | コメントなし | トラックバックなし

Hiki on Rack again

投稿者 okkez 2009-08-24 15:41:00 GMT

Hiki の Rack 対応のために Hiki の svn リポジトリに rack ブランチを切りました。 一応、ページの編集はできます。

動作確認してないのは

  • XML-RPC
  • ほとんどのプラグイン

です。

で、ローカルでの開発には git-svn を使っています。 使ってみた感じでは、いい感じだったのでちょっと手順をメモしておきます。

branches/rack は先に svn cp で作っておきました。 Hiki は svn の 標準的なディレクトリ構成になっているので -s オプションでいけました。

$ git svn clone --prefix svn/ -s https://svn.sourceforge.jp/svnroot/hiki/hiki/ hiki-git
$ git br -a
  svn/hitoshi
  svn/rack
  svn/tags/V0_4_2a
........ (tags/ なブランチが多いので略)
  svn/tags/v0_8_8
  svn/tags/v0_8_8_1
  svn/trunk
  svn/v0_5_branch
  svn/v0_6
  svn/v0_8_8
$ git br
* master
$ git svn info
Path: .
URL: https://svn.sourceforge.jp/svnroot/hiki/hiki/trunk
Repository Root: https://svn.sourceforge.jp/svnroot/hiki
Repository UUID: 684b846f-27f2-41ea-b66a-77a1bafa84c1
Revision: 1006
Node Kind: directory
Schedule: normal
Last Changed Author: fdiary
Last Changed Rev: 1006
Last Changed Date: 2009-08-24 14:53:26 +0900 (月, 24  8月 2009)

最初にできる master ブランチで git svn info を実行してみて URL が trunk じゃなかったら master を作り直した方が いいと思います。こんな感じです。

$ git co -b master2 remotes/svn/trunk
$ git br -D master
$ git br -m master2 master
$ git svn info
Path: .
URL: https://svn.sourceforge.jp/svnroot/hiki/hiki/trunk
Repository Root: https://svn.sourceforge.jp/svnroot/hiki
Repository UUID: 684b846f-27f2-41ea-b66a-77a1bafa84c1
Revision: 1006
Node Kind: directory
Schedule: normal
Last Changed Author: fdiary
Last Changed Rev: 1006
Last Changed Date: 2009-08-24 14:53:26 +0900 (月, 24  8月 2009)

この状態で master ブランチを編集して git svn dcommit すると svn の trunk に反映されます。 次に svn の rack ブランチをローカルでいじるためのブランチを用意します。

$ git co -b rack remotes/svn/rack
$ git svn info
Path: .
URL: https://svn.sourceforge.jp/svnroot/hiki/hiki/branches/rack
Repository Root: https://svn.sourceforge.jp/svnroot/hiki
Repository UUID: 684b846f-27f2-41ea-b66a-77a1bafa84c1
Revision: 1007
Node Kind: directory
Schedule: normal
Last Changed Author: okkez
Last Changed Rev: 1007
Last Changed Date: 2009-08-25 00:33:07 +0900 (火, 25  8月 2009)

URL が変わっていることに注意してください。 これでこのブランチをいじって git svn dcommit すると svn の rack ブランチに反映されます。

trunk の変更を rack ブランチに取り込む場合は git merge を使うのではなく、 git format-patch と git am を使うと綺麗に出来るようです。

trunk への変更が一つの場合。

$ git co master 
$ git format-patch HEAD^
(0001-xxx.patch というファイルが作成される)
$ git co rack
$ git am <さっきのファイル> # 複数ある場合は複数指定可能。ちゃんと順番にパッチをあててくれる。
$ git svn dcommit

複数の変更を取り込む場合は、git format-patch HEAD^ とかやるといいです。 パッチの数が多くなるときは -o オプションで出力先ディレクトリを分けておくと便利かもしれません。

カテゴリ ,  | タグ , ,  | コメントなし | トラックバックなし

Livecoding#6

投稿者 okkez 2009-07-12 02:00:00 GMT

Livecoding#6 に参加してきた。

今回の Livecoding はみんな成功しててあんまり面白くなかった。(メシウマ的な意味で)

やっぱり Livecoding では visual 的に何か魅せるものが見ていて面白いと思いました。

残念だったのは ust 中継が準備不足でできなかったこと。事前に skypechat room に集まっていたのに その辺の話が全然できていませんでした。見たかった人は本当にすみません。 irc chat も用意してあったのにほとんど会話がなくて外から見てた人は本当につまらなかったと思います。 直前にリポジトリ消失事件とかあったりしてバタバタしてたのも原因かもしれません。

今度から何かイベントがあるときで主催に近い位置にいるときは、もうちょっと運営に気を配ろうと思います。

カテゴリ  | タグ  | コメントなし | トラックバックなし

Redmine works with git repository on github.com

投稿者 okkez 2009-02-15 04:02:00 GMT

github にある git リポジトリと自分で建ててる Redmine とを連携させてみる。

最初の一歩は公式の Redmine - RedmineRepositories - Redmine に載ってるので簡単。

$ cd /path/to/redmine
$ sudo mkdir git_repositories
$ sudo chmod ... # 権限を調整する
$ cd git_repositories
$ git clone --bare git://github.com/<your_name>/<your_repo_name>.git
$ cd <your_repo_name>
## ここからがポイント。
$ git --bare remote add origin git://github.com/<your_name>/<your_repo_name>.git
$ git --bare fetch

ポイントは git clone –bare が git clone と違って自動的に remote を登録してくれないこと。 これを手動で登録すれば OK。 もちろん config ファイルを自分で編集しても大丈夫。

あとは cron なり、何なりで fetch すればいいはず。

Redmine のリポジトリには今、作成した bare リポジトリのフルパスを指定すれば OK 。

追記 (2008-02-22)

以前、書いた部分がちょっと不十分だったようなので追記。

以下のようにしないと、ちゃんと反映されないみたい。

$ git --bare fetch git_repo_path master:master

カテゴリ ,  | タグ ,  | コメントなし | トラックバックなし

Rails で JSON な view を使う方法

投稿者 okkez 2009-02-03 02:53:00 GMT

ちょっとひっかかったのでメモ。

jquery の treeview で動的にツリーを構築する場合は JSON 形式でデータを返さなければならない。 そんなときに使用する方法。

treeview の構築はこんな感じで。

jQuery("#ulid").treeview({
  url: "<%= url_for(:controller => 'foo', :action => 'tree', :format => 'json') %>",
  ajax: {
    data:{"authenticity_token": token},
    type: "post"
  }
})

action はこんな感じ。ファイル名は tree.json.erb とかで。

# ...
def tree
  # ... インスタンス変数とかの準備
  @data = Item.find(:all, :select => 'id, name', :order => 'name')
  respond_to do |format|
    format.json
  end
end
# ...

view はもっと複雑でもいいですがこんな感じで。

<%=
@data.map{|e|
  {
     :id => e.id,
     :text => e.name,
     :hasChildren => has_children?(e.id) # helper で実装する
  }
}.to_json
%>

カテゴリ ,  | タグ  | コメントなし | トラックバックなし