Place Holder's Life

living is easy, life is hard

Karma配置中的一些问题

之前看了icodeit的博客使用Karma运行JavaScript测试,试了一下karma,果然是非常好用。

关于使用karma基础流程,就请参照那篇博客。

这里主要针对我在配置karma的时候遇到的一些特殊问题进行一个总结。

使用karma-html-reporter配置生成的html测试报告

配置

package.json中的内容:

{
  "devDependencies": {
    "karma": "~0.10.8",
    "karma-html-reporter": "~0.1.1"
  }
}

执行npm install进行plugin的安装。

使用./node_modules/.bin/karma init初始化karma配置文件

然后打开karma.conf.js配置文件,添加html格式的report:

reporters: ['progress', 'html'],

htmlReporter: {
  outputDir: 'report',
  templatePath: __dirname + '/jasmine_template.html'
},

问题

然而这时候启动karma

./node_modules/.bin/karma start karma.conf.js

会报错:

ERROR [karma]: { [Error: ENOENT, open '/Users/twer/learn/jasmine/jasmine_template.html']
  errno: 34,
  code: 'ENOENT',
  path: '/Users/twer/learn/jasmine/jasmine_template.html' }
Error: ENOENT, open '/Users/twer/learn/jasmine/jasmine_template.html'
解决

由于karma-html-reporter为了保持生成报告的灵活性,所以在生成html的时候使用了template。也就是配置中的这一句:

  templatePath: __dirname + '/jasmine_template.html'

但是配置好的时候我们是没有自己的template 的,那要怎么办呢? 其实如果进入node_modules/karma-html-reporter/目录看一下的话,会发现这个目录下有一个叫jasmine_template.html的html文件。那如果我们将templatePath指向这个文件的话,会怎么样呢?

  templatePath: 'node_modules/karma-html-reporter/jasmine_template.html'

然后重启karma服务器

./node_modules/.bin/karma start karma.conf.js

会发现已经没有报错了,并且在report目录下,生成了一个新的目录,比如我的是Chrome 31.0.1650 (Mac OS X 10.7.5)。在这个目录下就会有我们生成的html报告了,打开看一下,会发现他的样式跟jasmine的SpecRunnerHtml结果是很像的,除了不能点链接。

到这里karma-html-reporter的配置就完成了。

在karma里借助jasmine-jquery来使用external fixtures

jasmine-jquery由于支持多种fixture的实现,所以被广泛的使用在jasmine测试中。 但是在karma中使用jasmine-jquery会存在一些配置的问题。

配置

首先要把jasmine-jquery的库文件放在files配置项里:

files: [
  'src/**/*.js',
  'test/*.js',
  'test/lib/jquery-1.10.2.min.js',
  'test/lib/jasmine-fixture.min.js',
  'test/lib/jasmine-jquery.js'
],

在jasmine测试中使用jasmine-jquery的loadFixtures方法:

jasmine.getFixtures().fixturesPath = path + 'fixtures';
loadFixtures('test_fixtures.html');

问题

那么在启动karma的时候会出现这样的错误:

Chrome 31.0.1650 (Mac OS X 10.7.5) Firefox fixtures should work with imported html with jasmine-jquery FAILED
Error: Fixture could not be loaded: base/test/fixtures/test_fixtures.html (status: error, message: undefined)
    at Object.$.ajax.error (/Users/twer/learn/jasmine/test/lib/jasmine-jquery.js:130:17)
    at c (/Users/twer/learn/jasmine/test/lib/jquery-1.10.2.min.js:4:26036)
    at Object.p.fireWith (/Users/twer/learn/jasmine/test/lib/jquery-1.10.2.min.js:4:26840)
    at k (/Users/twer/learn/jasmine/test/lib/jquery-1.10.2.min.js:6:14283)
    at r (/Users/twer/learn/jasmine/test/lib/jquery-1.10.2.min.js:6:18646)
    at Object.send (/Users/twer/learn/jasmine/test/lib/jquery-1.10.2.min.js:6:18771)
    at Function.x.extend.ajax (/Users/twer/learn/jasmine/test/lib/jquery-1.10.2.min.js:6:13722)
    at jasmine.Fixtures.loadFixtureIntoCache_ (/Users/twer/learn/jasmine/test/lib/jasmine-jquery.js:122:21)
    at jasmine.Fixtures.getFixtureHtml_ (/Users/twer/learn/jasmine/test/lib/jasmine-jquery.js:114:12)
    at jasmine.Fixtures.read (/Users/twer/learn/jasmine/test/lib/jasmine-jquery.js:77:28)

尝试

看了一下jasmine-jquery的源码,发现在loadFixtures的时候调用了jquery里面的ajax方法。也就是说,当运行这段代码的时候,js会从浏览器中取出这个html文件,而不是从本地硬盘读取。

而karma的原理是借助于node.js启动了一个服务器,那么如果这个html文件不在服务器上的话,js是无法从浏览器里取出这个文件的。

那么我们首先让这个文件能在服务器上出现,把html文件假如files配置项:

files: [
  'src/**/*.js',
  'test/*.js',
  'test/lib/jquery-1.10.2.min.js',
  'test/lib/jasmine-fixture.min.js',
  'test/lib/jasmine-jquery.js',
  {
    pattern: 'test/fixtures/**/*.html',
    watched: false,
    included: false
  }
],

这里稍微解释一下定义格式:每个定义的文件pattern都由三项属性:

  • watched, 文件的修改是否被监控;
  • included, 文件是否是测试代码;
  • served,文件是否出现在服务器上。

对于前面的字符串定义,其实是默认设置这三个属性为true的定义。那么其实我们的hmtl文件的修改不需要被监控,本身也不是测试代码,所以可以使用完整定义将这两项定义为false,只有文件是否出现在服务器上为true。

那么现在这个html文件应该可以被karma加载在服务器上了吧,重新运行karma,发现错误依旧。

解决

后来进行了大量搜索,最后在这个karma的github issue里找到了答案。

所谓karma-html2js-preprocessor,是一个预处理器,会将files配置项中的html文件都转化成js文件,就拿karma-html2js-preprocessor主页上的一个例子来说:

有一个test.html,内容为

<div>something</div>

会被转化为一个js文件template.html.js,内容为

window.__html__ = window.__html__ || {};
window.__html__['template.html'] = '<div>something</div>';

而且这个preprocessor会被默认加载,所以其实我们在前面写的pattern中的html文件已经全部变成js文件被karma加载了,这也是html文件在服务器上不能被找到的原因。

那么怎么让preprocessor不做这样的转化呢?我们需要在增加一条配置:

preprocessors: {
  '**/*.html': []
},

然后再重启karma服务器,就会发现一切正常了。