Return to Video

5.2 - FIRST, TDD e iniciación a RSpec

  • 0:00 - 0:04
    Muy bien, vamos a empezar con una aproximación muy práctica a las pruebas.
  • 0:04 - 0:08
    Las pruebas son algo que, tengo que admitir que hasta hace tres o cuatro ańos
  • 0:08 - 0:12
    Las pruebas son algo que, tengo que admitir que hasta hace tres o cuatro ańos
  • 0:12 - 0:16
    importante, yo creía que era importante, siempre traté de hacerlo, pero hacerlo de esta manera realmente cambió
  • 0:16 - 0:21
    mi vida. Y espero que cambie la vuestra también.
  • 0:21 - 0:25
    Y no, no estoy de campańa presidencial, esto es un... es igual. Muy bien, empecemos hablando de
  • 0:25 - 0:29
    pruebas unitarias. En el libro podéis encontrar algo de información sobre los diferentes tipos de pruebas.
  • 0:29 - 0:33
    Nos centraremos inicialmente en las pruebas unitarias y un poco en las pruebas funcionales,
  • 0:33 - 0:36
    y como con tantas otras cosas en esta clase, existe un acrónimo muy útil que ayuda a recordar
  • 0:36 - 0:40
    cómo deben ser las buenas pruebas. Una de las características es, deben ser rápidas -
  • 0:40 - 0:44
    no debería llevar mucho tiempo ejecutarlas; deben ser independientes,
  • 0:44 - 0:47
    esto es que ejecutar una prueba antes que otra no debería conllevar diferencias
  • 0:47 - 0:51
    esto es que ejecutar una prueba antes que otra no debería conllevar diferencias
  • 0:51 - 0:54
    el orden en el que se ejecuten, no deberían tener dependencias entre ellas;
  • 0:54 - 1:01
    deben ser "repetibles" - si una prueba encuentra un fallo, no debería hacerlo cada vez.
  • 1:01 - 1:05
    En algunos casos esto es fácil de conseguir, en otros es sorprendentemente sutil.
  • 1:05 - 1:08
    Auto-comprobación - lo que las pruebas solían significar no hace tantos para las empresas, es:
  • 1:08 - 1:12
    el software ha llegado de cualquier manera a este departamente de QA, y entonces la gente de QA
  • 1:12 - 1:16
    debería de alguna manera hurgar en él, y hacer cosas, y
    "Ah, ya está, eso funcionó, sí, eso funcionó"
  • 1:16 - 1:19
    No vamos a funcionar así más, bien? El código de las pruebas debe conocer él mismo
  • 1:19 - 1:23
    si superó o falló. No debería requerirse intervención humana para tomar esta decisión.
  • 1:23 - 1:27
    Y en un tiempo razonable. Esto significa que las pruebas deben escribirse al mismo tiempo
  • 1:27 - 1:30
    que se escribe el código. Si el código cambia, las pruebas también lo hacen.
  • 1:30 - 1:34
    De hecho, realmente vamos a hacer esto de forma más agresiva.
    vamos a escribir las pruebas antes de escribir el código.
  • 1:34 - 1:38
    Esto es, tan a tiempo como puedas. Es como un salto en el tiempo.
  • 1:38 - 1:42
    Qué significa esto?
    Porque, si las pruebas son rápidas, por qué necesitamos esto?
  • 1:42 - 1:46
    Bien, es porque podéis ejecutar un subconjunto de las pruebas todo el tiempo.
  • 1:46 - 1:49
    Si tienes miles y miles de pruebas unitarias, lo que no es raro en un proyecto de tamańo medio,
  • 1:49 - 1:53
    podría llevar, ya sabéis, como un minuto o dos ejecutar todo el conjunto de pruebas, lo que podría ralentizaros mucho.
  • 1:53 - 1:57
    Lo ideal es ser capaz de ejecutar rápidamente las pruebas que aplican sobre la parte del código que estáis tocando.
    Estáis trabajando, y no queréis nada que os rompa el ritmo.
  • 1:57 - 2:01
    Independientes. Por la misma razón, querríais ser capaces de ejecutar cualquier subconjunto
  • 2:01 - 2:05
    en cualquier orden posible.
  • 2:05 - 2:09
    No sería bueno que existan pruebas que sólo funcionasen adecuadamente
  • 2:09 - 2:13
    si se ejecutasen otras antes.
  • 2:13 - 2:17
    Repetibles. Ya sabéis, otra vez, ejecutándolas N veces, obtener los mismos resultados.
  • 2:17 - 2:20
    Si queréis aislar los fallos y habilitar la depuración automática, la repetibilidad es esencial.
  • 2:20 - 2:25
    Auto-comprobación. Como dije, ningún humano comprobará la salida.
  • 2:25 - 2:29
    Esto significa que podéis tener las pruebas ejecutándose en background todo el tiempo,
  • 2:29 - 2:33
    y siempre que cambies algo que rompa otra cosa a 25 millas de código de distancia,
  • 2:33 - 2:37
    alguna prueba detectará este hecho y te avisará del ello.
  • 2:37 - 2:40
    Y a tiempo. Como dije, vamos a hacer desarrollo basado en las pruebas,
  • 2:40 - 2:45
    donde escribiremos las pruebas antes de escribir el código.
  • 2:45 - 2:49
    Vamos a usar RSpec, que para mí es un lenguaje de dominio específico para escribir pruebas.
  • 2:49 - 2:53
    Para aquellos que no estén familiarizados con DSLs, es básicamente como un pequeńo lenguaje de programación
  • 2:53 - 2:58
    que sólo hace un pequeńo número de cosas en el dominio de una tarea. No pretende ser de propósito general.
  • 2:58 - 3:02
    Ya hemos visto ejemplos de esto. Las migraciones son un tipo de DSL, verdad?
  • 3:02 - 3:06
    Hay un conjunto de sentencias cuyo único trabajo es expresar los cambios en el esquema de la base de datos.
  • 3:06 - 3:10
    Las migraciones son un tipo de DSL que se encuentra embebido en Ruby, esto es,
  • 3:10 - 3:14
    las migraciones son símplemente código en Ruby, pero estilizadas para parecerse a la tarea que hacen.
  • 3:14 - 3:19
    De hecho, veremos que RSpec es un ejemplo similar. Podemos llamarlos DSL internos.
  • 3:19 - 3:23
    Está implementado dentro de otro lenguaje. Las expresiones regulares son otro tipo de DSL interno.
  • 3:23 - 3:27
    Es como un pequeńo sub-vocabulario de cosas que puedes hacer con expresiones regulares.
  • 3:27 - 3:32
    Un ejemplo diferente de DSL es SQL, para hacer consultas a bases de datos.
  • 3:32 - 3:36
    Es un lenguaje propiamente dicho, y aquellos de vosotros que hayáis trabajado con otros frameworks
  • 3:36 - 3:40
    antes de venir a Rails, normalmente habréis terminar teniendo que escribir consultas SQL
  • 3:40 - 3:44
    y después pasarlas como un string a alguien, verdad? Este es un ejemplo muy claro de cómo tratar con diferentes lenguajes.
  • 3:44 - 3:48
    En RSpec, cada prueba se denomina 'spec', viene de 'specification'
  • 3:48 - 3:52
    Sorprendentemente, se encuentran en un directorio llamado 'spec', ya que queremos mantener la simplicidad.
  • 3:52 - 3:56
    Hay un generador en Rails, 'rspec:install' que crea esta estructura de subdirectorios.
  • 3:56 - 4:01
    Todo esto está en el libro, y las asumiremos como leídas para algunas de las demos que haremos hoy
  • 4:01 - 4:05
    para las que ya hemos pasado por estos pasos de configuración.
  • 4:05 - 4:10
    Dónde se encuentra cada cosa? Los directorios bajo spec están diseńados para imitar dónde van las cosas
  • 4:10 - 4:14
    en tu aplicación, ya sabéis: en app/models tenemos los modelos,
  • 4:14 - 4:19
    en spec/models tenemos un fichero spec para cada modelo. Nada nuevo.
  • 4:19 - 4:24
    De la misma manera, tenemos specs para los controladores. Qué pasa con las vistas?
  • 4:24 - 4:28
    Bien, realmente no vamos a hacer specs para ellas. Se pueden hacer, pero son un poco
  • 4:28 - 4:33
    costosas de escribir - mucho de aquello que puedes probar en una vista lo puedes hacer realmente
  • 4:33 - 4:37
    en un spec de controlador, como veremos en un ejemplo hoy.
  • 4:37 - 4:42
    Además, hemos decidido que nuestra solución para escribir estas aplicaciones web de usuario es
  • 4:42 - 4:46
    que construimos historias de usuario para expresar las partes de la aplicación con las que el usuario realmente puede interactuar.
  • 4:46 - 4:50
    Así que, para todas las cosas que son parte de la vista - lo que es visible en la vista,
  • 4:50 - 4:54
    para todo lo que es clickable, etc, usaremos Cucumber.
  • 4:54 - 4:58
    Continuaremos haciendo esto.
  • 4:58 - 5:02
    La mayor parte de tiempo centraremos la atención en RSpec para
  • 5:02 - 5:05
    escribir specs para los modelos y los controladores
  • 5:05 - 5:08
    Empezaremos con un ejemplo de una nueva, hipotética funcionalidad de RottenPotatoes,
  • 5:08 - 5:13
    con la que podremos ańadir películas utilizando información extraída de TMDb.
  • 5:13 - 5:17
    TMDb es un sitio real, se parece mucho a IMDb, pero no es comercial. Es de tipo open-source.
  • 5:17 - 5:22
    La idea es que ellos ya tienen la información de las películas, y lo que queremos
  • 5:22 - 5:26
    es ańadir películas a RottenPotatoes, por que no simplemente sacar la información de allí?
  • 5:26 - 5:31
    Y de hecho, cuando miramos las historias de usuario, existe un paso que dice:
  • 5:31 - 5:36
    "Estoy rellenando términos de búsqueda, voy a buscar la película Inception,
  • 5:36 - 5:40
    y luego presiono el botón que dice 'buscar TMDb', no es así?
  • 5:40 - 5:45
    Se supone que existe un botón que de alguna manera me llevará a TMDb,
  • 5:45 - 5:49
    mirará si Inception está allí, y nos traerá de vuelta.
  • 5:49 - 5:53
    Así que la pregunta es, qué tenemos que hacer, qué tipo de código debemos escribir,
  • 5:53 - 5:57
    y que tipo de prueba es necesaria para convertir esta sentencia que está en rojo a algo funcional?
  • 5:57 - 6:01
    Antes de lanzarnos a ello, recordemos lo que hablamos sobre "la Cocina de Rails",
  • 6:01 - 6:05
    el tipo de recetas para hacer esto en Rails? Recordad que cuando ańadimos una nueva funcionalidad,
  • 6:05 - 6:08
    ańadimos una nueva ruta, necesitamos un nuevo método controlador y
  • 6:08 - 6:13
    quizá necesitemos una nueva vista, dependiendo de si una existente puede reutilizarse
  • 6:13 - 6:17
    o tenemos que hacer algo nuevo. Pero estos son pasos que siempre seguimos.
  • 6:17 - 6:20
    Bueno, empecemos de una vez.
  • 6:20 - 6:25
    Esta es una idea que veremos muchas, muchas veces; Empezaré a acostumbraros a la frase.
  • 6:25 - 6:29
    Esta es, "El código que te gustaría tener". Es una idea inmensamente poderosa una vez que te haces a ella.
  • 6:29 - 6:33
    Es un poco extrańo hacer las cosas de esta manera cuando empiezas, pero es muy poderosa.
  • 6:33 - 6:38
    Así que nos preguntamos: "Bien, cuando un usuario hace click en ese botón para 'buscar en TMDb', sabemos que
  • 6:38 - 6:42
    en algún sitio habrá una acción de controlador que recibirá la información.
  • 6:42 - 6:45
    Así que, qué debería hacer este método? Que debería hacer el método controlador cuando reciba el formulario de búsqueda?
  • 6:45 - 6:49
    Bueno, si preguntáis, en inglés - si escribimos lo que debería ser,
  • 6:49 - 6:52
    deberíamos decir: "Bien, veamos, debería llamar a algún método (que no hemos escrito aún)
  • 6:52 - 6:56
    que realmente iría a TMDb y buscaría la película". Tiene sentido.
  • 6:56 - 7:00
    "Si encuentra una película, debería renderizar algún tipo de vista con los resultados de la búsqueda para enseńar las coincidencias
  • 7:00 - 7:03
    (otra vez, aún no hemos creado la vista, pero lógicamente, esto es lo que vamos a
  • 7:03 - 7:07
    escribir que haremos)." No vamos a tener tiempo de hacer el paso tres hoy,
  • 7:07 - 7:11
    pero el 'sad path' es algo como, "Si no coincide, debería redireccionar a la hompage de RottenPotatoes y decir,
  • 7:11 - 7:15
    'No se encontraron coincidencias'. " Y si miráis el ejemplo en el libro,
  • 7:15 - 7:20
    realmente escribimos este 'sad path' en el capítulo de BDD.
  • 7:20 - 7:24
    Así que, dado que estas dos cosas - centrémonos en #1 y #2 - son las que el método controlador debería hacer,
  • 7:24 - 7:28
    así es como deberíamos expresarlo - dónde está mi ratón? Vamos allá-
  • 7:28 - 7:32
    Así es como expresaríamos todo esto usando RSpec. Y, bien. Entonces.
  • 7:32 - 7:38
    No hemos hecho demasiado, y ya sabéis, es bonito y rápido, verdad?
  • 7:38 - 7:43
    Y este es código RSpec legal. SpecHelper es simplemente un fichero que RSpec crea como parte del paso de instalación.
  • 7:43 - 7:48
    Hace algunas verificaciones para asegurarse de que todo está cargado.
  • 7:48 - 7:52
    Así que empezaremos diciendo, "Sobre qué trata esta prueba?"
  • 7:52 - 7:57
    O bien, vamos a describir el comportamiento de MoviesController,
  • 7:57 - 8:01
    y el controlador va a tener diferentes comportamientos, pero el que nos interesa aquí
  • 8:01 - 8:05
    es el comportamiento de búqueda en TMDb. Así que, podéis impaginar, que para cada comportamiento de controlador,
  • 8:05 - 8:09
    nuestra especificación crece, vamos a ańadir más bloques descriptivos dentro de este,
  • 8:09 - 8:13
    'describe MoviesController', y podéis seguir anidando, anidando y anidando.
  • 8:13 - 8:17
    'It' es realmente una llamada a un método en RSpec. Recibe un argumento, que es
  • 8:17 - 8:21
    un string describiendo lo que debería pasar. Y como veremos en un momento,
  • 8:21 - 8:25
    también recibe un segundo argumento: un procedimiento que realiza el test.
  • 8:25 - 8:29
    también recibe un segundo argumento: un procedimiento que realiza el test.
  • 8:29 - 8:33
    Pero por ahora, todo lo que hemos hecho ha sido transliterar. Pensamos en las tres cosas
  • 8:33 - 8:37
    que el método controlador debería hacer, y escribimos tres cosas en RSpec.
  • 8:37 - 8:41
    Esto es de hecho suficiente para empezar, y existe un screencast que os recomiendo que veáis
  • 8:41 - 8:44
    que está asociado con el capítulo del libro, que hace exactamente esto.
  • 8:45 - 8:48
    Todo lo que hace es ejecutar tres pruebas, y estas no hacen nada, así que RSpec las pinta en amarillo, verdad?
  • 8:48 - 8:52
    Amarillo significa 'aún no implementado', igual que para Cucumber.
    Todo lo que he hecho ha sido transcribir las tres cosas que dijimos que debería hacer.
  • 8:52 - 8:55
    Así que, gran acrónimo!
Title:
5.2 - FIRST, TDD e iniciación a RSpec
Description:

En este video, Armando presenta los cinco atributos para una buena prueba unitaria, describe el desarrollo basado en las pruebas y comienza con la demostración de RSpec.

more » « less
Video Language:
English

Spanish subtitles

Revisions