sravimohan/angular-testing-patterns

★ 0Forks 0GitHub ↗Compare

README

State of Angular Testing

  • Unit Testing (ng test)

  • End-to-End Testing (ng e2e)

  • Comparison: ng test vs ng e2e

    • Unit Testing (ng test)
      • Pros:
        • Fast execution
        • Isolates individual components
        • Easier to debug
      • Cons:
        • Limited scope (doesn't test integration)
        • May miss issues that only appear in a full application context
        • Requires extensive mocking, especially for Angular services and dependencies
    • End-to-End Testing (ng e2e)
      • Note here that e2e in this context is specifically about ng e2e and not the wider meaning of end-to-end testing. The main difference is the application is rendered to a browser as a user would use it. We will run these tests as part of CI. We will only mock the external dependencies like authentication and API calls.
      • Pros:
        • Tests the entire application flow
        • Catches integration issues
        • Simulates real user interactions
        • Easier to set up with tools like Playwright
      • Cons:
        • Slower execution
        • More complex to maintain
        • Harder to debug
  • Front-End Unit Testing Considerations

    • Should the DOM be included in unit tests?

      • Pros:
        • Ensures components render correctly
        • Catches issues related to template bindings and directives
        • Provides more realistic test scenarios
      • Cons:
        • Slower test execution
        • Increased complexity in test setup
        • Harder to isolate component logic from presentation
    • When to add tests:

      • TDD: Write tests first, then implement features.
      • For each task in Jira, update or delete tests as needed.
      • When the component's scope is stable and unlikely to change significantly.
    • Building iteratively without full scope:

      • Frequent test updates may be required.
      • Initial tests might have incomplete coverage.
      • Increased maintenance due to constant changes.
      • Potential for redundant work on tests for features that change or are removed.
      • Strategies:
        • Incremental testing: Update tests as scope evolves.
        • Modular design: Keep components decoupled.
        • Communication: Stay updated with stakeholders.
        • Flexible testing: Combine unit and end-to-end tests.
    • Focus unit tests on reasonably complex logic:

      • Avoid writing tests for trivial code.
      • Prioritize testing critical and complex parts of the application.
      • Use end-to-end tests to cover broader application behavior.
  • Pragmatic Unit Testing Guidelines for the Front-End

    • When to Write Unit Tests:
      • Complex Business Logic: Test components or services with complex logic.
      • Critical Functionality: Focus on critical parts of the application.
      • Reusable Components: Ensure reusable components work in different contexts.
      • Edge Cases: Cover likely edge cases that are hard to test manually.
    • When to Skip Unit Tests:
      • Simple Components: Skip tests for trivial components.
      • Rapid Prototyping: Focus on features first, add tests later.
      • Low-Risk Areas: Skip tests for low-risk, stable parts of the application.
    • Balancing Unit and End-to-End Tests:
      • Use unit tests for isolated logic and small components.
      • Use end-to-end tests for user flows and integration points.
    • Code Review Practices:
      • Discuss the need for tests during code reviews.
      • Focus on the value of tests rather than enforcing strict rules.
    • Front-End vs. Back-End Unit Testing
      • Front-End Unit Testing:
        • Focuses on user interface components and interactions.
        • Often requires mocking of services and dependencies.
        • Tests may include DOM manipulation and rendering.
        • More prone to changes due to evolving UI requirements.
      • Back-End Unit Testing:
        • Focuses on business logic, data processing, and APIs.
        • Typically involves less mocking as dependencies are more stable.
        • Tests are more stable and less likely to change frequently.
        • Often easier to isolate logic without dealing with UI complexities.
      • Different Rules for Front-End and Back-End:
        • Front-end tests should prioritize critical and complex UI logic.
        • Back-end tests should cover business logic and data integrity.
        • Avoid enforcing the same testing rules for both; tailor strategies to the specific needs of each layer.
    • Additional Interesting Thoughts:

Pragmatic Unit Testing Guidelines in Angular

  • Guidelines for Writing Unit Tests in Angular:
    • Focus on Business Logic:
      • Write unit tests for services and components that contain significant business logic.
      • Ensure that critical calculations, data transformations, and decision-making processes are thoroughly tested.
    • Test Reusable Components:
      • Prioritize testing for components that are reused across the application.
      • Verify that these components work correctly in different contexts and with various inputs.
    • Mock Dependencies:
      • Use Angular's testing utilities to mock services, HTTP calls, and other dependencies.
      • Focus on testing the component's logic rather than the behavior of its dependencies.
    • Avoid Over-Testing Simple Components:
      • Skip unit tests for trivial components with minimal logic, such as simple display components.
      • Rely on end-to-end tests to ensure these components render correctly within the application.
    • Use TestBed for Complex Components:
      • Utilize Angular's TestBed to set up and configure the testing environment for complex components.
      • Include necessary declarations, providers, and imports to mimic the real application environment.
    • Leverage Angular Testing Tools:
      • Use tools like Jasmine and Karma for writing and running unit tests.
      • Consider migrating to Jest or Web Test Runner for improved performance and features.
    • Maintain Test Readability:
      • Write clear and concise test cases that are easy to understand and maintain.
      • Use descriptive names for test cases to indicate their purpose and expected outcome.
    • Integrate Testing into CI/CD:
      • Ensure that unit tests are part of the continuous integration and deployment pipeline.
      • Run tests automatically on code changes to catch issues early in the development process.
    • Preference for End-to-End Testing:
      • Prioritize end-to-end tests for comprehensive coverage of user flows and integration points.
      • Use unit tests selectively for critical and complex logic that cannot be effectively tested through end-to-end tests.
      • Balance the use of both testing types to achieve thorough and efficient test coverage.
      • End-to-end tests are more resilient to refactoring, as they focus on user interactions and overall application behavior rather than internal implementation details.
    • Prefer Adding Tests When Reasonable:
      • Add tests when they provide significant value in catching bugs or ensuring critical functionality.
      • Avoid enforcing tests for every piece of code, especially trivial or low-risk areas.
      • Encourage developers to use their judgment to determine when tests are necessary.

Contributors

sravimohan

Issues