2012-03-16 12 views
42

To pytanie dotyczy ramy testowania aplikacji Mocha dla NodeJS.Jak mogę wykonać asynchroniczne testy Mocha (NodeJS) w kolejności?

Domyślne zachowanie wydaje się, aby rozpocząć wszystkie testy, a następnie przetwarzać callbacków async wejdą one w.

Podczas uruchamiania testów async, chciałbym uruchomić każdy test po część asynchroniczny z jeden wcześniej został wywołany.

Jak mogę to zrobić?

Odpowiedz

30

Nie chodzi o to, że "ustrukturyzowany kod działa w porządku, w jakim go uporządkowałeś" (zadziwia!) - ale raczej, jak sugeruje @chrisdew, zamówienia powrotne dla testów asynchronicznych nie mogą być zagwarantowane. Aby ponownie rozwiązać problem - testy, które znajdują się w dalszej części łańcucha (wykonanie synchroniczne), nie mogą zagwarantować, że wymagane warunki, ustawione przez testy asynchroniczne, będą gotowe do zakończenia ich działania (synchroniczne wykonanie).

Tak więc, jeśli wymagane są określone warunki w pierwszych testach (jak token logowania lub podobne), należy użyć haków, takich jak before(), które testują te warunki przed kontynuowaniem.

zawinąć testy zależne w bloku i uruchomić asynchronicznejbefore hak na nich (zawiadomienie „zrobić” w przed blokiem):

var someCondition = false 

// ... your Async tests setting conditions go up here... 

describe('is dependent on someCondition', function(){ 

    // Polls `someCondition` every 1s 
    var check = function(done) { 
    if (someCondition) done(); 
    else setTimeout(function(){ check(done) }, 1000); 
    } 

    before(function(done){ 
    check(done); 
    }); 

    it('should get here ONLY once someCondition is true', function(){ 
    // Only gets here once `someCondition` is satisfied 
    }); 

}) 
+0

W jaki sposób "someCondition' kiedykolwiek się zmienił, jeśli wcześniej callback jest zablokowany w pętli while ?! Tak nie działa JavaScript. – natevw

+0

Odpowiedź na twoje pytanie znajduje się w wierszu komentarza 3: "twoje ustawienia testów Async idą tutaj". Konkretnie: Asynchronizacja, warunki ustawień, z zakresu poza 'opisem()', które tworzą instancję przed 'before()'. Twoje ostatnie stwierdzenie o tym, że JavaScript nie działa w ten sposób, jest fałszywe. – papercowboy

+0

Podczas gdy twój kod utknął wielokrotnie sprawdzając! Kilka warunkow wielokrotnie, żaden inny twój kod nie może działać. (Wszystkie inne wywołania zwrotne związane ze zdarzeniami/zegarami będą uniemożliwione). Jedyny sposób, w jaki to zadziała, to sytuacja, w której jakiś parametr jest ustawiony na true przed rozpoczęciem pętli - w przeciwnym razie zawiesi się. Spróbuj. – natevw

7

Jestem zaskoczony tym, co napisałeś, kiedy używam. Używam mocha z testami w stylu bdd (opisz/it) i po prostu dodałem kilka testów console.logs do moich testów, aby sprawdzić, czy twoje roszczenia są w moim przypadku, ale na pozór nie.

Oto fragment kodu, którego użyłem, aby zobaczyć kolejność "end1" i "start1". Zostały właściwie zamówione.

describe('Characters start a work', function(){ 
    before(function(){ 
     sinon.stub(statusapp, 'create_message'); 
    }); 
    after(function(){ 
     statusapp.create_message.restore(); 
    }); 
    it('creates the events and sends out a message', function(done){ 
     draftwork.start_job(function(err, work){ 
     statusapp.create_message.callCount.should.equal(1); 
     draftwork.get('events').length.should.equal(
      statusapp.module('jobs').Jobs.get(draftwork.get('job_id')).get('nbr_events') 
     ); 
     console.log('end1'); 
     done(); 
     }); 
    }); 
    it('triggers work:start event', function(done){ 
     console.log('start2'); 
     statusapp.app.bind('work:start', function(work){ 
     work.id.should.equal(draftwork.id); 
     statusapp.app.off('work:start'); 
     done(); 
     }); 

Oczywiście, to mogło się zdarzyć przez przypadek też, ale mam mnóstwo testów, a jeśli będą one działać równolegle, na pewno będę mieć warunki rasa, że ​​nie mam.

Proszę również zapoznać się z this issue z trackera problemów mokki. Zgodnie z nim testy są przeprowadzane synchronicznie.

+0

To pokazuje tylko, że zamówiony kod jest uruchamiany w kolejności. To się nie dzieje przez przypadek. Tak to działa". – papercowboy

+0

Pokazuje to, że uporządkowane testy asynchroniczne są uruchamiane w kolejności: 'end1' będzie zawsze występował przed' start2'. Aby uprościć przykład, możesz zamienić zawartość pierwszego testu na "setTimeout (done, 1000)".A jeśli zastąpisz 'before' hook async, zawsze będzie on działał przed pierwszym testem. Jak rozumiem, jest to właśnie zachowanie, które interesowało rozrusznika tematu, a to zachowanie jest domyślne i jedyne, przynajmniej do tej pory. – skozin

5

Chciałem rozwiązać ten sam problem z naszej aplikacji , ale accepted answer nie działało dobrze dla nas. Zwłaszcza w someCondition nigdy nie będzie prawdą.

Korzystamy z obietnic w naszej aplikacji, dzięki czemu bardzo łatwo jest odpowiednio ustrukturyzować testy. Jednak kluczem jest jeszcze opóźnić wykonanie przez haku before:

var assert = require("assert"); 

describe("Application", function() { 
    var application = require(__dirname + "/../app.js"); 
    var bootPromise = application.boot(); 

    describe("#boot()", function() { 
    it("should start without errors", function() { 
     return bootPromise; 
    }); 
    }); 

    describe("#shutdown()", function() { 
    before(function() { 
     return bootPromise; 
    }); 

    it("should be able to shut down cleanly", function() { 
     return application.shutdown(); 
    }); 
    }); 
}); 
+3

Chciałbym umieścić drugi i trzeci wiersz kodu ('application = ...' i 'bootPromise = ...') wewnątrz asynchronicznego bloku 'before' w pakiecie najwyższego poziomu (" Application "). W przeciwnym razie każdy wyjątek wyrzucony z tego kodu nie zostanie poprawnie zarejestrowany i zgłoszony, a co gorsza, uniemożliwi wykonanie wszystkich pozostałych testów. – skozin

4

użycie mocha-steps

utrzymuje testy sekwencyjne niezależnie od tego czy są one asynchroniczny lub nie (to znaczy twoje funkcje done nadal działają dokładnie tak jak oni). Jest to bezpośredni zamiennik dla it i zamiast tego używasz step

+0

dlaczego to było głosowanie? –

+1

@JackMurphy dobre pytanie. – WiR3D

+0

To samo. Miałem ten sam problem i to mi pomogło. – hrishioa

Powiązane problemy