, ponieważ być może już wiesz, że wielu z nas, którzy mają dużą liczbę pisemnych testów jednostkowych, spotkało się z tym niełatwym do rozwiązania problemem. Mam ponad 3500 testów jednostkowych zapisanych w składni Jasmine po przewodniku AngularJs unit testing. Testy są wykonywane z biegaczem Karma.Urządzenie AngularJs testuje wycieki pamięci
Problem polega na tym, że nie można ich wykonać na raz ze względu na pewne wycieki pamięci. Podczas ich działania gromadzona jest pamięć niezależnie od tego, w jakiej przeglądarce są uruchamiane iw pewnym momencie przeglądarka ulega awarii i rozłącza się. Najlepszym sposobem obejścia tego problemu, który jest obecnie stosowany w społeczności, która ma ten problem, jest dzielenie testów na wiele przebiegów i na końcu uzyskiwanie poprawnego pokrycia przez scalanie wyników z pojedynczych przebiegów.
Kiedy po raz pierwszy spotkałem się z tym problemem, miałem około 1000 testów. Po przetestowaniu wszystkich dostępnych przeglądarek pod kątem dzielenia testów w wielu seriach okazało się, że nie jest to dobre rozwiązanie przez długi czas. Teraz testy są wykonywane w 14+ pojedynczych przebiegach, które są uruchamiane równolegle w celu skrócenia czasu na ukończenie, a mimo to IMO nie może trwale rozwiązać problemu, ale opóźnia go o trochę więcej ze względu na ograniczenia zasobów (RAM, CPU) i denerwujące zużycie czasu.
Ktoś może twierdzić, że mam wycieki pamięci w moim kodzie, co do których nie mogę zagwarantować, mimo że nie mam żadnych problemów zarówno podczas uruchamiania aplikacji w przeglądarce. Właśnie dlatego stworzyłem przykładowy projekt, który podkreśli ten problem.
Nie do odtworzenia tego problemu tworzę kątowym service który jest ciężki zużycia pamięci, takich jak ten:
app.factory('heavyLoad', function() {
// init
var heavyList = [];
var heavyObject = {};
var heavyString = '';
// populate..
return {
getHeavyList: function() { return heavyList; },
getHeavyObject: function() { return heavyObject; },
getHeavyString: function() { return heavyString; }
};
});
Po że mam proste directive który korzysta z tej usługi w celu zainicjowania wielu elementów DOM:
app.directive('heavyLoad', function (heavyLoad) {
return {
scope: {},
template: '' +
'<div>' +
' <h1>{{title}}</h1>' +
' <div ng-repeat="item in items">' +
' <div ng-repeat="propData in item">' +
' <p>{{propData}}</p>' +
' </div>' +
' </div>' +
'</div>',
link: function (scope, element) {
scope.items = heavyLoad.getHeavyList();
scope.title = heavyLoad.getHeavyString();
// add data to the element
element.data(heavyLoad.getHeavyList());
}
};
});
I na koniec dynamicznie rejestruję 1000 zestawów testów z test definition dla dyrektywy, która jest napisana zgodnie z sugestią w przewodniku Angular unit testing.
// define multiple suits with the same definition just for showcase
for (var i = 0; i < 1000; i += 1) {
describe('heavyLoad directive #' + i, testDefinition);
}
spróbować przykład tylko kasa projekt z GitHub i przed uruchomieniem karmę rozpocząć Run:
$ npm install
$ bower install
niecierpliwością czekam do znalezienia gdzie jest problem i rozwiązać go w końcu.
Cheers
Po pomyślnym zakończeniu refaktoryzacji wyniki ~ 4000 testów wykonano w ~ 2min. –
Jak mogłeś to zrobić? Przygotowałem poprzednie testy do uruchomienia przy użyciu 'tego' do czyszczenia przez Jasmine, ale po uruchomieniu 600 testów biegacz po prostu zawiedzie w PhantomJS. To samo ma miejsce, ale w Chrome uruchomiono mniej testów. –
Ponadto, począwszy od wersji 1.5.1 można użyć 'beforeAll' zamiast' beforeEach', aby kpić z modułu raz na opis, powinno to jeszcze bardziej poprawić wydajność. https://docs.angularjs.org/guide/unit-testing#using-beforeall- – vivascau