Unit Tests for a Novel

isobelvane3 pts0 comments

Letterer's Corner — Worldfall Skip to the text

P.F. Witt

A−

A+

Contents

Letterer's Corner

When George R. R. Martin needs to know the color of a minor knight’s eyes, he emails two<br>superfans who run a wiki, because after five thousand pages they hold the continuity of<br>Westeros better than he does. I find that fact comforting and alarming at the same time.<br>Comforting, because the best worldbuilder alive could not keep it all in his head either.<br>Alarming, because the industry-standard fallback is two patient people in Sweden.

I came to this problem from software, where we stopped trusting our heads decades ago.<br>The tool we reached for instead is called the unit test, and it deserves a short<br>introduction for readers who have never shipped code.

What a unit test is, and why programmers live by them

A large program is a million small promises. This function, given a date, returns the<br>right day of the week; that one, given an empty list, returns zero instead of crashing.<br>The program only works if thousands of these hold at once, and the program never stops<br>changing. It is edited daily, for years, by people who cannot remember every promise<br>the code has ever made, and changes do not stay where you put them: you improve how the<br>program handles dates, and something breaks in a corner of the billing code you have<br>never read, because it quietly depended on the old behavior.

In principle you could re-check everything by hand after every edit. In practice no<br>human ever has: there are too many promises, the checking is mind-numbing, the deadline<br>is Friday. We check what we remember to worry about, and things slip through. A unit<br>test is the working answer: a tiny script that checks exactly one promise (“give the<br>date function February 29th; confirm it doesn’t lie”) and complains loudly when it<br>breaks. One test is almost worthless. Thousands of them, rerun by a machine after every<br>change, without boredom, without skipping the ones it checked yesterday, are how<br>software holds together at all.

You still cannot test every case up front; nobody can, and bugs still get through. But<br>the suite is a ratchet: every escaped bug becomes a new test the day you fix it, and<br>the same mistake never comes back unannounced. The code forgets; the tests don’t.

If you have written a long story, you have lived the unfixed version of this. A novel<br>is edited the same way, daily, for years, by someone who cannot re-read the whole book<br>after every change. How the magic is rationed, who knows which secret by chapter<br>eleven, a character’s stated reason versus his real one: each is a promise some later<br>scene silently depends on, and a revision in chapter nineteen can break a promise made<br>in chapter three. So we spot-check what we remember to worry about, and things get<br>through. In fiction the escaped bug is called a continuity error, and readers of<br>serialized fantasy hunt them for sport.

So before drafting a word of my own book, I built the thing I would build at work: a<br>small test suite that runs against the story, and a habit of turning every mistake it<br>misses into a check it will never miss again. (A purist will read on and object that<br>what I built is closer to a linter than to a unit test suite. Granted. The habit is the<br>import, not the taxonomy.)

The idea in one paragraph

Treat the world of the story as data, and the chapters as code that depends on it. The<br>world lives as a graph of entities (characters, places, factions, magic systems), each<br>carrying small, individually addressable facts. Chapters declare, in machine-readable<br>front matter, which facts they dramatize and which declared motive every major character<br>choice serves. A linter walks the whole thing and fails loudly when a reference dangles,<br>a rule gets bent, or a choice serves no motive anyone wrote down. None of this judges the<br>prose. It guards the structure underneath the prose, the way tests guard a system while<br>you refactor it.

If that sounds like a story bible with a build step, it mostly is. The interesting<br>question is why story bibles always rot and this one doesn’t, and the answer is new;<br>it gets its own section near the end.

The rest of this post makes that concrete, and concreteness needs an example. So first,<br>the example, with all the context you need.

The example

First Keel is a fantasy novel I am writing, the first book of a series called<br>Worldfall. A permanent storm-sea has kept two<br>continents apart for so long they have mostly forgotten each other. Once in roughly<br>eighty years the storm dies for eleven months (an Opening), and the two worlds flood<br>into each other through one chokepoint port city: a compressed Columbian exchange, then<br>the door slams shut for another lifetime. A church, the Temple of the Calm, claims its<br>liturgy keeps the sea passable, and owns the calendar that says when it opens. The magic<br>system runs on linguistic divergence: the sealed centuries split one ancestral language<br>into two drifted branches, and the power is in the...

test unit never code story because

Related Articles