KarmaJS、Jasmine、RequireJS 等:如何使用 Require 测试模块 [英] KarmaJS, Jasmine, RequireJS, etc: How to Use Require for Testing Modules
问题描述
目前,我有一个练习项目来熟悉 KarmaJS 以及整个单元测试.广泛的问题是,我对 Karma 在幕后所做的事情确实没有透明的看法,而且我似乎无法在相关领域找到足够的文档.事不宜迟……
Currently, I have an exercise project up for getting comfortable with KarmaJS -- and Unit Testing, at large. The broad issue is that I really have no transparent view of what Karma is doing behind the scenes, and I can't seem to find adequate documentation in relevant areas. Without further delay...
这是我的文件夹结构:
root
|-/lib
|-/[dependencies] (/angular, /angular-mocks, /bootstrap, /etc) # from bower
|-/src
|-/[unreferenced directories] (/js, /css, /views) # not referenced anywhere
|-app.js # sets up angular.module('app', ...)
|-globals.js # may be referenced in RequireJS main file; not used.
|-index.html # loads bootstrap.css and RequireJS main file
|-main.js # .config + require(['app', 'etc'])
|-routeMap.js # sets up a single route
|-test-file.js # *** simple define(function(){ return {...}; })
|-/test
|-/spec
|-test-test-file.js # *** require || define(['test-file'])
|-.bowerrc # { "directory": "lib" }
|-bower.json # standard format
|-karma.conf.js # *** HELP!
|-test-main.js # *** Save Our Souls!!!
karma.conf.js
// Karma configuration
// Generated on Wed Nov 19 2014 15:16:56 GMT-0700 (Mountain Standard Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
//'test/spec/test-test-file.js',
//'lib/**/*.js',
//'src/**/*.js',
//'test/spec/**/*.js',
'test-main.js',
{pattern: 'lib/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/spec/*.js', included: true}
],
// list of files to exclude
exclude: [
'lib/**/!(angular|angular-mocks|angular-resource|angular-route|require|text).js',
'lib/**/**/!(jquery|bootstrap).js',
'src/app.js'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
test-main.js
var allTestFiles = [];
var TEST_REGEXP = /(spec|test).js$/i;
var pathToModule = function(path) {
return path.replace(/^/base//, '').replace(/.js$/, '');
};
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(pathToModule(file));
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base/src',
paths: {
angular: '../lib/angular/angular',
ngRoute: '../lib/angular-route/angular-route',
jquery: '../lib/jQuery/dist/jquery',
bootstrap: '../lib/bootstrap/dist/js/bootstrap',
models: 'models',
controllers: 'controllers',
globals: 'globals',
routeMap: 'routeMap'
},
shim: {
angular: {
exports: 'angular'
},
ngRoute: {
deps: ['angular']
},
jquery: {
exports: '$'
},
bootstrap: {
deps: ['jquery']
}
},
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
test-test-file.js
console.log('....................');
define(function(){
//console.log('testing test-file', testFile);
describe('Testing testing', function(){
it('should work', function(){
expect(true).toEqual(true);
});
});
});
test-file.js
define('testFile', [], function(){
return function init(sandbox){
var app, application = app = sandbox.app
, globals = sandbox.globals;
return {
some: 'module'
};
};
});
问题&说明
我希望听到答案的关键点是
Key points I would love to hear answers for are
- {pattern: '...', include: true|false } 有什么作用?
- 排除 bower 目录中所有额外内容的最佳方法.
- 我需要在 test-main.js 文件中包含哪些文件?
- 我需要在 karma.conf.js 文件中包含哪些文件?
- test-main.js 实际做了什么;有什么用?
我收到错误的次数和问题是只要我将规范包装在 define(...)
调用中——当我给模块一个 ID 时发生的事件——define('someId', function(){... })
-- 我需要从这个模块中返回一些东西吗,因为它是一个 define
调用?
The times I receive errors & issues is as soon as I wrap my spec in a define(...)
call -- event when I give the module an ID -- define('someId', function(){ ... })
-- do I need to return something out of this module, as it is a define
call?
其他时候,我收到'ol 错误:'/base/src/app.js 没有时间戳!'.当然是时间戳!我真傻……"——这到底是什么意思?!有时我会收到臭名昭著的Executed 0 of 0 ERROR".- 我也可以在这里使用一些清晰度,请.真的,我得到了很多 ERROR: '...no timestamp...' 错误——甚至 404s 当它似乎我应该使用 karma.conf.js files
配置将该库拉入...???
Other times, I receive the 'ol ERROR: 'There is no timestamp for /base/src/app.js!'. "Timestamp, of course! How silly of me..." -- what in the world does this mean?! Sometimes I get the infamous "Executed 0 of 0 ERROR" -- I could also use some clarity here, please. Really, I get plenty of ERROR: '...no timestamp...' errors -- and even 404
s when it seems I should be pulling that library in with the karma.conf.js files
config...???
似乎通常当我明确告诉 karma 排除src/app.js
时,我仍然会收到 404
和错误.
It even seems that usually when I explicitly tell karma to excludesrc/app.js
I still get 404
s and errors.
tl;dr
显然,我对 Karma 和 *DD 大体上是一个有点困惑的新手......
Obviously, I'm a bit of a confused novice about Karma and *DD at large...
当我的 karma.conf.js files
数组看起来像 [ 'test-main.js' 时,我可以很好地运行
-- 但是,如果我将测试包装在 RequireJS 定义调用中,我会得到不匹配的匿名定义()"em>"上面提到的错误.test-test-file.js
, 'test/spec/test-test-file.js' ]
I can run test-test-file.js
fine when my karma.conf.js files
array looks like [ 'test-main.js', 'test/spec/test-test-file.js' ]
-- but, still, if I wrap my test in a RequireJS define call I get the "Mismatching anonymous define()" error mentioned above.
似乎当我添加 { pattern: '...', include: false } 然后业力不会为给定的文件添加我的任何文件任何模式(???).
It seems that when I add { pattern: '...', include: false } then karma just doesn't add any of my files for the given pattern whatsoever (???).
如果有人甚至可以简单地指导我如何将 RequireJS 与 Karma 一起使用——也就是说,我可以将我的测试包装在一个 define/require 调用中并拉入我想要测试的模块... 那将不胜感激.
If someone can even simply direct me toward how to use RequireJS with Karma -- namely so that I can just wrap my tests in a define/require call and pull in the module I want to test... That would be greatly appreciated.
由于这些类型的问题要简短且仍能提供足够的信息有点困难,我希望我没有把它弄得太长.
As its somewhat difficult to keep these types of questions short and still provide adequate information, I hope I didn't make it too long.
在阅读了 glepretre 的答案和我自己的一些摆弄之后,我重新配置了我的项目如下:
After reading the answer from glepretre and some fiddling on my own, I reconfigured my project as follows:
- 将
test-main.js
移至test/test-main.js
, - 将 test-test-file.js 重命名为 testFileSpec.js -- 将其从
test/spec
移至test/
,
- Moved
test-main.js
totest/test-main.js
, - renamed test-test-file.js to testFileSpec.js -- moved it from
test/spec
totest/
,
karma.conf.js:
...
// list of files / patterns to load in the browser
files: [
{pattern: 'lib/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/**/*Spec.js', included: false},
'test/test-main.js'
],
....
test/test-main.js:
/* **************** HOW COME THE DEFAULT (Karma-generated) CONFIGURATION DOES ***NOT WORK???
var allTestFiles = [];
var TEST_REGEXP = /(spec|test).js$/i;
var pathToModule = function(path) {
return path.replace(/^/base//, '').replace(/.js$/, '');
};
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(pathToModule(file));
}
});
*/
var tests = [];
for (var file in window.__karma__.files) {
if (/Spec.js$/.test(file)) {
tests.push(file);
}
}
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base/src',
paths: {},
shim: {},
// dynamically load all test files
//deps: allTestFiles,
//
deps: tests,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
我现在正在成功运行单元测试!特别感谢 glepretre &所有其他贡献者.
感谢您的任何见解:)
推荐答案
好的,我会尝试一次解决每个问题:
OK, I will try to address each question at a time:
问题 1
- {pattern: '...', included: true|false } 有什么作用?
- what does { pattern: '...', included: true|false } do?
Karma 的默认行为是:
Karma's default behavior is to:
- 查找与
pattern
(强制属性)匹配的所有文件 - 观察它们的变化(
watched
选项),以便在您编辑代码时重新启动单元测试以提供实时结果(仅当您离开默认autoWatch
默认值为true
). - 使用自己的网络服务器为他们提供服务(
served
选项) - 使用
<script>
将它们包含在浏览器中(included
选项)
- find all files matching the
pattern
(mandatory property) - watch them for changes (
watched
option) in order to restart your unit tests to give you live result when you are editing your code (works if only you leave the defaultautoWatch
default value totrue
). - serve them using its own webserver (
served
option) - include them in the browser using
<script>
(included
option)
因此,在 karma 配置的 files
数组中,您可以通过仅添加字符串模式来使用默认行为:
So, in the files
array of the karma config you can use default behavior by adding only string patterns:
files: [
// this will match all your JS files
// in the src/ directory and subdirectories
'src/**/*.js'
]
或者使用完整的对象语法来自定义每个选项:
Or use the full object syntax to customize each option:
files: [
{pattern: 'src/**/*.js', watched: true, served: true, included: false}
]
使用 requireJS,你不希望它们被包含,因为它会与 requireJS 的行为冲突!
Using requireJS, you DO NOT want them to be included because it will be in conflict with requireJS behavior!
包括在内.说明: 是否应该使用 <script>
标签将文件包含在浏览器中?如果您想手动加载它们,请使用 false,例如.使用 Require.js.
Included. Description: Should the files be included in the browser using
<script>
tag? Use false if you want to load them manually, eg. using Require.js.
注意:注意在数组中添加文件/模式的顺序.很重要!为了进一步了解,请在您的业力配置中设置 logLevel: config.LOG_DEBUG
.
问题 2
- 我需要在 karma.conf.js 文件中包含哪些文件?
至少所有必需的文件都可以让您的组件正常运行以进行单元测试.
At least all required files for the proper functioning of your components for unit testing.
基本上,您的 define([])
和 require()
块中列出的所有文件.
Basically, all files listed in your define([])
and require()
blocks.
问题 3
- 排除 bower 目录中所有额外内容的最佳方法.
你到底想做什么?
根据我之前写的,您可以看到您可以选择性地添加测试中需要的文件.
Based on what I wrote before, you can see that you can add selectively the files you will need in your tests.
我用 '/bower_components/**/*.js'
甚至 '/bower_components/**/*.html'
当我的凉亭添加模式包正在使用模板.如果这是您所担心的,我从未注意到任何重大的性能问题...由您来定义您需要的文件模式.
I use to add the pattern '/bower_components/**/*.js'
and even '/bower_components/**/*.html'
when my bower packages are using templates. I never noticed any significant performance issue if that's what you are worried about... Up to you to define the file patterns you will need.
问题 4 &5
test-main.js 实际做了什么;有什么用?
what does test-main.js actually do; what's it for?
我需要在 test-main.js 文件中包含哪些文件?
what files do I need to include in the test-main.js file?
test-main.js
文件的目的是在启动 Karma 之前查找并加载您的测试文件.它连接了 Karma 和 requireJS 之间的点
The purpose of the test-main.js
file is to find and load your test files before starting Karma. It connects the dots between Karma and requireJS
您必须选择一个约定来命名您的测试文件,然后定义 TEST_REGEXP
以匹配所有这些文件.
You must choose a convention to name your test files and then define the TEST_REGEXP
to match all of them.
官方"角度风格指南和应用结构最佳实践建议使用后缀 *_test.js
.
The "official" angular style guide and best practices for app structure recommends using the suffix *_test.js
.
您的正则表达式不起作用,因为它被定义为捕获 "spec.js"||test.js"
或您的规范文件名以 file.js"
结尾;)请参阅 http://regex101.com/r/bE9tV9/1
Your regexp is not working because it is defined to catch "spec.js" || "test.js"
at the end or your spec file name is ending by "file.js"
;) Please see http://regex101.com/r/bE9tV9/1
还有一件事
我希望我已经足够清楚了.您可以使用 Angular + Require 查看我们项目的入门应用程序结构:angular-requirejs-ready.它已经使用 Karma 和 Protractor 进行了设置和测试.
I hope I was clear enough. You can have a look at our starter app structure for our projects using Angular + Require: angular-requirejs-ready. It's already set up and tested with both Karma and Protractor.
这篇关于KarmaJS、Jasmine、RequireJS 等:如何使用 Require 测试模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!