Qs: Testing
Why Testing?
Reduction in bugs reported after deployments, which led to faster release cycles and improved customer satisfaction.
Instill a culture of quality within the team.
How would you implement a more robust testing strategy?
Included both unit tests and end-to-end tests.
Assess current testing practices and identify key areas where additional testing could be most beneficial.
Used mental models like the Testing Pyramid to design our testing efforts and agreed on a desired code coverage.
In the initial step, we would be happy with anything above 60%.
What's A Testing Pyramid?
Metaphor for structuring automated tests.
Shape: pyramid — wide at the bottom, narrow at the top.
Core Idea:
Lots of unit tests (fast, isolated).
Fewer integration tests.
Even fewer E2E/UI tests (slow, brittle).
From top to bottom:
Manual and Exploratory Tests
UI and API Testing
Integration Testing
Component Testing
Unit Testing
What's Unit Testing?
Individual pieces of code — the smaller the better.
What's Component Testing?
Tests objects independently, such as modules, classes, and programs. More thorough than unit testing. Often need access to a database or other components. Slower than unit tests.
What's Integration Testing?
Combines the individual software modules and tests them together as a group.
What's Manual and Exploratory Tests?
TODO
Code Coverage
Software testing metric that measures the percentage of a program's source code that is executed when a test suite is run.
Measure % of functions that are tested.
AAA Pattern
Technique to write adequate test cases.
A = Arrange A = Act A = Assert
"Given > When > Then" Pattern
technique to write adequate test cases.
What is a Test Double?
A generic term (Umbrella Term) for any kind of object that replaces a real component in testing.
Includes dummy, stub, fake, mock, and spy.
Why Test Doubles?
To isolate the system under test (SUT) from external complexity.
Typically: test a function in isolation.
To do so, we need to provide a placeholder or replacement.
Types of Test Doubles?
Dummy
Placeholder
Does nothing
Fill unused params
Stub
Provide test data
Returns predefined values
Feed input to SUT
Fake
Lightweight version
Works but not production-ready
External Calls: APIs, DBs...
Mock
Verify interactions
Checks if calls were made
Ensure method was called
Summary:
Dummy = exists but unused
Stub = provides answers
Fake = simplified real thing
Mock = checks expectations
What's a Dummy?
Passed around only because the method signature requires it.
Never actually used in the test.
What's a Stub?
Provides predefined responses.
Used when the SUT needs some data.
No verification of interactions.
Why Stubs? Use Cases?
Avoiding External Calls - i.e. APIs, DBs - isolation & speed
Controlling Edge Cases - i.e. simulate errors or unusual data
Replacing Expensive or Random Behavior
Simulating Slow or Complex Logic - skip heavy processing
What's a Fake?
Has a simplified but working implementation.
Not suitable for production.
Example: in-memory DB.
Why use Mocks in Unit Tests?
If we do not provide a mock, the test will become an INTEGRATION TEST - not a unit test - as it will evaluate the function and its dependencies together.
Used to verify interactions with dependencies.
Typically created with a mocking framework (like Jest).
Are test doubles only used in Unit Testing?
No — test doubles are not only used in unit testing.
But unit testing is where they are most common and essential.
Test doubles can also be useful outside of unit tests:
Integration Testing: Sometimes you still want to isolate part of the system, e.g., replace a payment provider with a fake service to avoid hitting real APIs.
System / End-to-End (E2E) Testing: Often discouraged, but still possible when external services are too costly or unstable. Example: Using a mocked email server to capture emails instead of sending real ones.
To write a unit test for the following function we need to also ...
mockthe validateUser function so the test is constrained to the current functionstubthe fetch call, and return mock data to make the test independent of the availability/response of the backend
What are Spies?
Spy function records the calls to the external function
For instance, to spy on a specific method, and make sure it was called with the right inputs.
When testing with mocks, why use model without relations?
"Without relations" means the type includes only the User's scalar fields, not the relation fields.
Scalar Field = stores a single, indivisible value — something that is not another object or record - i.e. string, int, boolean, date, etc
Relation fields = represents a relationship between two entities/models/tables - typically correspond to foreign keys - i.e. relations One-to-one, One-to-many, Many-to-many
Coverage threshold levels
Conservative (80% overall, 70% per-file)
Pros: Achievable quickly, less friction, focuses on critical paths
Cons: May miss edge cases, lower confidence in refactoring
Best for: Early projects, rapid iteration, small teams
Moderate (85% overall, 75% per-file)
Pros: Good balance, catches most issues, reasonable maintenance
Cons: Some gaps remain, requires consistent discipline
Best for: Most production projects, growing codebases
Strict (90% overall, 80% per-file)
Pros: High confidence, safer refactoring, catches edge cases
Cons: Higher maintenance, can slow development, may encourage low-value tests
Best for: Critical systems, mature codebases, regulated industries
Coverage metrics
Lines
Pros: Simple, fast, easy to understand
Cons: Misses untested branches/conditions, can be misleading
Statements
Pros: More accurate than lines, accounts for multi-line statements
Cons: Similar to lines, still misses branch coverage
Functions
Pros: Ensures functions are called, good for API coverage
Cons: Doesn't verify behavior, can pass with shallow tests
Branches
Pros: Catches untested if/else, switch cases, ternaries; most valuable
Cons: Harder to achieve, can be noisy with defensive code
All metrics (recommended)
Pros: Comprehensive, catches different failure modes
Cons: Strictest, requires thorough testing
Per-file vs global thresholds
Per-file threshold
Pros: Prevents files with 0% coverage, ensures consistent quality
Cons: Can be strict for utility files, may need exceptions
Global threshold only
Pros: Flexible, allows some files to be lower if others are higher
Cons: Can hide files with no coverage
TODOs
Testing REST APIs
Testing REST APIs: Postman?
Testing REST APIs: Integration Tests?
Testing REST APIs: Unit Tests? SuperTest library?
Testing REST APIs: cURL Scripts ?
Last updated