Movie Store – Part 4
Test-Driven Development: write tests before writing code.
Unit testing results in modular code. Modular code is:
- easy to test.
- immune to bugs.
- easy to understand.
- scalable.
Task 1
1. Create a test that fails
Write a unit test named rentMovieTest
. rentMovieTest
asserts the movie at index 1 isn't available after rental.
Inside Store.java
, write code to make the test fail.
/** * Function name: rentMovie * @param name (String) * * Inside the function: * //nothing */
2. Make the test pass
Write code inside Store.java
to make the test pass.
/** * Function name: rentMovie * @param name * * Inside the function: * 1. Loop runs through every element * 2. Set the matching element's availability to false. * */
3. Refactor
Can the code be simpler?
Yes. It's doing too much work. Copy its indexing logic into another method named getMovieIndex
.
/** * Function name: getMovieIndex * @param name (String) * @return (int) * * Inside the function: * 1. returns index if it finds a movie. * 2. returns -1000 otherwise. * */
4. Refactor
Can the code be simpler?
Yes. IntStream
offers a more elegant approach to retrieve an index. Use IntStream
to run through a pipeline of functions.
-
range
: goes from 0 until the size. -
filter
: filters elements that match the predicate. The lambda expression receives each index inside the range and returns a boolean. -
findFirst
: returns the first element that matches the predicate and terminates the pipeline. If it can't find anything, the pipeline continues toorElse
. -
orElse
: returns a random value.orElse
terminates the pipeline no matter what.
Important: As you refactor, run the unit test to make sure there are no bugs.
5. Refactor
Can the code be simpler? No.
Task 2
1. Create a test that fails
Write a unit test named returnMovieTest
. returnMovieTest
asserts that a movie is available after return.
Inside Store.java
, write code to make the test fail.
/** * Function name: returnMovie * @param name (String) * * Inside the function: * //nothing */
2. Make the test pass
/** * Function name: returnMovie * @param name * * Inside the function: * 1. Set the movie's availability to true. */
3. Refactor
Can returnMovie
be simpler? No. The code should be one line.
Task 3
1. Create a test that fails
Write a unit test named movieNotInStock
. This unit test expects the code throw an IllegalStateException:
@Test(expected = IllegalStateException.class) <----
public void movieNotInStock() {
}
Inside the unit test, rent "The Godfather". Then, sell "The Godfather". Your test should fail because it expects an IllegalStateException
.
2. Make the test pass
Throw an IllegalStateException
from sellMovie
if the movie is already rented.
3. Refactor
Can sellMovie
be simpler? No.
Task 4: Run every test
If every test passes, your code is free of bugs.
Final Remarks
Compare your old code to the new code.
Old code: a giant method that performs too many tasks. The method is impossible to unit test and is vulnerable to bugs.
New code: more polished. Each method performs one task (modular) and is easy to test.
Therein lies the benefit of Test Driven Development!