web-dev-qa-db-ja.com

KarmaJS、Jasmine、RequireJSなど:モジュールのテストにRequireを使用する方法

RequireJSを使用したKarma + Jasmineテストの実行-地面から降りる

助けて! 。 。 。 _ __。 。 。 SOS!

現在、KarmaJSとユニットテスト全般に慣れるための演習プロジェクトがあります。広い問題は、カルマが舞台裏で何をしているのかについての透明な見方が本当になく、関連する分野で適切な文書を見つけることができないように思われることです。さらに遅れることなく...

これが私のフォルダ構造

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'
        };
    };

});

質問と説明

答えを聞きたいキーポイントは

  • {pattern: '...'、include:true | false}は何をしますか?
  • bowerディレクトリ内の余分なものをすべて除外するための最良の方法。
  • test-main.jsファイルにどのファイルを含める必要がありますか?
  • karma.conf.jsファイルにどのファイルを含める必要がありますか?
  • test-main.jsは実際に何をしますか。何のために?

エラーと問題が発生するのは、モジュールにIDを指定したときに仕様をdefine(...)call--イベントでラップするとすぐです--define('someId', function(){ ... })-define呼び出しなので、このモジュールから何かを返す必要がありますか?

また、 'olERROR:' /base/src/app.jsのタイムスタンプがありません! 'を受け取ることもあります。 「もちろん、タイムスタンプ!私はなんてばかげている...」-これはいったいどういう意味ですか?!時々私は悪名高い "Executed 0 of 0 ERROR"を取得します-ここでいくつかの明確さを使用することもできます。本当に、私はたくさんのエラーを受け取ります: '...タイムスタンプなし...'エラー-そしてそれが起こったときは404sseemskarma.conf.js files config ... ???を使用してそのライブラリをプルする必要があります

通常、カルマにexcludesrc/app.jsを明示的に指示すると、まだ404sとエラーが発生するようです。

tl; dr

明らかに、私はカルマと* DD全般について少し混乱した初心者です...

Karma.conf.js files配列がtest-test-file.jsのようになっている場合は、[ 'test-main.js', 'test/spec/test-test-file.js' ]を正常に実行できますが、それでも、テストをRequireJS定義呼び出しでラップすると、「上記のanonymous define() "エラーの不一致。

{pattern: '...'、include:false}を追加すると、カルマは追加されないようです。指定されたパターンのファイルを追加します(???)。

誰かがKarmaでRequireJSを使用する方法を簡単に指示できる場合、つまり、テストを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'

],
....

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と他のすべての貢献者に感謝します


洞察力をありがとう:)

20
Cody

OK、私は一度に各質問に対処しようとします:

質問1

  • {pattern: '...'、included:true | false}は何をしますか?

Karmaのデフォルトの動作は次のとおりです。

  • pattern(必須プロパティ)に一致するすべてのファイルを検索します
  • ユニットテストを再開してコードを編集しているときにライブ結果を提供するために、変更を監視します(watchedオプション)(デフォルトのautoWatchのデフォルト値をtrueのままにした場合にのみ機能します。
  • 独自のウェブサーバーを使用してそれらを提供します(servedオプション)
  • _<script>_(includedオプション)を使用してブラウザにそれらを含めます

したがって、カルマ構成のfiles配列では、文字列パターンのみを追加することでデフォルトの動作を使用できます。

_files: [
  // this will match all your JS files 
  // in the src/ directory and subdirectories
  'src/**/*.js'
]
_

または、完全なオブジェクト構文を使用して、各オプションをカスタマイズします。

_files: [
  {pattern: 'src/**/*.js', watched: true, served: true, included: false}
]
_

RequireJSを使用すると、requireJSの動作と競合するため、これらを含めたくありません。

含まれています。説明:ファイルは_<script>_タグを使用してブラウザに含める必要がありますか?それらを手動でロードする場合は、falseを使用します。 Require.jsを使用します。

から karma/config/files docs

注:配列にファイル/パターンを追加する順序に注意してください。重要です!詳細については、カルマ設定で_logLevel: config.LOG_DEBUG_を設定してください。

質問2

  • karma.conf.jsファイルにどのファイルを含める必要がありますか?

ユニットテスト用のコンポーネントが適切に機能するために必要な少なくともすべてのファイル。

基本的に、define([])およびrequire()ブロックにリストされているすべてのファイル。

質問3

  • bowerディレクトリ内の余分なものをすべて除外するための最良の方法。

あなたは正確に何をしようとしていますか?

以前に書いたことに基づいて、テストで必要になるファイルを選択的に追加できることがわかります。

Bowerパッケージがテンプレートを使用している場合は、パターン_'/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

もう1つ

私は十分に明確だったと思います。 Angular + Require: angular-requirejs-ready を使用して、プロジェクトのスターターアプリの構造を確認できます。これはすでにセットアップされており、Karmaと分度器。

28
glepretre