際際滷

際際滷Share a Scribd company logo
Unit testing techniques and
Role of Test doubles
Ritesh Mehrotra
About Techtalks
To build a community for
collaborative and continuous
learning
 Technology trends
 Tools and techniques
 Software engineering practices
 Ways of working
 Tech careers
About me
 Technical agility coach with Singapore Airlines
 Worked in Investment banking, Fintech and Software services
 Talk about Software craftsmanship, quality and agility
 Trainer for Agile Product and Delivery management (APM), Product
Ownership(APO), Facilitation(ATF) and Foundation (ICP) with ICAgile
 Co-founded TechTalks in 2016
Agenda
 Foundation of Unit testing
 Testing paradigm
 Unit of work
 Organizing a unit test
 Testing with dependencies
 Test doubles - Fakes, Stubs, Mocks, Dummies and Spies
 Examples
Unit testing foundation
What is a unit test?
Validates the expectations with the code
Why unit tests?
 Builds developer confidence in code
 Makes future changes easier
 Helps to improve software quality.
 Helps to understand the system behaviour.
 Strengthens deployability of the code
Cost of automated testing
Reference: xUnit Test patterns  Gerard Meszaros
How big is a unit?
 Instantiating an object?
 Setting field values?
 Or A CRUD operation?
Unit of work
Terminology
 SUT/CUT  System under test or Code under test
 Fixture  The environment to run the tests on the SUT/CUT
 Pre test conditions
 Post test cleanup
 DOC  depended-on component
Principles for unit testing
 Deterministic
 Automated
 Quick to run
 Should not fail when codes internal structure changes
 Should fail when the behavior of code changes
 Cheap to read, write and change
 Tests should reduce (and not introduce) risk.
 Tests should be isolated and not dependent on each other
Example: E-commerce
Fixture
Code smells with Fixtures
 Duplication
 Hurts readability and understandability
 Hard to maintain
Better Fixtures
 Explicit extraction
 Extract methods with fixture and teardown code
 Call method in each relevant test case
 Implicit reference
 @Before and @After annotated methods for setup/teardown
Example  Implicit Fixture
Organizing a unit test case - AAA pattern
Arrange
 Bring SUT to a desired state before
testing
Act
 Act on the SUT by executing the
methods
Assert
 Validate the output against
expectations
Automated Testing Strategies
Test pyramid
E2E Testing
Integration testing
Unit testing
 Each layer indicates a levels of
granularity for testing
 The lower levels focus on
isolated code behaviors
 Higher levels focus on
component integration and
overall system
 Unit testing is cheaper and E2E
testing is costlier in terms of
 Time to run
 Time to change
 Flakiness
Unit vs Integration Testing
Unit Testing vs Integration Testing
Characteristics Unit Test Integration Test
Interface Works independently of real
interface (File system, Database,
API)
Depends on interface
Time Quick to run Time consuming operation
Reliability Very reliable since meant to be
isolated
Flaky at time depending on
environment stability
Target Tests behavior of the code Tests behavior as well as
interactions between objects
Environment Environment independent Environment dependent
Testability examples
My Cleaning Robot
Use cases
Interaction with robot
Use Case  Robo Helper Greet
Time period of the day
 A class with static
method that returns
time period of the day
 Returns values
Morning, Afternoon
or Evening based on
LocalDateTime
Robot class code and test
Testcase
Implementation
Challenges
 System time (Data source)
tightly coupled within
TimeOfTheDay class
 Cant reuse this class
with any other source of
date/time
 It violates SRP  Fetches time
and processes it
 Unit test cannot be
deterministic
Consideration
Pass LocalDateTime as
parameter to TimePeriod
Refactored code
Implementation - Robot
Implementation - TimeOfTheDay
Inversion of
control
 Abstract concrete
implementation to an
interface
 Refactor to inject a stubbed
implementation to Robot
Dependency injection  Robot Class
DateTimeProvider implementations
Testing Robot Greeting
Real implementation Test implementation
Test doubles
Types of test doubles
Stubs Dummy Fakes
Mock Spies
Use case  Order robot supplies
Code Structure
Scenarios  Cart behavior
Cart class
Stub
A filler object to satisfy behavioral needs of code through
canned responses. Used as an alternative to expensive
integration testing for testing dependency responses
Cart test with stubs
With available stock Without stock
Dummy
A filler object to satisfy structural needs of code under test.
Used as a test helper and doesnt impact the behavior of code
under test.
Scenarios  Cart behavior with multiple items
Fake
A Fake object has a working implementation and behavior.
Though meant for testing purpose and not suitable for
production. For instance, using in-memory database instead of
connecting to real database instance for operations
Cart test with Fake inventory
Scenario  Invalid cart order
 Adding order to cart
 When item name is empty or when quantity is not greater than ZERO
 Dont call inventory service
 Dont add to cart
Spy
Spy is a stub that also records the interaction with caller
objects
Cart test with Spy inventory
Mock
Mock is a spy that verifies the interactions with caller object
and fails if it doesnt meet expectations
Mock class
Cart test with Mock inventory
Some Test frameworks
Java  Mockito, EasyMock
React - Jest
Javascript  Jasmine, Sinon
Python  unittest.mock
C#- Moq
Examples
Mockito mock
Alternative for expectation
when(inventoryService.reserve(anyString(),anyInt())).thenReturn(ItemStatus.RESERVED);
Alternative for verification
verify(inventoryService).reserve(cleaningBrushes.getItemName(),cleaningBrushes.getQuantity());
Mockito mock facts
 Its a test double, unless you want to call real method
 Stubbing is integrated with then methods
Mockito Spy
 Represents the concept of partial mock
 It calls real method, unless you want to mock
Mockito Spy with Stubbed return value
Conclusion
 Unit testing helps to keep code maintainable and understandable
 Helps to quickly validate the code expectations and hence ensuring
quality
 Test double strategies help to replace the behaviors of DOC and run
tests in isolation
Thank you

More Related Content

Unit Testing and role of Test doubles

  • 1. Unit testing techniques and Role of Test doubles Ritesh Mehrotra
  • 2. About Techtalks To build a community for collaborative and continuous learning Technology trends Tools and techniques Software engineering practices Ways of working Tech careers
  • 3. About me Technical agility coach with Singapore Airlines Worked in Investment banking, Fintech and Software services Talk about Software craftsmanship, quality and agility Trainer for Agile Product and Delivery management (APM), Product Ownership(APO), Facilitation(ATF) and Foundation (ICP) with ICAgile Co-founded TechTalks in 2016
  • 4. Agenda Foundation of Unit testing Testing paradigm Unit of work Organizing a unit test Testing with dependencies Test doubles - Fakes, Stubs, Mocks, Dummies and Spies Examples
  • 6. What is a unit test? Validates the expectations with the code
  • 7. Why unit tests? Builds developer confidence in code Makes future changes easier Helps to improve software quality. Helps to understand the system behaviour. Strengthens deployability of the code
  • 8. Cost of automated testing Reference: xUnit Test patterns Gerard Meszaros
  • 9. How big is a unit? Instantiating an object? Setting field values? Or A CRUD operation?
  • 11. Terminology SUT/CUT System under test or Code under test Fixture The environment to run the tests on the SUT/CUT Pre test conditions Post test cleanup DOC depended-on component
  • 12. Principles for unit testing Deterministic Automated Quick to run Should not fail when codes internal structure changes Should fail when the behavior of code changes Cheap to read, write and change Tests should reduce (and not introduce) risk. Tests should be isolated and not dependent on each other
  • 15. Code smells with Fixtures Duplication Hurts readability and understandability Hard to maintain
  • 16. Better Fixtures Explicit extraction Extract methods with fixture and teardown code Call method in each relevant test case Implicit reference @Before and @After annotated methods for setup/teardown
  • 17. Example Implicit Fixture
  • 18. Organizing a unit test case - AAA pattern Arrange Bring SUT to a desired state before testing Act Act on the SUT by executing the methods Assert Validate the output against expectations
  • 20. Test pyramid E2E Testing Integration testing Unit testing Each layer indicates a levels of granularity for testing The lower levels focus on isolated code behaviors Higher levels focus on component integration and overall system Unit testing is cheaper and E2E testing is costlier in terms of Time to run Time to change Flakiness
  • 22. Unit Testing vs Integration Testing Characteristics Unit Test Integration Test Interface Works independently of real interface (File system, Database, API) Depends on interface Time Quick to run Time consuming operation Reliability Very reliable since meant to be isolated Flaky at time depending on environment stability Target Tests behavior of the code Tests behavior as well as interactions between objects Environment Environment independent Environment dependent
  • 26. Use Case Robo Helper Greet
  • 27. Time period of the day A class with static method that returns time period of the day Returns values Morning, Afternoon or Evening based on LocalDateTime
  • 28. Robot class code and test Testcase Implementation
  • 29. Challenges System time (Data source) tightly coupled within TimeOfTheDay class Cant reuse this class with any other source of date/time It violates SRP Fetches time and processes it Unit test cannot be deterministic
  • 31. Refactored code Implementation - Robot Implementation - TimeOfTheDay
  • 32. Inversion of control Abstract concrete implementation to an interface Refactor to inject a stubbed implementation to Robot
  • 33. Dependency injection Robot Class
  • 35. Testing Robot Greeting Real implementation Test implementation
  • 37. Types of test doubles Stubs Dummy Fakes Mock Spies
  • 38. Use case Order robot supplies
  • 40. Scenarios Cart behavior
  • 42. Stub A filler object to satisfy behavioral needs of code through canned responses. Used as an alternative to expensive integration testing for testing dependency responses
  • 43. Cart test with stubs With available stock Without stock
  • 44. Dummy A filler object to satisfy structural needs of code under test. Used as a test helper and doesnt impact the behavior of code under test.
  • 45. Scenarios Cart behavior with multiple items
  • 46. Fake A Fake object has a working implementation and behavior. Though meant for testing purpose and not suitable for production. For instance, using in-memory database instead of connecting to real database instance for operations
  • 47. Cart test with Fake inventory
  • 48. Scenario Invalid cart order Adding order to cart When item name is empty or when quantity is not greater than ZERO Dont call inventory service Dont add to cart
  • 49. Spy Spy is a stub that also records the interaction with caller objects
  • 50. Cart test with Spy inventory
  • 51. Mock Mock is a spy that verifies the interactions with caller object and fails if it doesnt meet expectations
  • 53. Cart test with Mock inventory
  • 54. Some Test frameworks Java Mockito, EasyMock React - Jest Javascript Jasmine, Sinon Python unittest.mock C#- Moq
  • 56. Mockito mock Alternative for expectation when(inventoryService.reserve(anyString(),anyInt())).thenReturn(ItemStatus.RESERVED); Alternative for verification verify(inventoryService).reserve(cleaningBrushes.getItemName(),cleaningBrushes.getQuantity());
  • 57. Mockito mock facts Its a test double, unless you want to call real method Stubbing is integrated with then methods
  • 58. Mockito Spy Represents the concept of partial mock It calls real method, unless you want to mock
  • 59. Mockito Spy with Stubbed return value
  • 60. Conclusion Unit testing helps to keep code maintainable and understandable Helps to quickly validate the code expectations and hence ensuring quality Test double strategies help to replace the behaviors of DOC and run tests in isolation