KarmaJS、Jasmine、RequireJS 等:如何使用 Require 测试模块 [英] KarmaJS, Jasmine, RequireJS, etc: How to Use Require for Testing Modules

查看:19
本文介绍了KarmaJS、Jasmine、RequireJS 等:如何使用 Require 测试模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我有一个练习项目来熟悉 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 404s 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 404s 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' 时,我可以很好地运行 test-test-file.js, 'test/spec/test-test-file.js' ] -- 但是,如果我将测试包装在 RequireJS 定义调用中,我会得到不匹配的匿名定义()"em>"上面提到的错误.

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 to test/test-main.js,
  • renamed test-test-file.js to testFileSpec.js -- moved it from test/spec to test/,

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 default autoWatch default value to true).
  • 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.

来自 karma/config/files 文档

注意:注意在数组中添加文件/模式的顺序.很重要!为了进一步了解,请在您的业力配置中设置 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆