Jak wykonać tylko jedną specyfikację testową za pomocą angular-cli


143

Mam projekt Angular2 zbudowany z Angular-CLI (beta 20).

Czy istnieje sposób na uruchomienie testów tylko dla jednego wybranego pliku specyfikacji?

Kiedyś miałem projekt oparty na szybkim uruchomieniu Angular2 i mogłem ręcznie dodawać specyfikacje do pliku jasmine. Ale nie wiem, jak to ustawić poza testowaniem karmy lub jak ograniczyć testy karmy do określonych plików z kompilacjami Angular-CLI.

Odpowiedzi:


224

Każdy .spec.tsplik ma wszystkie testy pogrupowane w describeblok w następujący sposób:

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

Możesz łatwo uruchomić tylko ten pojedynczy blok, poprzedzając describenazwę funkcji f:

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

Jeśli masz taką funkcję, żadne inne describebloki nie będą działać. Przy okazji. możesz zrobić podobnie z it=> fiti jest też wersja „czarnej listy” - x. Więc:

  • fdescribei fitpowoduje, że działają tylko funkcje oznaczone w ten sposób
  • xdescribei xitpowoduje, że wszystkie funkcje oprócz zaznaczonych w ten sposób działają

1
Użyłem fdescribe w moim pliku helloworld.component.spec.ts, ale wyświetlane są również błędy pliku app.component.spec.ts.
Master Yoda

1
Dzieje się tak, ponieważ cały kod jest oceniany (w przeciwnym razie nie wiedziałby, że w twoich testach są opisy) - fdescribe ogranicza tylko wykonanie testów. Nadal musisz naprawić błędy składni / maszynopisu w innych plikach.
Tomek Sułkowski

3
Myślę, że chociaż OP zaakceptował tę odpowiedź, pytanie brzmiało ostro, jak ocenić tylko jeden plik specyfikacji: P
roberto tomás

4
To nie jest odpowiedź. @iislucas ma odpowiedź poniżej.
Ben Racicot

Czy mogę ustawić flagę w moim środowisku CI, która nie powiedzie się po napotkaniu fdescribelub xdescribe? Nie chcę, żeby niechlujny recenzent (ja) łączył PR, który pomija wszystkie moje testy.
ILikeFood

80

Skonfiguruj test.tsplik w srcfolderze:

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

Zastąp /\.spec\.ts$/nazwą pliku, który chcesz przetestować. Na przykład:/app.component\.spec\.ts$/

Spowoduje to uruchomienie testu tylko dla app.component.spec.ts.


8
należy zaakceptować odpowiedź, takie podejście usuwa ładunek gumpfy z logów - w przeciwieństwie do fdescribe, który jest gadatliwy
danday74

3
proste rozwiązanie :) zaoszczędziło sporo czasu.
Detoxic-Soul

Spowoduje to dopasowanie komponentów do wszystkiego, co znajduje się przed „app”, więc „product-app.component.spec.ts” lub „order-app.component.spec.ts” również będą pasować. Nie jestem najlepszy z regx. Czy istnieje sposób na konkretne kierowanie na „app.component.spec.ts”?
hanesjw

Próbowałem /^app.component\.spec\.ts$/, ale bez powodzenia. Wydaje się, że działa w testerze regex, ale ng test z jakiegoś powodu go nie lubi; powoduje błąd.
hanesjw

powinna być zalecaną odpowiedzią
Anil Vangari

55

Możesz przetestować tylko określony plik za pomocą Angular CLI ( ngpolecenie) w następujący sposób:

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

Dalsze dokumenty są dostępne pod adresem https://angular.io/cli/test

Zauważ, że chociaż działa to dla samodzielnych plików bibliotek, nie będzie działać dla komponentów / usług / itp. Dzieje się tak, ponieważ pliki angular mają zależności od innych plików (mianowicie src/test.tsw Angular 7). Niestety --mainflaga nie przyjmuje wielu argumentów.


2
To świetna sugestia i działa. Dziękuję Ci! Ponadto warto mieć świadomość, że jeśli spróbujemy skierować go na automatycznie wygenerowany component.spec.tsplik, zobaczymy, że testy nigdy się nie rozpoczną: 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... Jestem pewien, że dalsze obejście można zhakować razem, ale jest to coś, o czym należy pamiętać ponieważ konfiguracja wykonana w programie src/main.tsi jej importowanie nie są dostępne w tym przypadku.
pulkitsinghal

Kiedy uruchamiam całe testy za pomocą polecenia, ng ttest, który piszę, przechodzi, ale kiedy uruchamiam określony plik, wyświetla błąd. TypeError: Nie można odczytać właściwości „getComponentFromError” o wartości null w TestBedViewEngine._initIfNeeded (node_modules/@angular/core/fesm2015/testing.js: 3112: 1) w TestBedViewEngine.get (node_modules/@angular/score/fes: 3230: 1) w Function.get (node_modules/@angular/core/fesm2015/testing.js: 2960: 1) w UserContext. <anonymous> (src / app / timebar.service.spec.ts: 14:45) ”
canbax

1
Ta odpowiedź działa również w Angular 8. Powinna to być akceptowana odpowiedź, ponieważ spowoduje uruchomienie dokładnie jednego pliku specyfikacji testu.

2
W Angular 9 otrzymuję nieznaną opcję "--main" :(
rmcsharry

6

Jeśli chcesz mieć możliwość kontrolowania, które pliki są wybierane z wiersza poleceń, udało mi się to zrobić w Angular 7.

Podsumowując, musisz zainstalować, @angular-devkit/build-angular:browsera następnie utworzyć niestandardową wtyczkę pakietu internetowego, aby przekazać wyrażenie regularne pliku testowego. Na przykład:

angular.json - zmień program budujący testy z @angular-devkit/build-angular:browseri ustaw niestandardowy plik konfiguracyjny:

...

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

extra-webpack.config.js - utwórz konfigurację pakietu internetowego, która odczytuje wyrażenie regularne z wiersza poleceń:

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 - edytuj specyfikację

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

Następnie użyj w następujący sposób, aby zastąpić ustawienie domyślne:

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

Udokumentowałem tutaj historię , z góry przepraszam za typy i błędne linki. Podziękowania dla powyższej odpowiedzi autorstwa @ Aish-Anu za wskazanie mi właściwego kierunku.


4

To działa dla mnie w Angular 7. Opiera się na opcji --main polecenia ng. Nie jestem pewien, czy ta opcja jest nieudokumentowana i prawdopodobnie może ulec zmianie, ale działa dla mnie. Umieściłem wiersz w moim pliku package.json w sekcji skryptów. Tam, używając opcji --main z poleceniem ng test, określam ścieżkę do pliku .spec.ts, który chcę wykonać. Na przykład

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

Skrypt można uruchomić tak samo, jak każdy taki skrypt. Uruchamiam go w Webstorm, klikając „test 1” w sekcji npm.


3

Rozwiązałem ten problem samodzielnie, używając gruntów. Mam poniższy skrypt. Skrypt pobiera parametr wiersza poleceń określonego testu do uruchomienia i tworzy kopię pliku test.ts i umieszcza tam tę konkretną nazwę testu.

Aby to uruchomić, najpierw zainstaluj grunt-cli używając:

npm install -g grunt-cli

Umieść poniższe zależności gruntów w swoim pliku 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"

Aby go uruchomić, zapisz poniższy plik gruntowy jako Gruntfile.js w folderze głównym. Następnie z wiersza poleceń uruchom go jako:

grunt --target=app.component

Spowoduje to uruchomienie app.component.spec.ts.

Plik Grunt jest następujący:

/*
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']);

};

Patrząc na przyjęte rozwiązanie, nie sądzę, aby ten sposób był zalecany
Drenai

2
@Brian - moje rozwiązanie pozwala uniknąć konieczności modyfikowania kodu źródłowego, a tym samym zapobiega potencjalnym błędom przy wpisywaniu pliku. Moje rozwiązanie umożliwia po prostu określenie nazwy testu w wierszu poleceń poprzez automatyzację ręcznych kroków.
vanval,

Tak, to właściwie dobra uwaga. Istnieje duża szansa, że ​​zapomnisz usunąć xdescribe lub fdescribe - a Twój test zostanie trwale usunięty!
Drenai,

3
@Ryan, możesz zainstalować / skonfigurować tslint-jasmine-rules, aby sprawdzać wywołania fdescribe / fit / xdescribe / xit i zawieść działanie tslint; jeśli jest to część kroku poprzedzającego zatwierdzenie, zapobiega przypadkowemu sprawdzeniu w testach, czy są one skoncentrowane, czy wyłączone.
Neil Menzies

1

Dodając do tego dla ludzi takich jak ja, którzy szukali sposobu na uruchomienie jednej specyfikacji w Angular i znaleźli to SO.

Zgodnie z najnowszą dokumentacją Angular (wersja 9.0.6 w momencie pisania), ng testpolecenie ma --includeopcję, w której można określić katalog *.spec.(ts|tsx)plików lub .spec.(ts|tsx)sam pojedynczy plik.

https://angular.io/cli/test


0

Wystarczy niewielka zmiana w test.tspliku w folderze src:

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

Tutaj, test-example jest dokładna nazwa pliku, który musimy uruchomić

W ten sam sposób, jeśli chcesz przetestować tylko plik usługi, możesz zastąpić nazwę pliku, na przykład „/test-example.service”


0

To działało dla mnie w każdym przypadku:

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

Jednak zwykle otrzymywałem komunikat „TypeError: Cannot read property 'ngModule' of null” w tym celu:

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

Wersja @ angular / cli 10.0.4

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.