Each chapter is presented as a series of tests covering a small piece of the overall ray tracer. Since each one builds on previous chapters, you’ll be most successful if you read them in sequence.
You’ll implement your ray tracer in test-first style, writing a few tests at a time and making them pass by implementing the corresponding functions and features in code. The first half of the book is structured to take you smoothly from test to test, but as you get into the second half of the book, the pace picks up. With greater experience comes greater responsibility! You’ll still be given the tests, but there will be less hand-holding, and the tests will be presented in a more linear fashion, almost like a checklist.
Each chapter introduces one or more new features, discusses how the feature works at a high level, and then walks you through the tests and how to make them pass. The tests are posed as Cucumber scenarios,[2] but it is absolutely not necessary to use Cucumber to implement them. Please feel free to use whatever system you prefer to write your tests!
Typically, Cucumber is used to describe high-level interactions between a user and an application, but the tests in this book use it differently. Here, you’ll see it used to describe lower-level interactions, like how various inputs to a specific function might affect the function’s output. This lets the book walk you through the construction of an API, step by step, rather than just showing you the high-level behavior that you need to try to emulate. For example, consider the following hypothetical specification which describes the behavior of concatenating two arrays.
| Scenario: Concatenating two arrays should create a new array |
| Given a ← array(1, 2, 3) |
| And b ← array(3, 4, 5) |
| When c ← a + b |
| Then c = array(1, 2, 3, 3, 4, 5) |
It’s structured like any Cucumber scenario, but describes low-level API interactions:
It begins with two assumptions (“Given…And”), which must be true to start. These use left arrows (←) to assign two arrays to two variables, a and b.
After everything has been initialized, an action occurs (“When”). The result of this action is what is to be tested. Note that this also uses the left arrow, assigning the result of concatenating a and b to another variable, c.
Finally, an assertion is made (“Then”), which must be true. This uses the equals operator (=) to assert that the variable c is equal to the given array.
Your job as the reader is to implement each test, and then make each pass. You’re welcome to do so in Cucumber if you like—in fact, the Cucumber tests may be downloaded from the publisher,[3] to save you the effort of keying them all in by hand. But if Cucumber isn’t your thing, you can be just as successful by translating the Cucumber scenarios into whatever testing system you prefer. Honestly, part of the puzzle—part of the fun!—is translating each specification into a working unit test. The scenario tells you what the behavior should be. You get to decide how to make it happen.
While working through this book, you’re going to discover that an implementation that worked for one test might not work well (or at all) for a later test. You’ll need to be flexible and willing to refactor as you discover new requirements. That, or read the entire book through before beginning your implementation so you know what’s coming up.
Also, be aware that I’ve made many of the architectural decisions in this book with the goal of being easy to explain. Often, there will be more efficient ways to implement a function, or to architect a feature. You may disagree with the book at times, and that’s okay! This book is a roadmap, describing just one of many possible ways to get to the goal. Follow your own aesthetic sense. Make your code your own.
Lastly, at the end of each chapter is a section called “Putting It Together.” This is where you’ll find a description of something that builds on the code you wrote for that chapter and gives you a chance to play and experiment with your new code. Sometimes it will be a small project, and other times a list of possible things to try or directions to explore. It’s certainly possible to skip those sections if you’re in a hurry, but if you do you’ll be missing one of the most enjoyable parts of the journey.
18.217.194.39