AngularJs单元测试内存泄漏 [英] AngularJs unit testing memory leaks
问题描述
你可能已经知道了我们很多谁写单元测试量大会见了这不是平凡解的问题。我有写在各地3500+单元测试茉莉花继AngularJs的语法https://docs.angularjs.org /引导/单元测试>单元测试指南。测试与噶亚军执行。
as you may already know many of us who have a large quantity of written unit test has met with this not trivially solvable problem. I have around 3500+ unit tests written in the Jasmine syntax following the AngularJs unit testing guide. The tests are executed with Karma runner.
的问题是,它们不能一次全部由于一些内存泄漏执行。虽然它们运行内存建立了对他们的意见,并在某些时候浏览器崩溃和断开拼命地跑什么样的浏览器不管。我所知道的现在这是在有这个问题是在劈裂多次运行,并在年底测试从单一的合并运行的结果得到正确的覆盖社区所使用的最好的解决方法。
The problem is that they cannot be executed all at once due to some memory leaks. While running them the memory builds up no matter on what browser they are runned on and at some point the browser crashes and disconnects. The best workaround that I am aware of by now which is used in the community that have this problem is spliting the tests in multiple runs and at the end get the correct coverage by merging the results from the single runs.
当我第一次见到这个问题我有大约1000测试。与运行我已经分手在多个运行测试所有可用的浏览器尝试后,但事实证明,这不是很好的办法解决了很久。现在测试在14+被拼命地跑在平行于减少completition时间和仍然国际海事组织此不能永久解决这个问题,但延缓它由于资源限制(RAM,CPU)和恼人的时间消耗利特尔位单次运行执行。
When I first met with this problem I had around 1000 tests. After trying with all the available browsers for running I have split the tests in multiple runs, however it turned out that this is not good workaround for a long time. Now the tests are executed in 14+ single runs that are runned in parallel to reduce the time for completition and still IMO this cannot permanently solve the problem but delay it a litle bit because of resources limitation (RAM, CPU) and annoying time consumption.
有人可以说,我在我的code内存泄漏为其运行在浏览器中的应用程序时,我不能保证,即使我没有任何问题的一致好评。这就是为什么我创建了一个例子项目,将突出这一问题。
Someone can argue that I have memory leaks in my code for which I cannot guarantee even though I don't have any problems alike when running the application in the browser. That is why I have created an example project that will highlight this problem.
有再现这个问题,我创建一个角<一个href=\"https://github.com/saskodh/ng-unit-testing-leak/blob/master/src/services/heavyLoad-service.js\">service这是沉重的内存消耗是这样的:
There for reproducing this problem I am creating an Angular service which is heavy in memory consumption like this:
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; }
};
});
之后,我有一个简单的<一个href=\"https://github.com/saskodh/ng-unit-testing-leak/blob/master/src/directives/heavyLoad-directive.js\">directive使用这种服务来初始化许多DOM元素:
After that I have a simple directive which uses this service to initialize many DOM elements:
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());
}
};
});
和结尾我动态注册与<1000测试套件href=\"https://github.com/saskodh/ng-unit-testing-leak/blob/master/test/directives/heavyLoad-directive.spec.js\">test定义以作为角单元测试指南建议其BTW写入指令。
And at the end I am dynamically registering 1000 test suites with the test definition for the directive which btw is written as suggested in the Angular unit testing guide.
// define multiple suits with the same definition just for showcase
for (var i = 0; i < 1000; i += 1) {
describe('heavyLoad directive #' + i, testDefinition);
}
要试用此例从 GitHub上并运行前的因缘开始只签出项目的运行:
To try the example just checkout the project from GitHub and before running karma start run:
$ npm install
$ bower install
我期待着找到问题的所在,最后解决了。
I am looking forward to finding where the problem is and solving it finally.
干杯
推荐答案
这个问题是被遗忘的清理,需要每个测试之后进行。
加入后的测试的数量,因为存储器的消耗是稳定和测试可以在任何浏览器上运行不再重要。
The problem was in the forgotten clean-up that needs to be done after each test. After adding it the number of tests does not matter anymore because the memory consumption is stable and the tests can be run in any browser.
我已经加入了previous测试定义<一的修改href=\"https://github.com/saskodh/ng-unit-testing-leak/blob/master/test/directives/heavyLoad-directive.effective.spec.js\">here这显示了成功执行3000 dinamically注册的测试解决方案。
I have added a modification of the previous test definition here that shows the solution with successfully executing 3000 dinamically registered tests.
下面是测试如何貌似现在:
Here is how the test looks like now:
describe('testSuite', function () {
var suite = {};
beforeEach(module('app'));
beforeEach(inject(function ($rootScope, $compile, heavyLoad) {
suite.$rootScope = $rootScope;
suite.$compile = $compile;
suite.heavyLoad = heavyLoad;
suite.$scope = $rootScope.$new();
spyOn(suite.heavyLoad, 'getHeavyString').and.callThrough();
spyOn(suite.heavyLoad, 'getHeavyObject').and.callThrough();
spyOn(suite.heavyLoad, 'getHeavyList').and.callThrough();
}));
// NOTE: cleanup
afterEach(function () {
// NOTE: prevents DOM elements leak
suite.element.remove();
});
afterAll(function () {
// NOTE: prevents memory leaks because of JavaScript closures created for
// jasmine syntax (beforeEach, afterEach, beforeAll, afterAll, it..).
suite = null;
});
suite.compileDirective = function (template) {
suite.element = suite.$compile(template)(suite.$scope);
suite.directiveScope = suite.element.isolateScope();
suite.directiveController = suite.element.controller('heavyLoad');
};
it('should compile correctly', function () {
// given
var givenTemplate = '<div heavy-load></div>';
// when
suite.compileDirective(givenTemplate);
// then
expect(suite.directiveScope.title).toBeDefined();
expect(suite.directiveScope.items).toBeDefined();
expect(suite.heavyLoad.getHeavyString).toHaveBeenCalled();
expect(suite.heavyLoad.getHeavyList).toHaveBeenCalled();
});
});
有需要被清理后的两件事情:
There are two things that need to be cleaned-up:
- 使用$编译测试指令时编译元素
- 在描述函数范围内的所有变量
他们俩是棘手,很难发现和考虑。
对于第一个我已经知道但直到我发现的第二个这是茉莉的工作机制与它没有多大帮助。
我已经创建了一个问题他们的GitHub库,这应有助于找到更好的解决方案,或至少新$ P $垫本更快开发商之间的信息。
The two of them are tricky and hard to find out and take into consideration. For the first one I already knew but it didn't helped much until I've discovered the second which is related with how Jasmine works inside. I have created an issue on their GitHub repository which should help finding better solution or at least spread this information among developers faster.
我希望这个答案将是很多有这个问题的人有所帮助。我会写一些信息我完成我的重构所有其他测试过了。
I hope that this answer will be helpful for lot of people having this problem. I will write some info too after I finish refactoring all my other tests.
干杯!
这篇关于AngularJs单元测试内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!