ruby - rails - ¿Por qué MiniTest:: Spec no tiene una aserción wont_raise?
minitest rails (3)
Esto me molestó lo suficiente como para profundizar en las fuentes de MiniTest y proporcionar una implementación en mi archivo spec_helper.rb
:
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
Espero que esto resulte útil para alguien que también necesita wont_raise
. ¡Aclamaciones! :)
Test::Unit
de Ruby Test::Unit
tiene assert_nothing_raised
. Test::Unit
ha sido reemplazada por MiniTest . ¿Por qué las aseveraciones / expectativas de MiniTest no tienen nada de paralelo? Por ejemplo, puede esperar must_raise
pero no wont_raise
.
MiniTest implementa assert_nothing_raised
en su capa de compatibilidad de prueba :: unidad, pero en sus propias pruebas ( MiniTest::Unit
y MiniTest::Spec
) no implementa ninguna prueba como esta. La razón es, argumenta el programador, que probar nada planteado no es una prueba de nada; nunca esperas que se suba algo en una prueba, excepto cuando estás probando una excepción. Si se produce una excepción inesperada (no detectada) en el código de una prueba, recibirá una excepción informada en buenas condiciones por la prueba y sabrá que tiene un problema.
Ejemplo:
require ''minitest/autorun''
describe "something" do
it "does something" do
Ooops
end
end
Salida:
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
Que es exactamente lo que querías saber. Si no esperaba que se aumentara nada, no lo obtuvo y se lo dijeron.
Entonces, el argumento aquí es: ¡no use assert_nothing_raised
! Es solo una muleta sin sentido. Ver, por ejemplo:
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
Por otro lado, assert_nothing_raised
corresponde claramente a una cierta intuición entre los usuarios, ya que mucha gente espera que una wont_raise
vaya con must_raise
, etc. En particular, uno quisiera enfocar una afirmación en esto, no simplemente una prueba. Por suerte, MiniTest es extremadamente minimalista y flexible, por lo que si desea agregar su propia rutina, puede hacerlo. Por lo tanto, puede escribir un método que no pruebe ninguna excepción y devuelva un resultado conocido si no hay una excepción, y ahora puede afirmar sobre ese resultado conocido.
Por ejemplo (no digo que esto sea perfecto, solo estoy mostrando la idea):
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
El punto no es que sea una buena o mala idea, sino que nunca fue responsabilidad de MiniTest hacerlo por usted.
Si lo necesitas:
# test_helper.rb
module Minitest::Assertions
def assert_nothing_raised(*)
yield
end
end
Y para usarlo:
def test_unknown_setter
assert_nothing_raised do
result.some_silly_column_name = ''value''
end
end