2. § Introduction
§ What is a unit test?
§ What is TDD?
§ Why use TDD?
§ TDD Misconceptions
§ Are Unit test Useless?
§ What’s a good unit test?
§ Unit vs functional vs Integration
§ How to start TDD at work
§ Summary
§ Demo
3. § Tests are the first line of the defense
§ Enhance documentation
§ Help design your code
§ Help in refactoring, adding, modifying or removing features
§ Help in preventing broken builds to production
§ Help in developer understand the component requirement
4. § Very clearly defined purpose and set of attributes
§ ONE specific requirement for ONE specific method
6. § "Test-driven development (TDD) is a software development process that relies on
the repetition of a very short development cycle: requirements are turned into very
specific test cases, then the software is improved to pass the new tests, only." -
WikipediA
7. § Write a failing test (Red)
§ Implement the code and make the test pass (Green)
§ Refactor (If needed)
8. § TDD reduces production bug density by 40–80% (based on studies)
§ Reduces maintenance costs
§ Increase developer productivity in the long term
§ Encourage more modular design
§ Reduces code complexity
§ Reduces the interruption of the normal flow of software development
9. § It's too time consuming
§ You can't write test until you know the design and implement the code
§ You have to write all tests before you write the code
§ Everything needs unit tests
15. § Which component was tested?
§ What is the expected behavior?
§ What's the expected result?
§ What was the actual output?
§ How can the test be reproduced?
16. § Unit tests ensure that individual components of the app work as expected
§ Integration tests ensure that component collaborations work as expected
§ Functional tests ensure that the app works as expected from the user’s perspective
17. § Ideally, we'd start a new project with TDD
§ Start a new task with unit tests
§ Fix bugs with unit tests if possible
18. § TDD
§ Write a failing test (Red)
§ Implement the code and make the test pass (Green)
§ Refactor (If needed)
19. § Guidelines of successful tests
§ One assertion per test
§ Test output produces clear documentation
§ Tests are simple and understandable at a glance
§ Tests are treated like code
20. § Which component was tested?
§ What is the expected behavior?
§ What's the expected result?
§ What was the actual output?
§ How can the test be reprod uced?
21. § TDD does not replace architecture or Design
§ TDD will inform and validate (or not) your design
§ Weakness and flaws in design will be uncovered
§ Finding bugs in development is much better than finding them in production
§ “Perfect is the enemy of good.”Voltaire
22. § 5 Questions Every Unit Test Must Answer - https://medium.com/javascript-
scene/what-every-unit-test-needs-f6cd34d9836d
§ 5 Common Misconceptions About TDD & Unit Tests -
https://medium.com/javascript-scene/5-common-misconceptions-about-
tdd-unit-tests-863d5beb3ce9
§ Empirical Studies Show Test Driven Development Improves Quality -
https://www.infoq.com/news/2009/03/TDD-Improves-Quality
Notes de l'éditeur
We all know that we should write unit tests to prevent defects but a lot of us don't really know the essential ingredients of unit testing.
To have something reliable and durable, you can't just grab things and see if it fits together. There are specification to each component of the system.
There are checkpoints to make sure each part of the system is successful
Each individual component
Interaction of groups of component
Workings as a whole
Tests are the first line of the defense and will ensure the success of application.
In addition of making sure the system is working correctly, test can also:
Enhance existing (or not) documentation by showing an example of implementation
Help design your code
Help in refactoring, adding, modifying or removing features
Help in preventing broken builds to production
Help in developer understand the component requirement. The difficult things and surprises are tackled early on
Before we can get into a discussion of exactly what TDD is and how it works, it’s important to have a common and defined understanding about what a unit test is.
A unit test is a very specific type of test with a very clearly defined purpose and set of attributes. It tests ONE specific requirement for ONE specific method
They have the following attributes:
Targeted: test one thing, one set of inputs at a time
Isolated: The code tested should be isolated (from other code and external dependencies or events)
Repeatable/Predictable: if the code and test did not change, running the test any amount of time will produce the same result
Independent: Unit tests should be able to be run in any order. They should not expect or require that they follow a certain sequence
Encourages Simplification: If the testing of the function is too complex then most likely the function is doing too much
"Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved to pass the new tests, only." - Wikipedia
So:
Write a failing test (Usually displayed in Red)
Implement the code and make the test pass (Usually displayed in Green)
Refactor (If some issue with performance or really bad code)
The benefits of TDD have been tested on real projects by companies like Microsoft and IBM, and they found that the TDD process is enormously beneficial. Check out https://www.infoq.com/news/2009/03/TDD-Improves-Quality
TDD reduces production bug density by 40–80%. Says 90% in study.
Reduces maintenance costs: The teams' management reported subjectively a 15–35% increase in initial development time for the teams using TDD, though the teams agreed that this was offset by reduced maintenance costs
Increase developer productivity in the long term
Encourage more modular design
Reduces code complexity
Reduces the interruption of the normal flow of software development
Increase things like user retention, increase of users (Probably not at C1)
Reduce customer abandonment (Probably not at C1)
Reduce the costs of customer service (probably not at C1)
I hear this all the time:
It's too time consuming: While the process adds 10%-30% to initial development, over time, when you factor maintenance, bug fixes rewrites, this offsets in maintenance costs
You can't write test until you know the design and implement the code. Studies have concluded that writing tests first is more effective than adding tests later (TDD reduces production bug density by 40–90%). TDD forces you have a direction in mind before you start and having a better direction leads to better design
You have to write all tests before you write the code. Not true. We try things and explore options until we get the result we want
Everything needs unit tests: If you have to do a lot of mocking, perhaps that code doesn’t need a unit test. Maybe a functional tests would be better.
Badly designed and written tests can cause more pain than help.
The trouble with tests:
You can have Brittle tests: easy to break
You can have Complicated tests: Cost developer time to understand the test
Ignored Tests: When test repeatedly fails, developers loose confidence in validity and mark them as ignored. It happens all the time with false positives.
How to make them work
Follow Best Practices: Write tests like real code
Robust tests: Test the right things
Do and Learn
Code, code, code
The more you code, the easier it gets
So what’s a good unit test?
Features
Design aid: written during design phase, prior to implementation
Feature documentation & test of developer understanding: The test should provide a clear description of the feature being tested
QA/Continuous Delivery: The tests should halt the delivery pipeline on failure and produce a good bug report when they fail
Need a good bug report
The failure report should be able to show you exactly what failed and where to look
Built for speed
Running test should be quick and simple. Ideally, constantly running in the background.
Questions to ask
These are the 5 questions a unit test should easily answer when you look at it
Which component was tested?
What is the expected behavior?
What's the expected result?
What was the actual output?
How can the test be reproduced?
Unit tests ensure that individual components of the app work as expected. Assertions test the component API
Integration tests ensure that component collaborations work as expected. Assertions may test component API, UI, or side-effects (such as database I/O, logging, etc.…)
Functional tests ensure that the app works as expected from the user’s perspective. Assertions primarily test the user interface
For your current project, how do you start TDD?
Ideally, we'd start a new project with TDD
Start a new task with unit tests
Fix bugs with unit tests if possible
In summary, TDD is a good process to deliver better quality code and gives more confidence in delivery
The TDD cycle is:
Write a failing test (Red)
Implement the code and make the test pass (Green)
Refactor (If some issue with performance or really bad code)
One assertion per test (except when it makes sense. For example, checking if a function exists and is not null)
If many things are tested at once, you'll have to unravel the results
The test can become difficult to understand
(show good test vs crappy test)
Test output produces clear documentation
Naming the test with a specific naming convention (what's been tested, test conditions, expectation)
Tests are simple and understandable at a glance
Should be able to look at it and understand it immediately
Shouldn't be branching & looping
Tests are treated like code: refactored, optimized and improved
Easy to maintain & extend
Don't repeat yourself
Questions to ask
These are the 5 questions a unit test should easily answer when you look at it
Which component was tested?
What is the expected behavior?
What's the expected result?
What was the actual output?
How can the test be reproduced?
It’s a learning curve and it takes time to get the hang of it. A lot of times, it’s takes discipline to do it. Especially when you have deadlines and someone breathing down your neck.
TDD does not replace architecture or Design (You need to do some up front design and have a vision)
TDD will inform and validate (or not) your design
Weakness and flaws in design will be uncovered
Finding bugs in development is much better than finding them in production
“Perfect is the enemy of good.” Voltaire