Cómo ejecutar solo una especificación de prueba con angular-cli

143

Tengo la compilación del proyecto Angular2 con Angular-CLI (beta 20).

¿Hay alguna manera de ejecutar pruebas contra un solo archivo de especificaciones seleccionado?

Solía ​​tener un proyecto basado en el inicio rápido de Angular2, y podía agregar manualmente especificaciones al archivo de jazmín. Pero no sé cómo configurar esto fuera de las pruebas de karma o cómo limitar las pruebas de karma a archivos específicos con compilaciones de Angular-CLI.

Zielu
fuente

Respuestas:

224

Cada uno de sus .spec.tsarchivos tiene todas sus pruebas agrupadas en un describebloque como este:

describe('SomeComponent', () => {...}

Puede ejecutar fácilmente este bloque único, prefijando el describenombre de la función con f:

fdescribe('SomeComponent', () => {...}

Si tiene dicha función, no describese ejecutarán otros bloques. Por cierto. puedes hacer algo similar con it=> fity también hay una versión de "lista negra" x. Entonces:

  • fdescribey fithace que solo se ejecuten las funciones marcadas de esta manera
  • xdescribey xithace que todas las funciones marcadas de esta manera se ejecuten
Tomek Sułkowski
fuente
1
He usado fdescribe en mi archivo helloworld.component.spec.ts pero también se muestran los errores del archivo app.component.spec.ts.
Maestro Yoda
1
Esto se debe a que se está evaluando todo el código (de lo contrario, no sabría que HAY descripciones dentro de sus pruebas): fdescribe solo limita la ejecución de los resultados de las pruebas. Aún necesita corregir errores de sintaxis / mecanografía en otros archivos.
Tomek Sułkowski
3
Creo que aunque el OP aceptó esta respuesta, la pregunta era agudamente cómo evaluar solo un archivo de especificaciones: P
roberto tomás
44
Esta no es la respuesta. @iislucas tiene la respuesta a continuación.
Ben Racicot
¿Puedo configurar algún indicador en mi entorno de CI que fallará al encontrar fdescribeo xdescribe? No quiero que un crítico descuidado (yo) fusione un RP que omita todas mis pruebas.
ILikeFood
80

Configurar el test.tsarchivo dentro de la srccarpeta:

const context = require.context('./', true, /\.spec\.ts$/);

Reemplace /\.spec\.ts$/con el nombre del archivo que desea probar. Por ejemplo:/app.component\.spec\.ts$/

Esto ejecutará la prueba solo para app.component.spec.ts.

Aish Anu
fuente
8
debería aceptarse la respuesta, este enfoque elimina una carga de salida gumpfy en los registros, a diferencia de fdescribe, que es detallado
danday74
3
solución fácil :) ahorró mucho tiempo.
Detoxic-Soul
Esto hará coincidir los componentes con cualquier cosa anterior a la 'aplicación', por lo que 'product-app.component.spec.ts' u 'order-app.component.spec.ts' también coincidirían. No soy el mejor con regx. ¿Hay alguna manera de apuntar específicamente a 'app.component.spec.ts'?
hanesjw 01 de
Intenté /^app.component\.spec\.ts$/ pero no tuve suerte. Parece funcionar en un probador de expresiones regulares, pero a ng test no le gusta por alguna razón; produce un error
hanesjw 01 de
debería ser la respuesta recomendada
Anil Vangari
55

Puede probar solo un archivo específico con la CLI angular (el ngcomando) como este:

ng test --main ./path/to/test.ts

Otros documentos están en https://angular.io/cli/test

Tenga en cuenta que si bien esto funciona para archivos de biblioteca independientes, no funcionará para componentes angulares / servicios / etc. Esto se debe a que los archivos angulares dependen de otros archivos (a sabersrc/test.ts en Angular 7). Lamentablemente, la --mainbandera no toma múltiples argumentos.

iislucas
fuente
2
Esta es una gran sugerencia y funciona. ¡Gracias! Además, vale la pena tener en cuenta que si intentamos apuntarlo a un component.spec.tsarchivo generado automáticamente , veremos que las pruebas nunca comienzan: Error: AsyncTestZoneSpec is needed for the async() test helper but could not be found. Please make sure that your environment includes zone.js/dist/async-test.js... Estoy seguro de que se pueden hackear una solución alternativa más, pero es algo a tener en cuenta porque la configuración realizada dentro src/main.tsy sus importaciones no están disponibles en este caso.
pulkitsinghal
Cuando ejecuto pruebas completas usando el comando, ng tla prueba que estoy escribiendo pasa pero cuando ejecuto el archivo específico da error. TypeError: No se puede leer la propiedad 'getComponentFromError' de nulo en TestBedViewEngine._initIfNeeded (node_modules/@angular/core/fesm2015/testing.js: 3112: 1) en TestBedViewEngine.get (node_modules/@angular/core.fesm2015/test.fesm2015/test.fesm2015/test.fesmj15/test.fesm2015/test.fesm2015/test.fesm2015/test.fesm2015/test 3230: 1) en Function.get (node_modules/@angular/core/fesm2015/testing.js: 2960: 1) en UserContext. <anónimo> (src / app / timebar.service.spec.ts: 14: 45) "
canbax
1
Esta respuesta también funciona para Angular 8. Esta debería ser la respuesta aceptada porque ejecutará exactamente un archivo de especificaciones de prueba.
2
Para Angular 9 obtengo la opción desconocida "--main" :(
rmcsharry
6

Si desea poder controlar qué archivos se seleccionan desde la línea de comando, logré hacerlo para Angular 7.

En resumen, debe instalar @angular-devkit/build-angular:browsery luego crear un complemento de paquete web personalizado para pasar la expresión regular del archivo de prueba. Por ejemplo:

angular.json : cambia el generador de pruebas @angular-devkit/build-angular:browsery establece un archivo de configuración personalizado:

...

        "test": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "./extra-webpack.config.js"
            },
...

extra-webpack.config.js : crea una configuración de paquete web que lee la expresión regular desde la línea de comandos:

const webpack = require('webpack');
const FILTER = process.env.KARMA_FILTER;
let KARMA_SPEC_FILTER = '/.spec.ts$/';
if (FILTER) {
  KARMA_SPEC_FILTER = `/${FILTER}.spec.ts$/`;
}
module.exports = {
  plugins: [new webpack.DefinePlugin({KARMA_SPEC_FILTER})]
}

test.ts - edita la especificación

...
// Then we find all the tests.
declare const KARMA_CONTEXT_SPEC: any;
const context = require.context('./', true, KARMA_CONTEXT_SPEC);

Luego use lo siguiente para anular el valor predeterminado:

KARMA_FILTER='somefile-.*\.spec\.ts$' npm run test

Documenté la historia de fondo aquí , disculpas de antemano por tipos y enlaces erróneos. Gracias a la respuesta anterior por @ Aish-Anu por señalarme en la dirección correcta.

6EQUJ5
fuente
4

Esto funciona para mí en Angular 7. Se basa en la opción --main del comando ng. No estoy seguro de si esta opción no está documentada y posiblemente esté sujeta a cambios, pero funciona para mí. Puse una línea en mi archivo package.json en la sección de secuencias de comandos. Allí, usando la opción --main de con el comando ng test, especifico la ruta al archivo .spec.ts que quiero ejecutar. Por ejemplo

"test 1": "ng test --main E:/WebRxAngularClient/src/app/test/shared/my-date-utils.spec.ts",

Puede ejecutar el script mientras ejecuta cualquier script de este tipo. Lo ejecuto en Webstorm haciendo clic en "prueba 1" en la sección npm.

usuario2367418
fuente
3

Resolví este problema por mí mismo usando gruñido. Tengo el guión gruñido a continuación. Lo que hace el script es ejecutar el parámetro de línea de comando de la prueba específica y crea una copia de test.ts y coloca este nombre de prueba específico allí.

Para ejecutar esto, primero instale grunt-cli usando:

npm install -g grunt-cli

Ponga las siguientes dependencias grunt en su package.json:

"grunt": "^1.0.1",
"grunt-contrib-clean": "^1.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-exec": "^2.0.0",
"grunt-string-replace": "^1.3.1"

Para ejecutarlo, guarde el siguiente archivo grunt como Gruntfile.js en su carpeta raíz. Luego, desde la línea de comandos, ejecútelo como:

grunt --target=app.component

Esto ejecutará app.component.spec.ts.

El archivo Grunt es el siguiente:

/*
This gruntfile is used to run a specific test in watch mode. Example: To run app.component.spec.ts , the Command is: 
grunt --target=app.component
Do not specific .spec.ts. If no target is specified it will run all tests.
*/
module.exports = function(grunt) {
var target = grunt.option('target') || '';
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    clean: ['temp.conf.js','src/temp-test.ts'],
    copy: {
      main: {
        files: [
             {expand: false, cwd: '.', src: ['karma.conf.js'], dest: 'temp.conf.js'},
             {expand: false, cwd: '.', src: ['src/test.ts'], dest: 'src/temp-test.ts'}
             ],
      }
    },
    'string-replace': {
          dist: {
            files: {
              'temp.conf.js': 'temp.conf.js',
              'src/temp-test.ts': 'src/temp-test.ts'
            },
            options: {
              replacements: [{
                pattern: /test.ts/ig,
                replacement: 'temp-test.ts'
              },
              {
                pattern: /const context =.*/ig,
                replacement: 'const context = require.context(\'./\', true, /'+target+'\\\.spec\\\.ts$/);'
              }]
            }
        }
    },
    'exec': {
        sleep: {
          //The sleep command is needed here, else webpack compile fails since it seems like the files in the previous step were touched too recently
          command: 'ping 127.0.0.1 -n 4 > nul',
          stdout: true,
          stderr: true
        },
        ng_test: {
          command: 'ng test --config=temp.conf.js',
          stdout: true,
          stderr: true
        }
    }
  });

  // Load the plugin that provides the "uglify" task.
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-string-replace');
    grunt.loadNpmTasks('grunt-exec');
  // Default task(s).
  grunt.registerTask('default', ['clean','copy','string-replace','exec']);

};
vanval
fuente
Mirando la solución aceptada, no creo que se recomiende de esta manera
Drenai
2
@Brian: mi solución evita tener que modificar el código fuente y, por lo tanto, evita posibles errores al registrar el archivo. Mi solución permite simplemente especificar el nombre de la prueba en la línea de comandos mediante la automatización de los pasos manuales.
vanval
Sí, ese es un buen punto en realidad. Existe una buena posibilidad de que pueda olvidarse de eliminar xdescribe o fdescribe, ¡y su prueba se eliminará de forma permanente!
Drenai
3
@Ryan puede instalar / configurar tslint-jasmine-rules para verificar las llamadas fdescribe / fit / xdescribe / xit y fallar su ejecución tslint; Si esto es parte de un paso previo a la confirmación, evita que accidentalmente registres tus pruebas, ya sea enfocadas o deshabilitadas.
Neil Menzies
1

Además de esto para personas como yo que buscaban una forma de ejecutar una sola especificación en Angular y encontraron este SO.

De acuerdo con los últimos documentos de Angular (v9.0.6 en el momento de la escritura), el ng testcomando tiene una --includeopción donde puede especificar un directorio de *.spec.(ts|tsx)archivos o solo uno.spec.(ts|tsx) archivo.

https://angular.io/cli/test

terrenal
fuente
0

Solo se necesita un pequeño cambio en el test.tsarchivo dentro de la carpeta src:

const context = require.context('./', true, /test-example\.spec\.ts$/);

Aquí, test-example está el nombre exacto del archivo que necesitamos ejecutar

Del mismo modo, si solo necesita probar el archivo de servicio, puede reemplazar el nombre del archivo como "/test-example.service"

madhu srinivas
fuente
0

Esto funcionó para mí en todos los casos:

ng test --include='**/dealer.service.spec.ts'

Sin embargo, generalmente obtengo "TypeError: No se puede leer la propiedad 'ngModule' de null" para esto:

ng test --main src/app/services/dealer.service.spec.ts

Versión de @ angular / cli 10.0.4

PeterB
fuente