Welcome to the fourth chapter of the test driven development course.
In the last chapter, we learned how to write a trustworthy set of tests for a system under test.
In this chapter, we will visualize the TDD flow as a checklist so that you can easily follow and write
tests.
We will also learn about the three laws of TDD and use them in practice.
Finally, we will learn a new technique for discovering new scenarios.
Let's review our workflow so far rather than jumping into code.
We start by thinking about the scenario.
Then we translate the scenario into code and go through the red green refactor process.
Once we're done with the final refactoring, we check whether the test is trustworthy enough or not
by using the devil's advocate technique.
Then we check whether any other behavior is missing from the system under test.
You can check if the system under test needs any other behavior to complete its job by looking at the
production code.
As in our example, we looked at our flight class and realized that it did notrillionemember its bookings
and we added the flight remembers booking scenario.
If the system under test does its job entirely and doesn't require any other behavior, you can find
a new scenario for system under test.
Otherwise you can specify a new unit test to add a new behavior that's missing from the system under
test.
You can use this flowchart right here as a checklist while practicing TDD.
It would also be very helpful to keep an eye on the test driven development rules while writing tests.
Test driven development has three general rules.
Write production code only to pass a failing test.
Write no more of a unit test than sufficient to fail.
Write no more production code than necessary to pass one failing unit test.
You already know that you shouldn't write any production code as long as you don't have any failing
tests.
The second rule of TDD is to stop writing tests as soon as something meaningful fails.
Today we will see what it means in practice.
Now imagine that you have a failing test and you're writing enough production code to pass this test.
You shouldn't write more production code than necessary to pass the actual test.
If you realize that some behavior is missing from the production while trying to pass the test, don't
write production code for missing behavior while attempting to pass the test of another behavior.
For example, when the booking reduces the number of seats test was failing and we are trying to pass
it.
We didn't check for overbooking.
Instead, we wrote a separate test for the avoids overbooking scenario.
We've implemented three scenarios for the booking method.
Is booking the only thing that the flight class should do?
Well, no.
The flight class should also be able to cancel a booking.
Let's add a cancel booking method to our flight class.
Since we're designing the flight class at this point, we need to be specific about what parameters
the flight class needs for canceling a booking to the flight class needs to know how many seats it should
cancel and for which passenger.
So the parameters are the passenger email and the number of seats to cancel.
All right.
We've done enough design for the flight class.
The flight class should be able to cancel the booking.
But what does it mean to cancel the booking?
It's best to always answer this question before writing the actual test code.
When I cancel a booking, what should happen afterwards?
One of the consequences, I expect is that the number of seats should be reduced.
Let's say the flight had three seats of capacity initially and I have booked one seat on it.
Well, when I cancel my booking then three seats should remain bookable on the flight again.
Always try to lead scenarios by examples as we have done it right here.
Now let's translate this scenario into test code and practice applying the second rule of TDD.