因为你可能已经知道我们许多拥有大量书面单元测试的人已经遇到了这个不是简单的可解决的问题。在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进行测试指令
>描述函数范围内的所有变量

他们中的两个是棘手的,很难找出并考虑到。
对于我已经知道的第一个,但是直到我发现了与茉莉花在内部工作有关的第二个知识并没有多少帮助。
我已经在他们的GitHub存储库上创建了一个issue,它应该帮助找到更好的解决方案,或者至少在开发人员之间更快地传播这些信息。

我希望这个答案对许多有这个问题的人是有帮助的。在完成我所有其他测试之后,我也会写一些信息。

干杯!

AngularJs单元测试内存泄漏的更多相关文章

  1. 如何通过代码设置iOS的系统时区?

    我想通过代码在iOS中设置系统时区,日期时间.任何想法或私人api帮助我?示例:将时区设置为GMT8,将日期时间设置为2013年8月10日晚上8:30.怎么做?

  2. ios – 如何为NSNotification编写单元测试

    我在swift工作,我想刷新一个页面,所以我使用通知发送它,我在一个ViewController中发布通知并在另一个中添加观察者,它工作正常.我想要做的是在swift中添加单元测试.我查了很多网站但是没能做到.我是新手,不知道从哪里开始.基本上工作是,当我点击按钮通知被发布时,并且当加载下一个视图控制器时,添加通知观察者.我该怎么做单元测试提前致谢编辑:码并添加观察者解决方法一般的解决方案是:使用

  3. 如何在iOS中为预期的assert / assertionFailure编写单元测试?

    这里的问题是,当someString参数为空字符串时,您可以保证函数不会失败–在您的实际应用程序中.这是因为断言不在发布版本中运行.结果是你可以在开发过程中使用assert作为调试的一种形式,但如果这种情况在现实生活中发生,你应该按顺序处理它,而不是崩溃.因此测试断言“发生”是否真的不是一种有效的单元测试技术,这就是为什么你以这种方式使用它的麻烦.

  4. xcode – 如何在不影响单元测试目标构建的情况下更改发布目标的名称?

    我有一个发布目标和一个测试目标,我想更改发布目标的名称,但如果我这样做,我开始在测试目标中获得链接错误.由于它们是单元测试,我认为在测试目标中不会/应该是对发布目标的依赖,但显然存在.链接错误是:在重命名之前,XYZ.app是发布目标的名称.是否有自动或快速更新单元测试目标的方法,以便它保持步调状态?

  5. ios – 可以测试IBAction吗?

    对IBOutlets进行单元测试有点容易,但IBActions呢?我试图找到一种方法,但没有任何运气.有没有办法在ViewController中的IBAction和nib文件中的按钮之间进行单元测试连接?解决方法对于完整的单元测试,每个插座/操作需要三个测试:>插座是否连接到视野?

  6. ios app如何“知道”运行单元测试

    我知道我可以用xcodebuild开始我的应用程序的单元测试,但我想知道是什么告诉应用程序在启动期间运行测试,它是一个发送到应用程序的特殊参数,还是以不同的方式编译以运行测试?

  7. ios – 为什么重复创建和删除SKShapeNode和SKNode导致内存泄漏?

    使用Xcode附带的spritekit模板,我修改场景如下:该应用程序似乎继续使用更多内存,直到它挂起或崩溃.使用泄漏和分配工具,我发现了以下内容:泄漏:分配:从图像中可以看出,存在大量使用内存的Malloc调用.我不直接调用Malloc–似乎这些调用是由SpriteKit完成的.同样,存在许多内存泄漏,这似乎也是由于SKShapeNode,SKNode或其他SpriteKit对象造成的.我如何解决或解决此内存(泄漏)问题?

  8. ios – Xcode 6.1直到运行时才检测到单元测试

    我遇到了Xcode6.1.1没有检测到单元测试文件的问题.我运行了与之关联的方案,并在运行时找到了该文件,最后在单元测试导航器中找到了一个“rT”图标.这导致我到thisquestion,但没有一个答案对我有用.删除我的派生数据或重新启动Xcode没有任何帮助.接近工作的唯一事情是在Xcode运行时删除我的派生数据文件夹–当它重新编制索引时,它发现了我的三个方案中的一个中的所有测试文件.所有这些测

  9. xcode – 在仪器中运行SenTestingKit单元测试

    我正在开发一个数据库访问库,我试图使用已经写的单元测试检查内存泄漏.这些是基于SenTestingKit的逻辑测试,在Xcode4.2中设置了正常的方式.我可以使用Cmd-U运行它们,但是没有看到从仪器启动它们的方法,或者调用仪器来检查它们.我该怎么做这个工作?我需要编写新的案例并将其构建到应用程序中吗?

  10. Xcode:用于条件DEBUG / TEST代码的预处理器宏

    我在我的代码(例如AppDelegate.m)中有不应该为单元测试编译的部分,例如当您在创建新项目时选择“添加单元测试”时,目标是由Xcode设置的.在项目文件中,我已将标志CONfigURATION_TESTS添加到内置目标的MyAppTests的预处理器宏中,但未添加到MyApp目标.这是我发现的许多帖子中的建议方式.但是这不起作用,因为(我猜)MyAppTests目标将MyApp目标作为依赖

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部