¿Cuáles son las mejores prácticas para probar módulos en rspec? Tengo algunos módulos que se incluyen en algunos modelos y por ahora simplemente tengo pruebas duplicadas para cada modelo (con pocas diferencias). ¿Hay alguna manera de SECARLO?
ruby
unit-testing
rspec
Andrius
fuente
fuente
let(:dummy_class) { Class.new { include ModuleToBeTested } }
let(:class_instance) { (Class.new { include Super::Duper::Module }).new }
esa manera obtengo la variable de instancia que se usa con mayor frecuencia para probar de cualquier manera.include
no funciona para mí, pero loextend
hacelet(:dummy_class) { Class.new { extend ModuleToBeTested } }
subject(:instance) { Class.new.include(described_class).new }
Lo que dijo Mike. Aquí hay un ejemplo trivial:
código de módulo ...
fragmento de especificación ...
fuente
include Say
dentro de la declaración DummyClass en lugar de llamarextend
?extend
entrando en la instancia de la clase, es decir, después denew
haber sido llamado. Si hicieras esto antesnew
se llama, entonces tienes razóninclude
DummyClass
constante? ¿Por qué no solo@dummy_class = Class.new
? Ahora estás contaminando tu entorno de prueba con una definición de clase innecesaria. Este DummyClass se define para todas y cada una de sus especificaciones y en la siguiente especificación donde decide usar el mismo enfoque y volver a abrir la definición de DummyClass, es posible que ya contenga algo (aunque en este ejemplo trivial la definición está estrictamente vacía, en la vida real casos de uso es probable que algo se agregue en algún momento y luego este enfoque se vuelva peligroso.)Para los módulos que se pueden probar de forma aislada o burlándose de la clase, me gusta algo como:
módulo:
Especificaciones:
Puede parecer incorrecto secuestrar grupos de ejemplos anidados, pero me gusta la brevedad. ¿Alguna idea?
fuente
let
método descrito por @metakungfu es mejor.Encontré una solución mejor en la página de inicio de rspec. Aparentemente, admite grupos de ejemplo compartidos. ¡Desde https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/example-groups/shared-examples !
fuente
Fuera de mi cabeza, ¿podrías crear una clase ficticia en tu script de prueba e incluir el módulo en eso? Luego compruebe que la clase ficticia tiene el comportamiento de la manera que esperaría.
EDITAR: si, como se señala en los comentarios, el módulo espera que algunos comportamientos estén presentes en la clase en la que se mezclan, entonces trataría de implementar dummies de esos comportamientos. Solo lo suficiente para que el módulo esté feliz de realizar sus tareas.
Dicho esto, me pondría un poco nervioso por mi diseño cuando un módulo espera mucho de su clase host (¿decimos "host"?) - Si aún no heredé de una clase base o no puedo inyectar la nueva funcionalidad en el árbol de herencia, entonces creo que estaría tratando de minimizar cualquier expectativa que pueda tener un módulo. Mi preocupación es que mi diseño comenzaría a desarrollar algunas áreas de inflexibilidad desagradable.
fuente
Creo que la respuesta aceptada es la respuesta correcta, sin embargo, quería agregar un ejemplo de cómo usar rpsecs
shared_examples_for
yit_behaves_like
métodos. Menciono algunos trucos en el fragmento de código, pero para obtener más información, consulte esta guía de relishapp-rspec .Con esto puede probar su módulo en cualquiera de las clases que lo incluyen. Entonces realmente está probando lo que usa en su aplicación.
Veamos un ejemplo:
Ahora creemos especificaciones para nuestro módulo:
movable_spec.rb
fuente
Qué pasa:
fuente
Sugeriría que para módulos más grandes y muy usados uno debería optar por los "Grupos de ejemplo compartidos" como lo sugiere @Andrius aquí . Para cosas simples para las que no desea pasar por la molestia de tener varios archivos, etc., aquí le mostramos cómo garantizar el máximo control sobre la visibilidad de sus cosas ficticias (probado con rspec 2.14.6, simplemente copie y pegue el código en un archivo de especificaciones y ejecutarlo):
fuente
subject { dummy_class.new }
está funcionando. El caso consubject { dummy_class }
no me funciona.mi trabajo reciente, utilizando el menor cableado posible
Yo deseo
funcionó, pero no funciona (como en Ruby MRI 2.2.3 y RSpec :: Core 3.3.0)
Obviamente, describe_class no es visible en ese ámbito.
fuente
Para probar su módulo, use:
Para SECAR algunas cosas que usa en múltiples especificaciones, puede usar un contexto compartido:
Recursos:
fuente
También puedes usar el tipo de ayuda
Aquí está la documentación: https://www.relishapp.com/rspec/rspec-rails/v/3-3/docs/helper-specs/helper-spec
fuente
simplemente debe incluir su módulo en su archivo de especificaciones
mudule Test module MyModule def test 'test' end end end
en su archivo de especificacionesRSpec.describe Test::MyModule do include Test::MyModule #you can call directly the method *test* it 'returns test' do expect(test).to eql('test') end end
fuente
Una posible solución para probar el método del módulo que es independiente de la clase que los incluirá
Y especificaciones para ello
Y si quieres probarlos en SECO, entonces shared_examples es un buen enfoque
fuente
subject(:module_to_test_instance) { Class.new.include(described_class) }
. De lo contrario, realmente no veo nada malo en tu respuesta.Este es un patrón recurrente ya que necesitará probar más de un módulo. Por esa razón, esto es más que deseable para crear un ayudante para esto.
Encontré esta publicación que explica cómo hacerlo, pero estoy haciendo frente aquí ya que el sitio podría ser eliminado en algún momento.
Esto es para evitar que las instancias de objeto no implementen el método de instancia:: cualquier error que obtenga al intentar
allow
métodos endummy
clase.Código:
En
spec/support/helpers/dummy_class_helpers.rb
En
spec/spec_helper.rb
En sus especificaciones:
fuente