2012-02-16 6 views
35

スタンドアロンのJavascriptコードを開発する方法を理解しようとしています。コマンドラインから実行しているテストやモジュールでJavscriptコードを記述したいと思います。そこで、node.jsnpmをライブラリrequirejs,underscore、およびmochaと一緒にインストールしました。RequireJSでMochaテストを実行しているときに「定義されていません」と表示されるのはなぜですか?

私のディレクトリ構造は次のようになります。

src/utils.jsは、私は次のコードを使用して、書いています少しモジュールである
> tree . 
. 
├── node_modules 
├── src 
│   └── utils.js 
└── test 
    └── utils.js 

> cat src/utils.js 
define(['underscore'], function() { 

    "use strict"; 

    if ('function' !== typeof Object.beget) { 
     Object.beget = function (o) { 
      var f = function() { 
      }; 
      f.prototype = o; 
      return new f(); 
     }; 
    } 

}); 

test/utils.jsはテストです

私はトップレベルのディレクトリから実行しようとします(そうmochatestディレクトリを見て):

> mocha 

node.js:201 
     throw e; // process.nextTick error, or 'error' event on first tick 
      ^
Error: Calling node's require("../src/utils") failed with error: ReferenceError: define is not defined 
    at /.../node_modules/requirejs/bin/r.js:2276:27 
    at Function.execCb (/.../node_modules/requirejs/bin/r.js:1872:25) 
    at execManager (/.../node_modules/requirejs/bin/r.js:541:31) 
    ... 

は、だから私の質問は以下のとおりです。

  • これはコードを構造化するための正しい方法は何ですか?
  • テストが実行されないのはなぜですか?
  • この種のことを学ぶ最も良い方法は何ですか?私はGoogleで良い例を見つけるのに苦労しています。

おかげで...

[申し訳ありません - 一時的に間違ったコードからの結果を掲載。今すぐ固定]

PS私はrequirejsを使用しています。私はこのコード(またはその一部)をブラウザから実行したいからです。

更新/ソリューション

以下の回答ではない何かが、私は上記の試験スタイルにmocha -u tddを使用するために必要なことです。ここでは、最終的な(もアサートが必要です)テストおよびその使用である:私はrequirejsを使用していない

> cat test/utils.js 

var requirejs = require('requirejs'); 
requirejs.config({nodeRequire: require}); 

requirejs(['../src/utils', 'assert'], function(utils, assert) { 

    suite('utils', function() { 
     test('should always work', function() { 
      assert.equal(1, 1); 
     }) 
    }) 

}); 
> mocha -u tdd 

    . 

    ✔ 1 tests complete (1ms) 
+0

amdefineモジュールをインストールして、これらの行を追加する必要があります。if(typeof define!= 'function')<< = into (テストファイルではなく)動作させるために私の 'class'ファイル。これはテスト後にこれを削除するタスクがある必要があるので、迷惑なのです – devric

答えて

15

src/utils.jsが有効なNode.jsライブラリではないため、テストが実行されていない理由があります。 Node.jsのとCommonJSと共存するためにRequireJSのドキュメントによると

は、標準を必要とRequireJSのdefine機能がロードされているので、あなたのsrc/utils.jsファイルの先頭にadd a bit of boilerplateする必要があります。

RequireJSが「クラシック」のウェブブラウザ指向のソースコードを必要とすることができるように設計されましたので、私はまた、ブラウザで実行したい私のNode.jsライブラリと次のパターンを使用する傾向がある:

if(typeof require != 'undefined') { 
    // Require server-side-specific modules 
} 

// Insert code here 

if(typeof module != 'undefined') { 
    module.exports = whateverImExporting; 
} 

これは、他のNode.jsユーザーに余分なライブラリを必要としないという利点があり、クライアント上のRequireJSでよく機能します。

コードがNode.jsで実行されると、テストを開始できます。私は個人的には、たとえその後継のテストフレームワークであっても、モカよりもエキスポを好む。

+1

ありがとう!ボイラープレートで私のテストは失敗しているので、「スイート」(mochaから)を取得するために何をする必要があるかを知っているとは思いませんか?また、 "define"はブラウザコードでは機能しないと言っていますか?私は上記の代わりのアプローチのあなたの動機を理解していない - それはスタイルの "ちょっと"の質問ですか? –

+0

ああ、私はあなたのポイントを参照してください - あなたは、Webブラウザのためのノードのものを定義したくありません。 –

+0

あまりにも難しくない、あなたは '' require( 'mocha') ''定型句がありません。 [馬の口から真っ直ぐ撮った](https://github.com/visionmedia/mocha/blob/master/test/suite.js)が答えです。 (私はStackOverflowを初めて使ったので、コメントに複数行のソースコードを入れることができなかったことは分かりませんでした) –

-1

ので、私はその構文がどのように見えるかわからないんだけど、これは私が両方のコードを実行するために何をすべきかです輸入

、我々はノードまたはブラウザ内で実行されているかどうか::nodebrowser

var root = typeof exports !== "undefined" && exports !== null ? exports : window; 

その後、我々が正しく依存関係をつかむことができ、ブラウザでの場合や、(彼らはすでに利用可能になりますかを使用しています):

var foo = root.foo; 
if (!foo && (typeof require !== 'undefined')) { 
    foo = require('./foo'); 
} 

var Bar = function() { 
    // do something with foo 
} 

そして、必要なすべての機能は、他のファイルで使用するには、我々はルートにエクスポート:

root.bar = Bar; 

例については、GitHubは素晴らしい源です。あなたが好きなライブラリのコードを見て、彼らがどのようにしたかを見てください:)私はmochaを使って、ブラウザとノードの両方で使用できるjavascriptライブラリをテストしました。コードはhttps://github.com/bunkat/laterにあります。

4

このような設定をする方法については、Mochaのマニュアルには欠けています。そのためには、徹底したマジックの練習が必要です。

私はノードの下モカで動作するようにrequire.jsを使用して、ブラウザのファイルを取得するキーを見つけました:モカファイルがaddFileとそのスイートに追加したためにがあります

mocha.addFile('lib/tests/Main_spec_node'); 

そして第二に、非同期あなたのモジュールをロードするために、オプションのコールバックでbeforeEachを使用します。

describe('Testing "Other"', function(done){ 
    var Other; 
    beforeEach(function(done){ 
     requirejs(['lib/Other'], function(_File){ 
      Other = _File; 
      done(); // #1 Other Suite will run after this is called 
     }); 
    }); 

    describe('#1 Other Suite:', function(){ 
     it('Other.test', function(){ 
      chai.expect(Other.test).to.equal(true); 
     }); 
    }); 
}); 

私はこれを取得する方法のためのブートストラップを作成すべて動作中:https://github.com/clubajax/mocha-bootstrap

+0

beforeEachでの依存関係ロードの解決のための+1 – bennidi

1

ブラウザ用に設計されたJSモジュールを実行しようとしていますが、バックエンドではモジュールがcommonjs形式でロードされるため、動作しない可能性があります。このため、次の2つの問題に直面するだろう:

  1. を定義が定義されていない
  2. 0テストはdefineが定義されますブラウザで

を実行します。 requirejsで何かが必要なときに設定されます。しかし、nodejsはモジュールをcommonjsの方法でロードします。この場合のdefineは定義されていません。しかしrequirejsで必要なときに定義されます!

これはコードが非同期的に要求されていることを意味し、2番目の問題、つまり非同期実行の問題を引き起こします。 https://github.com/mochajs/mocha/issues/362

完全な使用例です。 モジュールをロードするためにrequirejs(amd)を設定しなければならないことを確認します。モジュールをロードするためにrequire(node/commonjs)を使用していません。

> cat $PROJECT_HOME/test/test.js 

var requirejs = require('requirejs'); 
var path = require('path') 
var project_directory = path.resolve(__dirname, '..') 

requirejs.config({ 
    nodeRequire: require, 
    paths: { 
    'widget': project_directory + '/src/js/some/widget' 
    } 
}); 

describe("Mocha needs one test in order to wait on requirejs tests", function() { 
    it('should wait for other tests', function(){ 
    require('assert').ok(true); 
    }); 
}); 


requirejs(['widget/viewModel', 'assert'], function(model, assert){ 

    describe('MyViewModel', function() { 
    it("should be 4 when 2", function() { 
     assert.equal(model.square(2),4) 
    }) 
    }); 

}) 

し、テストするモジュールの先頭へ

if (typeof define !== 'function') { 
    var define = require('amdefine')(module); 
} 

> cat $PROJECT_HOME/src/js/some/widget/viewModel.js 

define(["knockout"], function (ko) { 

    function VideModel() { 
     var self = this; 

     self.square = function(n){ 
      return n*n; 
     } 

    } 

    return new VideModel(); 
}) 
0

David's answerには、私はちょうどこれを追加するために必要な、十分に明確ではありませんでしたRequirejSドキュメント("Building node modules with AMD or RequireJS")で説明されているように、defineを使用している同じjsファイルのamdefineパッケージを追加してください:

npm install amdefine 

これによりamdefineモジュールが内部にあるnode_modulesフォルダが作成されます。

関連する問題