You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
6. E2E/UI system tests
5. E2E/UI isolated tests
-
4. API tests (out of process)
3. Integration tests (in memory)
-
2. Component tests (in memory)
1. Unit tests (in memory)
Unit Tests
Component Tests
Integration tests: look almost exactly like regular unit tests, but some of the dependencies are not stubbed out.
API tests: We are no longer instantiating the test in memory. The first time we need to actually deploy the application under test (or at least part of it) and invoke it through the network to run the test properly.
Unit Test: a piece of code that invokes a unit of work & checks one specific exit point as an end result of that work.
Unit test -> "unit" = "unit of work"
Unit of Work:
has entry point(s) (aka a 'beginning')
has exit point(s) (aka an 'ending')
does something useful
Best Practice: Write one unit test for each exit point
Entry points: Where the test triggers the unit of work
Exit points: There are 3 types of exit points, they either:
Return a value (or error) -- "return based exit points"
Noticeable state change -- "state based exit points"
Calls a 3rd party dependency
Testing "return based exit points" flow:
Trigger an entry point
Get something back
Check the value you got back
Testing "state based exit points" flow:
Call something
Do another call to check something else
Check if everything went as expected
Unit Test Checklist
You must be able to answer 'yes' to all of the following questions.
Can i run & get results form a test i wrote two weeks/months/years ago?
Can any member of my team run & get results from tests I wrote two weeks/months/years ago?
Can i run all the tests i've written in no more than a few mins?
Can i run all the tests i've written at the push of a button?
Can i write a basic test in no more than a few minutes?
Do my tests pass when there are bugs in another team's code?
Do my tests show the same results when run on different machines/environments?
Do my tests stop woriing it there's no database, network or deployment?
If i delete, move or change one test - do other tests remain unaffected?
Unit Test Best Practices
Use the "USE" naming system when naming tests. "USE" naming:
U: Unit under test
S: Scenario
E: Expectation
Example implementation: test('verifyPassword, given a failing rule, returns errors')
U: verifyPassword
S: given a failing rule
E: returns errors
Avoid writing asserts and the method call in the same action
# BAD
expect(verifier.verify("any value")[0]).toContain("fake reason");`
# GOOD:
const result = verifier.verify("any value");
expect(result[0]).toContain("fake reason");
Dont leave magic values in your tests
Try not to use "setups" at all (such as beforeEach methods). Introduce helper methods to simplify the tests' arrange part, and use those helper methods in each test.
SOP: Writing Unit Tests for Components
establish the acceptance criteria - write down the things the user story should accomplish
put those items into describe()/it() blocks with no code
Verify the static and dynamic aspects of the component, ensuring it behaves as expected in isolation before integrating it into larger parts of the application. Confirm both presentation & behavior.
A Component deals with several concerns, among others:
It renders the template into the HTML DOM.
It accepts data from parent Components using Input properties.
It emits data to parent Components using Outputs.
It reacts to user input by registering event handlers.
It renders the content (ng-content) and templates (ng-template) that are passed.
It binds data to form controls and allows the user to edit the data.
It talks to Services or other state managers.
It uses routing information like the current URL and URL parameters.
All these tasks 👆 need to be tested properly.
Types of component unit tests:
Rendering tests: Does the component render correctly with the default props or state?
User Interaction: Do buttons, dropdowns, and other interactive elements behave as expected?
Dynamic Behavior: Does the component update/react correctly when props, slots, or inputs change?
State Management: If the component uses local state, is it consistent with user interactions?
Best practices
Focus on User Actions and Outcomes: Test how the component responds to user interactions (clicks, selections, input), rather than how it’s implemented internally.
Verify Dynamic Content: If content in an element is dynamic or conditional, test that it displays the correct information to the user.
Prioritize Accessibility Elements: Validate that accessible elements, like labels for form fields, are correctly associated with their corresponding inputs.
Test Interactive Elements: If users can interact with an element (e.g., click a button, open a dropdown, enter text), include it in your tests.
Skip Purely Visual or Static Elements: Avoid testing static text, simple structural elements, or purely decorative items (e.g., <div> for layout) unless they impact user functionality or accessibility directly.
Test Critical Conditional Rendered Elements: If an element is shown or hidden based on certain conditions (e.g., error messages, loading spinners), ensure it appears as expected when the conditions are met.
pages/
Rendering: Does the page render correctly?
Data Loading: Does the page correctly fetch and display server-provided data for the user?
Error Handling: Are errors (e.g., 404, API failures) displayed in a user-friendly way?
Navigation: Are navigation links and redirections working correctly?
stores/
State Changes: Are user actions (e.g., toggling dark mode, adding items to a cart) accurately reflected in the store state?
Persistence: Is state persisting correctly (e.g., localStorage, cookies) when required?
Derived State: Are computed properties or getters providing correct values based on the store's state?
Reset and Initialization: Does the store initialize/reset correctly during user workflows?
Concurrency: Are multiple users or sessions handled gracefully, avoiding race conditions?
composables/
Functionality: Does the composable return the expected state or functions when used?
Reactiveness: Are changes to inputs (e.g., user search query, filters) properly tracked and reactive?