¿Es idiomático Ruby agregar un método assert () a la clase Kernel de Ruby?
Pregunta
Estoy ampliando mi comprensión de Ruby al codificar un equivalente de la unidad de Kent Beck en Ruby. Python (en el que escribe Kent) tiene un método assert () en el lenguaje que se usa ampliamente. Ruby no lo hace. Creo que debería ser fácil agregar esto, pero ¿es Kernel el lugar correcto para ponerlo?
BTW, Sé de la existencia de los distintos marcos de Unidades en Ruby : este es un ejercicio para aprender los idiomas de Ruby, en lugar de "hacer algo".
Solución
No, no es una buena práctica. La mejor analogía para afirmar () en Ruby es simplemente aumentar
raise "This is wrong" unless expr
y puede implementar sus propias excepciones si desea proporcionar un manejo de excepciones más específico
Otros consejos
Creo que es totalmente válido usar aserciones en Ruby. Pero estás mencionando dos cosas diferentes:
-
Los marcos
- xUnit utilizan métodos
afirmar
para verificar las expectativas de sus pruebas. Están diseñados para ser utilizados en su código de prueba, no en el código de su aplicación. - Algunos idiomas, como C, Java o Python, incluyen una construcción de
assert
que se utilizará dentro del código de sus programas, para verificar las suposiciones que realice sobre su integridad. Estas comprobaciones se crean dentro del propio código. No son una utilidad de tiempo de prueba, sino una de desarrollo.
Recientemente escribí solid_assert: una pequeña biblioteca de Ruby implementando una utilidad de afirmación de Ruby y también una publicación en mi blog que explica su motivación .. Dejé escribes expresiones en la forma:
assert some_string != "some value"
assert clients.empty?, "Isn't the clients list empty?"
invariant "Lists with different sizes?" do
one_variable = calculate_some_value
other_variable = calculate_some_other_value
one_variable > other_variable
end
Y se pueden desactivar para que afirmar
y invariante
se evalúen como declaraciones vacías. Esto le permite evitar cualquier problema de rendimiento en la producción. Pero tenga en cuenta que Los programadores pragmáticos recomiendan no desactivarlos. Solo debe desactivarlas si realmente afectan el rendimiento.
Con respecto a la respuesta que dice que la forma idiomática de Ruby está usando una declaración normal de raise
, creo que carece de expresividad. Una de las reglas de oro de la programación asertiva es no usar aserciones para el manejo normal de excepciones. Son dos cosas completamente diferentes. Si usa la misma sintaxis para los dos, creo que su código será más oscuro. Y, por supuesto, pierdes la capacidad de desactivarlos.
Puede estar convencido de que usar aserciones es una buena cosa porque dos libros clásicos de lectura obligatoria como El programador pragmático De Journeyman a Master y Code Complete dedican todo secciones para ellos y recomendar su uso. También hay un buen artículo titulado Programación con aserciones que ilustra muy bien de qué se trata la programación asertiva y cuándo usarla (está basada en Java, pero los conceptos se aplican a cualquier lenguaje).
¿Cuál es su razón para agregar el método de aserción al módulo Kernel? ¿Por qué no usar otro módulo llamado Assertions
o algo así?
Me gusta esto:
module Assertions
def assert(param)
# do something with param
end
# define more assertions here
end
Si realmente necesita que sus afirmaciones estén disponibles en todas partes , haga algo como esto:
class Object
include Assertions
end
Descargo de responsabilidad: no probé el código, pero en principio lo haría así.
No es especialmente idiomático, pero creo que es una buena idea. Especialmente si se hace así:
def assert(msg=nil)
if DEBUG
raise msg || "Assertion failed!" unless yield
end
end
De esa manera no hay impacto si decide no ejecutar con DEBUG (o algún otro conmutador conveniente, he usado Kernel.do_assert en el pasado) establecido.
Tengo entendido que estás escribiendo tu propio conjunto de pruebas para familiarizarte más con Ruby. Entonces, aunque Test :: Unit puede ser útil como guía, probablemente no sea lo que está buscando (porque ya ha hecho el trabajo).
Dicho esto, la afirmación de python es (para mí, al menos), más análoga a la de de C afirmar (3) . No está diseñado específicamente para pruebas unitarias, sino para detectar casos en los que "esto nunca debería suceder".
Cómo las pruebas unitarias integradas de Ruby tienden a ver el problema, entonces, es que cada clase de caso de prueba individual es una subclase de TestCase , y eso incluye un " afirmar " declaración que verifica la validez de lo que se le pasó y la registra para su informe.