AngularJs单元测试内存泄漏
因为你可能已经知道我们许多拥有大量书面单元测试的人已经遇到了这个不是简单的可解决的问题。在AngularJs
unit testing指南之后,我将以
Jasmine语法编写大约3500个单元测试。测试使用
Karma跑步机执行。
问题是由于一些内存泄漏,它们不能一次执行。在运行它们时,无论何时使用什么浏览器,在某些时候,浏览器崩溃并断开连接,内存将建立起来。现在我所了解的最好的解决方法是在社区中使用的,这个问题是在多次运行中分割测试,最后通过合并单次运行的结果来获得正确的覆盖。 当我第一次遇到这个问题,我有大约1000个测试。在尝试使用所有可用的浏览器进行运行后,我已经将测试分割成多个运行,但是事实证明,这不是很好的解决方案。现在测试在14个单独的运行中并行运行,以减少完成时间,而且仍然不能永久地解决问题,但是由于资源限制(RAM,CPU)和烦人的时间消耗而延迟测试。 有人可以认为我的代码中有内存泄漏,我无法保证,即使我在浏览器中运行应用程序时没有任何问题。这就是为什么我创建了一个突出显示这个问题的示例项目。 为了再现这个问题,我正在创建一个角度service,这是一个沉重的内存消耗如下所示: 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; } }; }); 之后,我有一个简单的directive,它使用这个服务来初始化许多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()); } }; }); 最后,我正在动态地注册1000个测试套件,其中test definition是针对“0700指南”中建议的btw指令。 // define multiple suits with the same definition just for showcase for (var i = 0; i < 1000; i += 1) { describe('heavyLoad directive #' + i,testDefinition); } 要尝试这个例子,刚刚从GitHub结帐项目,然后运行业务开始运行: $ npm install $ bower install 我期待着找到问题所在,最终解决问题。 干杯
这个问题是在每次测试后需要做的被遗忘的清理。
添加后,测试次数不再重要,因为内存消耗是稳定的,测试可以在任何浏览器中运行。 我添加了以前的测试定义here的修改,显示了成功执行3000个二进制登录测试的解决方案。 以下是测试的样子: 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(); }); }); 有两件事需要清理: >编译元素时使用$ compile进行测试指令 他们中的两个是棘手的,很难找出并考虑到。 我希望这个答案对许多有这个问题的人是有帮助的。在完成我所有其他测试之后,我也会写一些信息。 干杯! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |