|
| 1 | +# Aserciones |
| 2 | + |
| 3 | +Las aserciones son mezcladas como parte del [contexto de ejecución](./02-execution-context.md) proporcionado a cada implementación de prueba: |
| 4 | + |
| 5 | +```js |
| 6 | +test('los unicornios existen', t => { |
| 7 | + t.truthy('unicorn'); // asercion |
| 8 | +}); |
| 9 | +``` |
| 10 | + |
| 11 | +Las aserciones están vinculadas a sus pruebas, por lo que puedes asignarlas a una variable o pasarlas como argumentos: |
| 12 | + |
| 13 | +```js |
| 14 | +test('los unicornios existen', t => { |
| 15 | + const truthy = t.truthy; |
| 16 | + truthy('unicorn'); |
| 17 | +}); |
| 18 | +``` |
| 19 | + |
| 20 | +Si se encuentran múltiples fallas en las aserciones dentro de una sola prueba, AVA solo mostrará la *primera* de ellas. |
| 21 | + |
| 22 | +## Planificación de aserciones |
| 23 | + |
| 24 | +La planificacion de aserciones garantiza que las pruebas solo pasen cuando se haya ejecutado un número específico de aserciones. |
| 25 | +Te ayudará a detectar casos en los que las pruebas terminan demasiado pronto. También harán que las pruebas fallen si se ejecutan demasiadas aserciones, lo que puede ser útil si tiene aserciones dentro de callbacks o bucles. |
| 26 | + |
| 27 | +Si no especificas un plan de aserción, tu prueba aún fallará si no se ejecuta ninguna aserción. Debes establecer la opción `failWithoutAssertions` en` false` en la [configuración `package.json`] de AVA (./ 06-configuration.md) para deshabilitar este comportamiento. |
| 28 | + |
| 29 | +Ten en cuenta que, a diferencia de [`tap`] (https://www.npmjs.com/package/tap) y [` tape`] (https://www.npmjs.com/package/tape), AVA *no* finaliza automáticamente una prueba cuando se alcanza el recuento de aserciones planificado. |
| 30 | + |
| 31 | +Estos ejemplos darán como resultado una prueba exitosa: |
| 32 | + |
| 33 | +```js |
| 34 | +test('se resuelve a 3', t => { |
| 35 | + t.plan(1); |
| 36 | + |
| 37 | + return Promise.resolve(3).then(n => { |
| 38 | + t.is(n, 3); |
| 39 | + }); |
| 40 | +}); |
| 41 | + |
| 42 | +test.cb('invoca a un callback', t => { |
| 43 | + t.plan(1); |
| 44 | + |
| 45 | + someAsyncFunction(() => { |
| 46 | + t.pass(); |
| 47 | + t.end(); |
| 48 | + }); |
| 49 | +}); |
| 50 | +``` |
| 51 | + |
| 52 | +Estas no: |
| 53 | + |
| 54 | +```js |
| 55 | +test('el loop se ejecuta dos veces', t => { |
| 56 | + t.plan(2); |
| 57 | + |
| 58 | + for (let i = 0; i < 3; i++) { |
| 59 | + t.true(i < 3); |
| 60 | + } |
| 61 | +}); // Falla, 3 aserciones son ejecutadas lo cual es demasiado |
| 62 | + |
| 63 | +test('llama a un callback sincronicamente', t => { |
| 64 | + t.plan(1); |
| 65 | + |
| 66 | + someAsyncFunction(() => { |
| 67 | + t.pass(); |
| 68 | + }); |
| 69 | +}); // Falla, la prueba falla sincronicamente antes de que la asercion sea ejecutada |
| 70 | +``` |
| 71 | + |
| 72 | +## Omitiendo Aserciones |
| 73 | + |
| 74 | +Cualquier aserción puede omitirse usando el modificador `skip`. |
| 75 | +Las afirmaciones omitidas todavía se cuentan, por lo que no es necesario cambiar el recuento de afirmaciones planificadas. |
| 76 | + |
| 77 | +```js |
| 78 | +test('omitir asercion', t => { |
| 79 | + t.plan(2); |
| 80 | + t.is.skip(foo(), 5); // No necesitas cambiar tu plan cuando estas omitiendo |
| 81 | + t.is(1, 1); |
| 82 | +}); |
| 83 | +``` |
| 84 | + |
| 85 | +## Mensajes de afirmación mejorados |
| 86 | + |
| 87 | +Habilitando [Babel] (./recipes/babel.md) también habilitará [`power-assert`] (https://github.com/power-assert-js/power-assert), brindándote mensajes de afirmación más descriptivos. |
| 88 | + |
| 89 | +Tomemos este ejemplo, usando la [biblioteca `assert` estándar de Node](https://nodejs.org/api/assert.html): |
| 90 | + |
| 91 | +```js |
| 92 | +const a = /foo/; |
| 93 | +const b = 'bar'; |
| 94 | +const c = 'baz'; |
| 95 | +require('assert').ok(a.test(b) || b === c); |
| 96 | +``` |
| 97 | + |
| 98 | +Si lo pegas en un REPL de node, retornará: |
| 99 | + |
| 100 | +``` |
| 101 | +AssertionError: false == true |
| 102 | +``` |
| 103 | + |
| 104 | +Sin embargo, con la asercion de AVA "assert", esta prueba: |
| 105 | + |
| 106 | +```js |
| 107 | +test('aserciones mejoradas', t => { |
| 108 | + const a = /foo/; |
| 109 | + const b = 'bar'; |
| 110 | + const c = 'baz'; |
| 111 | + t.assert(a.test(b) || b === c); |
| 112 | +}); |
| 113 | +``` |
| 114 | + |
| 115 | +La salida será: |
| 116 | + |
| 117 | +``` |
| 118 | +6: const c = 'baz'; |
| 119 | +7: t.assert(a.test(b) || b === c); |
| 120 | +8: }); |
| 121 | +
|
| 122 | +Value is not truthy: |
| 123 | +
|
| 124 | +false |
| 125 | +
|
| 126 | +a.test(b) || b === c |
| 127 | +=> false |
| 128 | +
|
| 129 | +b === c |
| 130 | +=> false |
| 131 | +
|
| 132 | +c |
| 133 | +=> 'baz' |
| 134 | +
|
| 135 | +b |
| 136 | +=> 'bar' |
| 137 | +
|
| 138 | +a.test(b) |
| 139 | +=> false |
| 140 | +
|
| 141 | +b |
| 142 | +=> 'bar' |
| 143 | +
|
| 144 | +a |
| 145 | +=> /foo/ |
| 146 | +``` |
| 147 | + |
| 148 | +## Aserciones personalizadas |
| 149 | + |
| 150 | +Puedes usar cualquier biblioteca de aserciones en lugar o además de la incorporada, siempre que genere excepciones cuando la aserción falle. |
| 151 | + |
| 152 | +Sin embargo, esto no te brindará una experiencia tan agradable como la que obtendrías con las [aserciones integradas](#built-in-assertions), y no podrás usar la [planificación de aserciones] (#assertion-planning) ([mira #25] (https://github.com/avajs/ava/issues/25)). |
| 153 | + |
| 154 | +Tendrás que configurar AVA para que no falle las pruebas si no se ejecutan aserciones, porque AVA no puede decir si las aserciones personalizadas pasan. Establece la opción `failWithoutAssertions` en` false` en la [configuración `package.json`] de AVA (./06-configuration.md). |
| 155 | + |
| 156 | +```js |
| 157 | +const assert = require('assert'); |
| 158 | + |
| 159 | +test('custom assertion', t => { |
| 160 | + assert(true); |
| 161 | +}); |
| 162 | +``` |
| 163 | + |
| 164 | +## Aserciones incorporadas |
| 165 | + |
| 166 | +### `.pass(message?)` |
| 167 | + |
| 168 | +Aserción exitosa. |
| 169 | + |
| 170 | +### `.fail(message?)` |
| 171 | + |
| 172 | +Aserción fallida. |
| 173 | + |
| 174 | +### `.assert(value, message?)` |
| 175 | + |
| 176 | +Verifica que `value` es verdadero. Esto es [`power-assert`](#enhanced-assertion-messages) habilitado. |
| 177 | + |
| 178 | +### `.truthy(value, message?)` |
| 179 | + |
| 180 | +Varifica que `value` is verdadero. |
| 181 | + |
| 182 | +### `.falsy(value, message?)` |
| 183 | + |
| 184 | +Verifica que `value` es falso. |
| 185 | + |
| 186 | +### `.true(value, message?)` |
| 187 | + |
| 188 | +Verifica que `value` es verdadero. |
| 189 | + |
| 190 | +### `.false(value, message?)` |
| 191 | + |
| 192 | +Verifica que `value` es falso. |
| 193 | + |
| 194 | +### `.is(value, expected, message?)` |
| 195 | + |
| 196 | +Verifica que `value` es igual a `expected`. Esta verificación se basa en [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). |
| 197 | + |
| 198 | +### `.not(value, expected, message?)` |
| 199 | + |
| 200 | +Verifica que `value` no es igual a `expected`. Esta verificación se basa en [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). |
| 201 | + |
| 202 | +### `.deepEqual(value, expected, message?)` |
| 203 | + |
| 204 | +Verifica que `value` tiene valores identicos a `expected`. Mira [Concordance](https://github.com/concordancejs/concordance) prara mas detalles. |
| 205 | +Funciona con [elemento de React y `react-test-renderer`](https://github.com/concordancejs/react). |
| 206 | + |
| 207 | +### `.notDeepEqual(value, expected, message?)` |
| 208 | + |
| 209 | +Verifica que `value` no tenga valores identicos a `expected`. Lo contrario de `.deepEqual()`. |
| 210 | + |
| 211 | +### `.like(value, selector, message?)` |
| 212 | + |
| 213 | +Verifica que `value` sea como `selector`. Es una variante de `.deepEqual()`, sin embargo `selector` |
| 214 | +no necesita tener las mias propiedades que `value` tiene. |
| 215 | + |
| 216 | +En su lugar AVA deriva un objeto *comparable* a partir de `value`, basado en las propiedades anidadas identicas de `selector`. |
| 217 | +Este objeto es entonces comparado a `selector` haciendo uso de `.deepEqual()`. |
| 218 | + |
| 219 | +Cualquiera de los valores en `selector` que no sean objetos regulares deberian ser identicamente iguales a los valores correspondientes en `value`. |
| 220 | + |
| 221 | +En el siguiente ejemplo, la propiedad `map` de `value` debe ser identica a la de `selector`. |
| 222 | +Sin embargo, `nested.qux` es ignorado, puesto que no esta en el `selector`. |
| 223 | + |
| 224 | +```js |
| 225 | +t.like({ |
| 226 | + map: new Map([['foo', 'bar']]), |
| 227 | + nested: { |
| 228 | + baz: 'thud', |
| 229 | + qux: 'quux' |
| 230 | + } |
| 231 | +}, { |
| 232 | + map: new Map([['foo', 'bar']]), |
| 233 | + nested: { |
| 234 | + baz: 'thud', |
| 235 | + } |
| 236 | +}) |
| 237 | +``` |
| 238 | + |
| 239 | +### `.throws(fn, expectation?, message?)` |
| 240 | + |
| 241 | +Verifica que un error es retornado. `fn` debe ser una funcion que retorne un error. El valor retornado por la funcion *debe* ser un error. |
| 242 | +El error es retornado de forma que tu puedes ejecutar mas validaciones contra dicho error. |
| 243 | + |
| 244 | +`expectation` puede ser un objeto con una o mas de las siguientes propiedades: |
| 245 | + |
| 246 | +* `instanceOf`: un contructor, el error arrojado debe ser una instancia de |
| 247 | +* `is`: el error arrojado debe ser estrictamente igual a `expectation.is` |
| 248 | +* `message`: puede ser un string, el es comparado con el mensaje de error retornado, o una expresion regular, la cual es comparada con el mensaje |
| 249 | +* `name`: un valor esperado para `.name` del error retornado |
| 250 | +* `code`: un valor esperado para `.code` del error retornado |
| 251 | + |
| 252 | +`expectation` no necesitas especificarlo. Si no lo necesitas pero deseas crear un mensaje de asercion debes espeficiar `null`. |
| 253 | + |
| 254 | +Por ejemplo: |
| 255 | + |
| 256 | +```js |
| 257 | +const fn = () => { |
| 258 | + throw new TypeError('🦄'); |
| 259 | +}; |
| 260 | + |
| 261 | +test('throws', t => { |
| 262 | + const error = t.throws(() => { |
| 263 | + fn(); |
| 264 | + }, {instanceOf: TypeError}); |
| 265 | + |
| 266 | + t.is(error.message, '🦄'); |
| 267 | +}); |
| 268 | +``` |
| 269 | + |
| 270 | +### `.throwsAsync(thrower, expectation?, message?)` |
| 271 | + |
| 272 | +Verifica que se produce un error. `thrower` puede ser una función asincrónica que debería arrojar el error, o una promesa que debería ser rechazada. Esta afirmación debe ser esperada a que se termine (awaited). |
| 273 | + |
| 274 | +El valor arrojado *debe* ser un error. Se devuelve para que puedas ejecutar más verificaciones usandola. |
| 275 | + |
| 276 | +`expectation` puede ser un objeto con una o más de las siguientes propiedades: |
| 277 | + |
| 278 | +* `instanceOf`: un constructor, el error lanzado debe ser una instancia de |
| 279 | +* `is`: el error arrojado debe ser estrictamente igual a `expectation.is` |
| 280 | +* `message`: ya sea una cadena, que se compara con el mensaje de error arrojado, o una expresión regular, que se compara con este mensaje |
| 281 | +* `name`: el valor esperado de `.name` del error lanzado |
| 282 | +* `code`: el valor esperado de `.code` del error lanzado |
| 283 | + |
| 284 | +`expectation` no es necesario especificarlo. Si no lo necesitas pero deseas establecer un mensaje de aserción, debe especificar `null`. |
| 285 | + |
| 286 | +Ejemplo: |
| 287 | + |
| 288 | +```js |
| 289 | +test('throws', async t => { |
| 290 | + await t.throwsAsync(async () => { |
| 291 | + throw new TypeError('🦄'); |
| 292 | + }, {instanceOf: TypeError, message: '🦄'}); |
| 293 | +}); |
| 294 | +``` |
| 295 | + |
| 296 | +```js |
| 297 | +const promise = Promise.reject(new TypeError('🦄')); |
| 298 | + |
| 299 | +test('promesa rechazada', async t => { |
| 300 | + const error = await t.throwsAsync(promise); |
| 301 | + t.is(error.message, '🦄'); |
| 302 | +}); |
| 303 | +``` |
| 304 | + |
| 305 | +### `.notThrows(fn, message?)` |
| 306 | + |
| 307 | +Verifica que no se produce ningún error. `fn` debe ser una función que no debería arrojar errores. |
| 308 | + |
| 309 | +### `.notThrowsAsync(nonThrower, message?)` |
| 310 | + |
| 311 | +Verifica que no se produce ningún error. `nonThrower` puede ser una función asincrónica que no debería lanzar, o una promesa que debería resolverse exitosamente. |
| 312 | + |
| 313 | +Al igual que la aserción `.throwsAsync ()`, debe esperar a que se complete la aserción: |
| 314 | + |
| 315 | +```js |
| 316 | +test('promesa resuelta exitosamente', async t => { |
| 317 | + await t.notThrowsAsync(promise); |
| 318 | +}); |
| 319 | +``` |
| 320 | + |
| 321 | +### `.regex(contents, regex, message?)` |
| 322 | + |
| 323 | +Verifica que `contents` coincida con `regex`. |
| 324 | + |
| 325 | +### `.notRegex(contents, regex, message?)` |
| 326 | + |
| 327 | +Verifica que `contents` no coincida con `regex`. |
| 328 | + |
| 329 | +### `.snapshot(expected, message?)` |
| 330 | +### `.snapshot(expected, options?, message?)` |
| 331 | + |
| 332 | +Compara el valor `expected` con un snapshot registrado anteriormente. Los snapshots se almacenan para cada prueba, así que asegúrate de asignar títulos únicos a tus pruebas. Alternativamente, pasa un objeto `options` para seleccionar un snapshot específico, por ejemplo,` {id: 'my snapshot'} `. |
| 333 | + |
| 334 | +Las verificaciones de los snapshots no se pueden omitir cuando se actualizan los snapshots. |
| 335 | + |
| 336 | +### `.try(title?, implementation | macro | macro[], ...args?)` |
| 337 | + |
| 338 | +`.try()` te permite *probar* aserciones sin hacer que la prueba falle. |
| 339 | + |
| 340 | +La función de implementación se comporta igual que cualquier otra función de prueba. Incluso puedes usar macros. El primer argumento del título siempre es opcional. Los argumentos adicionales se pasan a la función de implementación o a la función macro. |
| 341 | + |
| 342 | +`.try ()` es una función asíncrona. Debes esperar a que se resuelva `await`. El objeto de resultado tiene métodos `commit ()` y `discard ()`. Debes decidir si haces `commit` o `discard` sobre el resultado. Si haces `commit` sobre un resultado fallido, su prueba fallará. |
| 343 | + |
| 344 | +Puede comprobar si el intento se aprobó utilizando la propiedad `pass`. Cualquier error de afirmación está disponible a través de la propiedad `errors`. El título del intento está disponible a través de la propiedad `title`. |
| 345 | + |
| 346 | +Los logs de `t.log ()` están disponibles a través de la propiedad `logs`. Puedes optar por conservar estos registros como parte de tu prueba pasando `{keepLogs: true}` a los métodos `commit ()` y `discard ()`. |
| 347 | + |
| 348 | +La función de implementación recibe su propio [contexto de ejecución] (./02-execution-context.md), al igual que una función de prueba. Debe tener cuidado de realizar solo aserciones utilizando el contexto de ejecución del intento. Al menos una afirmación debe aprobarse para que su intento sea marcado como exitoso. |
| 349 | + |
| 350 | +Puedes ejecutar varios intentos al mismo tiempo, dentro de una sola prueba. Sin embargo, no puedes usar snapshots cuando haces eso. |
| 351 | + |
| 352 | +Ejemplo: |
| 353 | + |
| 354 | +```js |
| 355 | +const twoRandomIntegers = () => { |
| 356 | + const rnd = Math.round(Math.random() * 100); |
| 357 | + const x = rnd % 10; |
| 358 | + const y = Math.floor(rnd / 10); |
| 359 | + return [x, y]; |
| 360 | +}; |
| 361 | + |
| 362 | +test('flaky macro', async t => { |
| 363 | + const firstTry = await t.try((tt, a, b) => { |
| 364 | + tt.is(a, b); |
| 365 | + }, ...randomIntegers()); |
| 366 | + |
| 367 | + if (firstTry.passed) { |
| 368 | + firstTry.commit(); |
| 369 | + return; |
| 370 | + } |
| 371 | + |
| 372 | + firstTry.discard(); |
| 373 | + t.log(firstTry.errors); |
| 374 | + |
| 375 | + const secondTry = await t.try((tt, a, b) => { |
| 376 | + tt.is(a, b); |
| 377 | + }, ...randomIntegers()); |
| 378 | + secondTry.commit(); |
| 379 | +}); |
| 380 | +``` |
0 commit comments