0

ロギングのテストを支援するテストライブラリがあります。

require 'stringio'

module RedirectIo
  def setup
    $stderr = @stderr = StringIO.new
    $stdin = @stdin = StringIO.new
    $stdout = @stdout = StringIO.new
    super
  end

  def teardown
    $stderr = STDERR
    $stdin = STDIN
    $stdout = STDOUT
    super
  end
end

これは、次のように使用することを目的としています。

require 'lib/redirect_io'

class FooTest < Test::Unit::TestCase
  include RedirectIo

  def test_logging
    msg = 'bar'
    Foo.new.log msg
    assert_match /^#{TIMESTAMP_REGEX} #{msg}$/, @stdout.string, 'log message'
  end
end

もちろん、テストライブラリの単体テストもあります。:)

require 'lib/redirect_io'

class RedirectIoTest < Test::Unit::TestCase
  def test_setup_and_teardown_are_mixed_in
    %W{setup teardown}.each do |method|
      assert_not_equal self.class, self.class.new(__method__).method(method).owner, "owner of method #{method}"
    end

    self.class.class_eval { include RedirectIo }
    %W{setup teardown}.each do |method|
      assert_equal RedirectIo, self.class.new(__method__).method(method).owner, "owner of method #{method}"
        end
  end

  def test_std_streams_captured
    %W{STDERR STDIN STDOUT}.each do |stream_name|
      assert_equal eval(stream_name), self.class.new(__method__).instance_eval("$#{stream_name.downcase}"), stream_name
    end

    self.class.class_eval { include RedirectIo }

    setup
    %W{STDERR STDIN STDOUT}.each do |stream_name|
      assert_not_equal eval(stream_name), self.class.new(__method__).instance_eval("$#{stream_name.downcase}"),
          stream_name
    end

    teardown
    %W{STDERR STDIN STDOUT}.each do |stream_name|
      assert_equal eval(stream_name), self.class.new(__method__).instance_eval("$#{stream_name.downcase}"), stream_name
    end
  end
end

RedirectIo.setupteardownがsuperを呼び出すことをテストする方法を理解するのに問題があります。何か案は?

4

1 に答える 1

1

私はそれを行う1つの方法を考え出しました。これにより、実際にはテストコードもはるかにクリーンになります。

require 'lib/redirect_io'

class RedirectIoTest < Test::Unit::TestCase
  class RedirectIoTestSubjectSuper < Test::Unit::TestCase
    def setup
      @setup = true
    end
    def teardown
      @teardown = true
    end
  end

  class RedirectIoTestSubject < RedirectIoTestSubjectSuper
    include RedirectIo
    def test_fake; end
  end

  def test_setup_and_teardown_are_mixed_in
    %W{setup teardown}.each do |method|
      assert_not_equal RedirectIoTestSubject, self.method(method).owner, "owner of method #{method}"
    end

    %W{setup teardown}.each do |method|
      assert_equal RedirectIo, RedirectIoTestSubject.new(:test_fake).method(method).owner, "owner of method #{method}"
    end
  end

  def test_std_streams_captured
    obj = RedirectIoTestSubject.new(:test_fake)
    $stderr = STDERR
    $stdin = STDIN
    $stdout = STDOUT

    obj.setup
    %W{STDERR STDIN STDOUT}.each do |stream_name|
      assert_not_equal eval(stream_name), eval("$#{stream_name.downcase}"), stream_name
    end

    obj.teardown
    %W{STDERR STDIN STDOUT}.each do |stream_name|
      assert_equal eval(stream_name), eval("$#{stream_name.downcase}"), stream_name
    end
  end

  def test_setup_and_teardown_call_super
    obj = RedirectIoTestSubject.new(:test_fake)
    obj.setup
    assert obj.instance_eval{@setup}, 'super called?'
    obj.teardown
    assert obj.instance_eval{@teardown}, 'super called?'
  end
end
于 2011-03-08T13:15:47.630 に答える