Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Rspec
Code

Pruebas de RSpec para principiantes, Parte 2

by
Length:LongLanguages:
This post is part of a series called RSpec Testing for Beginners.
RSpec Testing for Beginners, Part 1
RSpec Testing for Beginners, Part 3

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

El segundo artículo de esta breve serie te enseña cómo usar varios matchers que vienen con RSpec. También le muestra cómo dividir su suite de pruebas a través del etiquetado, cómo funcionan las devoluciones de llamada y cómo extraer algunos datos. Ampliamos un poco el kit básico de supervivencia del primer artículo y le mostramos lo suficiente como para ser peligroso sin demasiada cuerda para colgarte.

Temas

  • Comparadores
  • Let
  • Asuntos
  • Devoluciones de llamada
  • Generadores
  • Etiquetas

En el primer artículo pasamos bastante tiempo tratando de contestar el "por qué" de las pruebas. Sugiero que volvamos al "cómo" y nos ahorramos más contexto. Ya cubrimos esa parte ampliamente. Vamos a ver qué más RSpec tiene que ofrecer que usted como un principiante puede manejar de inmediato.

Comparadores

Así que esto va a acercarse al corazón de las cosas. RSpec le proporciona una tonelada de los llamados comparadores. Éstos son su pan y mantequilla cuando usted escribe sus expectativas. Hasta ahora has visto .to eq y .not_to eq. Pero hay un arsenal mucho mayor para escribir sus especificaciones. Puede probar para plantear errores, para valores de verdaderos y falsos, o incluso para clases específicas. Vamos a ejecutar algunas opciones para empezar:

  • .to eq
  • .not_to eq

Esto prueba las equivalencia.

Alguna especificacion

¡Atención!

Para mantener las cosas cortas, llene dos declaraciones de espera dentro de un bloque it. Sin embargo, es una buena práctica probar sólo una cosa por cada prueba. Esto mantiene las cosas mucho más enfocadas, y sus pruebas terminarán menos quebradizas cuando cambie las cosas.

  • .to be_truthy
  • .to be true

Alguna especificacion

La diferencia es que be_truthy es verdadero cuando no es nil o false. Así pasará si el resultado no es ninguno de estos dos—tipos de "verdadero". .to be true por otra parte sólo acepta un valor que es true y nada más.

  • .to be_falsy
  • .to be false

Alguna especificacion

Similar a los dos ejemplos anteriores, .to be_falsy espera que un valor false o nil, y .to be false sólo hará una comparación directa en false.

  • .to be_nil
  • .to_not be_nil

Y por último pero no menos importante, esto prueba exactamente por nil mismo. Te ahorro el ejemplo.

  • .to match()

Espero que ya tuvieras el placer de mirar expresiones regulares. De lo contrario, se trata de una secuencia de caracteres con la que puede definir un patrón que coloca entre dos barras diagonales para buscar cadenas. Un regex puede ser muy útil si desea buscar patrones más amplios que podría generalizar en tal expresión.

Alguna especificacion

Supongamos que estamos tratando con agentes como James Bond, 007, a quienes se asignan números de tres dígitos. Entonces podríamos probarlo de esta manera—primitivamente aquí, por supuesto.

  • >
  • <
  • <=
  • >=

Las comparaciones son más útiles de lo que uno podría pensar. Supongo que los ejemplos a continuación cubrirán lo que usted necesita saber.

Alguna especificacion

Ahora, estamos llegando a un lugar menos aburrido. También puede probar clases y tipos:

  • .to be_an_instance_of
  • .to be_a
  • .to be_an

Alguna especificacion

En el ejemplo ficticio anterior, puede ver que una lista de agentes que están asociados con una misión no son de clase Agent sino de ActiveRecord::Associations::CollectionProxy. Lo que debe quitar de este es que podemos probar fácilmente para las clases en sí, mientras que mantenerse altamente expresivo. .to be_a y .to be_an hacer una y la misma cosa. Usted tiene ambas opciones disponibles para mantener las cosas legibles.

Pruebas de errores también es muy conveniente en RSpec. Si usted es super fresco para Rails y no está seguro de qué errores el marco puede lanzar en usted, es posible que no sienta la necesidad de utilizar estos—por supuesto, que tiene total sentido. En una etapa posterior en su desarrollo, usted los encontrará muy prácticos, sin embargo. Usted tiene cuatro maneras de tratar con ellos:

  • .to raise_error

Esta es la forma más genérica. Cualquier error que se plantee será lanzado en su red.

  • .to raise_error(ErrorClass)

De esta manera puede especificar exactamente de qué clase debe proceder el error.

  • .to raise_error(ErrorClass, "Some error message")

Esto es aún más especifico ya que no sólo menciona la clase del error, sino un mensaje específico que debe ser lanzado con el error.

  • .to raise_error("Some error message)

O simplemente mencionar el mensaje de error en sí sin la clase de error. La parte esperada necesita ser escrita un poco diferente, sin embargo—necesitamos envolver la parte bajo el texto en un bloque de código en sí:

Alguna especificacion

  • .to start_with
  • .to end_with

Dado que a menudo se ocupan de las colecciones en la construcción de aplicaciones web, es bueno tener una herramienta para echar un vistazo a ellos. Aquí agregamos dos agentes, Q y James Bond, y sólo quería saber quién viene primero y último en la colección de agentes para una misión en particular—aquí Moonraker.

Alguna Especificación de Agente

  • .to include

Este también es útil para comprobar el contenido de las colecciones.

Alguna Especificación de Agente

  • predicate matchers

Estos predicate matchers son una característica de RSpec para crear dinámicamente comparadores para usted. Si tiene métodos de predicado en sus modelos, por ejemplo (terminando con un signo de interrogación), RSpec sabe que debe crear comparadores para que puedas utilizarlos en tus pruebas. En el ejemplo siguiente, queremos probar si un agente es James Bond:

Modelo Agent

Ahora, podemos utilizar esto en nuestras especificaciones así:

Alguna Especificación de Agente

RSpec nos permite usar el nombre del método sin el signo de interrogación—para formar una mejor sintaxis, supongo. Genial, ¿no?

Let

let y let! pueden parecer variables al principio, pero en realidad son métodos auxiliares. El primero es evaluado perezosamente, lo que significa que sólo se ejecuta y se evalúa cuando una especificación realmente lo usa, y el otro se deja con el bang (!) Se ejecuta sin importar si se utiliza por una especificación o no. Ambas versiones son memorizadas, y sus valores serán almacenados en caché dentro del mismo ámbito de ejemplo.

Algun archivo especificacion

La versión con ! que no se evalúa perezosamente puede ser mucho tiempo y por lo tanto costoso si se convierte en su nuevo amigo de lujo. ¿Por qué? Debido a que va a configurar estos datos para cada prueba en cuestión, no importa lo que, y eventualmente puede llegar a ser una de estas cosas desagradables que ralentizar su suite de pruebas de manera significativa.

Usted debe conocer esta característica de RSpec ya que let es ampliamente conocido y utilizado. Dicho esto, el próximo artículo le mostrará algunos problemas con los que debe tener en cuenta. Utilice estos métodos auxiliares con precaución, o al menos en pequeñas dosis por ahora.

Asuntos

RSpec le ofrece la posibilidad de declarar el tema bajo prueba muy explícitamente. Hay mejores soluciones para esto, y vamos a discutir las desventajas de este enfoque en el próximo artículo cuando muestro algunas cosas que generalmente desea evitar. Pero por ahora, echemos un vistazo a lo que subject puede hacer por usted:

Algun archivo especificacion

Este enfoque puede, por un lado, ayudarle a reducir la duplicación de código, tener un protagonista declarado una vez en un determinado ámbito, pero también puede conducir a algo llamado invitado misterioso. Esto simplemente significa que podríamos terminar en una situación en la que usamos datos para uno de nuestros escenarios de prueba, pero no tenemos idea de dónde viene y de qué se compone. Más sobre eso en el próximo artículo.

Devoluciones de llamada

En caso de que no son conscientes de las devoluciones de llamada todavía, permítanme darles un breve aviso. Las devoluciones de llamada se ejecutan en determinados puntos específicos del ciclo de vida del código. En términos de Rails, esto significa que tiene código que se ejecuta antes de que los objetos se creen, actualicen, destruyan, etc.

En el contexto de RSpec, es el ciclo de vida de las pruebas que se están ejecutando. Eso significa simplemente que puede especificar ganchos que deben ejecutarse antes o después de ejecutar cada prueba en el archivo de especificaciones, por ejemplo—o simplemente alrededor de cada prueba. Hay mas opciones especificas disponibles, pero le recomiendo evitar perder en los detalles por ahora. Lo primero es lo primero:

  • before(:each)

Esta devolución de llamada se ejecuta antes de cada ejemplo de prueba.

Algun archivo especificacion

Digamos que necesitaría un gadget determinado para cada prueba que ejecute en un determinado ámbito. before le permite extraer esto en un bloque y prepara este pequeño fragmento para usted convenientemente. Cuando configura los datos de esa manera, tiene que utilizar variables de instancia, por supuesto, para tener acceso a ella entre varios ámbitos.

¡Atención!

No se deje engañar por la conveniencia en este ejemplo. Sólo porque usted puede hacer este tipo de cosas no significa que usted debe hacerlas. Quiero evitar entrar en el territorio de AntiPatron y confundirlos mucho, pero por otro lado, quiero explicar los inconvenientes de estos simples simulacros ejercicios un poco también.

En el ejemplo anterior, sería mucho más expresivo si configura los objetos necesarios en una base de prueba por prueba. Especialmente en archivos de especificaciones más grandes, puede perder rápidamente la vista de estas pequeñas conexiones y hacer más difícil para los demás para reconstruir estos rompecabezas.

  • before(:all)

Este bloque before se ejecuta sólo una vez antes de todos los otros ejemplos en un archivo de especificaciones.

Algun archivo especificacion

Cuando te acuerdas de las cuatro fases de la prueba, los bloques before a veces son útiles para establecer algo para ti que necesita ser repetido sobre una base regular—probablemente cosas que es un poco más meta en la naturaleza.

after(:each)  y after(:all) tienen el mismo comportamiento pero se ejecutan simplemente después de que se hayan ejecutado las pruebas. after se utiliza a menudo para limpiar sus archivos, por ejemplo. Pero creo que es un poco pronto para abordar eso. Así memoriza, sepa que está allí en caso de que comience a necesitarlo, y vamos a pasar a explorar otras cosas más básicas.

Todas estas devoluciones pueden colocarse estratégicamente para satisfacer sus necesidades. Colóquelos en cualquier ámbito de bloque describe que necesite para ejecutarlos—no tienen que ser necesariamente colocados encima de su archivo de especificaciones. Pueden ser fácilmente anidados manera dentro de sus especificaciones.

Algun archivo especificacion

Como puede observar, puede colocar bloques de devolución de llamada en cualquier ámbito a su gusto, e ir tan profundo como usted necesita. El código en la devolución de llamada se ejecutará dentro del alcance de cualquier ámbito de bloque describe. Pero un poco de consejo: si siente la necesidad de anidar demasiado y las cosas parecen ser un poco complicado y desordenado, replantee su enfoque y considere cómo podría simplificar las pruebas y su configuración. ¡KISS! Keep it simple, stupid (Manténlo simple, estúpido). Además, preste atención a lo bien que se lee cuando obligamos a estas pruebas a fallar:

Salida

Generadores

Vamos a echar un vistazo a lo que los generadores que son proporcionados por RSpec para usted. Ya has visto uno cuando usamos rails generate rspec:install.. Este pequeño amigo hizo la configuración RSpec para nosotros rápida y fácil. ¿Qué más tenemos?

  • rspec:model

¿Quieres tener otra especificación de modelo ficticio?

Terminal

Salida

Rápido, ¿no? O una nueva especificación para una prueba de controlador, por ejemplo:

  • rspec:controller

Terminal

Salida

  • rspec:view

Lo mismo funciona para las vistas, por supuesto. Sin embargo, no estaremos probando ninguna vista. Las especificaciones para las vistas le dan la menor cantidad de dinero, y es totalmente suficiente en casi cualquier escenario para probar indirectamente sus opiniones a través de pruebas de características.

Las pruebas de características no son una especialidad de RSpec per se y son más adecuadas para otro artículo. Dicho esto, si usted es curioso, echa un vistazo a Capybara, que es una excelente herramienta para ese tipo de cosas. Le permite probar flujos completos que ejercen múltiples partes de su aplicación—probando características completas mientras simula la experiencia del navegador. Por ejemplo, un usuario que paga varios artículos en un carrito de la compra.

  • rspec:helper

La misma estrategia de generador nos permite también colocar un ayudante sin mucho alboroto.

Terminal

Salida

La parte doble de helper_helper no fue un accidente. Cuando le damos un nombre más "significativo", verá que RSpec sólo asigna _helper por sí mismo.

Terminal

Salida

Unas palabra sobre los ayudantes

No, este directorio no es un lugar para almacenar sus preciosos métodos de ayuda que surgen mientras refactoriza sus pruebas. Estos irían bajo spec/support, en realidad. spec/helpers es para las pruebas que debe escribir para sus ayudantes de vista—un ayudante como set_date sería un ejemplo común. Sí, la cobertura de prueba completa de su código también debe incluir estos métodos de ayuda. El hecho de que a menudo parecen pequeños y triviales no significa que debemos pasar por alto o ignorar su potencial para los errores que queremos atrapar. Cuanto más complejo resulta el ayudante, más razón tendrá que escribir una helper_spec para ello.

Sólo en caso de que empezar a jugar con él de inmediato, tenga en cuenta que usted necesita para ejecutar sus métodos de ayuda en un objeto helper cuando se escriben las pruebas de ayuda para trabajar. Así que sólo pueden ser expuestos con este objeto. Algo como esto:

Alguna especificacion Helper

Puede utilizar el mismo tipo de generadores para especificaciones de características, especificaciones de integración y especificaciones de correo. Éstos están fuera de nuestro alcance para hoy, pero usted puede confiarlos a la memoria para el uso futuro:

  • rspec:mailer
  • rspec:feature
  • rspec:integration

Un vistazo a las especificaciones generadas

Las especificaciones que creamos a través del generador de arriba están listas para funcionar, y puedes agregar sus pruebas allí de inmediato. Vamos a tener una mirada minúscula en una diferencia entre las especificaciones, sin embargo:

spec/models/dummy_model_spec.rb

spec/controllers/dummy_controller_controller_spec.rb

spec/helpers/dummy_helper_helper_spec.rb

No necesita un niño prodigio a darse cuenta de que todos ellos tienen diferentes tipos. Los metadatos :type de RSpec le dan la oportunidad de cortar y cortar sus pruebas a través de estructuras de archivos. Puede orientar estas pruebas un poco mejor de esa manera. Digamos que usted quiere tener algún tipo de ayudantes cargado sólo para las especificaciones del controlador, por ejemplo. Otro ejemplo sería que desea utilizar otra estructura de directorios para las especificaciones que RSpec no espera. Tener estos metadatos en sus pruebas hace posible continuar utilizando las funciones de soporte de RSpec y no disparar el conjunto de pruebas. Así que usted es libre de usar cualquier estructura de directorio funciona para usted si agrega el metadatos :type.

Por el contrario, sus pruebas RSpec estándar no dependen de esos metadatos. Cuando utilice estos generadores, se agregarán de forma gratuita, pero también puede evitarlos totalmente si no los necesita.

También puede utilizar estos metadatos para filtrar en sus especificaciones. Digamos que tiene un bloque before que debería ejecutarse sólo en las especificaciones del modelo, por ejemplo. ¡Estupendo! Para las suites de prueba más grandes, esto podría ser muy útil un día. Puede filtrar el grupo de pruebas que desea ejecutar—en lugar de ejecutar toda la suite, lo que puede tardar un tiempo.

Sus opciones se extienden más allá de las tres opciones de etiquetado anteriores, por supuesto. Aprendamos más sobre slicing y dicing sus pruebas en la siguiente sección.

Etiquetas

Cuando usted acumula un conjunto de pruebas más grande con el tiempo, no sólo será suficiente para ejecutar pruebas en ciertas carpetas para ejecutar RSpec pruebas de forma rápida y eficiente. Lo que usted quiere ser capaz de hacer es ejecutar pruebas que pertenecen juntos, pero podría estar repartidos en varios directorios. ¡Etiquetado al rescate! No me malinterpreten, la organización de sus pruebas inteligentemente en sus carpetas es clave, así, pero el etiquetado lleva esto un poco más.

Usted está dando a sus pruebas algunos metadatos como símbolos como ": wip", ": checkout", o lo que se adapte a sus necesidades. Cuando ejecuta estos grupos de pruebas enfocadas, simplemente especifique que RSpec debe ignorar la ejecución de otras pruebas esta vez proporcionando un indicador con el nombre de las etiquetas.

Algun archivo especificacion

Terminal

Salida

También podría ejecutar todo tipo de pruebas e ignorar un montón de grupos que están etiquetados de una manera determinada. Simplemente proporcione un tilde (~) delante del nombre de la etiqueta, y RSpec se alegrará de ignorar estas pruebas.

Terminal

Ejecutar varias etiquetas sincrónicamente tampoco es un problema:

Terminal

Como usted puede ver arriba, usted puede mezclar y emparejarlos a voluntad. La sintaxis no es perfecta—repetir --tag tal vez no es ideal—pero bueno, ¡tampoco es un gran problema! Sí, todo esto es un poco más de trabajo extra y de sobrecarga mental cuando compones las especificaciones, pero por el otro lado, realmente te proporciona una poderosa habilidad para dividir tu suite de pruebas bajo demanda. En proyectos más grandes, puede ahorrarle una tonelada de tiempo esa manera.

Consideraciones finales

Lo que has aprendido hasta ahora debe equiparte con lo básico absoluto para jugar con pruebas por tu cuenta—un kit de supervivencia para principiantes. Y realmente juega y comete errores tanto como puedas. Lleve a RSpec y todo la cosa guiada por pruebas a una vuelta, y no esperes escribir pruebas de calidad de inmediato. Todavía hay un par de pedazos que faltan antes de que usted se sienta cómodos y antes de que seas eficaz con él.

Para mí, esto fue un poco frustrante al principio porque era difícil ver cómo probar algo cuando todavía no lo había implementado y no entendía completamente cómo se comportaría.

Pruebas realmente demuestra si usted entiende un marco como Rails y saber cómo encajan las piezas. Cuando usted escribe pruebas, tendrá que ser capaz de escribir las expectativas de cómo un marco debe comportarse.

Eso no es fácil si estás empezando con todo esto. Tratar con múltiples lenguajes específicos de dominio—aquí RSpec y Rails, por ejemplo—además de aprender la API de Ruby puede ser confuso como el infierno. No se sienta mal si la curva de aprendizaje parece desalentadora; Se pondrá más fácil si te quedas con ella. Hacer que esta bombilla se apague no pasará durante la noche, pero para mí, valió mucho el esfuerzo.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.