Vraag Waarom heeft MiniTest :: Spec geen wont_raise-bewering?


Ruby's Test::Unit heeft assert_nothing_raised. Test::Unit is vervangen door MiniTest. Waarom hebben de beweringen / verwachtingen van MiniTest hier niets mee te maken? Je kunt het bijvoorbeeld verwachten must_raise maar niet wont_raise.


29
2017-09-19 16:48


oorsprong


antwoorden:


MiniTest implementeert assert_nothing_raised in de Test :: Unit-compatibiliteitslaag, maar in zijn eigen tests (MiniTest::Unit en MiniTest::Spec) het doet niet voer een test als deze uit. De reden is, zo stelt de programmeur, dat testen op niets dat wordt opgeworpen geen test van iets is; u nooit verwachten dat iets wordt verhoogd in een test, behalve tijdens het testen voor een uitzondering. Als er een onverwachte (niet-afgevangen) uitzondering in de code voor een test voorkomt, krijgt u een uitzondering die door de test in goede staat is gerapporteerd en weet u dat u een probleem ondervindt.

Voorbeeld:

require 'minitest/autorun'

describe "something" do
  it "does something" do
    Ooops
  end
end

Output:

Run options: --seed 41521

# Running tests:

E

Finished tests in 0.000729s, 1371.7421 tests/s, 0.0000 assertions/s.

  1) Error:
test_0001_does_something(something):
NameError: uninitialized constant Ooops
    untitled:5:in `block (2 levels) in <main>'

1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

Dat is precies wat je wilde weten. Als je verwachtte dat er niets zou worden verhoogd, heb je het niet begrepen en dat is je ook verteld.

Dus het argument hier is: niet gebruiken assert_nothing_raised! Het is gewoon een nietszeggende kruk. Zie bijvoorbeeld:

https://github.com/seattlerb/minitest/issues/70

https://github.com/seattlerb/minitest/issues/159

http://blog.zenspider.com/blog/2012/01/assert_nothing_tested.html

Aan de andere kant, duidelijk assert_nothing_raised komt overeen met wat intuïtie bij gebruikers, omdat zoveel mensen een a verwachten wont_raise gaan met must_raise, etc. In het bijzonder zou men willen focussen een bewering hierop, niet alleen maar een test. Gelukkig is MiniTest uiterst minimalistisch en flexibel, dus als je je eigen routine wilt toevoegen, dan kan dat. Dus je kunt een methode schrijven die voor geen uitzondering test en een bekende uitkomst retourneert als er geen uitzondering is, en nu kun je beweren dat die uitkomst bekend is.

Bijvoorbeeld (ik zeg niet dat dit perfect is, alleen het idee laten zien):

class TestMyRequire < MiniTest::Spec
  def testForError # pass me a block and I'll tell you if it raised
    yield
    "ok"
  rescue
    $!
  end
  it "blends" do
    testForError do
      something_or_other
    end.must_equal "ok"
  end
end

Het punt is niet dat dit een goed of slecht idee is, maar dat het nooit de verantwoordelijkheid van MiniTest was om het voor u te doen.


45
2017-09-19 16:48



Als je het nodig hebt:

# test_helper.rb

module Minitest::Assertions
  def assert_nothing_raised(*)
    yield
  end
end

En om het te gebruiken:

def test_unknown_setter
  assert_nothing_raised do
    result.some_silly_column_name = 'value'
  end
end

7
2018-05-11 08:40



Dit stoorde me genoeg om in de MiniTest-bronnen te graven en een implementatie in mijn spec_helper.rb het dossier:

module MiniTest
  module Assertions
    def refute_raises *exp
      msg = "#{exp.pop}.\n" if String === exp.last

      begin
        yield
      rescue MiniTest::Skip => e
        return e if exp.include? MiniTest::Skip
        raise e
      rescue Exception => e
        exp = exp.first if exp.size == 1
        flunk "unexpected exception raised: #{e}"
      end

    end
  end
  module Expectations
    infect_an_assertion :refute_raises, :wont_raise
  end
end 

Ik hoop dat dit nuttig is voor iemand anders die het ook nodig heeft wont_raise. Proost! :)


2
2017-09-01 15:52