Skip to content

Latest commit

 

History

History
731 lines (494 loc) · 22.9 KB

readme.md

File metadata and controls

731 lines (494 loc) · 22.9 KB

Nota del traductor

Esta es la traducción del archivo readme.md. Aquí hay un enlace a las diferencias con la rama master de AVA (Si al hacer clic en el enlace no se encuentran modificaciones en el archivo readme.md, será por que la traducción está actualizada).


AVA

Test runner futurista

Build Status: Linux Build status: Windows Coverage Status Gitter

A pesar de que JavaScript se ejecuta en un solo hilo, IO en Node.js puede ejecutarse en paralelo debido a su naturaleza asíncrona. AVA aprovecha esto y corre sus tests al mismo tiempo, lo que es especialmente beneficioso para tests pesados en IO. Además, los archivos de test se ejecutan en paralelo como procesos separados, que le da un mejor rendimiento y un entorno aislado para cada archivo de test. Cambiando de Mocha a AVA en Pageres llevó el tiempo de los test por debajo de 31 segundos, concretamente a 11 segundos. El tener tests que se ejecutan al mismo tiempo nos obliga a escribir tests atómicos, es decir, los tests no dependen del estado global o el estado de otros tests, lo que está muy bien!

Lea nuestra guía de contribución si está pensando en contribuir (issues/PRs/etc).

Tabla de contenidos

¿Por qué AVA?

Sintaxis de test

import test from 'ava';

test(t => {
	t.same([1, 2], [1, 2]);
});

Uso

Inicializar

Instalar AVA globalmente $ npm install --global ava y ejecutar $ ava --init (con cualquiera de las opciones) para añadir AVA a tu package.json o crear una.

{
	"name": "awesome-package",
	"scripts": {
		"test": "ava"
	},
	"devDependencies": {
		"ava": "^0.6.0"
	}
}

Crear tu archivo de test

import test from 'ava';
import delay from 'delay';

test('foo', t => {
	t.pass();
});

test('bar', async t => {
	t.plan(1);

	const bar = Promise.resolve('bar').then(delay(200));

	t.is(await bar, 'bar');
});

Ejecutar el test

$ npm test

CLI

$ ava --help

  Usage
    ava [<file|folder|glob> ...]

  Options
    --init       Add AVA to your project
    --fail-fast  Stop after first test failure
    --serial     Run tests serially
    --require    Module to preload (Can be repeated)
    --tap        Generate TAP output
    --verbose    Enable verbose output

  Examples
    ava
    ava test.js test2.js
    ava test-*.js
    ava test
    ava --init
    ava --init foo.js

  Default patterns when no arguments:
  test.js test-*.js test/**/*.js

Los directorios son recursivos por defecto. Los archivos que se encuentren en directorios llamados fixtures y helpers serán ignorados, así como los archivos que comienzan con _. Esto nos puede ser útil para tener helpers en el mismo directorio que los archivos de test.

ADVERTENCIA: COMPORTAMIENTO NO ESTÁNDAR: La CLI de AVA tratará siempre de encontrar y utilizar su instalación local de AVA. Esto será así incluso cuando se ejecuta el comando ava global. Este comportamiento no estándar resuelve un importante problema, y no debe tener ningún impacto en el uso diario.

Configuración

Todas las opciones de CLI pueden configurarse en la sección de 'ava' de su 'package.json'. Esto le permite modificar el comportamiento predeterminado del comando 'ava', para no tener que escribir varias veces las mismas opciones en el indicador de comandos.

{
  "ava": {
    "files": [
      "my-test-folder/*.js",
      "!**/not-this-file.js"
    ],
    "failFast": true,
    "serial": true,
    "tap": true,
    "verbose": true,
    "require": ["babel-core/register", "coffee-script/register"]
  }
}

Los argumentos pasados al CLI siempre tendrán prioridad sobre la configuración en 'package.json'.

Documentación

Los tests se ejecutan asincronamente y requieren devolver y soportar un objeto asíncrono (una promesa, u observable). Nosotros recomendamos altamente el uso de funciones asícronas; Hacen el código asíncrono, conciso y fácil de leer, y de forma implícita devuelven una promesa, por lo que no tiene que hacerla.

Si usted no devuelve uno de los objetos soportados y asincrónicos mencionados anteriormente, la prueba se considerará síncrona y terminará inmediatamente.

Si usted es incapaz de usar promesas u otros objetos asíncronos soportados, puede activar el "callback" por la definición de su test con test.cb([title], fn). Los test declarados de esta manera deben terminar manualmente con t.end(). Este modo está pensado principalmente para las APIs de tests con estilo callback.

Debe definir todas las pruebas de forma sincrona. No pueden estar definidos dentro de setTimeout, setImmediate, etc.

Los archivos de test se ejecutan desde el directorio actual, con lo que process.cwd() es siempre el mismo que __dirname. Puede tambien usar rutas de acceso relativas en lugar de hacer path.join(__dirname, 'relative/path').

Anatomía de test

Para crear un test, llamaremos a la función de test que requiera de AVA y pasaremos un nombre de test opcional y una función que contiene la ejecución del test. La función que pasemos será tomada en contexto como el primer argumento, dónde puedes invocar los diferentes métodos y aserciones de AVA.

test('name', t => {
	t.pass();
});

Nombre opcional del test

Dar nombre a un test es opcional, pero se recomienda usar uno si tenemos más de un test.

test(t => {
	t.pass();
});

También puede optar por utilizar una función nombrada en su lugar:

test(function name(t) {
	t.pass();
});

Plan de aserción

Un plan de aserción se puede utilizar para garantizar que un número determinado de aserciones se cumplen. El escenario más común es validar que el test no ha salido antes de ejecutar el número esperado de aserciones. También falla el test si se ejecutan demasiadas aserciones, puede ser útil si tiene aserciones dentro de callbacks o bucles.

Esto terminará en un test ejecutado satisfactoriamente:

test(t => {
	t.plan(1);

	return Promise.resolve(3).then(n => {
		t.is(n, 3);
	});
});

test.cb(t => {
	setTimeout(() => {
		t.pass();
		t.end();
	}, 100);
});

ADVERTENCIA: Cambio reciente de última hora.

AVA ya no soportará automáticamente la terminación de test via t.plan(...). Esto ayuda a prevenir falsos positivos si añade aserciones, pero olvidese de incrementar su recuento de plan.

// Esto ya no funcionará

test('auto ending is dangerous', t => {
	t.plan(2);

	t.pass();
	t.pass();

	// termina automáticamente después de llegar a las dos aserciones planificadas, se perderá la última
	setTimeout(() => t.fail(), 10000);
});

Para que esto funcione, ahora debe usar "callback mode" y llamar explícitamente t.end().

test.cb('explicitly end your tests', t => {
	t.plan(2);

	t.pass();
	t.pass();

	setTimeout(() => {
		// Este fallo ahora es recogido de forma fiable.
		t.fail();
		t.end();
	}, 1000);
});

Serial-tests

Mientras que la concurrencia es impresionante, hay algunas cosas que no se pueden hacer concurrentemente. En estos extraños casos, puede usar test.serial, lo que obligará a esos tests funcionar en serie antes de los concurrentes.

test.serial(t => {
	t.pass();
});

Only-tests

Only-tests fuerza a que se cumplan sólo los test que se ejecutan. Esto puede ser útil para el funcionamiento de sólo unos pocos tests durante el desarrollo.

test('will not be run', t => {
	t.fail();
})

test.only('will be run', t => {
	t.pass();
});

Skip-tests

Skip-tests se muestran como omitidos pero nunca ejecutados.

test.skip('will not be run', t => {
	t.fail();
});

Before & after hooks

Cuando se requiera empezar a preparar y/o abandonar, puede usar test.before() y test.after(), usandolo de la misma manera que test(). La función test permite el uso de test.before() y test.after(), siempre serán ejecutadas antes o despues de todos los tests. Puede usar incluso test.beforeEach() y test.afterEach() si necesita preparar algo antes y despues de cada test. Los hooks se ejecutan en serie en el archivo de test. Añada tantos como quiera. Opcionalmente puede especificar un título que se muestre en el error.

test.before(t => {
	// esto se ejecuta antes de todos los tests
});

test.before(t => {
	// esto se ejecuta después del anterior, pero antes de los tests
});

test.after('cleanup', t => {
	// esto se ejecuta despues de todos los tests
});

test.beforeEach(t => {
	// esto se ejecuta antes de cada test
});

test.afterEach(t => {
	// esto se ejecuta despues de cada test
});

test(t => {
	// test regular
});

Puede utilizar las funciones asíncronas, devolver objetos asincrónicos, o activar el "modo callback" en cualquiera de los hooks.

test.before(async t => {
	await promiseFn();
});

test.cb.beforeEach(t => {
	setTimeout(t.end);
});

test.afterEach.cb(t => {
	setTimeout(t.end);
});

test.after(t => {
   return new Promise(/* ... */);
});

Los hooks beforeEach y afterEach pueden compartir el contexto del test:

test.beforeEach(t => {
	t.context.data = generateUniqueData();
});

test(t => {
	t.is(t.context.data + 'bar', 'foobar');
});

El contexto por defecto es un objeto, pero también se puede asignar directamente:

test.beforeEach(t => {
	t.context = 'unicorn';
});

test(t => {
	t.is(t.context, 'unicorn');
});

Encadenar modificaciones de test

Puede encadenar modificaciones de test juntas de la siguiente manera:

test.before.skip([title], testFn);
test.skip.after(....);
test.serial.only(...);
test.only.serial(...);

Es especialmente util utilizar temporalmente skip o only en un test, sin perder la información y el comportamiento que los otros modificadores proporcionan.

Módulo aserción customizado

Puede utilizar cualquier módulo de aserción en lugar o además del que viene con AVA, pero no podrá utilizar el método .plan(), aún.

import assert from 'assert';

test(t => {
	assert(true);
});

Soporte a ES2015

AVA está construido con soporte a ES2015 a través de Babel 6. Sólo tiene que escribir sus pruebas en ES2015. No necesitará ninguna configuración adicional. Se puede utilizar cualquier versión de Babel en su proyecto. Utilizamos nuestro propio paquete de Babel con el es2015 y stage-2 preajustados.

Transpilando módulos importados

AVA actualmente sólo transpilará los tests que usted le pida que ejecute. No transpilará módulos que importen de fuera del test. Si bien hay razones válidas para adoptar este enfoque, puede que no sea lo que esperas!

Como solución simple, puede utilizar Babel's require hook con el fin de hacer transpilación sobre la marcha de los módulos que se importan posteriormente. Por que AVA soporta la sintaxis de módulo de ES2015, se puede utilizar para importar el hook requerido en sí:

import test from 'ava';
import 'babel-core/register';
import foo from './foo'; // <-- foo puede ser escrito en ES2015!

test('foo bar', t => {
	t.same('baz', foo('bar'));
});

#111 esta haciendo seguimiento de este tema como una mejora potencial.

Soporte a Promesas

Si usted devuelve una promesa en el test no necesitará poner fin de manera explícita al test, ya que terminará cuando la promesa se resuelva.

test(t => {
	return somePromise().then(result => {
		t.is(result, 'unicorn');
	});
});

Soporte a Generadores

AVA viene con soporte a generadores.

test(function * (t) {
	const value = yield generatorFn();
	t.true(value);
});

Soporte a funciones async

AVA viene con soporte a funciones async (async/await).

test(async function (t) {
	const value = await promiseFn();
	t.true(value);
});

// async arrow function
test(async t => {
	const value = await promiseFn();
	t.true(value);
});

Soporte a Observable

AVA viene con soporte a observables. Si devuelve un observable a partir de un test, AVA automáticamente podrá consumirlo hasta su finalización antes de terminar el test.

Si no necesita usar "callback mode" o llamar a t.end().

test(t => {
	t.plan(3);
	return Observable.of(1, 2, 3, 4, 5, 6)
		.filter(n => {
			// sólo números
			return n % 2 === 0;
		})
		.map(() => t.pass());
});

Soporte a Callback

AVA es compatible con el uso de t.end como callback final al utilizar las API de callback de error-first y node-style. AVA considerará como error cualquier valor truthy pasado como primer argumento de t.end. Tenga en cuenta que t.end requiere "callback mode", que se puede activar mediante el uso de la cadena test.cb.

test.cb(t => {
	// t.end comprueba automáticamente los errores para el primer argumento
	fs.readFile('data.txt', t.end);
});

Salida TAP opcional

AVA puede generar una salida TAP a través de la opción --tap para su uso con cualquier TAP reporter.

$ ava --tap | tap-nyan

API

test([título], cuerpo)

test.serial([título], cuerpo)

test.cb([título], cuerpo)

test.only([título], cuerpo)

test.skip([título], cuerpo)

test.before([título], cuerpo)

test.after([título], cuerpo)

test.beforeEach([título], cuerpo)

test.afterEach([título], cuerpo)

título

Tipo: string

Título de test.

cuerpo (contexto)

Tipo: function

Debe contener el test actual.

contexto

Pasado a la función de test y contiene los diferentes métodos de AVA y aserciones.

.plan(count)

Planifique cuántas aserciones hay en el test. El test fallará si el recuento actual de aserciones no coincide con las aserciones planificadas.

.end()

Finalizar el test. Sólo funciona con test.cb().

Aserciones

Las aserciones se mezclan en el contexto del test:

test(t => {
	t.ok('unicorn'); // aserción
});

Si se encuentran varios errores de aserción en un solo test, AVA sólo mostrará la primera.

.pass([mensaje])

Pasando la aserción.

.fail([mensaje])

Fallando la aserción.

.ok(valor, [mensaje])

Afirmando que valor es truthy.

.notOk(valor, [mensaje])

Afirmando que valor es falsy.

.true(valor, [mensaje])

Afirmando que valor es true.

.false(valor, [mensaje])

Afirmando que valor es false.

.is(valor, esperado, [mensaje])

Afirmando que valor es igual a esperado.

.not(valor, esperado, [mensaje])

Afirmando que valor no es igual a esperado.

.same(valor, esperado, [mensaje])

Afirmando que valor es profundamente igual a esperado.

.notSame(valor, esperado, [mensaje])

Afirmando que valor no es profundamente igual a esperado.

.throws(function|promise, error, [mensaje])

Afirmando que function arroja un error o promesa rechazada.

error puede contener un constructor, expresiones regulares, mensaje de error o la función de validación.

.doesNotThrow(function|promise, [mensaje])

Afirma que function no lanza un error o resuelve la promise.

.ifError(error, [mensaje])

Afirma que error es falsy.

Omitir aserciones

Cualquier aserción se puede omitir usando el modificador skip. Aunque se omitan dichas aserciones aún se cuentan, con lo que no hay necesidad de cambiar el contador de aserciones planificado.

test(t => {
  t.plan(2);
  t.skip.is(foo(), 5); // no hay necesidad de cambiar su contador planificado cuando omita aserciones.
  t.is(1, 1);
});

Aserciones mejoradas

AVA viene con power-assert incorporado, dándole mensajes de aserción más descriptivos. Lee el test y trata de inferir más información del código.

El siguiente test:

test(t => {
	const x = 'foo';
	t.ok(x === 'bar');
});

Normalmente dará la salida inútil:

false === true

Con las aserciones mejoradas, obtendrás:

t.ok(x === 'bar')
     |
     "foo"

Es cierto que se podría usar t.is() en este caso, y probablemente se debería, pero esto es sólo un ejemplo sencillo.

Probemos un ejemplo más avanzado:

test(t => {
	const a = /foo/;
	const b = 'bar';
	const c = 'baz';
	t.ok(a.test(b) || b === c);
});

Y ahí lo tienes:

t.ok(a.test(b) || b === c)
       |    |     |     |
       |    "bar" "bar" "baz"
       false

Todos los métodos assert se han mejorado.

¡Diviértete!

Entorno aislado

Cada archivo de test se ejecuta en un proceso de Node.js separado. Esto nos brinda un montón de beneficios. Los diferentes archivos de test ya no se afectan entre sí. Como archivos de test moqueados con el ambiente global, comandos internos imperativos, etc. Sin embargo, se hace principalmente por razones de rendimiento. Aunque Node.js puede ejecutar simultáneamente IO asíncrono, eso no ayuda mucho cuando las pruebas son operaciones síncronas pesadas que bloquean el hilo principal. Mediante la ejecución de tests al mismo tiempo y archivos de test en paralelo, tomamos todas las ventajas de los sistemas modernos.

Consejos

Los archivos temporales

Ejecutar tests simultáneamente tiene algunos desafíos, hacer IO es uno. Por lo general, los test por defecto crean directorios temporales en el directorio de test actual y lo limpian al final. Esto no funcionará cuando se ejecuten tests en paralelo y entrando en conflicto entre sí. La forma correcta de hacerlo es utilizar un nuevo directorio temporal para cada test. Los módulos tempfile y temp-write pueden ser útiles.

Depuración

AVA ejecuta pruebas en paralelo por defecto, que es subóptimo cuando se necesita depurar algo. En su lugar, ejecuta pruebas en serie con la opción --serial:

$ ava --serial

Cobertura de código

Puede usar istanbul para la cobertura de código como AVA spawns the test files, pero puede usar nyc en su luegar, que es básicamente istanbul con soporte para subprocesos.

Desde la versión 5.0.0 utiliza source maps para reportar la cobertura de su código real, independientemente de la transpilación. Asegúrese de que el código que está probando incluye un source map en línea o referencia a un archivo de source map de origen. Si usa babel/registerse puede establecer la opción sourceMaps en su .babelrc a inline.

FAQ

Por qué no mocha, tape, node-tap?

Mocha requiere el uso de globales implícitas como describe y it por defecto (que utilizan la mayoría de las personas), sin demasiadas opiniones buenas, hinchado, síncrono por defecto, ejecuta los tests en serie y es lento. Tape y node-tap son bastante buenos. AVA está muy inspirado en su sintaxis. Sin embargo, ambos ejecutan los tests en serie y han hecho de TAP un ciudadano de primera clase que ha hecho en mi humilde opinión que sus códigos base sean un poco enrevesadas y acopladas. La salida de TAP es difícil de leer, así que siempre terminan usando una herramienta de reporte de TAP externa. AVA tiene bastantes buenas opiniones y es concurrente. Viene con un simple reporter por defecto y tiene voluntad en el futuro de dar apoyo a Tun TAP reporter.

¿Cómo es el nombre escrito y pronunciado?

AVA, no Ava o ava. Pronunciado /ˈeɪvə/ ay-və.

¿Cuál es el fondo de la cabecera?

Andromeda galaxy.

Concurrencia vs. paralelismo

Concurrencia no es paralelismo. Permite paralelismo. Aprende más.

Soporte

Relacionado

Creado por

Sindre Sorhus Kevin Mårtensson Vadim Demedes James Talmage
Sindre Sorhus Kevin Mårtensson Vadim Demedes James Talmage



AVA