Как выполнить только одну тестовую спецификацию с помощью angular-cli

159

У меня есть проект Angular2, построенный с помощью Angular-CLI (beta 20).

Есть ли способ запустить тесты только для одного выбранного файла спецификации?

Раньше у меня был проект, основанный на быстром запуске Angular2, и я мог вручную добавлять спецификации в файл jasmine. Но я не знаю, как настроить это за пределами тестирования кармы или как ограничить тесты кармы конкретными файлами с помощью сборок Angular-CLI.

Zielu
источник

Ответы:

248

В каждом .spec.tsфайле все тесты сгруппированы в describeблоки следующим образом:

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

Вы можете легко запустить только этот единственный блок, добавив к describeимени функции префикс f:

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

Если у вас есть такая функция, никакие другие describeблоки работать не будут. Кстати. вы можете сделать то же самое с помощью it=>, fitа также есть версия «черного списка» - x. Так:

  • fdescribeи fitвызывает только функции , помеченные таким образом , чтобы запустить
  • xdescribeи xitвызывает выполнение всех функций, кроме отмеченных таким образом
Томек Сулковски
источник
1
Я использовал fdescribe в своем файле helloworld.component.spec.ts, но также отображаются ошибки файла app.component.spec.ts.
Мастер Йода
1
Это потому, что весь код оценивается (иначе он не узнал бы, что в ваших тестах есть fdescribes) - fdescribe только ограничивает выполнение результатов тестов. Вам все еще необходимо исправить ошибки синтаксиса / машинописного текста в других файлах.
Томек Сулковски
3
Я думаю, хотя OP принял этот ответ, на самом деле вопрос заключался в том, как оценить только один файл спецификации: P
roberto tomás
5
Это не ответ. У @iislucas есть ответ ниже.
Ben
1
Могу ли я установить какой-нибудь флаг в моей среде CI, который не сработает при обнаружении fdescribeили xdescribe? Я не хочу, чтобы неряшливый рецензент (я) слил PR, который пропускает все мои тесты.
ILikeFood,
92

Настроить test.tsфайл внутри srcпапки:

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

Замените /\.spec\.ts$/имя файла, который хотите проверить. Например:/app.component\.spec\.ts$/

Это запустит тест только для app.component.spec.ts.

Айш Ану
источник
10
должен быть принят ответ, этот подход удаляет массу неуклюжего вывода в журналах - в отличие от fdescribe, который является подробным
danday74 08
3
простое решение :) сэкономило много времени.
Detoxic Spirit
Это будет соответствовать компонентам с чем-либо до 'app', поэтому 'product-app.component.spec.ts' или 'order-app.component.spec.ts' также будет совпадением. Я не лучший игрок с regx. Есть ли способ настроить таргетинг на app.component.spec.ts?
hanesjw 01
Я попробовал /^app.component\.spec\.ts$/, но не повезло. Кажется, работает в тестере регулярных выражений, но ng test по какой-то причине не нравится; выдает ошибку.
hanesjw 01
должен быть рекомендуемый ответ
Анил Вангари
62

Вы можете протестировать только определенный файл с помощью Angular CLI ( ngкоманда) следующим образом:

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

Дополнительная документация находится на https://angular.io/cli/test.

Обратите внимание, что, хотя это работает для файлов автономных библиотек, это не будет работать для компонентов / служб / и т. Д. Angular. Это связано с тем, что файлы angular зависят от других файлов (а именно от src/test.tsAngular 7). К сожалению, --mainфлаг не принимает несколько аргументов.

иислукас
источник
2
Это отличное предложение, и оно работает. Спасибо! Кроме того, стоит знать, что если мы попытаемся указать его на автоматически сгенерированный component.spec.tsфайл, мы увидим, что тесты никогда не начнутся: 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... Я уверен, что дальнейшее обходное решение может быть взломано вместе, но это то, что нужно знать из-за того, что настройка, выполненная внутри, src/main.tsи ее импорт в этом случае недоступны.
пулькицингал
Когда я запускаю все тесты с помощью команды, ng tтест, который я пишу, проходит, но когда я запускаю конкретный файл, он выдает ошибку. TypeError: невозможно прочитать свойство getComponentFromError, имеющее значение null в TestBedViewEngine._initIfNeeded (node_modules/@angular/core/fesm2015/testing.js: 3112: 1) в TestBedViewEngine.get (node_modules/@angular/core/fesm2015/testing. 3230: 1) в Function.get (node_modules/@angular/core/fesm2015/testing.js: 2960: 1) в UserContext. <anonymous> (src / app / timebar.service.spec.ts: 14: 45) "
canbax
1
Этот ответ работает и для Angular 8. Это должен быть принятый ответ, потому что он будет запускать только один тестовый файл спецификации.
2
Для Angular 9 я получил неизвестную опцию "--main" :(
rmcsharry
10

Это работало для меня в каждом случае:

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

Однако я обычно получал «TypeError: Cannot read property 'ngModule' of null» для этого:

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

Версия @ angular / cli 10.0.4

PeterB
источник
К вашему сведению: можно использовать даже более сложные подстановочные знаки. Только убедитесь, что вы обращаетесь *.spec.tsв любом случае. Например, чтобы запускать только тесты общих папок или выполнять поиск внутри src / app, используйте ng test --include='src/app/{shared,search}/*.spec.ts'.
Томас Праксль
Вам также может потребоваться указать файл конфигурации karma, например --karma-config karma.conf.js, иначе он попытается загрузить файл конфигурации, src/а не по корневому пути.
Крыло
6

Если вы хотите иметь возможность контролировать, какие файлы выбираются из командной строки, мне удалось сделать это для Angular 7.

Таким образом, вам необходимо установить, @angular-devkit/build-angular:browserа затем создать настраиваемый плагин webpack для передачи регулярного выражения тестового файла. Например:

angular.json - измените построитель тестов @angular-devkit/build-angular:browserи установите собственный файл конфигурации:

...

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

extra-webpack.config.js - создайте конфигурацию webpack, которая считывает регулярное выражение из командной строки:

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 - редактировать спецификацию

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

Затем используйте следующее, чтобы изменить значение по умолчанию:

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

Я задокументировал предысторию здесь , заранее извиняюсь за типы и неправильные ссылки. Благодарим за ответ @ Aish-Anu, который указал мне в правильном направлении.

6EQUJ5
источник
4

У меня это работает в Angular 7. Он основан на опции --main команды ng. Я не уверен, что эта опция недокументирована и, возможно, может быть изменена, но у меня она работает. Я помещаю строку в свой файл package.json в раздел скриптов. Здесь, используя параметр --main с командой ng test, я указываю путь к файлу .spec.ts, который хочу выполнить. Например

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

Вы можете запускать сценарий так же, как и любой такой сценарий. Я запускаю его в Webstorm, щелкнув «test 1» в разделе npm.

user2367418
источник
3

Решил для себя эту проблему с помощью grunt. У меня есть сценарий ворчания ниже. Что делает сценарий, так это берет параметр командной строки конкретного теста для запуска, создает копию test.ts и помещает туда это конкретное имя теста.

Чтобы запустить это, сначала установите grunt-cli, используя:

npm install -g grunt-cli

Поместите следующие зависимости grunt в свой 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"

Чтобы запустить его, сохраните приведенный ниже файл grunt как Gruntfile.js в корневой папке. Затем из командной строки запустите его как:

grunt --target=app.component

Это запустит app.component.spec.ts.

Файл Grunt выглядит следующим образом:

/*
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
источник
Глядя на принятое решение, я не думаю, что этот способ рекомендуется
Дренай
2
@Brian - мое решение позволяет избежать изменения исходного кода и, следовательно, предотвращает возможные ошибки при проверке файла. Мое решение позволяет просто указать имя теста в командной строке, автоматизируя шаги вручную.
vanval
Да, на самом деле это хороший момент. Есть большая вероятность, что вы могли забыть удалить xdescribe или fdescribe - и ваш тест будет удален навсегда!
Дренай
3
@Ryan вы можете установить / настроить tslint-jasmine-rules для проверки вызовов fdescribe / fit / xdescribe / xit и сбоя запуска tslint; если это часть этапа предварительной фиксации, это предотвратит случайную проверку ваших тестов, сфокусированных или отключенных.
Нил Мензис
3

Добавьте к этому людей вроде меня, которые искали способ запустить одну спецификацию в Angular и нашли этот SO.

Согласно последним документам Angular (v9.0.6 на момент написания), у ng testкоманды есть --includeопция, в которой вы можете указать каталог *.spec.(ts|tsx)файлов или только один.spec.(ts|tsx) файл.

https://angular.io/cli/test

землянин
источник
1

Требуется небольшое изменение test.tsфайла внутри папки src:

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

Вот, test-example точное имя файла, который нам нужно запустить

Таким же образом, если вам нужно протестировать только служебный файл, вы можете заменить имя файла на "/test-example.service"

Мадху Шринивас
источник
1

В терминале bash мне нравится использовать двойное тире. Используя VS Code, вы можете щелкнуть правой кнопкой мыши файл спецификации в проводнике или на открытой вкладке. Затем выберите «Копировать относительный путь». Выполните команду ниже, вставив относительный путь из буфера обмена.

npm t -- --include relative/path/to/file.spec.ts

Двойное тире сигнализирует об окончании параметров вашей команды npm tи передает все, что находится после этого, следующей команде, на которую указывает ng t. Не требует доработки и быстро дает желаемый результат.

Мэтт Вудрафф
источник