2008-09-29 15 views
61

Estoy expandiendo mi comprensión de Ruby mediante la codificación de un equivalente de xUnit de Kent Beck en Ruby. Python (en el que Kent escribe) tiene un método assert() en el idioma que se usa ampliamente. Ruby no. Creo que debería ser fácil agregar esto, pero ¿Kernel es el lugar correcto para ponerlo?¿Es idiomático que Ruby agregue un método assert() a la clase Kernel de Ruby?

BTW, Sé de la existencia de varios frameworks de unidades en Ruby - este es un ejercicio para aprender los modismos de Ruby, en lugar de "hacer algo".

+3

Me gustan los problemas que hacen ambas cosas: enseñarte y hacer algo. :) –

Respuesta

77

No, no es una buena práctica. La mejor analogía para afirmar() en Ruby es simplemente una cuestión de

raise "This is wrong" unless expr 

y se puede poner en práctica sus propias excepciones si desea proporcionar para el manejo de

+22

También puede usar 'fail if [expr]', si lo desea, lo que arroja un Runtime Error. –

+6

'fail' es un alias para 'raise', ¿no es así? Ambos dan 'RuntimeError'. (¿Quizás uno es más idiomático?) –

+0

Consulte "error" aquí: http://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html –

14

¿Cuál es el motivo para agregar el método assert al módulo Kernel? ¿Por qué no usar otro módulo llamado Assertions o algo así?

De esta manera:

module Assertions 
    def assert(param) 
    # do something with param 
    end 

    # define more assertions here 
end 

Si realmente necesita sus afirmaciones a estar disponible en todas partes hacer algo como esto:

class Object 
    include Assertions 
end 

Negación: no he probado el código, pero, en principio, Yo lo haría así.

+1

¿No es este parche parche? Estás alterando la clase 'Object'. – tsikov

+0

Sí, eso es parche de mono clásico. Esa es la manera de hacerlo, si realmente tiene que hacer que el método 'assert' esté disponible globalmente. Sin embargo, no recomendaría a nadie que use parches de mono como este en proyectos que no sean juguetes. –

4

Según tengo entendido, usted está escribiendo su propio conjunto de pruebas como una forma de familiarizarse con Ruby. Entonces, aunque Test :: Unit podría ser útil como guía, probablemente no sea lo que estás buscando (porque ya ha hecho el trabajo).

Dicho esto, la afirmación de python es (para mí, al menos), más análoga a C assert(3). No está específicamente diseñado para pruebas unitarias, sino para detectar casos en los que "esto nunca debería suceder". Como las pruebas de unidades incorporadas de Ruby tienden a ver el problema, cada clase de caso de prueba individual es una subclase de TestCase, y eso incluye una declaración de "afirmación" que verifica la validez de lo que se le pasó. y lo registra para informar.

6

No es especialmente idiomática excepción más específica, pero yo creo que es una buena idea. Sobre todo 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 correr con depuración (o algún otro interruptor conveniente, que he usado en el pasado Kernel.do_assert) conjunto.

25

Creo que es totalmente válido para usar aseveraciones en Ruby. Pero usted menciona dos cosas diferentes:

  • xUnit frameworks usa assert métodos para verificar las expectativas de sus pruebas. Están destinados a ser utilizados en su código de prueba, no en su código de aplicación.
  • Algunos lenguajes como C, Java o Python incluyen una construcción assert destinada a ser utilizada dentro del código de sus programas, para verificar las suposiciones que hace sobre su integridad. Estos controles están construidos dentro del código mismo. No son una utilidad de tiempo de prueba, sino una herramienta de tiempo de desarrollo.

Hace poco escribí solid_assert: a little Ruby library implementing a Ruby assertion utility y también a post in my blog explaining its motivation .. Se permite escribir 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 puede desactivarse de manera assert y invariant se evalúan como declaraciones vacías. Esto le permite evitar cualquier problema de rendimiento en la producción. Pero tenga en cuenta que The Pragmatic Programmers desaconseja su desactivación. Solo debe desactivarlos si realmente afectan el rendimiento.

En cuanto a la respuesta que dice que la manera idiomática de Ruby usa una declaración normal raise, creo que carece de expresividad. Una de las reglas de oro de la programación asertiva no es utilizar aserciones para el manejo de excepciones normales. 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, usted pierde la capacidad de desactivarlos.

Puede estar convencido de que usar afirmaciones es algo bueno porque dos libros clásicos de lectura obligatoria como The Pragmatic Programmer From Journeyman to Master y Code Complete les dedican secciones completas y recomiendan su uso. También hay un buen artículo titulado Programming with assertions que ilustra muy bien qué es la programación asertiva y cuándo usarla (está basada en Java, pero los conceptos se aplican a cualquier idioma).

+0

También sugiero "Escribir código sólido" de Steve Maguire, que está extremadamente orientado a C, pero habla de afirmaciones, estrategias de prueba e ideas sobre la construcción de funciones que también se aplican a la construcción de métodos. –

+0

Nice little gem- gracias – Yarin

Cuestiones relacionadas