2012-03-16 947 views
42

Esta pregunta se relaciona con el marco de prueba de Mocha para NodeJS.¿Cómo puedo ejecutar pruebas de Mocha asíncronas (NodeJS) en orden?

comportamiento

El valor por defecto parece ser la de iniciar todas las pruebas, y luego procesar las devoluciones de llamada asincrónicas a medida que llegan.

Cuando la ejecución de pruebas asincrónicos, me gustaría correr cada prueba después la parte asíncrona de la uno antes ha sido llamado.

¿Cómo puedo hacer esto?

Respuesta

30

El punto no es tanto que el "código estructurado se ejecuta en el orden en que se ha estructurado" (sorprender!) -, sino más bien como @chrisdew sugiere, las órdenes de restitución para las pruebas asincrónicos no se puede garantizar. Para replantear el problema: las pruebas que se encuentran más abajo en la cadena (ejecución síncrona) no pueden garantizar que las condiciones requeridas, establecidas por las pruebas asíncronas, estarán listas cuando se ejecuten.

Así que si usted está requiriendo ciertas condiciones que deberán establecerse en las primeras pruebas (como un inicio de sesión de fichas o similares), usted tiene que usar ganchos como before() que ponen a prueba estas condiciones están recogidas antes de continuar.

abrigo de las pruebas dependientes en un bloque y ejecutar un asíncronobefore gancho en ellos (notar el 'hecho' en el antes del bloque):

var someCondition = false 

// ... your Async tests setting conditions go up here... 

describe('is dependent on someCondition', function(){ 

    // Polls `someCondition` every 1s 
    var check = function(done) { 
    if (someCondition) done(); 
    else setTimeout(function(){ check(done) }, 1000); 
    } 

    before(function(done){ 
    check(done); 
    }); 

    it('should get here ONLY once someCondition is true', function(){ 
    // Only gets here once `someCondition` is satisfied 
    }); 

}) 
+0

¿Cómo cambiaría 'someCondition' alguna vez si la devolución de llamada anterior está bloqueada en un ciclo while? Esta no es la forma en que funciona JavaScript. – natevw

+0

La respuesta a su pregunta se encuentra en la línea de comentario 3: "... aquí suben las condiciones de configuración de las pruebas Async". Específicamente: Async, condiciones de configuración, con alcance fuera de 'describe()' que crea una instancia antes de 'antes()'. Su última afirmación de que Javascript no funciona de esta manera es falsa. – papercowboy

+0

Mientras su código se bloquea varias veces comprobando! AlgunaCondición una y otra vez, no se puede ejecutar ninguno de sus otros códigos. (Todas las otras devoluciones de llamada asociadas con eventos/temporizadores se impedirán de ejecutarse.) La única forma en que esto funcionaría es si alguna Condición se establece como verdadera antes de que comience el ciclo; de lo contrario, se bloqueará. Intentalo. – natevw

7

Me sorprende lo que escribiste mientras uso. Uso mocha con las pruebas de estilo bdd (describe/it), y acabo de agregar algunos console.logs a mis pruebas para ver si tus afirmaciones son válidas en mi caso, pero aparentemente no es así.

Aquí está el fragmento de código que he usado para ver el orden de "end1" y "start1". Fueron ordenados apropiadamente.

describe('Characters start a work', function(){ 
    before(function(){ 
     sinon.stub(statusapp, 'create_message'); 
    }); 
    after(function(){ 
     statusapp.create_message.restore(); 
    }); 
    it('creates the events and sends out a message', function(done){ 
     draftwork.start_job(function(err, work){ 
     statusapp.create_message.callCount.should.equal(1); 
     draftwork.get('events').length.should.equal(
      statusapp.module('jobs').Jobs.get(draftwork.get('job_id')).get('nbr_events') 
     ); 
     console.log('end1'); 
     done(); 
     }); 
    }); 
    it('triggers work:start event', function(done){ 
     console.log('start2'); 
     statusapp.app.bind('work:start', function(work){ 
     work.id.should.equal(draftwork.id); 
     statusapp.app.off('work:start'); 
     done(); 
     }); 

Por supuesto, esto podría haber sucedido por casualidad también, pero tengo un montón de pruebas, y si iban a ejecutar en paralelo, sin duda lo que las condiciones de carrera, que yo no tengo.

Consulte también this issue desde el rastreador de problemas de mocha. Según él, las pruebas se ejecutan sincrónicamente.

+0

Esto solo muestra que el código ordenado se ejecuta en orden. Eso no sucede por accidente. Asi es como funciona". – papercowboy

+0

Esto muestra que las pruebas asíncronas ordenadas se ejecutan en orden: 'end1' siempre ocurrirá antes de' start2'. Para simplificar el ejemplo, puede reemplazar el contenido de la primera prueba con 'setTimeout (done, 1000)'.Y si reemplaza el gancho 'before' con el asincrónico, siempre se ejecutará antes de la primera prueba. Según tengo entendido, este es exactamente el comportamiento que interesó al iniciador de temas, y este comportamiento es el predeterminado y el único, al menos por ahora. – skozin

5

quería resolver este mismo problema con nuestra aplicación , pero el accepted answer no funcionó bien para nosotros. Especialmente en el someCondition nunca sería cierto.

Utilizamos promesas en nuestra aplicación y esto facilitó la estructura de las pruebas en consecuencia. La clave, sin embargo sigue siendo para retrasar la ejecución a través de la before gancho:

var assert = require("assert"); 

describe("Application", function() { 
    var application = require(__dirname + "/../app.js"); 
    var bootPromise = application.boot(); 

    describe("#boot()", function() { 
    it("should start without errors", function() { 
     return bootPromise; 
    }); 
    }); 

    describe("#shutdown()", function() { 
    before(function() { 
     return bootPromise; 
    }); 

    it("should be able to shut down cleanly", function() { 
     return application.shutdown(); 
    }); 
    }); 
}); 
+3

Será mejor que coloque la segunda y la tercera línea de código ('application = ...' y 'bootPromise = ...') dentro del bloque 'before' de asincronización en el paquete de nivel superior (" Aplicación "). De lo contrario, cualquier excepción lanzada desde este código no será capturada e informada correctamente y, lo que es peor, evitará la ejecución de todas las pruebas restantes. – skozin

4

uso mocha-steps

mantiene pruebas secuenciales sin tener en cuenta si son asíncrono o no (es decir, sus done funciones siguen funcionando exactamente como lo hicieron). Es un reemplazo directo para it y en su lugar usa step

+0

¿por qué se ha votado? –

+1

@JackMurphy buena pregunta. – WiR3D

+0

Lo mismo. Tuve el mismo problema y esto me ayudó. – hrishioa

Cuestiones relacionadas