Frage

Ich versuche zu verstehen, wie man einen eigenständigen JavaScript-Code entwickelt. Ich möchte Javscript -Code mit Tests und Modulen schreiben, die aus der Befehlszeile ausgeführt werden. Also habe ich installiert node.js und npm zusammen mit den Bibliotheken requirejs, underscore, und mocha.

Meine Verzeichnisstruktur sieht so aus:

> tree .
.
├── node_modules
├── src
│   └── utils.js
└── test
    └── utils.js

wo src/utils.js ist ein kleines Modul, das ich schreibe, mit dem folgenden Code:

> 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();
        };
    }

});

und test/utils.js ist der Test:

> cat test/utils.js 
var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

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

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

});

was ich dann versuche, aus dem Verzeichnis der obersten Ebene zu rennen (also mocha sieht das test Verzeichnis):

> 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)
    ...

Also meine Fragen sind:

  • Ist dies der richtige Weg, um Code zu strukturieren?
  • Warum läuft mein Test nicht?
  • Was ist der beste Weg, um so etwas zu lernen? Es fällt mir schwer, mit Google gute Beispiele zu finden.

Vielen Dank...

Entschuldigung - momentan veröffentlichte Ergebnisse aus falschem Code; jetzt behoben

PS Ich benutze Anforderungenjs, weil ich diesen Code (oder etwas davon) später auch aus einem Browser ausführen möchte.

Update / Lösung

Etwas, das nicht in den folgenden Antworten steht, ist, dass ich verwenden musste mocha -u tdd Für den obigen Teststil. Hier ist der endgültige Test (der ebenfalls behaupten) und deren Verwendung erforderlich ist:

> 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)
War es hilfreich?

Lösung

Der Grund, warum Ihr Test nicht läuft src/utils.js ist keine gültige Node.js -Bibliothek.

Gemäß der Anforderungsdokumentation müssen Sie mit Node.js und den CommonJS Standard zusammenarbeiten, um Standard zu erfordern Fügen Sie ein bisschen Kesselplatte hinzu oben in deinem src/utils.js Datei, die Js fordern define Funktion ist geladen.

Da RequestJS jedoch so konzipiert war, dass er "klassisch" von Webbrowser-orientiertem Quellcode benötigt werden kann, verwenden ich das folgende Muster mit meinen Node.js-Bibliotheken, die ich auch im Browser ausführen möchte:

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

// Insert code here

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

Dies hat den Vorteil, dass keine zusätzliche Bibliothek für andere Node.js -Benutzer erforderlich ist, und funktioniert im Allgemeinen gut mit Anforderungen für den Client.

Sobald Sie Ihren Code in node.js ausgeführt haben, können Sie mit dem Testen beginnen. Ich persönlich bevorzuge Expresso gegenüber Mokka, obwohl es sich um den Nachfolge -Test -Framework handelt.

Andere Tipps

Die Mokka -Dokumentation fehlt, wie dieses Zeug eingerichtet werden kann, und es ist verwirrend, aufgrund all der Zaubertricks, die es unter der Motorhaube tut, herauszufinden.

Ich fand die Schlüssel zum Erhalten von Browserdateien mithilfe erfordern.js Um in Mokka unter dem Knoten zu arbeiten: Mokka hat die Dateien zu ihren Suiten mit hinzuzufügen addFile:

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

Und zweitens, verwenden Sie beforeEach Mit dem optionalen Rückruf, um Ihre Module asynchron zu laden:

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

Ich habe eine Bootstrap erstellt, um das alles zum Laufen zu bringen: https://github.com/clubajax/mocha-bootstrap

Sie versuchen, JS -Module auszuführen, die für Browser (AMD) entwickelt wurden, aber im Backend funktioniert es möglicherweise nicht (da Module die CommonJS -Weise geladen werden). Aus diesem Grund werden Sie zwei Probleme haben:

  1. Define ist nicht definiert
  2. 0 Tests laufen

Im Browserdefine wird definiert. Es wird festgelegt, wenn Sie etwas mit Anforderungen benötigen. Aber NodeJS lädt moduliert den CommonJS -Weg. define In diesem Fall ist nicht definiert. Aber es wird definiert, wenn wir mit Anforderungen benötigt werden!

Dies bedeutet, dass wir jetzt asynchron Code benötigen und das zweite Problem, ein Problem mit der asynchronisierten Ausführung.https://github.com/mochajs/mocha/issues/362

Hier ist ein vollständiges Beispiel. Schauen Sie, dass ich Anforderungen (AMD) konfigurieren musste, um die Module zu laden. Wir verwenden keine Anforderungen (Knoten/CommonJs), um unsere Module zu laden.

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

})

Und für das Modul, das Sie testen möchten:

> 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();
})

Nur für den Fall Davids Antwort war nicht klar genug, ich musste nur dazu hinzufügen:

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

Oben in der JS -Datei, in der ich verwende define, wie in forderjs docs beschrieben ("Knotenmodule mit AMD oder fordertjs" bauen ") und im selben Ordner fügen Sie das hinzu amdefine Paket:

npm install amdefine

Dies schafft das node_modules Ordner mit dem amdefine Modul im Inneren.

Ich benutze nicht requirejs Ich bin mir also nicht sicher, wie diese Syntax aussieht, aber so tue ich, um Code beides auszuführen node und die browser:

Stellen Sie für Importe fest, ob wir im Knoten oder im Browser ausgeführt werden:

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

Dann können wir alle Abhängigkeiten korrekt abrufen (sie werden entweder bereits im Browser verfügbar sein oder wir verwenden require):

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

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

Und dann jede Funktionalität, die von anderen Dateien verwendet werden muss, exportieren wir sie in Root:

root.bar = Bar;

Wie für Beispiele, GitHub ist eine großartige Quelle. Gehen Sie einfach den Code für Ihre Lieblingsbibliothek an, um zu sehen, wie sie es gemacht haben :) Ich habe verwendet mocha So testen Sie eine JavaScript -Bibliothek, die sowohl im Browser als auch im Knoten verwendet werden kann. Der Code ist bei verfügbar https://github.com/bunkat/later.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top