come forse già sapete molti di noi che hanno una grande quantità di test di unità scritte hanno incontrato questo problema non banalmente risolvibile. Ho circa 3500+ test unitari scritti nella sintassi Jasmine seguendo la guida di AngularJs unit testing. I test sono eseguiti con il corridore Karma.L'unità AngularJs verifica perdite di memoria
Il problema è che non possono essere eseguiti tutti in una volta a causa di alcune perdite di memoria. Durante l'esecuzione, la memoria si accumula indipendentemente dal browser su cui vengono eseguiti e ad un certo punto il browser si blocca e si disconnette. Il miglior trucco di cui sono a conoscenza ormai che è usato nella comunità che ha questo problema è quello di dividere i test in più esecuzioni e alla fine ottenere la copertura corretta unendo i risultati delle singole esecuzioni.
Quando ho incontrato per la prima volta questo problema, ho avuto circa 1000 test. Dopo aver provato con tutti i browser disponibili per l'esecuzione, ho suddiviso i test in più esecuzioni, tuttavia è risultato che non è una buona soluzione per un lungo periodo di tempo. Ora i test vengono eseguiti in più di 14 sessioni singole che vengono eseguite in parallelo per ridurre il tempo di completamento e ancora IMO non è in grado di risolvere il problema in modo definitivo, ma di ritardarlo a causa della limitazione delle risorse (RAM, CPU) e del fastidioso consumo di tempo.
Qualcuno può obiettare che ho perdite di memoria nel mio codice per le quali non posso garantire anche se non ho alcun problema allo stesso modo durante l'esecuzione dell'applicazione nel browser. Ecco perché ho creato un progetto di esempio che metterà in evidenza questo problema.
C'è per la riproduzione di questo problema che sto creando un angolare service che è pesante nel consumo di memoria in questo modo:
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; }
};
});
Dopo che ho un semplice directive che utilizza questo servizio per inizializzare molti elementi 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());
}
};
});
E alla fine sto registrando in modo dinamico 1000 suite di test con la test definition per la direttiva, che btw è scritto come suggerito nella guida unit testing angolare.
// define multiple suits with the same definition just for showcase
for (var i = 0; i < 1000; i += 1) {
describe('heavyLoad directive #' + i, testDefinition);
}
Per provare l'esempio appena checkout il progetto da GitHub e prima di eseguire karma iniziare run:
$ npm install
$ bower install
Non vedo l'ora di trovare dove è il problema e risolvere finalmente.
Acclamazioni
Dopo aver eseguito correttamente i risultati del refactoring sono stati eseguiti circa 4000 test in ~ 2min. –
Come sei riuscito a farlo? Ho impostato i test precedenti per usare "this" per la pulizia di Jasmine, ma dopo aver eseguito 600 test il runner fallisce su PhantomJS. La stessa cosa si verifica ma con meno test eseguiti su Chrome. –
Inoltre, a partire da 1.5.1 puoi usare 'beforeAll' invece di' beforeEach' per deridere il modulo una volta per descrizione, dovrebbe migliorare le prestazioni ancora di più. https://docs.angularjs.org/guide/unit-testing#using-beforeall- – vivascau