リファクタリングRubyエディション6.5のテストコードを書いてみた

今、リファクタリングRubyエディションを読んでいます。6.5 一時変数からチェインへで、Selectクラスは、@optionsという配列にadd_optionを呼ぶたびに西暦を加えていきます。このテストコードを考えたのですが、結構面倒だったので、記事を書きます。

はじめ、テストコードでは配列をアサートすればいいかなと考えたのですが、そうではなかったです。配列とSelectの要素を比較するため、Selectクラスに要素のサイズを得るメソッドsizeと要素を取り出すメソッドelemを追加しました。

Selectクラスに追加したコード

def size
	@options.size
end

def elem(i)
	@options[i]
end

また、Selectの要素と配列の要素を比較するため、Test::Unitのassert_blockを使いました。テストコードは次のようになります。

require ‘test/unit’
require_relative ‘select’

class TestSelect < Test::Unit::TestCase def test_add_options result = Select.add_options expected_result = [1999, 2000, 2001, 2002] assert_block("array error") { boolean = true if (expected_result.size != result.size) boolean = false else for i in 0...expected_result.size do if (expected_result[i] != result.elem(i)) boolean = false end end boolean end } end end [/ruby] テスト対象コードをいじるのはあまり好ましくないだろうけど、ちょっと他の方法は思いつきませんでした。また、asssert_blockを使うときには、どの要素の値がどうで、期待値がどうとか表示できるようにした方がいいのでしょうが、目的がリファクタリングのためのテストコード作成だったので、そこまではやりませんでした。なお、assert_block内で、真偽値をreturnで返すようなことをやると、うまくテストコードが動きませんでした。

リファクタリングRubyエディション6.1に対するテストコード

今、リファクタリングRubyエディションを読んでいます。
6章に入ったら、いきなり標準出力するコードのリファクタリングが出てきます。JUnit実践入門を以前読んだとき、標準出力するコードのテストをやるには、スパイを利用して難しかった記憶があります。Rubyのテストでも、そうなのかなと、ググったのですが、Arieteという便利なgemがあることがわかりました。Rubyの標準出力をキャプチャしてユニットテストで使いやすくするモジュール Ariete
gemは次のようにインストールします。

$ gem install ariete

リファクタリング前のテスト対象コード owing.rb は

class Owing
	def initialize(name)
		@name = name
	end

	def print_owing(amount)
		print_banner
		puts "name: #{@name}"
		puts "amount: #{amount}"
	end

	def print_banner
		puts "banner"
	end

end

です。これに対するテストコード test_owing.rb は

require ‘test/unit’
require ‘ariete’
require_relative ‘owing’

class TestOwing < Test::Unit::TestCase include Ariete def setup @owing = Owing.new('foo') end def test_print_owing result = capture_stdout {@owing.print_owing(10)} expected_result = "banner\n" + "name: foo\n" + "amount: 10\n" assert_equal(expected_result, result) end end[/ruby] になります。 これで、標準出力しているコードでも、リファクタリングできるようになります。

リファクタリングRubyエディションの第1章のテストコードを作った

今、リファクタリングRubyエディションを読んでいるんだけど、第1章のリファクタリングの写経が終わった。
この本では、リファクタリングの前に、リファクタリング対象コードに対するテストコードを書けと書いてあるのに、ユニットテストの紹介は第4章で手短にしか説明していない。また、第1章のビデオレンタルシステムのサンプルコードのリファクタリングでは、テストコードが掲載されていなくて、テストコードなしでリファクタリングするのは怖いし、できない。自分はRSpecを使ったテストの勉強はしたのだが、RubyのTest::Unitテストフレームワークの勉強ははじめてだ(本当言うと、10年以上前に、Ruby 256倍シリーズでユニットテストの勉強をした覚えがあるが、やり方をすっかり忘れてしまった)。そこで、第1章のサンプルコードに対するテストファイルを作成した。テスト項目をグループ分けしていなかったり、同じような記述をメソッド抽出していないけど、テストコードだからいいかと思う。テストコードはGitHubに上げたので、使いたい人がいたら、どうぞ。ただし、なるべくテスト対象コードを本の記述の通りに入力したつもりだが、ascii、html両フォーマットでのフッター行の期待する文字列が正しくなく、テストコードが動作しない場合があるかもしれない。その場合は、修正するので、Pull Requestを送って欲しい。

https://github.com/andropenguin/testfiles_refactoring_ruby_chap01.git

IntelliJ IDEAでRuby on Railsアプリの新規作成にハマった

Ubuntu 12.04にIntelliJ IDEAを入れ、Rubyプラグインを入れました。ruby、railsはRVMを使い、マルチユーザでインストールしました。そのとき、Railsアプリ新規作成でハマったので、書きます。

新規作成時、ConfigureでRuby SDKを設定する必要がありますが、RVMでマルチユーザでrubyをインストールした場合、デフォルトではrubyの場所は/usr/local/rvm/bin/ruby/rubyと表示されます。これや、同じディレクトリ内のバージョン付きのrubyを選択すると、次の設定画面で、”Your SDK doesn’t contain Rails Framework”といわれ、Railsプロジェクトが作れません。rubyの選択では、/usr/local/rvm/rubies/ruby-1.9.3-p362/bin/rubyのように、/usr/loval/rvm/rubies配下のrubyを選択すべきです。このようにすると、次の設定画面で、Railsのバージョンが表示されます。

Ruby on RailsによるWebアプリケーションスーパーサンプルを読んで

中村真一郎氏のRuby on RailsによるWebアプリケーションスーパーサンプルを1日1~2時間(日によっては3時間)、21日かけて読みました。

全体的な感想は、次のとおりです。

この本はrails gで生成されるファイルで、修正することもないファイルの内容を掲載したりして、やたらとページを稼いでいる割には、なんでそういうコードを書くのかとか、テストコードはどういう考え方でこういう書き方をしますとかの説明があまりなかった。追記するファイルも、内容を全部掲載することが多く、追記する前後だけ掲載すればいいんじゃないと思った。データベース操作、テストの紹介も表面的で、広く浅くだ。本格的なサンプルアプリは、最後の章のブログシステムだけ。サンプル本とうたっているので、いろいろなアプリの実例が載っているかと期待していたので、期待外れだった。この本では、DataMapper、 MongoDB、Rspec、Cucumber、Herokuを取り上げているのが特徴だが、それぞれの説明は浅く中途半端な印象が否めない。それらの特徴を除けば、基礎Ruby on RailsでRuby on Railsで勉強した方が、基本的なことは身につきやすいと思う。なお、この本で扱っているRuby on Railsのバージョンは3.0.5で、現在の最新版は3.2.1だが、本を通読するには、本の環境 ruby 1.9.2、rails 3.0.5に合わせた方がいいだろう。それでも、一部使用するソフトウエアが本のバージョンと乖離していて、動作しないサンプルもあり、Ruby on Railsのバージョンを3.2に変えたり、ググって、解決する必要があった。これに関連してだが、本のサポートページがないかと調べたら、Ruby on RailsによるWebアプリケーション・スーパーサンプル改訂版サポートサイトが引っかかったんだが、本の正誤情報などなく、やたらと広告が貼ってあって苦笑した。(記事末尾、追記参照)

今日読んだ、5-5 Herokuにアプリケーションを公開するで、ハマったので記録しておく。Herokuはsqlite3はサポートしていないようで、postgresqlを使用しないとダメみたい。http://stackoverflow.com/questions/7963561/heroku-stack-cedar-cannot-run-git-push-heroku-master にしたがって、Gemfileで

group :production do
  gem 'pg'
end
group :development, :test do
  gem 'sqlite3'
end

と記述し、

$ git add Gemfile
$ git commit -m "Removed sqlite3 from Gemfile"
$ git push heroku master

すると、pgをインストールしろと言われる。色々ググると、postgressqlをインストールして、pgをオプション付きでインストールしないとダメみたい。(http://d.hatena.ne.jp/piggery/20120521とか)

$ sudo apt-get instal postgresql
$ gem install pg -- --with-pg-config=/usr/bin/pg_config

libpg-devがねーよと言われるんだが、Ubuntuにはそんなパッケージがない。さらにググると、http://askubuntu.com/questions/105514/rails-libpq-dev-nasty-dependenciesとかが引っかかり、

$ bundle install --without production

するといいらしい。だけど、

You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.

と言われるので、

$ bundle install
$ git add .
$ git commit -m "modify lock file"
$ git push heroku master

で、アプリをディプロイできた。色々いじくりまわしたので、書き忘れた操作があるかもしれないし、誤記もあるかもしれない。

追記 Sep 13, 2012 夜。記事をアップした日の夜、Ruby on RailsによるWebアプリケーション・スーパーサンプル改訂版サポートサイトにアクセスしたら、 Rails3.1 (11) のリンクに、Rails 3.1対応の記事が載せられている。昼間見たときは、ここのサイト、広告リンクばかりに見えたんだけどね。見間違いだったのかなぁ。