New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
SharedStylesHost isn't cleaning up styles between Karma test specs #31834
Comments
Bump on this issue. |
Hello, As a workaround, adding this to my // Fixing this bug: https://stackoverflow.com/questions/51752862/angular-unit-tests-are-leaking-styles
afterEach(() => {
window.document.querySelectorAll("style").forEach((style: HTMLStyleElement) => style.remove());
}); I use Jest but there should be a similar mechanism for Jasmine. Hope this helps |
Another bump on this issue. This seems like a relatively straightforward fix with nontrivial performance gains. |
For the same workaround zelliott just mentioned, I made a function you can use called It would be great if this could be addressed in the framework itself! |
I believe this also happens in production if shared component from two different angular apps are running at the same time? What is the correct way to clean up all the added styles when the component is removed? |
Angular's `TestBed` by default only removes a test component from the document body and destructs individual component fixtures. It never destroys the test module properly, but always re-creates it. This means that providers are not necessarily cleaned up (could leak in memory) and component styles are not cleaned up / deduped. This results in thousands of style elements in the browsers. Ultimately causing significantly increased memory consumption and CPU blocking. This potentially leads to repeated crashes within browsers (as seen in BrowserStack and Saucelabs in the past). Initial testing of this change unveiled a reduction from 30min tests to 5min in BrowserStack. This is a signficant improvement and we should consider moving this change upstream with: angular/angular#31834. Benefits are: reduced test time; increased test/browser stability; isolated tests without leaking styles and services.
Angular's `TestBed` by default only removes a test component from the document body and destructs individual component fixtures. It never destroys the test module properly, but always re-creates it. This means that providers are not necessarily cleaned up (could leak in memory) and component styles are not cleaned up / deduped. This results in thousands of style elements in the browsers. Ultimately causing significantly increased memory consumption and CPU blocking. This potentially leads to repeated crashes within browsers (as seen in BrowserStack and Saucelabs in the past). Initial testing of this change unveiled a reduction from 30min tests to 5min in BrowserStack. This is a signficant improvement and we should consider moving this change upstream with: angular/angular#31834. Benefits are: reduced test time; increased test/browser stability; isolated tests without leaking styles and services.
Angular's `TestBed` by default only removes a test component from the document body and destructs individual component fixtures. It never destroys the test module properly, but always re-creates it. This means that providers are not necessarily cleaned up (could leak in memory) and component styles are not cleaned up / deduped. This results in thousands of style elements in the browsers. Ultimately causing significantly increased memory consumption and CPU blocking. This potentially leads to repeated crashes within browsers (as seen in BrowserStack and Saucelabs in the past). Initial testing of this change unveiled a reduction from 30min tests to 5min in BrowserStack. This is a signficant improvement and we should consider moving this change upstream with: angular/angular#31834. Benefits are: reduced test time; increased test/browser stability; isolated tests without leaking styles and services.
Looks like this is being fixed in #38336. |
Angular's `TestBed` by default only removes a test component from the document body and destructs individual component fixtures. It never destroys the test module properly, but always re-creates it. This means that providers are not necessarily cleaned up (could leak in memory) and component styles are not cleaned up / deduped. This results in thousands of style elements in the browsers. Ultimately causing significantly increased memory consumption and CPU blocking. This potentially leads to repeated crashes within browsers (as seen in BrowserStack and Saucelabs in the past). Initial testing of this change unveiled a reduction from 30min tests to 5min in BrowserStack. This is a signficant improvement and we should consider moving this change upstream with: angular/angular#31834. Benefits are: reduced test time; increased test/browser stability; isolated tests without leaking styles and services.
Until the fix lands, you can add to afterEach(() => {
getTestBed().inject(傻DomSharedStylesHost).ngOnDestroy();
}); Unlike the workaround mentioned above #31834 (comment), this only cleans the necessary stylesheets and not the global ones. This speeds up our |
There is currently a known issue with the framework when testing that leaks style. See angular#31834 A possible temporary workaround is to manually call the service that adds/aremoves the style. See angular#31834 (comment) This workaround will be unnecessary when angular#38336 lands. This speeds up the `ng test` task locally by ~30%: - before: Executed 649 of 652 (skipped 3) SUCCESS (24.161 secs / 20.072 secs) - after: Executed 649 of 652 (skipped 3) SUCCESS (17.854 secs / 15.584 secs)
There is currently a known issue with the framework when testing that leaks style. See angular#31834 A possible temporary workaround is to manually call the service that adds/aremoves the style. See angular#31834 (comment) This workaround will be unnecessary when angular#38336 lands. This speeds up the `ng test` task locally by ~30%: - before: Executed 649 of 652 (skipped 3) SUCCESS (24.161 secs / 20.072 secs) - after: Executed 649 of 652 (skipped 3) SUCCESS (17.854 secs / 15.584 secs)
Angular's `TestBed` by default only removes a test component from the document body and destructs individual component fixtures. It never destroys the test module properly, but always re-creates it. This means that providers are not necessarily cleaned up (could leak in memory) and component styles are not cleaned up / deduped. This results in thousands of style elements in the browsers. Ultimately causing significantly increased memory consumption and CPU blocking. This potentially leads to repeated crashes within browsers (as seen in BrowserStack and Saucelabs in the past). Initial testing of this change unveiled a reduction from 30min tests to 5min in BrowserStack. This is a signficant improvement and we should consider moving this change upstream with: angular/angular#31834. Benefits are: reduced test time; increased test/browser stability; isolated tests without leaking styles and services.
@cexbrayat I've tried your suggestion, but I think I've messed up since no performance change
Here's my // This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import { 傻DomSharedStylesHost } from '@angular/platform-browser';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import 'zone.js/dist/zone.js';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
declare const require: {
context(
path: string,
deep?: boolean,
filter?: RegExp
): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Patch to ensure SharedStylesHost cleanup styles between Karma test specs
afterEach(() => getTestBed().inject(傻DomSharedStylesHost).ngOnDestroy());
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context); Quite sure that's not how it was supposed to be added ... |
@AndrewKushnir what's blocking the MR in 38336 and resolution of this issue? This issue is pretty significant and for large apps could have a MAJOR impact on unit test execution. An issue like this opened in July 2019 and still not resolved boggles my mind. |
@elesueur the fix for the described issue would be a breaking change and we are looking at possible ways on how to make it less break-y for users. |
Am I correct in saying this has been fixed in Angular 13? https://blog.angular.io/angular-v13-is-now-available-cce66f7bc296#1cd7 It seems that the default behavior is to remove styles. The old behavior can be kept using: getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false }
}); |
@reduckted Yes exactly, this issue is fixed on v13 by default (94ba59b) |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
馃悶 Bug Report
Affected package
Latest
Is this a regression?
No
Description
Wheen testing components via
TestBed.createComponent
, Angular appends inline styles associated with the component via the SharedStylesHost service. These inline styles are cleaned up when the service is destroyed.Unfortunately, these inline styles are never cleaned up in Karma unit tests. This appears to be because each SharedStylesHost service is never destroyed, apparently because each associated NgModule is never destroyed between specs. This isn't a problem when you have <10 Karma specs, but when you have >100 , and each spec appends 25
<style>
tags, by the 100th spec you have 2500 redundant<style>
tags in your document head.馃敩 Minimal Reproduction
https://stackblitz.com/edit/angular-testing-exxbrh (old version of angular, but repros on latest)
馃實 Your Environment
Angular Version:
Floating version of Angular 2 RC branch. Repros on latest.
The text was updated successfully, but these errors were encountered: