You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/03-code-quality/05-testing-mocha/article.md
+33-36Lines changed: 33 additions & 36 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,45 +1,43 @@
1
-
2
1
# Test automatizados con mocha
3
2
4
-
Los tests automáticos deben ser considerados como una tarea más.
5
-
6
-
Debe ser parte del "conocimiento mínimo" de un/a desarrollador/a.
3
+
Los tests automáticos deben ser considerados como una tarea más, y son ampliamente usasdos en proyectos reales.
7
4
8
5
## ¿Por qué necesitamos tests?
9
6
10
-
Cuando escribimos una función, normalmente imaginamos qué debe hacer: Para ciertos parámetros, que resultado.
7
+
Cuando escribimos una función, normalmente imaginamos qué debe hacer: Para ciertos parámetros, qué resultado.
11
8
12
9
Durante el desarrollo, podemos comprobar la función ejecutándola y comparando el resultado con la salida esperada. Por ejemplo, podemos hacer eso en la consola.
13
10
14
-
Si algo esta incorrecto -- entonces corregimos el código, ejecutamos de nuevo, comprobamos resultado -- y así sucesivamente hasta que funcione.
11
+
Si algo está incorrecto -- entonces corregimos el código, ejecutamos de nuevo, comprobamos resultado -- y así sucesivamente hasta que funcione.
15
12
16
-
Pero esa "re-ejecuciones" manuales son imperfectas.
13
+
Pero esas "re-ejecuciones" manuales son imperfectas.
17
14
18
15
**Cuando testeamos un código re-ejecutándolo manualmente es fácil obviar algo.**
19
16
20
-
Por ejemplo, si estamos creando una función `f`. Escribimos algo de código, testeamos: `f(1)` funciona, pero `f(2)` no funciona. Corregimos el código y ahora funciona `f(2)`. ¿Está completo? Hemos olvidado re-testear `f(1)`. Esto puede resultar error.
17
+
Por ejemplo, estamos creando una función `f`. Escribimos algo de código, testeamos: `f(1)` funciona, pero `f(2)` no funciona. Corregimos el código y ahora funciona `f(2)`. ¿Está completo? Hemos olvidado re-testear `f(1)`. Esto puede resultar error.
21
18
22
19
Todo esto es muy típico. Cuando desarrollamos algo, mantenemos muchos casos de uso posibles en la cabeza. Pero es complicado esperar que un/a programador/a compruebe todos después de cada cambio. Por lo que deviene fácil arreglar una cosa y romper otra.
23
20
24
-
**Los tests automatizados implican escribir los tests por separado, además del código. Pueden ser ejecutados fácilmente y comprueban todos los casos de uso principales.**
21
+
**Los tests automatizados implican escribir los tests por separado, además del código. Ellos ejecutan nuestras funciones de varias formas y comparan los resultados con los esperados.**
25
22
26
-
## Behavior Driven Development (BDD)
23
+
## Desarrollo guiado por comportamiento (Behavior Driven Development, BDD)
27
24
28
-
Vamos a usar una técnica llamada [Desarrollo guiado por comportamiento](http://en.wikipedia.org/wiki/Behavior-driven_development) o por sus siglas en inglés, BDD. Es una aproximación utilizada en muchos proyectos. BDD no es solo hacer test. Es más.
25
+
Vamos a usar una técnica llamada [Desarrollo guiado por comportamiento](https://es.wikipedia.org/wiki/Desarrollo_guiado_por_comportamiento) o por sus siglas en inglés, BDD.
29
26
30
27
**BDD son tres cosas en uno: tests, documentación y ejemplos.**
31
28
32
-
Basta de palabras, veamos un ejemplo:
29
+
PAra entender BDD, examinaremos un caso de desarrollo práctico:
33
30
34
-
## Desarrollo de "potencia de un número (pow)": la especificación
31
+
## Desarrollo de potencia de un número "pow": la especificación
35
32
36
33
Digamos que queremos hacer una función `pow(x, n)` que eleve `x` a la potencia de un entero `n`. Asumimos que `n≥0`.
37
34
38
35
Esta tarea es sólo un ejemplo: Hay un operador `**` en JavaScript que hace eso, pero queremos concentrarnos en el flujo de desarrollo que puede ser aplicado a tareas más complejas.
39
36
40
37
Antes de crear el código de `pow`, podemos imaginar lo que hace la función y describirlo.
41
38
42
-
Esa descripción es llamada *especificación* o una spec y se asemeja a:
39
+
Esa descripción es llamada *especificación* o "spec" y contiene las descripciones de uso junto con los test para probarlas, como:
40
+
43
41
```js
44
42
describe("pow", function() {
45
43
@@ -53,33 +51,35 @@ describe("pow", function() {
53
51
Una spec tiene los tres bloques principales mostrados abajo:
54
52
55
53
`describe("titulo", function() { ... })`
56
-
: Qué funcionalidad estamos describiendo. Utilizado para agrupar los "trabajadores" -- los bloques `it`. En nuestro caso estamos describiendo la función `pow`.
54
+
: Qué funcionalidad estamos describiendo. En nuestro caso estamos describiendo la función `pow`. Utilizado para agrupar los "workers" (trabajadores) -- los bloques `it`.
57
55
58
56
`it("titulo", function() { ... })`
59
57
: En el título de `it` introducimos una descripción entendible en forma humana del caso de uso. El segundo argumento es la función que testea eso.
60
58
61
59
`assert.equal(value1, value2)`
62
60
: El código dentro del bloque `it`, si la implementación es correcta, debe ejecutar sin errores.
63
61
64
-
Las funciones `assert.*` son usadas para comprobar cuando `pow` funciona como esperamos. Justo aquí utilizamos una de ellas -- `assert.equal`, que compara argumentos y produce un error si los mismos no son iguales. Arriba se está comprobando que el resultado de `pow(2, 3)` es igual a `8`.
62
+
Las funciones `assert.*` son usadas para comprobar cuando `pow` funciona como esperamos. Justo aquí utilizamos una de ellas -- `assert.equal`, que compara argumentos y produce un error si los mismos no son iguales. Arriba se está comprobando que el resultado de `pow(2, 3)` sea igual a `8`. Hay otros tipos de comparaciones y comprobaciones que veremos más adelante.
65
63
66
-
Hay otros tipos de comparaciones y comprobaciones que veremos más adelante.
64
+
La especificación puede ser ejecutada, y hará los los test dictados en el bloque `it`. Lo veremos luego.
67
65
68
66
## El flujo de desarrollo
69
67
70
68
El flujo de desarrollo podría asemejarse a:
71
69
72
70
1. Un spec inicial es escrito, con tests para la funcionalidad más básica.
73
71
2. Una implementación inicial es creada.
74
-
3. Para comprobar que funciona, ejecutamos el framework de test [Mocha](http://mochajs.org/) (detallado más adelante) que ejecuta el spec. Los errores son mostrados. Hacemos correcciones hasta que todo funciona.
72
+
3. Para comprobar que funciona, ejecutamos el framework de test [Mocha](http://mochajs.org/) (detallado más adelante) que ejecuta el spec. Mostrará los errores mientras la funcionalidad no esté completa. Hacemos correcciones hasta que todo funciona.
75
73
4. Ahora tenemos una implementación inicial con tests.
76
74
5. Añadimos más casos de uso al spec, seguramente no soportados aún por la implementación. Los tests empiezan a fallar.
77
75
6. Ir a 3, actualizar la implementación hasta que los tests no den errores.
78
76
7. Repetir pasos 3-6 hasta que la funcionalidad este lista.
79
77
80
78
De tal forma que el desarrollo es iterativo. Escribimos la especificación, la implementamos, aseguramos que los tests pasen y entonces escribimos más tests y volvemos a asegurar que pasen, etc. Al final tenemos una implementación funcionando con tests para ella.
81
79
82
-
En nuestro caso, el primer paso esta completo: tenemos una spec inicial para `pow`. Vamos a realizar la implementación. Pero antes de comenzar hemos de asegurarnos que los test se ejecutan (no hay errores de sintáxis ni de compilación pero van a fallar todos).
80
+
Veamos el flujo de desarrollo en nuestro caso práctico.
81
+
82
+
El primer paso esta completo: tenemos una spec inicial para `pow`. Ahora, antes de realizar la implementación, usamos algunas librería JavaScript para ejecutar los tests, solo para asegurarnos que funcionen (van a fallar todos).
83
83
84
84
## La spec en acción
85
85
@@ -99,7 +99,7 @@ La página HTML con estos frameworks y la spec de `pow`:
99
99
La página puede ser dividida en cinco partes:
100
100
101
101
1. El `<head>` -- importa librerías de terceros y estilos para los tests.
102
-
2. El `<script>` con la función a comprobar, en nuesro caso -- cont el código de `pow`.
102
+
2. El `<script>` con la función a comprobar, en nuesro caso -- con el código de `pow`.
103
103
3. Los tests -- en nuestro caso un fichero externo `test.js` que contiene un sentencia `describe("pow", ...)`al inicio.
104
104
4. El elemento HTML `<div id="mocha">` utilizado para la salida de los resultados.
105
105
5. Los test se inician con el comando `mocha.run()`.
@@ -200,7 +200,7 @@ function pow(x, n) {
200
200
}
201
201
```
202
202
203
-
Para estar seguros que la función trabaja bien, vamos a hacer comprobaciones para más valores. En lugar de escribir bloques `it`s manualmente, vamos a generarlos con un `for`:
203
+
Para estar seguros de que la función trabaja bien, vamos a hacer comprobaciones para más valores. En lugar de escribir bloques `it`s manualmente, vamos a generarlos con un `for`:
204
204
205
205
```js
206
206
describe("pow", function() {
@@ -225,7 +225,7 @@ El resultado:
225
225
226
226
## `Describe` anidados
227
227
228
-
Vamos a añadir más tests. Pero antes, hay que apuntar que la función `makeTest` y la instrución `for` deben ser agrupados juntos. No queremos `makeTest` en otros tests, solo se necesita en el `for`: su tarea común es comprobar cómo `pow` eleva dad una potencia concreta.
228
+
Vamos a añadir más tests. Pero antes, hay que apuntar que la función `makeTest` y la instrución `for` deben ser agrupados juntos. No queremos `makeTest` en otros tests, solo se necesita en el `for`: su tarea común es comprobar cómo `pow` eleva a una potencia concreta.
229
229
230
230
Agrupar tests se realiza con `describe`:
231
231
@@ -301,7 +301,7 @@ Normalmente, `beforeEach/afterEach` (`before/after`) son usados para realizar la
301
301
302
302
## Extender los spec
303
303
304
-
La funcionalidad básica de `pow` está completa. La primera iteracción del desarrollo está hecha. Cuando acabemos de celebrar y beber champán -- sigamos adelante y mejorémosla.
304
+
La funcionalidad básica de `pow` está completa. La primera iteración del desarrollo está hecha. Cuando acabemos de celebrar y beber champán -- sigamos adelante y mejorémosla.
305
305
306
306
Como se dijo, la función `pow(x, n)` está dedicada a trabajar con valores enteros positivos `n`.
307
307
@@ -336,10 +336,9 @@ El resultado con los nuevos tests:
336
336
El test recién creado falla, porque nuestra implementación no lo soporta. Así es como funciona la metodología BDD: primero escribimos un test que falle y luego realizamos la implementación para que pase.
337
337
338
338
```smart header="Otras comprobaciones"
339
-
340
339
Por favor, ten en cuenta la comprobación `assert.isNaN`: ella comprueba que el valor es `NaN`.
341
340
342
-
Hay otras comprobaciones en Chai también, por ejemplo:
341
+
Hay otras comprobaciones en Chai también [Chai](http://chaijs.com), por ejemplo:
343
342
344
343
- `assert.equal(value1, value2)` -- prueba la igualdad `value1 == value2`.
@@ -386,27 +385,25 @@ El spec puede ser usado de tres formas:
386
385
387
386
Con la especificación, podemos mejorar de forma segura, cambiar, incluso reescribir la función desde cero y estar seguros que seguirá funcionando.
388
387
389
-
Esto es especialmente importante en proyectos largos cuando una función es usada en muchos sitios. Cuando cambiamos una función, no hay forma manual de comprobar si cada sitio dónde se usaba sigue funcionando correctamente.
388
+
Esto es especialmente importante en proyectos largos cuando una función es usada en muchos sitios. Cuando cambiamos una función, no hay forma manual de comprobar si cada sitio donde se usaba sigue funcionando correctamente.
390
389
391
-
Sin tests, la gente tiene dos maneras:
390
+
Sin tests, la gente tiene dos opciones:
392
391
393
-
1. Realizar el cambio, no importa nada más. Luegos los usuarios encontrán errores y deberán notificarlos. Si podemos abordarlo.
394
-
2.La gente tiene miedo de cambiar funciones si el castigo por error es duro. Entonces el código envejecerá de forma descuidada con telarañas, nadie querrá meterse en él y eso no es bueno.
392
+
1. Realizar el cambio, no importa nada más. Luego nuestros usuarios encontrán errores porque probablemente fallemos en encontrarlos.
393
+
2.Si el castigo por errores es duro, la gente tendrá miedo de hacer cambios en las funciones. Entonces el código envejecerá, nadie querrá meterse en él y eso no es bueno para el desarrollo.
395
394
396
-
**¡Las pruebas automáticas son lo contrario a eso!**
395
+
**¡El test automatizado ayuda a evitar estos problemas!**
397
396
398
-
Si el proyecto esta cubierto de pruebas, no tendremos ese problema. Podemos correr los tests y hacer multitud de comprabaciones en cuestión de segundos.
397
+
Si el proyecto esta cubierto de pruebas, no tendremos ese problema. Podemos correr los tests y hacer multitud de comprobaciones en cuestión de segundos.
399
398
400
399
**Además, un código bien probado tendrá una mejor arquitectura.**
401
400
402
401
Naturalmente, porque el código será más fácil de cambiar y mejorar. Pero no sólo eso.
403
402
404
403
Al escribir tests, el código debe estar organizado de tal manera que cada función tenga un propósito claro y explícito, una entrada y una salida bien definida. Eso implica una buena arquitectura desde el principio.
405
404
406
-
En la vida real a veces las cosas no son tan fáciles. A veces, es difícil escribir una especificación antes que el código, porque no esta claro aún cómo dee comportarse dicho código. Pero en general, escribir los tests hace el desarrollo más rápido y más estable.
407
-
408
-
## ¿Qué viene ahora?
405
+
En la vida real a veces no es tan fácil. A veces es difícil escribir una especificación antes que el código, porque no está claro aún cómo debe comportarse dicho código. Pero en general, escribir los tests hace el desarrollo más rápido y más estable.
409
406
410
-
Al final en el tutorial encontrarás muchas tareas respaldadas con pruebas. Ahí tenemos más ejemplos prácticos de tests.
407
+
En el tutorial encontrarás más adelante muchas tareas respaldadas con pruebas. Veremos más ejemplos prácticos de tests.
411
408
412
-
Escribir tests requiere un buen conocimiento de JavaScript. Pero nosotros justo acabamos de empezar a aprenderlo. Así que para comenzar no es necesario que escribas tests, pero sí que seas capaz de leerlos y entenderlos, incluso ejemplos más complejos que aparecerán más adelante en este capítulo.
409
+
Escribir tests requiere un buen conocimiento de JavaScript. Pero nosotros justo acabamos de empezar a aprenderlo. Así que para comenzar no es necesario que escribas tests, pero deberías ser capaz de leerlos incluso si son más compleos que en este capítulo.
0 commit comments