¿Cómo omitir una prueba mediante programación en mocha?

142

Tengo un código donde ciertas pruebas siempre fallarán en el entorno de CI. Me gustaría deshabilitarlos en función de una condición ambiental.

¿Cómo omitir mediante programación una prueba en mocha durante la ejecución del tiempo de ejecución?

Gajus
fuente
3
Programación saltarse una prueba está cubierta por this.skip()en mochajs.org/#inclusive-tests y la respuesta de @ zatziky a continuación. El resto de las respuestas son obsoletas para Mocha v3 +
Patrick
1
describe.skip ('descripción', () => {}) / describe.only ('descripción', () => {}) / it.skip ('descripción', () => {}) / it. only ('description', () => {})
Jun711
alguna respuesta aceptada?
Paul Rooney el

Respuestas:

168

Puede omitir las pruebas colocando una x delante de la descripción o el bloque, o colocando una .skipdespués.

xit('should work', function (done) {});

describe.skip('features', function() {});

También puede ejecutar una sola prueba colocando un .onlyen la prueba. por ejemplo

describe('feature 1', function() {});
describe.only('feature 2', function() {});
describe('feature 3', function() {});

Solo el bloque de características 2 se ejecutará en este caso.

No parece haber una forma de saltarse las pruebas mediante programación, pero podría hacer algún tipo de verificación en una beforeEachdeclaración y solo ejecutar la prueba si se estableció el indicador.

beforeEach(function(){
    if (wrongEnvironment){
        runTest = false
    }
}

describe('feature', function(){
    if(runTest){
         it('should work', function(){
            // Test would not run or show up if runTest was false,
         }
    }
}
KJ3
fuente
8
Su segundo intento de solución no funcionará, porque el orden de ejecución no es el que usted piensa. Cuando se beforeEachejecuta la llamada, Mocha registra la función anónima (el "gancho") para uso futuro , cuando se describeejecuta la llamada, Mocha ejecuta inmediatamente la función anónima que se le pasó. Entonces, para cuando if (runTest)se ejecute, el beforeEach gancho no se habrá ejecutado.
Louis
22
¿Cómo esta respuesta tiene 27 votos a favor? La pregunta se refiere a las pruebas de omisión programática, por lo que no es útil agregar ".skip" o ".only". Luego dice explícitamente que no puede hacer lo que el OP quiere hacer, a pesar del hecho de que otras respuestas le dicen cómo hacerlo.
Graeme Perrow
3
No funcionará, no es una respuesta a la pregunta, vea la respuesta de @Gajus en su lugar
NorTicUs
1
Esta respuesta tiene méritos para una pregunta diferente que no se hizo aquí. No tengo el poder de cambiar nada aquí. Vea la respuesta this.skip ().
Andrew Martinez
3
esto no responde a la pregunta
Ingo Renner
109

Hay una forma no documentada de omitir pruebas mediante programación:

// test.js

describe('foo', function() {
  before(function() {
    this.skip();
  });

  it('foo', function() {
    // will not run
    console.log('This will not be printed');
  });
});

corriendo:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

Esto se discute en https://github.com/mochajs/mocha/issues/1901 .

Gajus
fuente
13
A los lectores les gustaría saber que esto marca todo describecomo omitido (es decir, se omiten todas las pruebas en el describe).
Louis
Documentación de "pruebas pendientes" de Mocha: mochajs.org/#pending-tests
lasec0203
describe.skip ('descripción', () => {}) / describe.only ('descripción', () => {}) / it.skip ('descripción', () => {}) / it. only ('description', () => {})
Jun711
No entiendo por qué se vota este tipo de respuesta. es un truco, y no uno bonito.
chenop
2
documentación real mochajs.org/#inclusive-tests , no es un truco por cierto, sino un método correcto para excluir algunas pruebas basadas en la configuración del tiempo de ejecución. es decir, responde exactamente lo que hizo la pregunta original. Gracias @xavdid
WowPress.host
41

Esta respuesta funciona para ES6 .

En vez de:

describe('your describe block', () => {

Usted quiere:

(condition ? describe : describe.skip)('your describe block', () => {

Esto condicionalmente omite todas las pruebas en el bloque de descripción SI la condición es falsa.

O, en lugar de:

it('your it block', () => {

Usted quiere:

(condition ? it : it.skip)('your it block', () => {

Esto condicionalmente omite una prueba SI la condición es falsa.

danday74
fuente
44
Entiendo lo que estás sugiriendo, pero primero necesitas definir una descripción contextual como esta: const contextualDescribe = shouldAvoidTests ? describe.skip : describe luego puedes usarla: contextualDescribe('your it block', () => {
Ser
3
@Ser Para entrar en una sola línea, utilicé algo como esto:(condition ? describe : describe.skip)('your describe block', () => {
joshden
¿Cómo hacer esto asíncrono? Necesito buscar la condición de omisión basada en un indicador de redis, que es una operación asíncrona (almacenamos indicadores de características en redis).
Patrick Finnigan el
ha pasado un tiempo, pero también he tenido este tipo de necesidad antes, creo que acabo de envolver todas las cosas de mocha en una función que se llamó después de que se completó la devolución de llamada asincrónica - no puedo recordar los detalles exactos
danday74
Solía ​​usar esta técnica pero ahora me falla. intente simplemente escribir(it)('my test', () => {})
cyrf
33

Uso el tiempo de ejecución saltando de Mocha para el mismo escenario que estás describiendo. Es el copiar y pegar de los documentos :

it('should only test in the correct environment', function() {
  if (/* check test environment */) return this.skip();

  // make assertions
});

Como puede ver, omite la prueba según el entorno. Mi propia condición es if(process.env.NODE_ENV === 'continuous-integration').

Amio.io
fuente
2
¡Convenido! ¿Puede ser un trazador de líneas haciendo un regreso temprano tal vez? Me gusta: if (/* skipTestCondition */) return this.skip();- editar: funciona: D
SidOfc
12

para saltear las pruebas, use describe.skipoit.skip

describe('Array', function() {
  it.skip('#indexOf', function() {
    // ...
  });
});

para incluir pruebas que podría usar describe.onlyoit.only


describe('Array', function() {
  it.only('#indexOf', function() {
    // ...
  });
});

Más información en https://mochajs.org/#inclusive-tests

lfender6445
fuente
6

Depende de cómo desee omitir la prueba mediante programación. Si las condiciones para omitir se pueden determinar antes de ejecutar cualquier código de prueba, puede llamar ito it.skipsegún sea necesario, según una condición. Por ejemplo, esto omitirá algunas pruebas si la variable de entorno ONEse establece en cualquier valor:

var conditions = {
    "condition one": process.env["ONE"] !== undefined
    // There could be more conditions in this table...
};

describe("conditions that can be determined ahead of time", function () {
    function skip_if(condition, name, callback) {
        var fn = conditions[condition] ? it.skip: it;
        fn(name, callback);
    };

    skip_if("condition one", "test one", function () {
        throw new Error("skipped!");
    });

    // async.
    skip_if("condition one", "test one (async)", function (done) {
        throw new Error("skipped!");
    });

    skip_if("condition two", "test two", function () {
        console.log("test two!");
    });

});

Si las condiciones que desea verificar solo se pueden determinar en el momento de la prueba, es un poco más complicado. Si no desea acceder a nada que no sea estrictamente hablando parte de la API de prueba, puede hacer esto:

describe("conditions that can be determined at test time", function () {
    var conditions = {};
    function skip_if(condition, name, callback) {
        if (callback.length) {
            it(name, function (done) {
                if (conditions[condition])
                    done();
                else
                    callback(done);
            });
        }
        else {
            it(name, function () {
                if (conditions[condition])
                    return;
                callback();
            });
        }
    };

    before(function () {
        conditions["condition one"] = true;
    });

    skip_if("condition one", "test one", function () {
        throw new Error("skipped!");
    });

    // async.
    skip_if("condition one", "test one (async)", function (done) {
        throw new Error("skipped!");
    });

    skip_if("condition two", "test two", function () {
        console.log("test two!");
    });

});

Mientras que mi primer ejemplo fue marcar las pruebas como omitidas formalmente (también conocido como "pendiente"), el método que acabo de mostrar evitará realizar la prueba real, pero las pruebas no se marcarán como omitidas formalmente. Serán marcados como aprobados. Si realmente quiere omitirlos, no conozco ninguna forma de acceder a las partes que no son parte de la API de prueba:

describe("conditions that can be determined at test time", function () {
    var condition_to_test = {}; // A map from condition names to tests.
    function skip_if(condition, name, callback) {
        var test = it(name, callback);
        if (!condition_to_test[condition])
            condition_to_test[condition] = [];
        condition_to_test[condition].push(test);
    };

    before(function () {
        condition_to_test["condition one"].forEach(function (test) {
            test.pending = true; // Skip the test by marking it pending!
        });
    });

    skip_if("condition one", "test one", function () {
        throw new Error("skipped!");
    });

    // async.
    skip_if("condition one", "test one (async)", function (done) {
        throw new Error("skipped!");
    });

    skip_if("condition two", "test two", function () {
        console.log("test two!");
    });

});
Louis
fuente
3

No estoy seguro de si esto califica como "omisión programática", pero para omitir selectivamente algunas pruebas específicas para nuestro entorno de CI, utilizo la función de etiquetado de Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). En describe()o it()mensajes, puede agregar una etiqueta como @ no-ci. Para excluir esas pruebas, se puede definir una específica "objetivo ci" en su package.json y el uso --grepy --invertparámetros como:

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
martín
fuente
Esta es una de las formas de saltear las pruebas. Un pequeño ejemplo sería realmente útil. Pero definitivamente estoy de acuerdo en que el enlace que compartió tiene un ejemplo al principio. @martin
Krishna Pravin
2

Puede usar mi paquete mocha-assume para saltarse las pruebas mediante programación, pero solo desde fuera de las pruebas. Lo usas así:

assuming(myAssumption).it("does someting nice", () => {});

Mocha-asumir solo ejecutará su prueba cuando myAssumptionesté true, de lo contrario la saltará (usandoit.skip ) con un buen mensaje.

Aquí hay un ejemplo más detallado:

describe("My Unit", () => {
    /* ...Tests that verify someAssuption is always true... */

    describe("when [someAssumption] holds...", () => {
        let someAssumption;

        beforeAll(() => {
            someAssumption = /* ...calculate assumption... */
        });

        assuming(someAssumption).it("Does something cool", () => {
            /* ...test something cool... */
        });
    });
});

Utilizándolo de esta manera, puede evitar fallas en cascada. Digamos que la prueba "Does something cool"siempre fallará cuando alguna Suposición no se cumple, pero esta suposición ya se probó anteriormente (enTests that verify someAssuption is always true" ).

Por lo tanto, la falla de la prueba no le brinda ninguna información nueva. De hecho, incluso es un falso positivo: la prueba no falló porque "algo bueno" no funcionó, sino porque no se cumplió una condición previa para la prueba. con mocha-assumeusted a menudo puede evitar tales falsos positivos.

David Tanzer
fuente
Esto es realmente genial, triste porque el proyecto parece estar abandonado ...
Victor Schröder
@ VictorSchröder Bueno, tuve la impresión de que nadie lo estaba usando. Podría intentar mejorarlo en las próximas semanas, si tuviera tiempo. ¿Puedes abrir un problema en github y decirme qué te gustaría ver?
David Tanzer
Todavía no lo estoy usando, @David Tanzer, acabo de encontrar su idea realmente genial . Me veo haciendo preparación de pruebas y saltos condicionales bastante y este tipo de interfaz es mucho más legible. Todavía tengo que intentarlo, pero imagino que sería genial poder encadenar varios supuestos y admitir funciones asíncronas como supuestos. Tal vez todo esto ya sea compatible, no lo he comprobado.
Victor Schröder
1
Sin embargo, hay un problema con el segundo ejemplo en esta respuesta. No beforeAllse garantiza la ejecución del gancho antes de que se recopilen todas las pruebas. En realidad, es muy probable que solo se ejecute después, pero en este caso assuming(someAssumption)ya habría recibido el valor inicial (indefinido). Es necesario envolver esa parte en una función también para lograr el efecto deseado.
Victor Schröder
2

Podemos escribir una buena función de contenedor limpio para ejecutar condicionalmente las pruebas de la siguiente manera:

function ifConditionIt(title, test) {
  // Define your condition here
  return condition ? it(title, test) : it.skip(title, test);
}

Esto puede ser requerido y utilizado en sus pruebas de la siguiente manera:

ifConditionIt('Should be an awesome test', (done) => {
  // Test things
  done();
});
dcr24
fuente
Creo que esta es, con mucho, la solución más elegante presentada aquí. Se puede ampliar fácilmente para hacer una lógica más complicada, y tiene la ventaja adicional de que las pruebas omitidas de esta manera se marcan como omitidas en el informe de la prueba
Joshua Evans,
0

Digamos que quería omitir mi prueba parametrizada si la descripción de mi prueba contuviera la cadena "foo", haría esto:

// Skip parametrized test if description contains the string "foo"
(test.description.indexOf("foo") === -1 ? it : it.skip)("should test something", function (done) {
    // Code here
});

// Parametrized tests
describe("testFoo", function () {
        test({
            description: "foo" // This will skip
        });
        test({
            description: "bar" // This will be tested
        });
});

En su caso, creo que si quisiera verificar las variables de entorno, podría usar NodeJS:

process.env.ENV_VARIABLE

Por ejemplo (Advertencia: ¡no he probado este bit de código!), Tal vez algo como esto:

(process.env.NODE_ENV.indexOf("prod") === -1 ? it : it.skip)("should...", function(done) {
    // Code here
});

Donde puede configurar ENV_VARIABLE para que sea lo que esté quitando, y usando ese valor, omita o ejecute la prueba. (Para su información, la documentación para el NodeJS 'process.env está aquí: https://nodejs.org/api/process.html#process_process_env )

No tomaré el crédito completo por la primera parte de esta solución, encontré y probé la respuesta y funcionó perfectamente para omitir las pruebas basadas en una condición simple a través de este recurso: https://github.com/mochajs/mocha/issues / 591

¡Espero que esto ayude! :)

Rubicón
fuente
0

En realidad, esto no está utilizando las características de mocha, sino que lo modifica para obtener el comportamiento que quería.

Quería omitir cualquier 'es' posterior en mis pruebas de mocha de transportador y uno 'eso' falló. Esto se debió a que una vez que fallaba un paso de una prueba de viaje, era casi seguro que el resto fallaría, y puede tomar mucho tiempo y acaparar el servidor de compilación si están usando el navegador espera a que aparezcan elementos en una página, etc.

Cuando solo se ejecutan pruebas de mocha estándar (no transportador), esto se puede lograr con los ganchos globales BeforeEach y afterEach adjuntando un indicador 'skipSubsequent' al padre de la prueba (describir) de esta manera:

    beforeEach(function() {
      if(this.currentTest.parent.skipSubsequent) {
            this.skip();
      }
    }); 


    afterEach(function() {
      if (this.currentTest.state === 'failed') {
        this.currentTest.parent.skipSubsequent = 'true'
      }
    })

Al intentar esto con transportador y moca, el alcance de 'esto' ha cambiado y el código anterior no funciona. Terminas con un mensaje de error como 'error al llamar a done ()' y el transportador se detiene.

En cambio, terminé con el código a continuación. No es el más bonito, pero termina reemplazando la implementación de las funciones de prueba restantes con un this.skip (). Esto probablemente dejará de funcionar si / cuando las partes internas de mocha cambian con versiones posteriores.

Fue resuelto a través de algunas pruebas y errores al depurar e inspeccionar los componentes internos de mocha ... sin embargo, ayuda a completar las suites de prueba del navegador cuando las pruebas fallan.

beforeEach(function() {

    var parentSpec = this.currentTest.parent;

    if (!parentSpec.testcount) {
        parentSpec.testCount = parentSpec.tests.length;
        parentSpec.currentTestIndex = 0;
    } else {
        parentSpec.currentTestIndex = parentSpec.currentTestIndex + 1;
    }

    if (parentSpec.skipSubsequent) {

        parentSpec.skipSubsequent = false;
        var length = parentSpec.tests.length;
        var currentIndex = parentSpec.currentTestIndex;

        for (var i = currentIndex + 1; i < length; i++) {
            parentSpec.tests[i].fn = function() {
                this.skip();
            };
        }
    }
});


afterEach(function() {
    if (this.currentTest.state === 'failed') {
        this.currentTest.parent.skipSubsequent = 'true'
    }
});
Paul Silvester
fuente
-2

Como @danielstjules respondió aquí hay una manera de saltear la prueba. @autor de este tema ha copiado la respuesta de la discusión de mochajs de github.com, pero no hay información sobre qué versión de mocha está disponible.

Estoy usando el módulo grunt-mocha-test para integrar la funcionalidad de prueba mocha en mi proyecto. Saltando a la última versión (por ahora): 0.12.7, tráeme la versión 2.4.5 de mocha con la implementación de this.skip ().

Entonces, en mi package.json

  "devDependencies": {
    "grunt-mocha-test": "^0.12.7",
    ...

Y entonces

npm install

Y me hace feliz con este gancho:

describe('Feature', function() {

    before(function () {

        if (!Config.isFeaturePresent) {

            console.log('Feature not configured for that env, skipping...');
            this.skip();
        }
    });
...

    it('should return correct response on AB', function (done) {

        if (!Config.isABPresent) {

           return this.skip();
        }

        ...
Victor Perov
fuente
-2

Por favor no Su infraestructura de compilación debe reconocer como tal una prueba que no funciona de manera consistente en todos los entornos. Y puede ser muy desorientador cuando las compilaciones de CI tienen un número diferente de pruebas ejecutadas que las locales.

También arruina la repetibilidad. Si se ejecutan diferentes pruebas en el servidor y local, puedo hacer que las pruebas fallen en el desarrollo y pasen en CI o viceversa. No hay una función de forzado y no tengo forma de corregir de forma rápida y precisa una compilación fallida.

Si debe desactivar las pruebas entre entornos, en lugar de ejecutar pruebas condicionalmente, etiquete sus pruebas y use un filtro para eliminar las pruebas que no funcionan en ciertos objetivos de compilación. De esa manera, todos saben lo que está sucediendo y atenúa sus expectativas. También les permite a todos saber que hay inconsistencia en el marco de prueba, y alguien podría tener una solución que los haga funcionar nuevamente de manera adecuada. Si solo silencia la prueba, es posible que ni siquiera sepan que hay un problema.

Jason
fuente