KarmaJS,Jasmine,RequireJS等:如何使用需要测试模块

Cod*_*ody 20 unit-testing requirejs jasmine karma-runner karma-jasmine

使用RequireJS运行Karma + Jasmine测试 - 开始

救命!..._ _ _...SOS!

目前,我有一个练习项目,以满足KarmaJS和单元测试的需求.广泛的问题是,我真的没有透视Karma在幕后所做的事情,而且我似乎无法在相关领域找到足够的文件.没有进一步延迟......

这是我的文件夹结构:

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!!!
Run Code Online (Sandbox Code Playgroud)

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
  });
};
Run Code Online (Sandbox Code Playgroud)

测试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
});
Run Code Online (Sandbox Code Playgroud)

测试 - 测试 - file.js

console.log('....................');

define(function(){
    //console.log('testing test-file', testFile);

    describe('Testing testing', function(){
        it('should work', function(){
            expect(true).toEqual(true);
        });
    });

});
Run Code Online (Sandbox Code Playgroud)

测试file.js

define('testFile', [], function(){

    return function init(sandbox){
        var app, application = app = sandbox.app
          , globals = sandbox.globals;

        return {
            some: 'module'
        };
    };

});
Run Code Online (Sandbox Code Playgroud)

问题与描述

我希望听到答案的关键点是

  • 什么{pattern:'...',include:true | false }呢?
  • 排除凉亭目录中所有额外内容的最佳方法.
  • 我需要在test-main.js文件中包含哪些文件?
  • 我需要在karma.conf.js文件中包含哪些文件?
  • test-main.js实际上做了什么; 这是为了什么?

的时候,我收到错误及问题,只要我换我的规格在为define(...)呼叫-事件,当我给一个模块ID - define('someId', function(){ ... })- 我需要返回的东西出这个模块,因为它是一个define电话吗?

其他时候,我收到了"醇错误:'没有时间戳/base/src/app.js’!."时间戳,当然!我真傻......" - 这对世界来说意味着什么?!有时我会得到臭名昭着的" 0错误执行0 " - 我也可以在这里使用一些清晰度.真的,我得到了大量的错误:'...没有时间戳...'错误 - 甚至404看起来我应该用karma.conf.js files配置拉那个库时......

它甚至似乎通常当我明确告诉业力排除src/app.js我仍然得到404s和错误.

TL;博士

显然,我对Karma和*DD有点困惑的新手......

test-test-file.js当我的karma.conf.js files数组看起来像时,我可以正常运行[ 'test-main.js', 'test/spec/test-test-file.js' ]- 但是,如果我将我的测试包装在RequireJS定义调用中,我会得到上面提到的" Mismatching anonymous define() "错误.

似乎当我添加{pattern:'...',include:false }时, karma就不会为给定的模式添加任何文件(???).

如果有人甚至可以简单地指导我如何将RequireJS与Karma一起使用 - 也就是说我可以将我的测试包装在一个define/require调用中并拉入我要测试的模块......我将不胜感激.

由于有些难以将这些类型的问题保持简短并仍然提供足够的信息,我希望我没有做太长时间.


编辑

在阅读了glepretre的答案和我自己的一些小提琴后,我重新配置了我的项目如下:

  • 搬到test-main.jstest/test-main.js,
  • test-test- file.js重命名为testFileSpec.js - 将其test/spec移至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'

],
....
Run Code Online (Sandbox Code Playgroud)

测试/测试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
});
Run Code Online (Sandbox Code Playgroud)

我现在正在成功运行单元测试!特别感谢glepretre和所有其他贡献者.


感谢您的任何见解:)

gle*_*tre 29

好的,我会尝试一次解决每个问题:

问题1

  • 什么{pattern:'...',包括:true | false }吗?

Karma的默认行为是:

  • 找到所有匹配的文件pattern(强制属性)
  • 观察它们的更改(watched选项),以便在编辑代码时重新启动单元测试以提供实时结果(只有保留默认autoWatch默认值才有效true).
  • 使用自己的网络服务器(served选项)为他们服务
  • 使用<script>(included选项)将它们包含在浏览器中

因此,在fileskarma配置的数组中,您可以通过仅添加字符串模式来使用默认行为:

files: [
  // this will match all your JS files 
  // in the src/ directory and subdirectories
  'src/**/*.js'
]
Run Code Online (Sandbox Code Playgroud)

或使用完整对象语法自定义每个选项:

files: [
  {pattern: 'src/**/*.js', watched: true, served: true, included: false}
]
Run Code Online (Sandbox Code Playgroud)

使用requireJS,您不希望它们被包含在内,因为它将与requireJS行为冲突!

包括在内.描述:文件是否应使用<script>标签包含在浏览器中?如果要手动加载,请使用false,例如.使用Require.js.

来自karma/config/files文档

注意:请注意在数组中添加文件/模式的顺序.这很重要!要了解更多信息,请logLevel: config.LOG_DEBUG在您的业力配置中进行设置.

问题2

  • 我需要在karma.conf.js文件中包含哪些文件?

至少所有必需的文件,以便您的组件正常运行以进行单元测试.

基本上,您define([])require()块中列出的所有文件.

问题3

  • 排除凉亭目录中所有额外内容的最佳方法.

你准备做什么?

根据我之前写的内容,您可以看到您可以有选择地添加测试中需要的文件.

我用来添加模式'/bower_components/**/*.js',甚至'/bower_components/**/*.html'当我的凉亭包使用模板时.如果你担心的话,我从未注意到任何重大的性能问题......由你来定义你需要的文件模式.

问题4和5

  • test-main.js实际上做了什么; 这是为了什么?

  • 我需要在test-main.js文件中包含哪些文件?

test-main.js文件的目的是在启动Karma之前查找并加载测试文件.它连接了Karma和requireJS之间的点

您必须选择一个约定来命名您的测试文件,然后定义TEST_REGEXP匹配所有它们.

"官方" 角度样式指南和应用程序结构的最佳实践建议使用后缀*_test.js.

编辑:您的正则表达式无法正常工作,因为它被定义为"spec.js" || "test.js"在最后捕获或您的规范文件名称以结尾"file.js";)请参阅http://regex101.com/r/bE9tV9/1

还有一件事

我希望我很清楚.您可以使用Angular + Require:angular-requirejs-ready查看我们的项目的入门应用程序结构.它已经与Karma和Protractor一起设置和测试.