2012-10-30 7 views
6

Mam wiele testów, które są praktycznie takie same. W interesie DRY i możliwości skanowania chciałbym streścić testy w jedną funkcję, a następnie wywołać tę funkcję za pomocą kilku parametrów. Funkcja będzie wtedy wywoływać it i dodać specyfikację do pakietu.Czy można zdefiniować specyfikację Jasmine wewnątrz funkcji i nadal mieć przed nią zastosowanie do niej?

Wygląda na to, że działa, z wyjątkiem tego, że specyfikacje nie są uruchamiane w taki sam sposób, jak inne specyfikacje, a nazwa beforeEach nie jest wywoływana przed specyfikacjami zdefiniowanymi we wspólnej funkcji.

define(['modules/MyModule','jasmine/jasmine'], function(MyModule) { 

    describe('myModule', function() { 

     function commonTests(params) { 
      it('should pass this test OK', function() { 
       expect(true).toBe(true); 
      }); 

      it('should fail because module is undefined', function() { 
       expect(module[params.method]()).toBe('whatever'); 
      }); 
     } 

     var module; 

     beforeEach(function() { 
      module = new MyModule(); 
     }); 

     describe('#function1', function() { 
      commonTests({ 
       method: 'function1' 
      }); 
     }); 

     describe('#function2', function() { 
      commonTests({ 
       method: 'function2' 
      }); 
     }); 

    }); 

}); 

Czy jest jakiś sposób to zrobić i zachowaniu funkcjonalności beforeEach i afterEach?

UPDATE:

Wygląda jak mam mój przykład nie tak, przepraszam. Tu jest tak, że kończy się niepowodzeniem:

define(['modules/MyModule'], function(MyModule) { 

    function commonTests(params) { 
     it('will fail because params.module is undefined', function() { 
      expect(typeof params.module).toBe('object'); 
      expect(typeof params.module[params.method]).toBe('function'); 
     }); 

     it('has a few tests in here', function() { 
      expect(true).toBe(true); 
     }); 
    } 


    describe('MyModule', function() { 

     var module; 

     beforeEach(function() { 
      module = new MyModule(); 
     }); 

     describe('#function1', function() { 
      commonTests({ 
       module: module, 
       method: 'function1' 
      }); 
     }); 

     describe('#function2', function() { 
      commonTests({ 
       module: module, 
       method: 'function2' 
      }); 
     }); 

    }); 
}); 

myślę, że to nie działa, ponieważ wartość module jest zachowana w ramach wezwania do commonTests zamiast zawsze przy użyciu bieżącej wartości module jak w pierwszym przykładzie. Wyślę moje rozwiązanie, kiedy tam dotrę ...

Odpowiedz

4

Dzięki Andreas za wskazanie, że mój pierwszy przykład faktycznie przepracowanych! Ostateczne rozwiązanie używam jest bardzo podobna:

define(['modules/MyModule'], function(MyModule) { 

    var module; 

    function commonTests(params) { 
     it('will not fail because module is shared', function() { 
      expect(typeof module).toBe('object'); 
      expect(typeof module[params.method]).toBe('function'); 
     }); 

     it('has a few tests in here', function() { 
      expect(true).toBe(true); 
     }); 
    } 


    describe('MyModule', function() { 

     beforeEach(function() { 
      module = new MyModule(); 
     }); 

     describe('#function1', function() { 
      commonTests({ 
       method: 'function1' 
      }); 
     }); 

     describe('#function2', function() { 
      commonTests({ 
       method: 'function2' 
      }); 
     }); 

    }); 
}); 

Chociaż jeśli potrzebne, aby mieć zdolność przechodzenia w module jako argument do commonTests trzeba by podjąć nieco inne podejście i mieć inną funkcję każdy it blok:

define(['modules/MyModule'], function(MyModule) { 

    var module; 

    function commonTest1(params) { 
     expect(typeof module).toBe('object'); 
     expect(typeof module[params.method]).toBe('function'); 
    } 

    function commonTest2(params) { 
     expect(true).toBe(true); 
    } 


    describe('MyModule', function() { 

     beforeEach(function() { 
      module = new MyModule(); 
     }); 

     describe('#function1', function() { 

      it('will not fail because module is shared', function() { 
       commonTest1({ method: 'function1' }); 
      }); 

      it('has a few tests in here', function() { 
       commonTest2({ method: 'function1' }); 
      }); 

     }); 

     describe('#function2', function() { 

      it('will not fail because module is shared', function() { 
       commonTest1({ method: 'function2' }); 
      }); 

      it('has a few tests in here', function() { 
       commonTest2({ method: 'function2' }); 
      }); 

     }); 

    }); 
}); 

ten sposób egzekucje funkcji zawierających wspólne testy jest opóźnione aż po beforeEach dobiegł końca zwrotnego.

0

tak, ten scenariusz działa dobrze dla nas. Używamy chutzpah, aby uruchomić testy w naszych bramkowanych checkinach, a nasze testy zakończyłyby się niepowodzeniem bez funkcji afterEach.

Ale linia define wygląda jak require.js. Mieliśmy kilka problemów z tym ... Przypuszczam, że MyModule jest undefined lub nie jest zdefiniowany jako oczekiwany. Czy próbowałeś ustawić punkt przerwania w metodzie beforeEach, aby sprawdzić, czy został wywołany i jaką wartość ma MyModule? Jak dzwonisz na testy?

Po uruchomieniu kodu bez linii define funkcja beforeEach otrzymuje nazwę 4x - zgodnie z oczekiwaniami. Przy okazji skorzystałem z chutzpah.console.exe, aby wywołać testy.

Edit:

Tak, teraz mogę odtworzyć problem na moim komputerze. I jest dla mnie o wiele bardziej zrozumiałe. Na początku module jest niezdefiniowana, ponieważ każda zmienna jest niezdefiniowana jako pierwsza. Następnie rejestrujesz swoje funkcje w jaśminu, używając beforeEach i describe. Jasmine zaczyna się od oceny

function() { 
    commonTests({ 
     module: module, 
     method: 'function1' 
    }); 
} 

który został przekazany do pierwszego describe. Na linii module: module JS kopiuje odniesienie z var module do nowej właściwości obiektów module i to odnosi się do tej pory do undefined. Gdy beforeEach zwrotna jest wywoływana zmienia odniesienie do var module do prawidłowej wartości, ale źle referencyjny został już kopiowane ...

Próbowałem przenieść var module powyżej function commonTests i stosować tę zmienną w testach zamiast params.module i przechodzą zgodnie z oczekiwaniami. Nie wiem, czy jest to opcja w twoim środowisku, ale mam nadzieję, że to pomoże.

Greets, Andreas

+0

Interesujące, masz rację oczywiście: to require.js. Rzecz w tym, że wiem, że MójModuł jest ładowany OK, ponieważ są inne testy, które go używają, które nie są w "testach wspólnych" (które zostawiłem dla zwięzłości) i przechodzą dobrze. Po uruchomieniu debuggera w 'commonTests' i sprawdzeniu wartości' module' jest to wartość 'niezdefiniowana'. Ma poprawną wartość w testach poza "testami wspólnymi" ... Dzięki za rozpatrzenie tego! –

+0

Przypuszczam, że pozostałe testy znajdują się w dwóch "opisowych" wywołaniach na dole, prawda? Pamiętam, że przeczytałem coś o zakresach 'var' w JS. W niektórych przypadkach zmienne zdefiniowane za pomocą funkcji 'var' w funkcjach są dostępne tylko po wyrażeniu' var'. Jeśli tak jest w tym przypadku, spróbujesz uzyskać dostęp do globalnego 'module' (który nie istnieje) w' commonTests'. Być może możesz spróbować przenieść 'var module;' i 'beforeEach' na szczyt otaczającego' opisania'. – Andreas

+0

Dzięki Andreas, rzuciłem okiem i porównałem ten przykład z moim kodem, który był nieco inny. Wysłałem aktualizację w pytaniu ... –

Powiązane problemy