testdiff - Test::Unitのテスト結果をdiff形式で表示する

目的

Test::Unitでassertに失敗したときに表示されるメッセージを、unified diff形式で表示したい。
配列や文字列を操作するメソッドをテストしたときの表示が、

<"A\nB\nC\n"> expected but was
<"A\nC\nD\n">.

となるよりは、

--- expected
+++ actual
 A
-B
 C
+D

のように表示してほしい。

結果

diff表示ライブラリ作成と、テストケースクラスのメソッド拡張で実現した。

  1. tinydiff.rb(https://sssvn.jp/svn/spikelet/ruby/diff/tinydiff.rb)をロードパスが通った場所におく
  2. テストケースクラスにメソッドを追加
require 'tinydiff'
class TestSomeClass < Test::Unit::TestCase
  def assert_equal_with_diff(expected, actual, message=nil)
    full_message = build_message(message, <<EOT)
--- expected
+++ actual
#{TinyDiff::diff(expected, actual)}
EOT
    assert_block(full_message) { expected == actual }
  end

  def test_foo()
    asswert_equal_with_diff(...)
  end
end

以下、詳細。

diff表示ライブラリの作成

下記で詳解されているAlgorithm::SimpleDiffをベースに、diff表示に必要な最小限のクラスを作成した。
http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-list/39747?39726-40127

文字列、もしくは文字列の配列を受け取り、各行または要素ごとのdiff結果をunified diff形式の文字列にして返却する。

ライブラリ: https://sssvn.jp/svn/spikelet/ruby/diff/tinydiff.rb

実行例:https://sssvn.jp/svn/spikelet/ruby/diff/sample-tinydiff.rb

% ruby sample-tinydiff.rb
---- diff between strings ----
  this is the first line.
 -this is the second line.
  this is the third line.
 +second line is removed and forth line is added.
---- diff between arrays ----
  A
  B
 -C
  D
  E
 +F

テスト実行クラスでdiffを表示するassertを定義

(Test::Unitの使い方は、プログラミング言語 Ruby リファレンスマニュアルあたりを参照)。

require 'tinydiff'
class TestSomeClass < Test::Unit::TestCase
  def assert_equal_with_diff(expected, actual, message=nil)
    full_message = build_message(message, <<EOT)
--- expected
+++ actual
#{TinyDiff::diff(expected, actual)}
EOT
    assert_block(full_message) { expected == actual }
  end

  def test_foo()
    asswert_equal_with_diff(...)
  end
end

こうすることで、assert失敗時のメッセージが(いくらか)わかりやすくなった。

実施例

TinyDiffを組み込んだテストケースの参考として、以下を挙げておく: