12

PegJS と requirejs を使用してプロジェクトをテストしようとしています。AMDモジュール(定義)として実装されたソースファイルがいくつかあり、require APIを介してロードされます。ディレクトリ構造の下:

js/
   somefile.js
   main.js
   parser.js
test/
   parser.spec.js

PegJS 文法ファイルをロードし、PegJS を使用してペグ パーサーを作成するためのparser.jsモジュールを作成しました。

define(function() {
  'use strict';

  var PEG = require('pegjs');
  var grammarFile = 'grammar.peg'

return {
  parse: function(fs, content, debug) {
    var grammar = fs.readFileSync(grammarFile, 'utf8').toString();
    // Build parser from grammar
    var parser = PEG.buildParser(grammar, { trace: debug });
    [...]

これは、ノードを使用してコマンドラインで実行される main.js で正常に機能します。ここで、カルマ、ジャスミン、PhantomJS を使用してプロジェクトをテストしたいと考えています。次のようなkarma.conf.jsがあります。

frameworks: ['jasmine', 'requirejs'],
files: [
  { pattern: './test/**/*.spec.js', included: false },
  { pattern: './js/**/*.js', included: false},
  './test/test-main.js',
],

また、次のように構成されたtest-main.jsという名前のブートストラップ ファイルが必要です。

'use strict';

var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;

// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
  console.log(file);
  if (TEST_REGEXP.test(file)) {
    // Normalize paths to RequireJS module names.
    // If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
    // then do not normalize the paths
    var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
    allTestFiles.push(file);
  }
});

require.config({
  // Karma serves files under /base, which is the basePath from your config file
  baseUrl: '/base/js',
  // dynamically load all test files
  deps: allTestFiles,
  // we have to kickoff jasmine, as it is asynchronous
  callback: window.__karma__.start
});

ここで、テスト ( grunt karma) を起動すると、次のエラーが発生しました。

PhantomJS 1.9.8 (Linux 0.0.0) ERROR: Error{message: 'Module name "pegjs" has not been loaded yet for context: _. Use require([])

そこで、Karma によってロードされたファイルに pegjs をこのようにkarma.conf.jsとして含めようとしました。

files: [
  { pattern: 'node_modules/pegjs/lib/**/*.js', included: true  },
  { pattern: './test/**/*.spec.js', included: false },
  { pattern: './js/**/*.js', included: false},
  './test/test-main.js'
],

これを行うと、まだエラーが発生します。

Error: Module name "utils/arrays" has not been loaded yet for context: _. Use require([])

pegjs モジュールの中を見ると、確かに arrays.js ファイルがあります。

compiler/
compiler.js
grammar-error.js
parser.js
peg.js
utils/
  arrays.js
  classes.js
  objects.js

したがって、配列も含めようとしています:

files: [
  { pattern: 'node_modules/pegjs/lib/utils/arrays.js', included: true },
  { pattern: 'node_modules/pegjs/lib/**/*.js', included: true  },
  { pattern: './test/**/*.spec.js', included: false },
  { pattern: './js/**/*.js', included: false},
  './test/test-main.js'
],

私は得る:

ReferenceError: Can't find variable: module
at /blabla/node_modules/pegjs/lib/utils/arrays.js:108

なぜなら:

108 module.exports = arrays;

そこで、npm モジュールをロードする代わりに、bower モジュールを次のようにロードしようとしました。

files: [
  { pattern: 'bower_components/pegjs/peg-0.9.0.js', included: true },
  { pattern: './test/**/*.spec.js', included: false },
  { pattern: './js/**/*.js', included: false},
  './test/test-main.js'
],

そして、ここに再び行きます:

PhantomJS 1.9.8 (Linux 0.0.0) ERROR: Error{message: 'Module name "pegjs" has not been loaded yet for context: _. Use require([])

また、karma で生成された Web ページに pegjs を含めないようにしました。

files: [
  { pattern: 'bower_components/pegjs/peg-0.9.0.js', included: false },
  { pattern: './test/**/*.spec.js', included: false },
  { pattern: './js/**/*.js', included: false},
  './test/test-main.js'
],

しかし、それは失敗します:

PhantomJS 1.9.8 (Linux 0.0.0) ERROR: 'There is no timestamp for /base/bower_components/pegjs/peg-0.9.0!'

bower_component フォルダーを js フォルダー内に配置しようとしましたが、うまくいきませんでした。

だから、ここから行くべきかどうかはわかりません... Googleまたはここで関連するものが見つかりませんでした。カルマでrequirejs / pegjsを使用するのは特定の問題のようです...どんなアイデアでも大歓迎です。

次のダンの答えを更新してください:

そこで、 parser.jsで同期の require から非同期の require に切り替えます。

define(['../bower_components/pegjs/peg-0.9.0'], function(PEG) {
  'use strict';

  var grammarFile = 'grammar.peg'

return {
  parse: function(fs, content, debug) {
    var grammar = fs.readFileSync(grammarFile, 'utf8').toString();
    // Build parser from grammar
    var parser = PEG.buildParser(grammar, { trace: debug });
    [...]

karma.conf.js にpegjs bower コンポーネントを含めようとしました:

{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: false },

または含まない:

{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: true },

ただし、常に同じエラーが発生します。

Error: Script error for "/blabla/bower_components/pegjs/peg-0.9.0", needed by: /blabla/js/parser.js
http://requirejs.org/docs/errors.html#scripterror
at /blabla/node_modules/requirejs/require.js:140

はい、ファイルが存在します:

$ file /home/aa024149/share/logofrjs/bower_components/pegjs/peg-0.9.0.js 
/blabla/bower_components/pegjs/peg-0.9.0.js: ASCII text, with very long lines

UPDATE2 : 最終的に理解し、許容できる解決策を見つけました。

4

3 に答える 3

1

私の知る限り、Karma はブラウザーでテストを実行するテスト フレームワークです。

これは、多数のノード モジュールのテストには適していません。

ブラウザには、これを同期的に行う機能がありません: var PEG = require('pegjs'). require([])これが、pegjs の読み込みが終了したときに実行されるコールバックを渡すものを使用するように求めている理由です。

pegjs の bower バージョンを使用し、それrequire('pegjs')が呼び出される前に読み込まれることを確認すると、ここで役立つ場合があります。これにより、pegjs がコンテキスト _ (デフォルトの requirejs コンテキストだと思います) に対して既に読み込まれていることが保証されます。

また、ファイル システムからファイルをロードすることもできないfs.readFileSync(grammarFile, 'utf8')ため、別の方法でロードする必要があります。peg 文法を files 配列に配置してから、 requirejs テキスト プラグインを使用してロードすることで、Karma に peg 文法をホストするように依頼できます。

テストしているモジュールが、ブラウザではなく node.js で実行することを目的としている場合は、コードをブラウザで実行するのではなくノードで実行するテスト フレームワークを使用する方が適している可能性があります。ノードモジュールを利用できます。これをブラウザーに向けている場合は、より具体的にブラウザーを対象とするように書き直します。

于 2015-12-01T10:17:12.373 に答える