Skip to content

feat(core): add opt-in test module teardown configuration #42566

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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Jun 13, 2021

We currently have two long-standing issues related to how TestBed tests are torn down:

  1. The dynamically-created test module isn't going to be destroyed, preventing the ngOnDestroy hooks on providers from running and keeping the component style nodes in the DOM.
  2. The test root elements aren't going to be removed from the DOM. Instead, they will be removed whenever another test component is created.

By themselves, these issues are easy to resolve, but given how long they've been around, there are a lot of unit tests out there that depend on the broken behavior.

These changes address the issues by introducing APIs that allow users to opt into the correct test teardown behavior either at the application level via TestBed.initTestEnvironment or the test suite level via TestBed.configureTestingModule.

At the moment, the new teardown behavior is opt-in, but the idea is that we'll eventually make it opt-out before removing the configuration altogether.

Fixes #18831.

@google-cla google-cla bot added the cla: yes label Jun 13, 2021
expect(fixtureDocument.body.contains(fixture.nativeElement)).toBe(false);
});

it('should re-throw errors that were thrown during fixture cleanup', () => {
Copy link
Member Author

@crisbeto crisbeto Jun 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One note here: the original design only called for test module errors to be re-thrown, not test component, but I decided to make this change, because I was looking at how the Components repo is working around this and I realized that not throwing errors during test component destruction can still lead to difficult to trace down bugs. For reference: https://github.com/angular/components/blob/master/test/karma-test-shim.js#L61

@crisbeto crisbeto force-pushed the testbed-teardown branch 2 times, most recently from 0a5748c to dd2cb6e Compare June 13, 2021 08:33
@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer area: core Issues related to the framework runtime area: testing Issues related to Angular testing features, such as TestBed target: minor This PR is targeted for the next minor release labels Jun 13, 2021
@ngbot ngbot bot modified the milestone: Backlog Jun 13, 2021
@crisbeto crisbeto marked this pull request as ready for review June 13, 2021 09:09
@pullapprove pullapprove bot requested review from alxhub and AndrewKushnir June 13, 2021 09:10
@josephperrott josephperrott self-requested a review June 14, 2021 19:24
Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks @crisbeto! I've just left a few comments, please have a look when you get a chance.

* @publicApi
*/
export interface ModuleTeardownOptions {
/** Whether the test module should be destroyed after every test. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be great to mention a default value here too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I avoid mentioning default values in docs, because they inevitably go out of sync when the default changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, got it. I just noticed that you've added the default value description to the rethrowErrors field, but not this one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't anticipate for the rethrowErrors default value to change, whereas the teardown one will.

}

/**
* Object used to configure the test module teardown behavior in `TestBed`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd need to add more info here to explain why these options exist and provide recommendations on when they should be used/changed and what the plan is (that these options will eventually be deprecated and removed, so we do not encourage using them unless it's absolutely needed and blocking tests).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to have a silent rollout of this in 12.1.0 and then add a page in the docs similar to https://angular.io/guide/migration-update-libraries-tslib.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for additional info, I'd propose adding a couple sentences to describe that:

Suggested change
* Object used to configure the test module teardown behavior in `TestBed`.
* Object used to configure the test module teardown behavior in `TestBed`.
* This option is exposed as a public API to allow switching to the legacy TestBed behavior temporarily
* (where testing module was not removed as a part of the test teardown process) in case your tests rely on
* this old behavior. These config options will be deprecated and removed in the future versions of Angular.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that people who aren't familiar with the TestBed internals would know what this is referring to.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can update the message to make it more user-friendly. I'd like to include some information about the fact that these config options are temporary and developers should not rely on them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we should capture the fact that it's temporary when we eventually add the page on AIO. Also the plan is to provide schematics that add the parameter and then remove it once we've changed the default value so hopefully people won't have to deal with it themselves.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ModuleTeardownOptions would become discoverable on the AIO once this PR is merged, see
https://pr42566-893884a.ngbuilds.io/api/core/testing/ModuleTeardownOptions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that providing all the context behind the option would take a few paragraphs of text which seems like overkill for an API doc. E.g. the design doc for these changes takes 170 words to explain the issues.

Copy link
Member

@josephperrott josephperrott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@crisbeto
Copy link
Member Author

@AndrewKushnir I've addressed the feedback.

@josephperrott I've pushed a fix for it. I had to revert one place where I tried to make something a couple lines shorter, but it ended up causing the error.

}

// Otherwise use the configured behavior or default to rethrowing.
return instanceOptions?.rethrowErrors ?? environmentOptions?.rethrowErrors ?? true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to extract this default value to a const too (similar to TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the constant made sense for the teardown option since we're going to change it over time. I don't anticipate for the error rethrowing default behavior to change.

* @publicApi
*/
export interface ModuleTeardownOptions {
/** Whether the test module should be destroyed after every test. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, got it. I just noticed that you've added the default value description to the rethrowErrors field, but not this one.

}

/**
* Object used to configure the test module teardown behavior in `TestBed`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for additional info, I'd propose adding a couple sentences to describe that:

Suggested change
* Object used to configure the test module teardown behavior in `TestBed`.
* Object used to configure the test module teardown behavior in `TestBed`.
* This option is exposed as a public API to allow switching to the legacy TestBed behavior temporarily
* (where testing module was not removed as a part of the test teardown process) in case your tests rely on
* this old behavior. These config options will be deprecated and removed in the future versions of Angular.

Copy link
Contributor

@atscott atscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewed-for: public-api

@pullapprove pullapprove bot requested a review from IgorMinar June 16, 2021 16:40
Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-for: public-api

@mary-poppins
Copy link

You can preview 0a272fd at https://pr42566-0a272fd.ngbuilds.io/.
You can preview dd2cb6e at https://pr42566-dd2cb6e.ngbuilds.io/.
You can preview b7a29d2 at https://pr42566-b7a29d2.ngbuilds.io/.
You can preview 893884a at https://pr42566-893884a.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 0a272fd at https://pr42566-0a272fd.ngbuilds.io/.
You can preview dd2cb6e at https://pr42566-dd2cb6e.ngbuilds.io/.
You can preview b7a29d2 at https://pr42566-b7a29d2.ngbuilds.io/.
You can preview 893884a at https://pr42566-893884a.ngbuilds.io/.

Copy link
Contributor

@jessicajaniuk jessicajaniuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🍪

Reviewed-for: public-api

crisbeto added 3 commits June 17, 2021 19:02
We currently have two long-standing issues related to how `TestBed` tests are torn down:
1. The dynamically-created test module isn't going to be destroyed, preventing the `ngOnDestroy` hooks on providers from running and keeping the component `style` nodes in the DOM.
2. The test root elements aren't going to be removed from the DOM. Instead, they will be removed whenever another test component is created.

By themselves, these issues are easy to resolve, but given how long they've been around, there are a lot of unit tests out there that depend on the broken behavior.

These changes address the issues by introducing APIs that allow users to opt into the correct test teardown behavior either at the application level via `TestBed.initTestEnvironment` or the test suite level via `TestBed.configureTestingModule`.

At the moment, the new teardown behavior is opt-in, but the idea is that we'll eventually make it opt-out before removing the configuration altogether.

Fixes angular#18831.
@dylhunn dylhunn removed the action: presubmit The PR is in need of a google3 presubmit label Jun 17, 2021
@dylhunn dylhunn closed this in 873229f Jun 17, 2021
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jun 25, 2021
Angular 12.1.0 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jun 25, 2021
Angular 12.1.0 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jun 26, 2021
Angular 12.1.0 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.
clydin pushed a commit to angular/angular-cli that referenced this pull request Jul 7, 2021
In version 12.1, the framework added the `destroyAfterEach` an opt-in feature that improves tests performance and also addresses two long-standing issues.

The idea, is to have this enabled by default in the future.  Related PR: angular/angular#42566

Closes #21280
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jul 15, 2021
Angular 12.1.2 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jul 16, 2021
Angular 12.1.2 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.
amysorto pushed a commit to angular/components that referenced this pull request Jul 16, 2021
Angular 12.1.2 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.
amysorto pushed a commit to angular/components that referenced this pull request Jul 16, 2021
Angular 12.1.2 includes [opt-in automatic test module teardown](angular/angular#42566) which is similar to our logic of destroying the current fixture. These changes clean up our monkey patches and use the new option instead.

(cherry picked from commit d090617)
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jul 18, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: core Issues related to the framework runtime area: testing Issues related to Angular testing features, such as TestBed cla: yes target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Destroy listeners aren't called in TestBed
7 participants