TEST DRIVEN DEVELOPMENT
Content


 1. Definition of Unit Test and benefits of writing unit
    tests.
 2. TDD introduction, methodology and benefits.
 3. Effective use of TDD.
 4. Applying TDD to our project.
What is a “Unit Test”?


  A "unit" is a piece of code, method or function that
  has a single responsibility.
  A "unit test" is a piece of code that invokes another
  piece of code and checks the correctness of some
  assumptions. If the assumptions turn out to be
  wrong, the unit test has failed.
Unit Test Benefits
  compare to Integration Test




             Integration Test                                 Unit Test
• A integration test group 2 or more        • A unit test tests only a single unit in
  dependent units and test to see if they     isolation
  work properly together.
• Integration tests are harder to write,    • Unit tests are easy to implement, they
  easy to fail if they have an external       works with fake dependencies(Stub and
  dependency which is unavailable for         Mock), run and give results quickly
  some reason
• Integration tests are hard to maintain.   • Unit tests are super easy to maintain
  When a test fail, we have to debug to       because they cover a small piece of
  see what is our problem.                    functionality.
• Integration tests help to document        • Unit tests help to design and document
  main features of our application.           our code.
TDD Introduction


  Traditional approach: many people feel that the best time
  to write unit tests for software is after the software has
  been written. It sounds reasonable but there is code we
  can’t write unit test without modifying. There’re many
  cases we have to modify our code to make it unit-testable,
  which may lead to other problems, slow down our
  schedule…
  Test Driven Development: Write tests first, use unit tests
  drive the design and document our code. With TDD, we
  begin with the end in mind.
TDD Methodology


  The general TDD cycle goes as follows:
  1.   Write a failing test first to prove code or functionality is
       missing. The test will fail because we haven't implemented
       that functionality yet.
  2.   Make the test pass by writing production code that meets
       the expectations of your test. At that moment, we just need
       to pass the test, the code should be as simple as possible.
  3.   Refactor your code when the test passes, make it more
       readable, remove code duplication...
  By writing and passing unit tests, we add more
  functionality, a bit at a time until all requirements are
  fulfilled.
TDD Benefits


  Writing unit tests actively will make most of our code are
  covered by unit tests. That will raise the confidence in the
  code.
  Help to create quality code, better designs, document our
  code....Write test first help us really understand the design
  of code. Instead of writing code to do something, we're
  starting by outlining all conditions we may have, all
  expected output.
  Speed up our development in a long run. We done when
  we finish the last line of code, we don't need to spend
  much time debugging, we don't need to manually check if
  our new features break the old code, existing features.
TDD Benefits
Effective use of TDD


TDD brings us a lot of benefits.          TDD = Too
However, there is no silver bullet, TDD     Damn
doesn’t ensure project success. On the     Difficult
other hand, TDD is a double-edges
sword and if it is done incorrectly, it
will waste our time, lower our code
quality.
In order to apply TDD effectively, we
have to know exactly what to test and
how to write a good unit test.
What to test?


  Any classes and components that contain logical
  code, e.g. if…else, for, switch…case, any calculation
  or interaction with other components, calls to
  external methods.
  Logical code could be found on server side or client
  size. We have to test them all.
Unit testing on server side


   Repository Layer: verify the persistence and retrieval
   implementations produce the correct results.
   Business Logic Layer: focus on verifying the business rules
   and their interactions with Repository Layer. The tests do
   not actually store data in the repository but use a fake
   repository and verify the business services layers uses it
   correctly.
   Web Layer: we create unit test for request handlers, verify
   their interactions with business service, e.g., "Are they
   called correctly?", "Are the view models returned
   correctly?"
Unit testing on client side


   The basic rule is to test anything a designer would not
   change. We would not test that a specific font value
   was set or a specific background color of an element
   was used.
   We test the property values of a view model, whether
   a calculation is correct, an event is triggered, a DOM
   element are modified correctly, a AJAX callback
   function has been called or not...
How to write a good unit test?


 A good unit test must be simple, trustworthy, maintainable and
 readable.
   Naming unit test:
   MethodUnderTest_Scenario_ExpectedBehavior()
    ex: AuthorizeUser_WrongUserName_ReturnFalse()
   Avoid logic in tests: having logic will increase chances of having
   bugs in unit tests. avoid "if, switch, for..." to generate input, try
   to hard code.
   Testing only one thing, avoid testing multiple aspects: each unit
   test should generally take one action and make one assertion. if
   our tests contain more than a single assert and the first assert
   fails, it will throw exception and the second assert never run.
How to write a good unit test?


  Avoid duplication: put duplicated code in TestCleanup and
  TestInitialize method for maintainable reason.
  Don't test things that obviously work.
  Enforce test isolation: a test should always run in its little
  world, isolated from its dependencies. We do not want to
  think our subject under test is broken because one of its
  dependencies broke and caused the subject under test to
  fail. If We test like this, We might spend a lot of time
  tracking down bugs in the wrong place. Testing how things
  operate together is the domain of integration testing, not
  unit testing.
Applying TDD to our project


  Server side: We still have not implemented business
  services yet, so, most of code reside in action’s
  Execute methods. In those methods, we don’t care
  about what business services do or what they return,
  we only need to test, if we have to, whether they
  have been called correctly or not.
Applying TDD to our project


 On client side, we have 3 layers that contain logic:
   View Model: verify all behaviors(CopyUser, LoadUser…),
   computed properties
   Repository: verify whether the call to server has been
   made and callback function has been triggered correctly or
   not.
   Presenter: most of our UI logic resides here. We should
   write unit test to verify circumstances, e.g. whether a
   button is enabled/disabled, a list is empty, selected item
   changed, user click Save button.
How to write unit-testable code?


Just need to remember: “objects do not create other objects on
which they rely to do their work. Instead, they get the objects that
they need from an outside source”.

We have 4 common ways to achieve this: Constructor, Setter and
Getter, Interface, Service Locator(factory pattern, local factory
method).

All necessary techniques can be found in:
   The Art of Unit Testing – Manning
   Test-driven Development By Example - Addison Wesley
   Dependency Injection in .NET - Manning
Q&A

Test driven development

  • 1.
  • 2.
    Content 1. Definitionof Unit Test and benefits of writing unit tests. 2. TDD introduction, methodology and benefits. 3. Effective use of TDD. 4. Applying TDD to our project.
  • 3.
    What is a“Unit Test”? A "unit" is a piece of code, method or function that has a single responsibility. A "unit test" is a piece of code that invokes another piece of code and checks the correctness of some assumptions. If the assumptions turn out to be wrong, the unit test has failed.
  • 4.
    Unit Test Benefits compare to Integration Test Integration Test Unit Test • A integration test group 2 or more • A unit test tests only a single unit in dependent units and test to see if they isolation work properly together. • Integration tests are harder to write, • Unit tests are easy to implement, they easy to fail if they have an external works with fake dependencies(Stub and dependency which is unavailable for Mock), run and give results quickly some reason • Integration tests are hard to maintain. • Unit tests are super easy to maintain When a test fail, we have to debug to because they cover a small piece of see what is our problem. functionality. • Integration tests help to document • Unit tests help to design and document main features of our application. our code.
  • 5.
    TDD Introduction Traditional approach: many people feel that the best time to write unit tests for software is after the software has been written. It sounds reasonable but there is code we can’t write unit test without modifying. There’re many cases we have to modify our code to make it unit-testable, which may lead to other problems, slow down our schedule… Test Driven Development: Write tests first, use unit tests drive the design and document our code. With TDD, we begin with the end in mind.
  • 6.
    TDD Methodology The general TDD cycle goes as follows: 1. Write a failing test first to prove code or functionality is missing. The test will fail because we haven't implemented that functionality yet. 2. Make the test pass by writing production code that meets the expectations of your test. At that moment, we just need to pass the test, the code should be as simple as possible. 3. Refactor your code when the test passes, make it more readable, remove code duplication... By writing and passing unit tests, we add more functionality, a bit at a time until all requirements are fulfilled.
  • 7.
    TDD Benefits Writing unit tests actively will make most of our code are covered by unit tests. That will raise the confidence in the code. Help to create quality code, better designs, document our code....Write test first help us really understand the design of code. Instead of writing code to do something, we're starting by outlining all conditions we may have, all expected output. Speed up our development in a long run. We done when we finish the last line of code, we don't need to spend much time debugging, we don't need to manually check if our new features break the old code, existing features.
  • 8.
  • 9.
    Effective use ofTDD TDD brings us a lot of benefits. TDD = Too However, there is no silver bullet, TDD Damn doesn’t ensure project success. On the Difficult other hand, TDD is a double-edges sword and if it is done incorrectly, it will waste our time, lower our code quality. In order to apply TDD effectively, we have to know exactly what to test and how to write a good unit test.
  • 10.
    What to test? Any classes and components that contain logical code, e.g. if…else, for, switch…case, any calculation or interaction with other components, calls to external methods. Logical code could be found on server side or client size. We have to test them all.
  • 11.
    Unit testing onserver side Repository Layer: verify the persistence and retrieval implementations produce the correct results. Business Logic Layer: focus on verifying the business rules and their interactions with Repository Layer. The tests do not actually store data in the repository but use a fake repository and verify the business services layers uses it correctly. Web Layer: we create unit test for request handlers, verify their interactions with business service, e.g., "Are they called correctly?", "Are the view models returned correctly?"
  • 12.
    Unit testing onclient side The basic rule is to test anything a designer would not change. We would not test that a specific font value was set or a specific background color of an element was used. We test the property values of a view model, whether a calculation is correct, an event is triggered, a DOM element are modified correctly, a AJAX callback function has been called or not...
  • 13.
    How to writea good unit test? A good unit test must be simple, trustworthy, maintainable and readable. Naming unit test: MethodUnderTest_Scenario_ExpectedBehavior() ex: AuthorizeUser_WrongUserName_ReturnFalse() Avoid logic in tests: having logic will increase chances of having bugs in unit tests. avoid "if, switch, for..." to generate input, try to hard code. Testing only one thing, avoid testing multiple aspects: each unit test should generally take one action and make one assertion. if our tests contain more than a single assert and the first assert fails, it will throw exception and the second assert never run.
  • 14.
    How to writea good unit test? Avoid duplication: put duplicated code in TestCleanup and TestInitialize method for maintainable reason. Don't test things that obviously work. Enforce test isolation: a test should always run in its little world, isolated from its dependencies. We do not want to think our subject under test is broken because one of its dependencies broke and caused the subject under test to fail. If We test like this, We might spend a lot of time tracking down bugs in the wrong place. Testing how things operate together is the domain of integration testing, not unit testing.
  • 15.
    Applying TDD toour project Server side: We still have not implemented business services yet, so, most of code reside in action’s Execute methods. In those methods, we don’t care about what business services do or what they return, we only need to test, if we have to, whether they have been called correctly or not.
  • 16.
    Applying TDD toour project On client side, we have 3 layers that contain logic: View Model: verify all behaviors(CopyUser, LoadUser…), computed properties Repository: verify whether the call to server has been made and callback function has been triggered correctly or not. Presenter: most of our UI logic resides here. We should write unit test to verify circumstances, e.g. whether a button is enabled/disabled, a list is empty, selected item changed, user click Save button.
  • 17.
    How to writeunit-testable code? Just need to remember: “objects do not create other objects on which they rely to do their work. Instead, they get the objects that they need from an outside source”. We have 4 common ways to achieve this: Constructor, Setter and Getter, Interface, Service Locator(factory pattern, local factory method). All necessary techniques can be found in: The Art of Unit Testing – Manning Test-driven Development By Example - Addison Wesley Dependency Injection in .NET - Manning
  • 18.