Nightmare.js和代码覆盖率

简洁版本:

我无法从我使用nightmare.js和mocha写的testing中看到代码覆盖率。 到目前为止,我已经尝试过使用伊斯坦布尔和_mocha。

大版本:

我有一个小项目:

/public/index.html

<html lang="en"> <head> <meta charset="UTF-8"> <title>My Website</title> <script src="./js/hello.js"></script> </head> <body> <h1>My Website</h1> </body> </html> 

/public/js/hello.js

 window.hello = function hello(){ return 'world'; }; 

该网站使用快递和永远运行。

当我试图使用nightmare.js来testing它。

/test/test.js

 var path = require('path'); var Nightmare = require('nightmare'); var should = require('should'); /*global describe */ /*global it */ describe('Simple demo', function () { this.timeout(15000); var url = 'http://localhost:9000'; it('check hello world result', function (done) { new Nightmare() .goto(url) .evaluate(function () { /*global hello */ return hello(); }, function (value) { var expected = "world"; if (value === null) { false.should.equal(true); return done(); } value.should.equal(expected); return done(); }) .run(); }); it('should get the index title', function (done) { var expected = 'My Website'; new Nightmare() .goto(url) .title(function (title) { title.should.equal(expected); done(); }) .run(); }); }); 

testing正在通过

 $ mocha Simple demo ✓ check hello world result (2089ms) title = Alexandria ✓ should get the index title (1947ms) 2 passing (4s) 

但是,我无法从我的testing中获得代码覆盖率报告。

我已经尝试了一些命令,如:

 $ istanbul cover _mocha -- test/test.js -u exports -R spec No coverage information was collected, exit without writing coverage information $ istanbul cover --hook-run-in-context _mocha -- -R spec No coverage information was collected, exit without writing coverage information 

那么,有人能够创buildnightmare.jstesting的代码覆盖率报告? 如果不是,那么使用其他工具还有一些相似之处?

我在我的项目中也遇到了同样的问题。 我找不到任何用简单的方法解决这个问题的库或者configuration,但是通过一些实现和Gruntconfiguration,你可以从Grunt进程获得代码覆盖。

我在项目中使用的依赖关系:

 "chai": "^3.5.0", "grunt": "^0.4.5", "grunt-contrib-clean": "^0.7.0", "grunt-contrib-copy": "^0.8.2", "grunt-express-server": "^0.5.3", "grunt-istanbul": "^0.7.1", "grunt-mocha-test": "^0.12.7", "istanbul": "^0.4.4", "nightmare": "^2.2.0" 

我的项目结构:

 public/ -- public folder for index.html src/ -- source folder for hello.js test/ -- mocha tests implementation server/ -- express implementation for server.js coverage/ -- HTML report from code coverage report/ -- HTML report from mocha tests dist/ -- folder which is used by express server to get content, generated by Grunt 

你必须从Grunt运行的步骤:

 grunt.registerTask('test_hello', [ 'clean', // clean dist/ folder 'copy:public', // copy public files from public/ (ex. index.html) to dist/ 'instrument', // generate instruments (ex. hello.js) for code coverage from src/ by istanbul 'express', // run express server from dist/ folder 'mochaTest', // run mocha tests with nightmare and generate HTML report to report/ folder 'report_coverage' // generate HTML report from code coverage to coverage/ folder ]); 

咕噜声configuration:

 module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-express-server'); grunt.loadNpmTasks('grunt-istanbul'); grunt.loadNpmTasks('grunt-mocha-test'); grunt.initConfig({ clean: { dist: ['dist/', 'report/', 'coverage/'] }, copy: { public: { expand: true, cwd: 'public/', src: ['**'], dest: 'dist/' } }, instrument: { files: ['**/*.js'], options: { cwd: 'src/', lazy: true, basePath: 'dist/' } }, express: { dev: { options: { port: 9000, script: 'server/server.js', background: true } } }, mochaTest: { hello: { options: { timeout: 10000, captureFile: 'report/results.txt', // Optionally capture the reporter output to a file quiet: false, // Optionally suppress output to standard out (defaults to false) clearRequireCache: false // Optionally clear the require cache before running tests (defaults to false) }, src: ['test/*.js'] }, } }); grunt.registerTask('report_coverage', function () { var coverage = require('./test/utils/coverage'); coverage.generateReport(); }); grunt.registerTask('test_hello', [ 'clean', // clean dist/ folder 'copy:public', // copy public files from public/ (ex. index.html) to dist/ 'instrument', // generate instruments (ex. hello.js) for code coverage from src/ by istanbul 'express', // run express server from dist/ folder 'mochaTest:hello', // run mocha tests with nightmare and generate HTML report to report/ folder 'report_coverage' // generate HTML report from code coverage to coverage/ folder ]); } 

我也创build了类,它允许我从每个梦魇实例收集代码覆盖率:

 var istanbul = require('istanbul'); var reporter = new istanbul.Reporter(), sync = true; var Coverage = function () { this.loadCodeCoverage = function (dom, done) { dom .evaluate(function () { return window.__coverage__; // this variable store all information about code coverage }) .then(function (coverageDate) { if (coverageDate) { this.getCollector().add(coverageDate); } done(); }.bind(this)) .catch(function (error) { done(error); }); } // load page by nightmare this.getCollector = function () { if (!this.collector) { this.collector = new istanbul.Collector(); } return this.collector; } this.generateReport = function () { reporter.add('text'); reporter.addAll(['lcov', 'clover']); reporter.write(this.collector, sync, function () { console.log('All reports generated'); }); } } module.exports = new Coverage(); 

对于上面的configuration文件test / test.js应该具有以下结构:

 var should = require('should'); var coverage = require('./utils/coverage'); /*global describe */ /*global it */ describe('Simple demo', function () { this.timeout(15000); var url = 'http://localhost:9000'; before(function (done) { global.dom = new Nightmare() .goto(url) .evaluate(function () { return 'test'; }) .then(function(result) { done(); }) .catch(function(error) { done(error); }); }); after(function (done) { coverage.loadCodeCoverage(dom, done); }); it('check hello world result', function (done) { dom.evaluate(function () { /*global hello */ return hello(); }) .then(function(value) { var expected = "world"; if (value === null) { false.should.equal(true); return done(); } value.should.equal(expected); return done(); }) .catch(function(error) { done(error); }); }); it('should get the index title', function (done) { var expected = 'My Website'; dom.title(function (title) { title.should.equal(expected); done(); }); }); }); 

如果一切正常,你应该得到的控制台信息和HTML代码覆盖面报告应生成文件夹覆盖/

 Running "report_coverage" task ------------------------------------|----------|----------|----------|----------|----------------| File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines | ------------------------------------|----------|----------|----------|----------|----------------| js/ | 100 | 100 | 100 | 100 | | hello.js | 100 | 100 | 100 | 100 | | ------------------------------------|----------|----------|----------|----------|----------------| All files | 100 | 100 | 100 | 100 | | ------------------------------------|----------|----------|----------|----------|----------------| 

我仍然存在的问题是,对于每个testing说明,我必须在beforeafter添加方法。 可能很高兴有这些实现只在一个地方,例如在Gruntconfiguration,我不需要记住他们当我正在做新的testing说明。

如果有人before方法中find更一般的解决scheme,将会非常感激。

我想提出另一种方法。 它基本上归结为

  1. 用伊斯坦布尔的应用程序代码
  2. 从浏览器获取覆盖率数据并将其传递给testing过程(这样我们可以提取它)
  3. 运行报告

这是一个代码片段,可以做到这一点

 nightmare .evaluate(() => window.__coverage__) // this executes in browser scope .end() // terminate the Electron (browser) process .then((cov) => { // this executes in Node scope // handle the data passed back to us from browser scope const strCoverage = JSON.stringify(cov); const hash = require('crypto').createHmac('sha256', '') .update(strCoverage) .digest('hex'); const fileName = `/tmp/coverage-${hash}.json`; require('fs').writeFileSync(fileName, strCoverage); done(); // the callback from the test }) .catch(err => console.log(err)); 

有关详细信息和实际提交的链接,请查看我的博客: http : //atodorov.org/blog/2017/08/12/code-coverage-from-nightmarejs-tests/