让 requirejs 与 Jasmine 一起工作
Getting requirejs to work with Jasmine
我首先想说的是,我是RequireJS的新手,甚至对Jasmine更是新手。
我在使用SpecRunner时遇到了一些问题,需要JS。 我一直在关注Uzi Kilon和Ben Nadel(以及其他一些人(的教程,他们帮助了一些人,但我仍然遇到一些问题。
似乎,如果在测试中抛出了一个错误(我可以特别想到一个类型错误(,规范运行器 html 将显示。 这告诉我我在javascript中有一些问题。 但是,在我修复这些错误后,不再显示 HTML。 我根本无法显示测试运行程序。 有人会发现我的代码有问题会导致此问题吗?
这是我的目录结构:
Root
|-> lib
|-> jasmine
|-> lib (contains all of the jasmine lib)
|-> spec
|-> src
|-> jquery (jquery js file)
|-> require (require js file)
index.html (spec runner) specRunner.js
以下是 SpecRunner(索引(的 HTML:
<!doctype html>
<html lang="en">
<head>
<title>Javascript Tests</title>
<link rel="stylesheet" href="lib/jasmine/lib/jasmine.css">
<script src="lib/jasmine/lib/jasmine.js"></script>
<script src="lib/jasmine/lib/jasmine-html.js"></script>
<script src="lib/jquery/jquery.js"></script>
<script data-main="specRunner" src="lib/require/require.js"></script>
<script>
require({ paths: { spec: "lib/jasmine/spec" } }, [
// Pull in all your modules containing unit tests here.
"spec/notepadSpec"
], function () {
jasmine.getEnv().addReporter(new jasmine.HtmlReporter());
jasmine.getEnv().execute();
});
</script>
</head>
<body>
</body>
</html>
这是规范运行器.js(配置(
require.config({
urlArgs: 'cb=' + Math.random(),
paths: {
jquery: 'lib/jquery',
jasmine: 'lib/jasmine/lib/jasmine',
'jasmine-html': 'lib/jasmine/lib/jasmine-html',
spec: 'lib/jasmine/spec/'
},
shim: {
jasmine: {
exports: 'jasmine'
},
'jasmine-html': {
deps: ['jasmine'],
exports: 'jasmine'
}
}
});
这是一个规格:
require(["../lib/jasmine/src/notepad"], function (notepad) {
describe("returns titles", function() {
expect(notepad.noteTitles()).toEqual("");
});
});
记事本来源:
define(['lib/jasmine/src/note'], function (note) {
var notes = [
new note('pick up the kids', 'dont forget to pick up the kids'),
new note('get milk', 'we need two gallons of milk')
];
return {
noteTitles: function () {
var val;
for (var i = 0, ii = notes.length; i < ii; i++) {
//alert(notes[i].title);
val += notes[i].title + ' ';
}
return val;
}
};
});
和注释来源(JIC(:
define(function (){
var note = function(title, content) {
this.title = title;
this.content = content;
};
return note;
});
我已经确保,就应用程序而言,路径是正确的。 一旦我开始工作,我就可以配置该路径,这样它就不会那么令人讨厌。
我设法通过一些试验和错误来解决这个问题。 主要问题是,当您编写规范时,它不是您想要创建的要求,而是您想要使用定义:
源语言:
require(["/lib/jasmine/src/notepad"], function (notepad) {
describe("returns titles", function() {
expect(notepad.noteTitles()).toEqual("pick up the kids get milk");
});
});
加工:
define(["lib/jasmine/src/notepad"], function (notepad) {
describe("returns titles", function () {
it("something", function() {
expect(notepad.noteTitles()).toEqual("pick up the kids get milk ");
});
});
});
在做了一些研究之后,很明显,当使用 RequireJS 时,您希望 require(( 使用的任何内容都必须包装在一个定义中(现在我猜似乎很明显(。 您可以看到,在 specRunner.js 文件中,执行测试时使用了 require(因此需要"定义"规范。
另一个问题是,在创建规范时,describe(( 和 it(( 是必需的(而不仅仅是我在发布的例子中的描述(。
源语言:
describe("returns titles", function() {
expect(notepad.noteTitles()).toEqual("pick up the kids get milk");
});
加工:
describe("returns titles", function () {
it("something", function() {
expect(notepad.noteTitles()).toEqual("pick up the kids get milk ");
});
});
我还更改了测试运行器所在的位置,但这是一个重构,并没有改变测试结果。
同样,这是文件和更改的内容:
注意.js:保持不变
记事本.js:保持不变
索引.html:
<!doctype html>
<html lang="en">
<head>
<title>Javascript Tests</title>
<link rel="stylesheet" href="lib/jasmine/lib/jasmine.css">
<script data-main="specRunner" src="lib/require/require.js"></script>
</head>
<body>
</body>
</html>
specRunner.js:
require.config({
urlArgs: 'cb=' + Math.random(),
paths: {
jquery: 'lib/jquery',
'jasmine': 'lib/jasmine/lib/jasmine',
'jasmine-html': 'lib/jasmine/lib/jasmine-html',
spec: 'lib/jasmine/spec/'
},
shim: {
jasmine: {
exports: 'jasmine'
},
'jasmine-html': {
deps: ['jasmine'],
exports: 'jasmine'
}
}
});
require(['jquery', 'jasmine-html'], function ($, jasmine) {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function (spec) {
return htmlReporter.specFilter(spec);
};
var specs = [];
specs.push('lib/jasmine/spec/notepadSpec');
$(function () {
require(specs, function (spec) {
jasmineEnv.execute();
});
});
});
记事本规格.js:
define(["lib/jasmine/src/notepad"], function (notepad) {
describe("returns titles", function () {
it("something", function() {
expect(notepad.noteTitles()).toEqual("pick up the kids get milk");
});
});
});
只是将其添加为使用Jasmine 2.0独立的人的替代答案。我相信这也适用于 Jasmine 1.3,但异步语法不同且有点丑陋。
这是我修改后的 SpecRunner.html 文件:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v2.0.0</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css">
<!--
Notice that I just load Jasmine normally
-->
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script>
<!--
Here we load require.js but we do not use data-main. Instead we will load the
the specs separately. In short we need to load the spec files synchronously for this
to work.
-->
<script type="text/javascript" src="js/vendor/require.min.js"></script>
<!--
I put my require js config inline for simplicity
-->
<script type="text/javascript">
require.config({
baseUrl: 'js',
shim: {
'underscore': {
exports: '_'
},
'react': {
exports: 'React'
}
},
paths: {
jquery: 'vendor/jquery.min',
underscore: 'vendor/underscore.min',
react: 'vendor/react.min'
}
});
</script>
<!--
I put my spec files here
-->
<script type="text/javascript" src="spec/a-spec.js"></script>
<script type="text/javascript" src="spec/some-other-spec.js"></script>
</head>
<body>
</body>
</html>
现在下面是一个示例规范文件:
describe("Circular List Operation", function() {
// The CircularList object needs to be loaded by RequireJs
// before we can use it.
var CircularList;
// require.js loads scripts asynchronously, so we can use
// Jasmine 2.0's async support. Basically it entails calling
// the done function once require js finishes loading our asset.
//
// Here I put the require in the beforeEach function to make sure the
// Circular list object is loaded each time.
beforeEach(function(done) {
require(['lib/util'], function(util) {
CircularList = util.CircularList;
done();
});
});
it("should know if list is empty", function() {
var list = new CircularList();
expect(list.isEmpty()).toBe(true);
});
// We can also use the async feature on the it function
// to require assets for a specific test.
it("should know if list is not empty", function(done) {
require(['lib/entity'], function(entity) {
var list = new CircularList([new entity.Cat()]);
expect(list.isEmpty()).toBe(false);
done();
});
});
});
这是Jasmine 2.0文档中异步支持部分的链接:http://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support
Jasmine 2.0 独立版的另一个选项是创建一个引导.js文件,并将其设置为在加载所有 AMD 模块后运行测试。
在我们的案例中,编写测试的理想最终用户案例是不必在一次显式列表中列出我们所有的规范文件或依赖项,只需要将您的 *spec 文件声明为具有依赖项的 AMD 模块。
理想规范示例:spec/javascript/sampleController_spec.js
require(['app/controllers/SampleController'], function(SampleController) {
describe('SampleController', function() {
it('should construct an instance of a SampleController', function() {
expect(new SampleController() instanceof SampleController).toBeTruthy();
});
});
});
理想情况下,加载依赖项并运行规范的背景行为对于任何想要编写测试的项目的人来说都是完全不透明的,除了创建一个带有 AMD 依赖项的 *spec.js 文件之外,他们不需要做任何事情。
为了使这一切正常工作,我们创建了一个引导文件并配置 Jasmine 以使用它 (http://jasmine.github.io/2.0/boot.html(,并添加了一些魔法来包装需要暂时延迟运行测试,直到我们加载完 deps 之后:
我们的引导.js的"执行"部分:
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload;
// Stack of AMD spec definitions
var specDefinitions = [];
// Store a ref to the current require function
window.oldRequire = require;
// Shim in our Jasmine spec require helper, which will queue up all of the definitions to be loaded in later.
require = function(deps, specCallback){
//push any module defined using require([deps], callback) onto the specDefinitions stack.
specDefinitions.push({ 'deps' : deps, 'specCallback' : specCallback });
};
//
window.onload = function() {
// Restore original require functionality
window.require = oldRequire;
// Keep a ref to Jasmine context for when we execute later
var context = this,
requireCalls = 0, // counter of (successful) require callbacks
specCount = specDefinitions.length; // # of AMD specs we're expecting to load
// func to execute the AMD callbacks for our test specs once requireJS has finished loading our deps
function execSpecDefinitions() {
//exec the callback of our AMD defined test spec, passing in the returned modules.
this.specCallback.apply(context, arguments);
requireCalls++; // inc our counter for successful AMD callbacks.
if(requireCalls === specCount){
//do the normal Jamsine HTML reporter initialization
htmlReporter.initialize.call(context);
//execute our Jasmine Env, now that all of our dependencies are loaded and our specs are defined.
env.execute.call(context);
}
}
var specDefinition;
// iterate through all of our AMD specs and call require with our spec execution callback
for (var i = specDefinitions.length - 1; i >= 0; i--) {
require(specDefinitions[i].deps, execSpecDefinitions.bind(specDefinitions[i]));
}
//keep original onload in case we set one in the HTML
if (currentWindowOnload) {
currentWindowOnload();
}
};
我们基本上将我们的AMD语法规范保存在一个堆栈中,弹出它们,需要模块,执行带有我们的断言的回调,然后在所有内容加载完成后运行Jasmine。
此设置允许我们等到加载各个测试所需的所有 AMD 模块,并且不会通过创建全局变量来破坏 AMD 模式。事实上,我们暂时覆盖了require,并且只使用require加载我们的应用程序代码(我们在jasmine.yml中的`src_dir:
是空的(,但这里的总体目标是减少编写规范的开销。
您可以在组合中使用done
与 before 过滤器来测试异步回调:
beforeEach(function(done) {
return require(['dist/sem-campaign'], function(campaign) {
module = campaign;
return done();
});
});
这就是我如何使用 AMD/requirejs 在 html 中运行茉莉花规范的方式,用于我的所有来源和规范。
这是我的索引.html文件,它加载了茉莉花,然后加载了我的"单元测试启动器":
<html><head><title>unit test</title><head>
<link rel="shortcut icon" type="image/png" href="/jasmine/lib/jasmine-2.1.3/jasmine_favicon.png">
<link rel="stylesheet" href="/jasmine/lib/jasmine-2.1.3/jasmine.css">
<script src="/jasmine/lib/jasmine-2.1.3/jasmine.js"></script>
<script src="/jasmine/lib/jasmine-2.1.3/jasmine-html.js"></script>
<script src="/jasmine/lib/jasmine-2.1.3/boot.js"></script>
</head><body>
<script data-main="javascript/UnitTestStarter.js" src="javascript/require.js"></script>
</body></html>
然后我的UnitTestStarter.js是这样的:
require.config({
"paths": {
....
});
require(['MySpec.js'], function()
{
jasmine.getEnv().execute();
})
- 如何在php中创建一个函数,该函数与文本区域一起工作,通过输入类似[color:red]的内容来打印具有等效颜色的文本
- document.title函数可以't设置它与php一起工作
- "此网站似乎使用滚动链接定位效果.这可能不能很好地与异步平移一起工作;
- 非常简单的js测试;Don’不要和Minko一起工作
- 无法使我的文本参数与我的查询一起工作
- 为什么Angularjs验证don't与输入[type=“number”]一起工作
- 无法使vash 0.8.0与express 4.12.3一起工作
- 如何使Angular JS控制器与指令一起工作
- 无法使autocompletion与bootstrap和php代码点火器一起工作
- 注入的元素和jQuery脚本.如何让他们一起工作
- 两个独立工作的javascript函数,但不能一起工作
- 角度和砖石一起工作
- Node http-proxy-middleware 不能与本地服务器一起工作
- jQuery脚本不想一起工作
- page.js使examples/hash与hashbang:true一起工作
- javascript使jquery倒计时与UTC时间一起工作
- jQuery.not()选择器无法与类一起工作
- Rails3-可排序列表不能与wysihtml5一起工作
- 替换匹配函数给出了未定义的错误,但它与替换一起工作
- 按钮上的数据加载消息无法与ajax调用一起工作