2013-06-24 10 views
16

Pracuję nad aplikacją kątową napisaną w składni CommonJS i używam zadania pomrukowego z zadaniem grunt-contrib-requirejs do przetłumaczenia plików źródłowych na format AMD i kompilacji do jednego pliku wyjściowego. Moim celem jest, aby Karma pracowała z RequireJS i zachowała moje pliki źródłowe i pliki spec w składni CommonJS.Testowanie z karmą i RequireJS z plikami w składni CommonJS

byłem w stanie uzyskać prostego testu przechodzącą w formacie AMD o następującej strukturze pliku:

-- karma-test 
    |-- spec 
    | `-- exampleSpec.js 
    |-- src 
    | `-- example.js 
    |-- karma.conf.js 
    `-- test-main.js 

oraz następujące pliki:

karma.conf.js

// base path, that will be used to resolve files and exclude 
basePath = ''; 

// list of files/patterns to load in the browser 
files = [ 
    JASMINE, 
    JASMINE_ADAPTER, 
    REQUIRE, 
    REQUIRE_ADAPTER, 
    'test-main.js', 
    {pattern: 'src/*.js', included: false}, 
    {pattern: 'spec/*.js', included: false} 
]; 

// list of files to exclude 
exclude = []; 

// test results reporter to use 
// possible values: 'dots', 'progress', 'junit' 
reporters = ['progress']; 

// web server port 
port = 9876; 

// cli runner port 
runnerPort = 9100; 

// enable/disable colors in the output (reporters and logs) 
colors = true; 

// level of logging 
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 
logLevel = LOG_DEBUG; 

// enable/disable watching file and executing tests whenever any file changes 
autoWatch = true; 

// Start these browsers, currently available: 
browsers = ['Chrome']; 

// If browser does not capture in given timeout [ms], kill it 
captureTimeout = 60000; 

// Continuous Integration mode 
// if true, it capture browsers, run tests and exit 
singleRun = false; 

przykład.js

define('example', function() { 
    var message = "Hello!"; 

    return { 
     message: message 
    }; 
}); 

exampleSpec.js

define(['example'], function(example) { 
    describe("Example", function() { 
     it("should have a message equal to 'Hello!'", function() { 
      expect(example.message).toBe('Hello!'); 
     }); 
    }); 
}); 

test-main.js

var tests = Object.keys(window.__karma__.files).filter(function (file) { 
     return /Spec\.js$/.test(file); 
}); 

requirejs.config({ 
    // Karma serves files from '/base' 
    baseUrl: '/base/src', 

    // Translate CommonJS to AMD 
    cjsTranslate: true, 

    // ask Require.js to load these files (all our tests) 
    deps: tests, 

    // start test run, once Require.js is done 
    callback: window.__karma__.start 
}); 

Jednak moim celem jest napisanie zarówno plik źródłowy i plik spec w Składnia CommonJS z takimi samymi wynikami, jak:

example.js

var message = "Hello!"; 

module.exports = { 
    message: message 
}; 

exampleSpec.js

var example = require('example'); 

describe("Example", function() { 
    it("should have a message equal to 'Hello!'", function() { 
     expect(example.message).toBe('Hello!'); 
    }); 
}); 

Ale mimo flagę cjsTranslate ustawiony true, właśnie ten błąd:

Uncaught Error: Module name "example" has not been loaded yet for context: _. Use require([]) 
http://requirejs.org/docs/errors.html#notloaded 
at http://localhost:9876/adapter/lib/require.js?1371450058000:1746 

Jakieś pomysły na to, jak można to osiągnąć?


Edit: Znalazłem ten problem dla repo karma runner: https://github.com/karma-runner/karma/issues/552 i tam kilka uwag, które mogą pomóc z tym problemem, ale nie miałem szczęścia z nich do tej pory.

Odpowiedz

11

Rozwiązanie, które znalazłem, wymagało użycia grunt i napisania pewnych niestandardowych zadań zadawania. Proces przebiega w następujący sposób:

Utwórz zadanie pomruku, aby utworzyć plik requirejs bootstrap, znajdując wszystkie specyfikacje, używając wzorca pliku, przechodząc przez nie i budując tradycyjny styl AMD, wymagaj bloku i twórz tymczasowy plik z kodem takim jak ten :

require(['spec/example1_spec.js' 
,'spec/example2_spec.js', 
,'spec/example3_spec.js' 
],function(a1,a2){ 
// this space intentionally left blank 
}, "", true); 

Tworzenie RequireJS grunt zadanie, które kompiluje powyższy plik bootstrap i wyjścia jednego pliku js, który będzie faktycznie obejmowała wszystkie kody źródłowe, specyfikacje i bibliotek.

requirejs: { 
     tests: { 
      options: { 
       baseUrl: './test', 
       paths: {}, // paths object for libraries 
       shim: {}, // shim object for non-AMD libraries 
       // I pulled in almond using npm 
       name: '../node_modules/almond/almond.min', 
       // This is the file we created above 
       include: 'tmp/require-tests', 
       // This is the output file that we will serve to karma 
       out: 'test/tmp/tests.js', 
       optimize: 'none', 
       // This translates commonjs syntax to AMD require blocks 
       cjsTranslate: true 
      } 
     } 
    } 

Utwórz zadanie grunt że ręcznie uruchamia serwer karmy i służyć pojedynczy plik skompilowany js że teraz mamy do testów.

Dodatkowo udało mi się rów REQUIRE_ADAPTER w pliku karma.conf.js a następnie tylko zawierać pojedynczy plik skompilowany js zamiast wzorców, które dopasowane cały kod źródłowy i specyfikacje, więc wygląda to teraz:

// base path, that will be used to resolve files and exclude 
basePath = ''; 

// list of files/patterns to load in the browser 
files = [ 
    JASMINE, 
    JASMINE_ADAPTER, 
    REQUIRE, 
    'tmp/tests.js' 
]; 

// list of files to exclude 
exclude = []; 

// test results reporter to use 
// possible values: 'dots', 'progress', 'junit' 
reporters = ['progress']; 

// web server port 
port = 9876; 

// cli runner port 
runnerPort = 9100; 

// enable/disable colors in the output (reporters and logs) 
colors = true; 

// level of logging 
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 
logLevel = LOG_INFO; 

// enable/disable watching file and executing tests whenever any file changes 
autoWatch = true; 

// Start these browsers, currently available: 
browsers = ['PhantomJS']; 

// If browser does not capture in given timeout [ms], kill it 
captureTimeout = 60000; 

// Continuous Integration mode 
// if true, it capture browsers, run tests and exit 
singleRun = true; 

W konfiguracji zadania pomrukowego dla kompilacji requirejs konieczne było również użycie almond w celu rozpoczęcia wykonywania testu (wykonanie testu zawiesiłoby się bez niego). Możesz to zobaczyć w powyższej konfiguracji zadania wymuszenia.

1

Jest kilka rzeczy. Po pierwsze: mogłem pominąć pewne szczegóły w twoim pytaniu (ponieważ jest ono bardzo duże) - bardzo mi przykro z tego powodu.

W skrócie, można do kasy Backbone-boilerplate wip testową gałąź organizacji: https://github.com/backbone-boilerplate/backbone-boilerplate/tree/wip

Pierwsze: RequireJS nie obsługuje nieopakowanych surowego moduł common.js. cjsTranslate to narzędzie R.js (narzędzie do kompilacji) umożliwiające konwertowanie plików CommonJD na AMD podczas kompilacji. W związku z tym wymaganie modułu surowego CJS nie będzie działać.Aby rozwiązać ten problem, możesz użyć serwera do filtrowania wysłanych skryptów i skompilowania ich do formatu AMD. Na BBB, mijamy plik przez statyczny służyć kompilować je:

drugie: Karma requirejs plugin nie działa super dobrze - i jest to jakoś łatwe w użyciu requireJS bezpośrednio. Na BBB udało nam się to: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/test/jasmine/test-runner.js#L16-L36

Mam nadzieję, że to pomoże!

+0

Łącze BBB nie działa, link do zatwierdzenia dla tego samego pliku o zmienionej nazwie: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/eb172e0ac9accb16d1d46e288052be0bded052bb/test/runner.js – MrYellow

Powiązane problemy