3

わずかに異なるセットアップ方法で多くの一般的なテストを共有する必要がある2つの単体テストがあります。私が次のようなものを書くと

class Abstract < Test::Unit::TestCase
  def setup
    @field = create
  end

  def test_1
    ...
  end
end

class Concrete1 < Abstract
  def create
    SomeClass1.new
  end
end

class Concrete2 < Abstract
  def create
    SomeClass2.new
  end
end

その場合、Concrete1はAbstractからテストを継承していないようです。または、少なくとも私はそれらをEclipseで実行させることはできません。Concrete1を含むファイルに対して「すべてのテストケースを実行」を選択すると、Abstractは実行されたくありませんが、実行されます。Concrete1を指定すると、テストはまったく実行されません。Concrete1でtest_1を指定すると、それが見つからないと文句を言います( "uncaught throw:invalid_test(ArgumentError)")。

Rubyは初めてです。ここで何が欠けていますか?

4

2 に答える 2

6

問題は、私が知る限り、Test::Unitどのクラスがから継承するかを追跡Test::Unit::TestCaseし、その結果、直接継承するクラスからのテストを実行することです。

これを回避する方法は、必要なテストを使用してモジュールを作成し、から派生するクラスにそのモジュールを含めるTest::Unit::TestCaseことです。

require 'test/unit'

module TestsToInclude
  def test_name
    assert(self.class.name.start_with?("Concrete"))
  end
end

class Concrete1 < Test::Unit::TestCase
  include TestsToInclude

  def test_something_bad
    assert(false)
  end
end

class Concrete2 < Test::Unit::TestCase
  include TestsToInclude

  def test_something_good
    assert(true)
  end
end

出力:

ロードされたスイート
開始
.F。。
0.027873秒で終了しました。

  1)失敗:
test_something_bad(Concrete1)[a.rb:13]:
<false>は真ではありません。

4つのテスト、4つのアサーション、1つの失敗、0のエラー

シェルが1を返しました
于 2010-04-01T22:45:30.650 に答える
2

問題は、Test::Unit::TestCaseデフォルトではスーパークラスで定義されたテストを明示的に実行しないことです。特に、 true を返さTestSuiteCreatorない限りテストを実行しないことに注意してください ( https://github.com/test-unit/test-unit/blob/2.5.5/lib/test/unit/testsuitecreator.rb#L40 ):Test::Unit::TestCase#valid?

def append_test(suite, test_name)
  test = @test_case.new(test_name)
  yield(test) if block_given?
  suite << test if test.valid?
end

また、テスト ケースが有効かどうかを判断するものは何ですか? このクラスがそのメソッドを明示的に定義した場合、またはメソッドがModule( https://github.com/test-unit/test-unit/blob/2.5.5/lib/test /unit/testcase.rb#L405-L418 ):

def valid? # :nodoc:
  return false unless respond_to?(@method_name)
  test_method = method(@method_name)
  if @internal_data.have_test_data?
    return false unless test_method.arity == 1
  else
    return false unless test_method.arity <= 0
  end
  owner = Util::MethodOwnerFinder.find(self, @method_name)
  if owner.class != Module and self.class != owner
    return false
  end
  true
end

したがって、基本的に、別の単体テスト クラスをサブクラス化し、スーパークラスの単体テストを実行する場合は、次のいずれかを実行できます。

  • サブクラスでこれらのテスト メソッドを再定義し、スーパークラスのテスト メソッドを呼び出させる
  • すべてのメソッドをモジュールに移動します (このスレッドの他の回答で説明されているように)
  • valid?サブクラスのメソッドを再定義して、 true を返します。

def valid? return true end

于 2014-10-22T01:01:39.903 に答える