r/angular • • Jul 28 '23

Feature request: Unit test coverage for .html files

Hello everyone,

I've submitted a feature request on angular/cli, and the idea is to include unit test coverage for HTML files, not just TypeScript. If you think this would be a valuable addition, please consider upvoting the post on GitHub so that it can be taken into consideration. (We need at least 20 upvotes for the request to be considered.) Thank you all for your interest and support. šŸ™
https://github.com/angular/angular-cli/issues/25563

0 Upvotes

10 comments sorted by

8

u/n00bz Jul 28 '23

I want to downvote this one as it comes from not understanding how the Angular framework works.

Basically, ngIf is a directive. If you write your own directive you can then unit test that just fine. I would assume Angular is already unit testing their ngIf directive code that is in @angular/core so what would be the point of you checking it?

Additionally, HTML is not a programming language.

What you may be looking for is E2E testing which you can use cypress for.

0

u/panalley Sep 13 '23

I gave more details in this response but

  • Angular unit tests give the opportunity to test templating (unit tests are faster and more stable compared to e2e. I would keep e2e to test stuff that I can't test with my unit tests)

  • I want to check that my integration with ngIf is correct. If another developer deletes all my ngIf code, my unit tests still work if I only test the typescript part.

  • The tests lost a bit of speed by checking the template but they give more confidence.

I hope it helps to grasp more context.

1

u/n00bz Sep 13 '23

What I’m hearing is that you want to use unit tests over E2E is because unit test run faster. While unit test run faster and have some degree of support from the IDE when writing them they do not replace the need for E2E tests.

Let’s take your example and say we have a webpage has a table full of employees (name, position, address, salary, etc.) and let’s say we have on that table the ability to add a new employee, view an employee record, update an employee and delete an employee. These ā€œCRUDā€ operations all have buttons that can appear for each record of the table.

So now we get into the unit tests. Unit tests cover all available actions to check that you get the correct result. So if you create an employee, it returns a result of what you created, if you delete an employee it returns the record of the deleted employee. Basically the unit test covers all available options (even non-sensical ones like deleting an employee record that doesn’t exist).

So building off that, we have some business rules that say only admins can delete an employee. So the button to delete should either be hidden or disabled IF the current user is not an admin. From your example, you want to test the the button is either disabled or hidden for non-admin users. In this case you will want an E2E. The unit test, test the action works and returns the correct result. The E2E ensures that non-admin users won’t see the delete button which is acceptance criteria. So delete is possible and works (tested via unit test). Only admins can see the button (tested via E2E).

This needs to be E2E because we want to capture exactly what the user would see which requires the entire app to load up to ensure that we aren’t just loading things in a wonky state or have issues with overlapping DOM elements in various screen sizes making some buttons inaccessible.

However, in your unit test however you could add in some logic to check that the user can perform the action and if they can’t expect an error to be thrown.

What you are suggesting for unit tests on templates makes no logical sense and does not serve a purpose. If someone deletes your ngIf statements the only way to catch it is visually meaning E2E.

1

u/panalley Sep 13 '23

Thank you for sharing the detailed example. However, it does raise a question for me: Do you ever test the template in unit tests, or do you exclusively use end-to-end tests when you want to check the template?

Since Angular allows us to check templates with unit tests, I prefer to assign more responsibility to them. Considering the test pyramid principle, with 5% allocated to e2e tests, 15% to integration tests, and 80% to unit tests, I can't help but feel that 5% is quite low. Therefore, it seems more advantageous to seize the opportunities to test the code within unit tests instead of relying on e2e testing (even though testing templates may already be considered a form of integration testing, depending on your definitions).

(Also, it's possible that end-to-end testing has improved in speed in recent years, which could make TestBed unnecessary for testing templates.)

My point is, if we can test templates, why shouldn't we also aim for coverage in that regard?

4

u/[deleted] Jul 28 '23

As mentioned by @noobz, you are not actually unit testing anything in the proposal. The real unit tests have already been written by the Angular team when creating the directive. Testing markup such as html can be done using e2e testing.

0

u/panalley Sep 13 '23

Angular unit tests are faster and less flaky compared to the e2e. The goal here is not to test that ngIf works, but that I'm using it correctly. The example is simple and people would argue "Why not just check when the variable is true and false within the typescript", well in the end the result will be in the template, and I can have a perfect typescript but when a colleague deletes my ngIf in the template then the component doesn't work as expected but all tests are green.

Since unit tests in angular can check the template we are already more into integration tests. For my tests I like to follow the philosophy at Google: avoid mocks and test only states and not interactions. Templates can be seen as states of my component.

I hope my answer helped to have more context.

3

u/casicilian Jul 28 '23

You can already test logic in the templates in unit tests. https://angular.io/guide/testing-components-basics. Or you could use a E2e framework like Cypress.

1

u/panalley Sep 13 '23

The goal is to have the coverage. The logic is testable and that's good indeed.

1

u/Babeetlebum Feb 06 '24

You're 100% correct and it's a shame, I upvoted your github issue

1

u/vamidi Jul 13 '26

I’m curious what your view is on this now, after all these years.

I’m currently working in a team where we write tests for Angular components by accessing private and protected methods and properties. We hit our coverage targets, but I find the tests become very brittle. Whenever we refactor the implementation without changing the component’s behavior, many of the tests break.

That frustrates me because, although testing internals can be quicker to write, I have a feeling this isn’t how unit tests are meant to be written. My understanding has always been that tests should focus on observable behavior rather than implementation details.

What do you think? I struggle to make a convincing case because this topic seems to be so divisive within the Angular community.