TDD – Validate Shopping Cart Quantity
In this series on Test-Driven Development (TDD), we are using a unit tests-first approach to drive the creation of a ShoppingCart class. The classic use case for ShoppingCart would be in eCommerce software, for example. Currently, we are building up the capability to put items into ShoppingCart via an Add() method – e.g. 5 Apples, 1 Ferrari, 3 bars of chocolate – you get the idea.
Last time we made our ShoppingCart throw an exception when Add() didn’t receive a valid Product – i.e. the Product argument was null.
Add() also requires a valid quantity of Product. We should test for adding an invalid quantity into our ShoppingCart. What is the simplest invalid quantity? How about 0? Is there a point of adding 0 Bananas into our ShoppingCart? No, there is not. More Thorns to cover off before we hit The Gold.
OK, let’s write the unit test in the highly readable Given-When-Then format:
We have two build errors in our test. Not compiling is failing. We expected the test to fail – so far, so good.
Please note that we are passing a dummy Product into Add(). At this point, it does not matter what the Product is as long as it is not null.
What are our build errors?
- Add() is not expecting a second argument, and
- ZeroQuantity exception does not exist.
The test drives us to fix these errors. Let’s add the quantity parameter to Add():
This action fixed the first build problem in our new unit test:
However, we have a new problem: Creating a new parameter on Add() broke a previous unit test:
How do we fix this unit test? Let’s add a valid quantity argument of, say, 3. Any positive integer value would work.
Why do we use a valid parameter? 0 would also work. The problem is that a 0 quantity, an invalid value, may confuse a casual reader of the test: Is this test about a null Product or 0 quantity or both? It’s just about null Product. We should always aim to sidestep ambiguity. Therefore we set the quantity to 3.
OK, we have dealt with this diversion of fixing an earlier, broken test, let’s come back to our new unit test. We have one more build error remaining – we need a ZeroQuantity exception. Let’s create it:
Now our test builds:
Running all unit tests for ShoppingCart results in:
Unsurprisingly, we are getting a MissingProduct exception, not a ZeroQuantity exception. Add() in its current form is always throwing a MissingProduct exception:
It is as this point that we get to qualify with a conditional statement as to when we throw the MissingProduct exception:
Interestingly, the implementation code lags behind the tests by one iteration. We didn’t need the if statement before – we were only testing for MissingProduct exception. Now that we are also throwing a ZeroQuantity exception, the conditional is necessary.
That looks much better. Let’s rerun our tests:
All tests are passing and ShoppingCart.Add() now handles a 0 quantity.