Тестирование с помощью Karma и RequireJS с файлами в синтаксисе CommonJS
Я работаю над приложением angular, которое написано в синтаксисе CommonJS и использует задачу grunt с задачей grunt-contrib-requirejs, чтобы перевести исходные файлы в формат AMD и скомпилировать их в один выходной файл. Моя цель - заставить Karma работать с RequireJS и хранить исходные файлы и файлы спецификаций в синтаксисе CommonJS.
Мне удалось получить простую тестовую передачу в формате AMD со следующей структурой:
-- karma-test
|-- spec
| `-- exampleSpec.js
|-- src
| `-- example.js
|-- karma.conf.js
`-- test-main.js
и следующие файлы:
karma.conf.js
// base path, that will be used to resolve files and exclude
basePath = '';
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
REQUIRE,
REQUIRE_ADAPTER,
'test-main.js',
{pattern: 'src/*.js', included: false},
{pattern: 'spec/*.js', included: false}
];
// list of files to exclude
exclude = [];
// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];
// web server port
port = 9876;
// cli runner port
runnerPort = 9100;
// enable / disable colors in the output (reporters and logs)
colors = true;
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_DEBUG;
// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;
// Start these browsers, currently available:
browsers = ['Chrome'];
// If browser does not capture in given timeout [ms], kill it
captureTimeout = 60000;
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;
example.js
define('example', function() {
var message = "Hello!";
return {
message: message
};
});
exampleSpec.js
define(['example'], function(example) {
describe("Example", function() {
it("should have a message equal to 'Hello!'", function() {
expect(example.message).toBe('Hello!');
});
});
});
тест-main.js
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return /Spec\.js$/.test(file);
});
requirejs.config({
// Karma serves files from '/base'
baseUrl: '/base/src',
// Translate CommonJS to AMD
cjsTranslate: true,
// ask Require.js to load these files (all our tests)
deps: tests,
// start test run, once Require.js is done
callback: window.__karma__.start
});
Однако моя цель - записать как исходный файл, так и файл spec в синтаксисе CommonJS с теми же результатами, например:
example.js
var message = "Hello!";
module.exports = {
message: message
};
exampleSpec.js
var example = require('example');
describe("Example", function() {
it("should have a message equal to 'Hello!'", function() {
expect(example.message).toBe('Hello!');
});
});
Но несмотря на то, что флаг cjsTranslate
установлен на true
, я просто получаю эту ошибку:
Uncaught Error: Module name "example" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
at http://localhost:9876/adapter/lib/require.js?1371450058000:1746
Любые идеи о том, как это можно сделать?
Изменить: я нашел эту проблему для репозитория карма-бегун: https://github.com/karma-runner/karma/issues/552 и есть несколько комментариев, которые могут помочь с этой проблемой, но до сих пор мне не повезло.
Ответы
Ответ 1
Решение, которое я в конечном итоге обнаружил, использовал grunt и написал некоторые пользовательские задачи. Процесс выполняется следующим образом:
Создайте задачу grunt для создания файла bootstrap requirejs, найдя все спецификации с использованием шаблона файла, перейдя через них и создав традиционный стиль AMD, требующий блокировку и создающий временный файл с таким кодом:
require(['spec/example1_spec.js'
,'spec/example2_spec.js',
,'spec/example3_spec.js'
],function(a1,a2){
// this space intentionally left blank
}, "", true);
Создайте задачу requireJS grunt, которая компилирует вышеуказанный файл начальной загрузки и выводит один файл js, который будет эффективно включать весь исходный код, спецификации и библиотеки.
requirejs: {
tests: {
options: {
baseUrl: './test',
paths: {}, // paths object for libraries
shim: {}, // shim object for non-AMD libraries
// I pulled in almond using npm
name: '../node_modules/almond/almond.min',
// This is the file we created above
include: 'tmp/require-tests',
// This is the output file that we will serve to karma
out: 'test/tmp/tests.js',
optimize: 'none',
// This translates commonjs syntax to AMD require blocks
cjsTranslate: true
}
}
}
Создайте задачу grunt, которая вручную запускает сервер karma и обслуживает один скомпилированный js файл, который мы теперь тестируем.
Кроме того, мне удалось вырезать REQUIRE_ADAPTER
в файле karma.conf.js
, а затем включить только один скомпилированный js файл вместо шаблонов, соответствующих всем исходным кодам и спецификациям, поэтому теперь он выглядит следующим образом:
// base path, that will be used to resolve files and exclude
basePath = '';
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
REQUIRE,
'tmp/tests.js'
];
// list of files to exclude
exclude = [];
// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];
// web server port
port = 9876;
// cli runner port
runnerPort = 9100;
// enable / disable colors in the output (reporters and logs)
colors = true;
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;
// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;
// Start these browsers, currently available:
browsers = ['PhantomJS'];
// If browser does not capture in given timeout [ms], kill it
captureTimeout = 60000;
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = true;
В конфигурации задания grunt для компиляции requirejs также необходимо использовать almond для запуска выполнения теста (выполнение теста зависает без него). Вы можете видеть, что это используется в конфигурационной программе requirejs grunt выше.
Ответ 2
Есть пара вещей. Прежде всего: я мог бы пропустить некоторые детали в вашем вопросе (так как это супер огромный) - так жаль об этом.
Короче говоря, вы можете захотеть проверить организацию тестирования ветвей-боилеров wip
: https://github.com/backbone-boilerplate/backbone-boilerplate/tree/wip
Сначала: RequireJS не поддерживает развернутый необработанный модуль common.js. cjsTranslate
- это инструмент R.js(инструмент построения) для преобразования Commonjs в AMD, совместимый во время сборки. Таким образом, требуемый модуль CJS raw не будет работать. Чтобы решить эту проблему, вы можете использовать сервер для фильтрации отправляемых скриптов и компиляции их в формат AMD. На BBB мы передаем файл через статическую службу для их компиляции:
Второй: плагин для исправления Karma не работает очень хорошо - и это как-то просто использовать requireJS напрямую. На BBB, как нам это удалось: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/test/jasmine/test-runner.js#L16-L36
Надеюсь, это поможет!