So führen Sie nur eine Testspezifikation mit angle-cli aus

142

Ich habe Angular2-Projekt mit Angular-CLI (Beta 20) erstellt.

Gibt es eine Möglichkeit, Tests nur für eine ausgewählte Spezifikationsdatei auszuführen?

Früher hatte ich ein Projekt, das auf Angular2-Schnellstart basierte, und ich konnte der Jasmin-Datei manuell Spezifikationen hinzufügen. Aber ich weiß nicht, wie ich dies außerhalb von Karma-Tests einrichten oder wie ich Karma-Tests auf bestimmte Dateien mit Angular-CLI-Builds beschränken kann.

Zielu
quelle

Antworten:

224

In jeder Ihrer .spec.tsDateien sind alle Tests wie folgt in describeBlöcken zusammengefasst:

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

Sie können einfach nur diesen einzelnen Block ausführen, indem Sie dem describeFunktionsnamen Folgendes voranstellen f:

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

Wenn Sie eine solche Funktion haben, werden keine anderen describeBlöcke ausgeführt. Übrigens. Sie können ähnliche Dinge mit it=> tun fitund es gibt auch eine "Blacklist" -Version - x. So:

  • fdescribeund fitverursacht nur diese Weise markierte Funktionen ausgeführt werden
  • xdescribeund xitbewirkt, dass alle bis auf diese Weise markierten Funktionen ausgeführt werden
Tomek Sułkowski
quelle
1
Ich habe fdescribe in meiner Datei helloworld.component.spec.ts verwendet, aber die Fehler der Datei app.component.spec.ts werden ebenfalls angezeigt.
Meister Yoda
1
Dies liegt daran, dass der gesamte Code ausgewertet wird (andernfalls würde er nicht wissen, dass Ihre Tests fdescribes enthalten) - fdescribe schränkt nur die Ausführung der Testergebnisse ein. Sie müssen dennoch Syntax- / Typoskriptfehler in anderen Dateien beheben.
Tomek Sułkowski
3
Ich denke, obwohl das OP diese Antwort akzeptierte, war die Frage genau, wie man nur eine Spezifikationsdatei auswertet: P
roberto tomás
4
Dies ist nicht die Antwort. @iislucas hat die Antwort unten.
Ben Racicot
Kann ich in meiner CI-Umgebung ein Flag setzen, das bei der Begegnung fehlschlägt fdescribeoder xdescribe? Ich möchte nicht, dass ein schlampiger Prüfer (ich) eine PR zusammenführt, die alle meine Tests überspringt.
ILikeFood
80

test.tsDatei im srcOrdner konfigurieren :

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

Ersetzen Sie /\.spec\.ts$/durch den Dateinamen, den Sie testen möchten. Beispielsweise:/app.component\.spec\.ts$/

Dies führt den Test nur für aus app.component.spec.ts.

Aish Anu
quelle
8
Sollte eine Antwort akzeptiert werden, entfernt dieser Ansatz eine Menge gumpfy Ausgabe in den Protokollen - im Gegensatz zu fdescribe, das ausführlich ist
danday74
3
einfache Lösung :) viel Zeit gespart.
Detoxic-Soul
Dadurch werden Komponenten mit allen Elementen vor der 'App' abgeglichen, sodass 'product-app.component.spec.ts' oder 'order-app.component.spec.ts' ebenfalls übereinstimmen. Ich bin nicht der Größte mit Regx. Gibt es eine Möglichkeit, die 'app.component.spec.ts' gezielt anzusprechen?
Hanesjw
Ich habe versucht, /^app.component\.spec\.ts$/, aber kein Glück. Scheint in einem Regex-Tester zu funktionieren, aber ng Test mag es aus irgendeinem Grund nicht. erzeugt einen Fehler.
Hanesjw
sollte die empfohlene Antwort sein
Anil Vangari
55

Sie können nur bestimmte Dateien mit der Angular CLI (dem ngBefehl) wie folgt testen :

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

Weitere Dokumente finden Sie unter https://angular.io/cli/test

Beachten Sie, dass dies zwar für eigenständige Bibliotheksdateien funktioniert, jedoch nicht für eckige Komponenten / Dienste / etc. Dies liegt daran, dass src/test.tsAngular- Dateien Abhängigkeiten von anderen Dateien aufweisen (nämlich in Angular 7). Leider nimmt die --mainFlagge nicht mehrere Argumente an.

Iislucas
quelle
2
Dies ist ein großartiger Vorschlag und es funktioniert. Danke dir! Darüber hinaus sollten Sie sich darüber im Klaren sein, component.spec.tsdass die Tests niemals beginnen , wenn wir versuchen, sie auf eine automatisch generierte Datei zu verweisen : 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... Ich bin sicher, dass weitere Problemumgehungen gemeinsam gehackt werden können, aber es ist etwas, das Sie beachten sollten src/main.tsDies liegt daran, dass das Setup und die Importe in diesem Fall nicht verfügbar sind.
Pulkitsinghal
Wenn ich ganze Tests mit dem Befehl ausführe, besteht ng tder Test, den ich schreibe, die Prüfung, aber wenn ich die spezifische Datei ausführe, wird ein Fehler ausgegeben. TypeError: Die Eigenschaft 'getComponentFromError' von null kann bei TestBedViewEngine._initIfNeeded (node_modules/@angular/core/fesm2015/testing.js: 3112: 1) unter TestBedViewEngine.get (node_modules/@angular/core/fesm20/) nicht gelesen werden. 3230: 1) unter Function.get (node_modules/@angular/core/fesm2015/testing.js: 2960: 1) unter UserContext. <Anonym> (src / app / timebar.service.spec.ts: 14: 45) "
Canbax
1
Diese Antwort funktioniert auch für Angular 8. Dies sollte die akzeptierte Antwort sein, da genau eine Testspezifikationsdatei ausgeführt wird.
2
Für Angular 9 bekomme ich die unbekannte Option "--main" :(
rmcsharry
6

Wenn Sie steuern möchten, welche Dateien über die Befehlszeile ausgewählt werden, habe ich dies für Angular 7 geschafft.

Zusammenfassend müssen Sie @angular-devkit/build-angular:browserein benutzerdefiniertes Webpack-Plugin installieren und anschließend erstellen, um die Regex der Testdatei weiterzuleiten. Beispielsweise:

angle.json - Ändern Sie den Test Builder von @angular-devkit/build-angular:browserund legen Sie eine benutzerdefinierte Konfigurationsdatei fest:

...

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

extra-webpack.config.js - Erstellen Sie eine Webpack-Konfiguration, die den regulären Ausdruck über die Befehlszeile liest:

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 - Bearbeiten Sie die Spezifikation

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

Verwenden Sie dann Folgendes, um die Standardeinstellung zu überschreiben:

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

Ich habe die Hintergrundgeschichte hier dokumentiert und mich im Voraus für Typen und falsche Links entschuldigt. Dank an die Antwort von @ Aish-Anu, die mich in die richtige Richtung gelenkt hat.

6EQUJ5
quelle
4

Dies funktioniert für mich in Angular 7. Es basiert auf der Option --main des Befehls ng. Ich bin nicht sicher, ob diese Option nicht dokumentiert ist und möglicherweise geändert werden kann, aber sie funktioniert für mich. Ich habe eine Zeile in meine package.json-Datei im Skriptabschnitt eingefügt. Dort gebe ich mit der Option --main mit dem Befehl ng test den Pfad zur Datei .spec.ts an, die ich ausführen möchte. Beispielsweise

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

Sie können das Skript ausführen, während Sie ein solches Skript ausführen. Ich starte es in Webstorm, indem ich im Abschnitt "npm" auf "Test 1" klicke.

user2367418
quelle
3

Ich habe dieses Problem mit Grunzen für mich gelöst. Ich habe das Grunzskript unten. Das Skript verwendet den Befehlszeilenparameter des jeweiligen Tests, erstellt eine Kopie von test.ts und fügt diesen spezifischen Testnamen dort ein.

Um dies auszuführen, installieren Sie zuerst grunt-cli mit:

npm install -g grunt-cli

Fügen Sie die folgenden Grunzabhängigkeiten in Ihre package.json ein:

"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"

Um es auszuführen, speichern Sie die folgende Grunt-Datei als Gruntfile.js in Ihrem Stammordner. Führen Sie es dann über die Befehlszeile aus als:

grunt --target=app.component

Dadurch wird app.component.spec.ts ausgeführt.

Die Grunzdatei ist wie folgt:

/*
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
quelle
Wenn ich mir die akzeptierte Lösung
anschaue,
2
@Brian - meine Lösung vermeidet das Ändern des Quellcodes und verhindert somit mögliche Fehler beim Einchecken der Datei. Meine Lösung ermöglicht es, nur den Testnamen in der Befehlszeile anzugeben, indem die manuellen Schritte automatisiert werden.
Vanval
Ja, das ist eigentlich ein guter Punkt. Es besteht eine gute Chance, dass Sie vergessen, xdescribe oder fdescribe zu entfernen - und Ihr Test wird dauerhaft entfernt!
Drenai
3
@ Ryan Sie können tslint-jasmine-rules installieren / konfigurieren, um nach Aufrufen von fdescribe / fit / xdescribe / xit zu suchen und Ihren tslint-Lauf fehlzuschlagen. Wenn dies Teil eines Precommit-Schritts ist, wird verhindert, dass Sie versehentlich Ihre Tests fokussiert oder deaktiviert einchecken.
Neil Menzies
1

Hinzu kommt, dass Leute wie ich nach einer Möglichkeit gesucht haben, eine einzelne Spezifikation in Angular auszuführen, und diese SO gefunden haben.

Gemäß den neuesten Angular-Dokumenten (Version 9.0.6 zum Zeitpunkt des Schreibens) verfügt der ng testBefehl über eine --includeOption, mit der Sie ein Verzeichnis von *.spec.(ts|tsx)Dateien oder nur eine einzelne .spec.(ts|tsx)Datei selbst angeben können .

https://angular.io/cli/test

Erdamerikaner
quelle
0

Nur eine kleine Änderung in der test.tsDatei im src-Ordner erforderlich :

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

Hier, test-example ist der genaue Dateiname, den wir ausführen müssen

Wenn Sie nur die Servicedatei testen müssen, können Sie den Dateinamen wie "/test-example.service" ersetzen.

Madhu Srinivas
quelle