It's all plain and simple with such a straightforward app... However, when you factor in authentication, slow back-end responses, multiple features depending on the same data, scrolling, and timeouts, you end up with a mess that takes more than an hour to complete, and it's not reliable. It becomes a substantial amount of code that must be maintained and modified with each requirement change...
More complex situations of course make the testing requirements more complex, but there are ways to handle these things. For example in this codebase: github.com/joshuamorony/refresh-app I'm using the Firebase emulators with mock auth data when doing E2E tests, and for other types of back end calls you can have the E2E testing framework intercept these requests and provide mock responses. Things like page objects also help with this maintenance aspect as if the way a particular action in the application happens is changed you can change it in one place.
@@JoshuaMorony Are you primarily conducting testing on the frontend component of the application, excluding real-world scenarios that involve backend-to-frontend communication? Doesn't this approach seem futile? Isn't that what unit and integration tests are designed to address?
@@kmiasko whilst you can make real requests to backends if you want, the general idea is typically that you assume the backend does what it is supposed to do and mock the responses to make the frontend tests easier/faster, and yes typically the purpose of these E2E tests is to test that the frontend works - you would have separate tests on the backend for actually testing your API if that is necessary. Or, it may not be necessary if you're using something like Firebase, you can probably just assume their API does what it says it does, and you just need to make sure the correct requests are made (and, as in the repo I linked, you might write unit tests for your security rules). It doesn't seem futile to me, and it's pretty commonplace, but certainly you can fairly decide that E2E tests don't provide value for your own situations and not use them.
@@JoshuaMorony Testing the frontend for proper functionality also entails verifying whether loaders function as expected while waiting for data. Prolonged server responses or unexpected order of multiple requests returning from the backend can lead to unexpected behaviors in the frontend. Do you also simulate random timings in your end-to-end (e2e) tests? If not, testing only the ideal scenario may appear to be merely a superficial test coverage rather than thoroughly evaluating the robustness of the application. Please understand, I'm not implying that your approach is incorrect or futile; I'm simply expressing a bias due to our extensive experience with e2e testing in our company, which unfortunately did not yield significant benefits. It's possible that we were not executing it correctly.
@@kmiasko in terms of what I personally do (not that it would be the best general approach) yes I do treat my E2E tests as more superficial "happy path" scenarios, and for handling more granular details (like error responses) I would generally cover that in unit/integration tests. If you wanted to put more emphasis on the E2E tests though, you certainly could simulate various trouble scenarios/errors (though I wouldn't be a fan of simulating slow responses, since it would increase the test execution time significantly)
Question: As a developer, should I skip the E2E tests in favour of just unit tests if we have a QA department that runs automated E2E tests on our Angular frontend?
I also prefer e2e tests to just test the UI. Imho unit tests are more important when there is more logic involved (like in backends) or to test edge-cases.
What do you think about worrying less about smaller unit tests by writing more integration tests instead, an opinion that was shared by Kent C. Dodds? As smaller unit tests have, in a way, less value by the fact that they only cover very little, so that when they pass, they don’t add a lot of confidence that the app is working as intended. As you’ve demonstrated e2e tests that test user requirements do provide a lot of confidence but they require a lot of setup in real-world examples. The suggestion was to write mostly integration tests / bigger unit tests that cover multiple application parts as they are a good middle ground of providing confidence while not having the drawbacks of real e2e tests. On that note I think Cypress „component tests“ fit perfectly for these kind of tests as they do test multiple parts of the application but aren’t full-blown e2e tests.
When I'm testing I don't really aim for a particular type of test or a certain amount of them - I mostly base the decision around what test I need to write in order to give me confidence that this feature does what it is supposed to do. I'm not too familiar with Kent's view, but where this usually ends up landing is probably at least somewhat in line with the view you mention. I say "unit" test typically, but it depends how you want to define that, most of the "unit" tests I am writing could be considered integration tests as a lot of them are essentially triggering some action in the DOM and checking something somewhere in the component happened. I write very few tests that are more strictly "unit" tests (e.g. just testing an individual method for example).
I think that is not too far off my position on that. What I’ve seen is teams mostly start off by writing no tests at all, the next stage is they write lots and lots of tests that essentially boil down to „the code that I wrote is the code that I wrote“ (very small unit tests that provide little value). Now Kent’s position can be summed up by „Write tests. Not too many. mostly integration.“ and with integration, he means „test multiple components together where it makes sense“. It’s a good rule of thumb I think for teams that are just starting out developing a good testing strategy.
Depends what level of granularity you want - the E2E tests the whole feature so we can reasonably confidently say we know it works. This is the response I gave to a similar question in a previous video: "You can decide whether it provides any value in specific circumstances, but generally it just gives you a greater level of granularity and faster feedback. Given the "delete" functionality for example - I could (and did) write an E2E test that tests clicking the delete button and removing a checklist. However, if that fails I don't specifically know where/why it failed - with these more granular tests I can more easily see that it failed because the "delete" even did not emit, or because the "remove$" source in the service was never next-ed, or because the logic in the service for handling the delete is not executing properly, and so on. Unit tests are generally quicker/easier to run so we get this feedback faster, and we can also see specifically where a problem is. So generally, I like to use E2E tests for broad user story style tests, but mostly I focus on having more unit/integration tests (maybe something like 5-10 unit/integration tests for every E2E test)." And personally, I tend to test some things with integration/unit tests that I don't with E2E tests. Something like "should show a loading spinner when the thing is loading" is something I tend to have in unit tests, and the broader E2E test would just be something more like "it displays the thing"