Test-Driven Development with React and TypeScript: Building Maintainable React Applications 2nd Edition Juntao Qiu pdf download
Test-Driven Development with React and TypeScript: Building Maintainable React Applications 2nd Edition Juntao Qiu pdf download
or textbooks at https://ebookmass.com
https://ebookmass.com/product/test-driven-development-with-
react-and-typescript-building-maintainable-react-
applications-2nd-edition-juntao-qiu/
https://ebookmass.com/product/react-and-react-native-fifth-edition-
mikhail-sakhniuk/
https://ebookmass.com/product/%e7%8e%b0%e4%bb%a3%e5%85%a8%e6%a0%88%e5%
bc%80%e5%8f%91-%e4%bd%bf%e7%94%a8-
typescript%e3%80%81react%e3%80%81node-
js%e3%80%81webpack-%e5%92%8c-docker-frank-zammetti/
https://ebookmass.com/product/master-react-in-5-days-become-a-react-
expert-in-under-a-week-eric-sarrion/
https://ebookmass.com/product/master-react-in-5-days-become-a-react-
expert-in-under-a-week-eric-sarrion-2/
Test-Driven Development in Go Simion
https://ebookmass.com/product/test-driven-development-in-go-simion/
https://ebookmass.com/product/react-hooks-in-action-meap-03-john-
larsen-larsen/
https://ebookmass.com/product/hands-on-test-driven-development-using-
ruby-ruby-on-rails-and-rspec-1st-edition-greg-donald/
https://ebookmass.com/product/hands-on-test-driven-development-using-
ruby-ruby-on-rails-and-rspec-1-converted-edition-greg-donald/
Juntao Qiu
Test-Driven Development with React and TypeScript: Building
Maintainable React Applications
Juntao Qiu
Wantirna, 3152, VIC, Australia
v
Table of Contents
vi
Table of Contents
vii
Table of Contents
viii
Table of Contents
Unit Tests����������������������������������������������������������������������������������������������������������132
Refactoring��������������������������������������������������������������������������������������������������133
Book Detail Page�����������������������������������������������������������������������������������������137
File Structure�����������������������������������������������������������������������������������������������139
Testing Data������������������������������������������������������������������������������������������������������141
User Interface Refinement��������������������������������������������������������������������������������143
Using Grid System���������������������������������������������������������������������������������������144
Handling Default Value��������������������������������������������������������������������������������������146
A Failing Test with undefined����������������������������������������������������������������������146
One Last Change?���������������������������������������������������������������������������������������������149
Summary����������������������������������������������������������������������������������������������������������150
ix
Table of Contents
x
Table of Contents
Index�������������������������������������������������������������������������������������������������259
xi
About the Author
Juntao Qiu is an accomplished software
developer renowned for his expertise
in producing high-quality and easily
maintainable code. He is committed to
helping individuals improve their code-
writing abilities and generously shares his vast
knowledge and experience through multiple
platforms, including books such as this one
and Maintainable React (Leanpub, 2022).
In addition, Juntao hosts a YouTube channel (@icodeit.juntao) where
he provides valuable insights, tips, and best practices for writing clean
code and performing refactoring. Juntao’s goal is to empower developers,
enabling them to reach their full potential and have a positive impact on
the software development industry.
xiii
About the Technical Reviewers
Jeff Friesen is a freelance teacher and
software developer with an emphasis on
Java. In addition to authoring Java I/O, NIO
and NIO.2 (Apress) and Java Threads and
the Concurrency Utilities (Apress), Jeff has
written numerous articles on Java and other
technologies (such as Android) for JavaWorld
(JavaWorld.com) – now InfoWorld (www.
infoworld.com/category/java/), informIT
(InformIT.com), Java.net (no longer in existence), SitePoint (SitePoint.
com), and other websites. Jeff can be contacted via his email address:
jefff@xplornet.ca.
xv
Acknowledgments
I am profoundly grateful to my ThoughtWorks colleagues for their
enthusiastic engagement and invaluable contributions during the
development of this book. Our project discussions were a fountain of
insight, enriching the narrative with an array of diverse perspectives. A
special acknowledgment goes to Evan Bottcher for his meticulous review
and for providing an eloquent foreword for the book.
Before embarking on the second edition, I reached out to my
newsletter (https://juntao.substack.com/) subscribers with a survey,
seeking their expectations for the new iteration. The response was
overwhelming and deeply informative – my heartfelt thanks go out to
those dedicated readers who took the time to provide their input.
I must extend my profound appreciation to the editorial team for their
indispensable support throughout the second edition’s journey. Their
expert advice has proven invaluable in refining the text, and it’s their
tireless dedication that has brought this project to fruition.
Finally, upon first sharing my book’s vision with my colleagues
at ThoughtWorks, the outpouring of valuable feedback I received –
spanning from minor typographical corrections to substantial technical
suggestions – was truly overwhelming. In particular, on a cool morning
in May 2020, I was greeted with an uplifting email from Hannah Bourke,
who not only expressed her appreciation for the book but also offered
her editing assistance as a native English speaker and fellow developer.
Her subsequent pull requests offered not just high-quality language
corrections but also insightful technical review comments from a learner’s
perspective.
xvii
Acknowledgments
xviii
Foreword 1
Sometimes, I find it hard to believe that it’s been more than two decades
since Kent Beck published Extreme Programming Explained including
Test-Driven Development (TDD) as a core practice. In the years since then,
the use of automated testing has become quite commonplace, something
that almost all developers are familiar with – however, the “Red-Green-
Refactor” cycle of TDD is often missing. The reality is that building
software test first is not easy or trivial in real-world software development
and requires deliberate practice and usually someone experienced to
learn from.
At ThoughtWorks, my role is Head of Engineering – responsible for the
quality of the software that our teams produce for and with our clients.
We set a high standard for the “internal” quality of the code we produce,
wanting it to be maintainable and extensible so that it can quickly be
changed with confidence. Test-Driven Development is a default practice
in ThoughtWorks – our experience shows that the practice leads to better
software design and good confidence from a comprehensive automated
test suite.
In my years at ThoughtWorks, I’ve seen the phenomenal rise in the
importance of JavaScript and browser applications. In 2010, we advised
that the industry should treat JavaScript as a first-class language (www.
thoughtworks.com/radar/languages-and-frameworks/javascript-
as-a-first-class-language) on the ThoughtWorks Technology Radar,
applying all of the same engineering rigor as other platforms. As one of
the authors of the Technology Radar, I’ve seen and helped document the
explosion of tooling and frameworks in JavaScript, many of which have
been related to the area of test automation.
xix
Foreword 1
Evan Bottcher
March 2021
xx
Foreword 2
Landing in the middle of a React project that had very low test coverage,
in a team that had aspirations to improve it, but without a clear strategy
of how to go about it, I struggled to find resources that stepped out how to
approach testing for a frontend project. I couldn’t find a clear explanation
of how to implement Test-Driven Development for a UI, let alone
specifically for React. This book couldn’t have come at a better time.
There are a plethora of different testing methodologies and libraries
available just for React. The ones you choose will depend on many
things. This book doesn’t prescribe a particular solution but establishes
the purpose of tests in driving out specifications and suggests an overall
approach, with practical guidance and examples. Juntao provides a
holistic explanation of the purpose and implementation of Test-Driven
Development for React, demonstrating the benefits of moving testing
earlier in the process, improving the robustness and design of our code.
Juntao’s years of experience, his eagerness and passion for learning
and sharing his knowledge in a didactic way, help to make this a relevant,
practical, and engaging guide to follow and have given me confidence in
my own testing strategies.
Hannah Bourke
March 2021
xxi
Introduction
This comprehensive book is your ultimate guide to mastering Test-Driven
Development (TDD) in the context of React and TypeScript. Whether you're
a seasoned developer seeking to refine your skills or a newcomer eager to
embrace industry-standard practices, this book caters to all levels of expertise.
Spanning a wide range of topics, each chapter in this book is
thoughtfully designed to provide you with a deep understanding of TDD
principles and their application in real-world scenarios. Let's take a
glimpse into the chapters and their role in your learning journey:
xxiii
Introduction
By following along with each chapter, you'll not only acquire the
knowledge and skills to excel in TDD but also experience the benefits
firsthand. Faster feedback cycles, improved code quality, enhanced
collaboration, and the confidence to make changes and add new features
are just a few of the advantages you'll gain.
Are you ready to embark on a transformative journey toward
becoming a more confident, efficient, and skilled developer? Test-Driven
Development with React and TypeScript: Building Maintainable React
Applications is your comprehensive companion. Let the power of TDD
guide your development process, elevate your coding skills, and lay the
foundation for a successful career in software development. Get ready to
dive in and unlock the full potential of TDD in your React projects.
xxiv
CHAPTER 1
A Brief History
of Test-Driven
Development
My purpose in writing this chapter is not to copy and paste cliches from
blogs or to make it seem like I was part of the historic events (such as the
Agile Manifesto or Extreme Programming activities) that led to the creation
of Test-Driven Development as a methodology – believe me, I’m not that old.
However, I do believe that providing context around the topics we’ll be
discussing in this book can be helpful. In this chapter, we’ll explore the basic
workflow of TDD and the various practical approaches used by different
schools of thought. If you prefer to jump straight into the code, feel free to do
so by navigating to the next chapter and getting your hands dirty.
1
https://martinfowler.com/bliki/ExtremeProgramming.html
© Juntao Qiu 2023 1
J. Qiu, Test-Driven Development with React and TypeScript,
https://doi.org/10.1007/978-1-4842-9648-6_1
Chapter 1 A Brief History of Test-Driven Development
• Eliminate duplication
The cycle repeats with each new feature or functionality, with the goal
of producing high-quality code that meets the specified requirements
and is maintainable over time. The Red-Green-Refactor cycle (Figure 1-1)
emphasizes writing automated tests before writing any production code,
ensuring that the code is continually tested and improved as it evolves.
2
Chapter 1 A Brief History of Test-Driven Development
This book aims to address these questions and equip you with the
knowledge and skills necessary to apply these techniques with confidence
in your daily workflow. By the end of the book, you should be well
equipped to implement the discussed techniques effectively.
3
Chapter 1 A Brief History of Test-Driven Development
4
Chapter 1 A Brief History of Test-Driven Development
Types of TDD
Although TDD is a broad and diverse concept with many variations and
different schools, such as UTDD, BDD, ATDD, and others, it traditionally
implied Unit Test–Driven Development or UTDD. However, the TDD
discussed in this book is an extended version of the conventional concept,
known as Acceptance Test–Driven Development (ATDD), which places a
strong emphasis on writing acceptance tests from the business perspective
and using them to drive the development of production code.
2
SOLID is an acronym for a set of principles in object-oriented design that
promote maintainability, flexibility, and extensibility of software. Each letter
in SOLID represents a principle: Single Responsibility Principle (SRP), Open/
Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation
Principle (ISP) and Dependency Inversion Principle (DIP).
5
Chapter 1 A Brief History of Test-Driven Development
Having various tests in different layers can ensure that we are always
on the right track and have the correct functionality.
When you look at this process closely, you find that during the
development stage, the acceptance test could be failing for quite some
time. The feedback loop turns out to be very long, and there is a risk that
an always-failed test means no test (protection) at all.
Developers could be confused about whether there are defects in the
implementation or whether there is any implementation at all.
To resolve this problem, you have to write acceptance tests in relatively
small chunks, testing a tiny slice of the requirement at a time. Alternatively,
you could use the “fake it until you make it” approach, as we are going to
use across this book.
The steps almost remain the same; only an extra fake step is added:
7
Chapter 1 A Brief History of Test-Driven Development
Behavior-Driven Development
Another important variation of TDD is BDD, or Behavior-Driven
Development. Behavior-Driven Development is an agile practice that
encourages collaboration among different roles, developers, quality engineers,
business analysts, or even other interested parties in a software project.
Although BDD is to some extent a general idea about how software
development should be managed by both business interests and technical
insight, the practice of BDD involves some specialized tools. For example,
a Domain-Specific Language (DSL) is used to write tests in natural
language that can be easily understood by nontechnical people and can be
interpreted by code and executed behind the scenes.
The following code snippet of a BDD test case shows how a
requirement can be described:
Prerequisites of TDD
To be candid, TDD can be a challenging methodology to apply. Several
prerequisites must be met before implementing it effectively. A crucial
prerequisite for TDD is a developer’s ability to detect code smells and
refactor them toward better design. Suppose, for example, you encounter
smelly code, such as a lack of abstractions or magic numbers, and are
unsure how to improve it. In that case, TDD alone may not be sufficient.
While the TDD workflow must be followed, there is a risk of creating
unmaintainable tests in addition to producing low-quality code.
8
Chapter 1 A Brief History of Test-Driven Development
There are a lot of tutorials and articles out there to describe techniques
you should use to do TDD, and some may even involve describing how to
split tasks before implementing TDD. However, things discussed in those
tutorials are often oversimplified and can be hard to apply to a real-world
project directly.
For example, in a web application, both the interaction and a
considerable portion of business logic now exist in the frontend: the
UI. The traditional techniques of how to write a unit test to drive backend
logic are already outdated.
Tasking
Another critical skill required by TDD is splitting a large requirement into
smaller chunks through tasking. I would suggest every developer should
learn how to split requirements before they even start to write their first test.
We’ll discuss the tasking process in detail in the next chapter.
10
Chapter 1 A Brief History of Test-Driven Development
11
Chapter 1 A Brief History of Test-Driven Development
Summary
Refactoring depends on the sense and experience of identifying code
smells. Once you find a code smell, you can then apply the corresponding
refactoring technique. And then we may achieve maintainable, human-
readable, extendable, and clean code along the way.
In the next chapter, we will introduce a concrete example to
demonstrate how to apply TDD step by step. Along with that example,
we will also cover the fundamental skills needed for implementing TDD,
including how to use the jest testing framework and how to do tasking with
real-world examples.
Further Reading
There is extensive debate around TDD – every now and then, you would
see people arguing about whether we need TDD or not or the right way
to implement TDD. I found the following articles are really helpful in
understanding some of those arguments:
3
https://blog.cleancoder.com/uncle-bob/2016/11/10/TDD-Doesnt-work.html
4
https://martinfowler.com/articles/is-tdd-dead/
12
Chapter 1 A Brief History of Test-Driven Development
5
www.goodreads.com/book/show/3735293-clean-code
6
https://martinfowler.com/books/refactoring.html
13
CHAPTER 2
1
https://jestjs.io/
© Juntao Qiu 2023 15
J. Qiu, Test-Driven Development with React and TypeScript,
https://doi.org/10.1007/978-1-4842-9648-6_2
Chapter 2 Get Started with Jest
mkdir jest-101
cd jest-101
npm init -y #init the current folder with default settings
2
https://nodejs.org/en/download
16
Chapter 2 Get Started with Jest
After the installation, you can run jest --init to specify some default
settings, such as where jest should find the test files and the source code,
which environment (there are a lot) jest should run against (browser or
node for the backend), and so on. You have to answer some questions to
let jest understand your requirements; for now, let’s just accept all the
default settings by saying Yes for all the questions.
Note that if you have installed jest globally (with npm install jest -g),
you can use the following command to init the config directly:
jest --init
Otherwise, you will have to use the local installation by npx, which
looks for jest binary from node_modules/.bin/ and invokes it:
17
Chapter 2 Get Started with Jest
And then create a babel.config.js file in the root of our project (the
jest-101 folder), with the following content:
module.exports = {
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
module.exports = {
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-typescript',
],
};
We’re all set now. It’s time to write our first Jest test.
18
Chapter 2 Get Started with Jest
The file ends with "test.ts", that means it’s a pattern that jest will
recognize and treat them as tests, as defined in the jest.config.js we
generated previously:
describe("calculator", function () {
it("should be able to add two numbers", function () {
expect(add(1, 2)).toEqual(3);
});
});
19
Chapter 2 Get Started with Jest
export { add };
PASS src/calc.test.ts
calculator
✓ add two numbers (1 ms)
describe("calculator", () => {
it("should perform addition", () => {});
it("should perform subtraction", () => {});
it("should perform multiplication", () => {});
it("should perform division", () => {});
});
describe("calculator", () => {
describe("should perform addition", () => {
it("adds two positive numbers", () => {});
it("adds two negative numbers", () => {});
it("adds one positive and one negative numbers", () => {});
});
});
21
Chapter 2 Get Started with Jest
context. This way, the test suite is easier to understand and more closely
aligned with the needs of the stakeholders who will ultimately benefit from
the software being tested.
describe("Checkout", () => {
it("should check if any appliance is broken", () => {});
it("should refund guest when checkout is earlier than
planned", () => {});
});
});
describe("addition", () => {
it("adds two positive numbers", () => {
const options = {
precision: 2,
};
22
Chapter 2 Get Started with Jest
describe("addition", () => {
let calc = null;
beforeEach(() => {
const options = {
precision: 2,
};
calc = new Calculator(options);
});
23
Chapter 2 Get Started with Jest
describe("database", () => {
let db = null;
beforeEach(() => {
db.connect("localhost", "9999", "user", "pass");
});
afterEach(() => {
db.disconnect();
});
});
24
Chapter 2 Get Started with Jest
beforeAll(() => {
db.connect("localhost", "9999", "user", "pass");
});
afterAll(() => {
db.disconnect();
});
Basic Usages
Equality
toEqual and toBe may be the most common matchers you will find and use
in almost every test case. As the name implies, they are used to assert whether
values are equal to each other (the actual value and the expected value).
For example, it can be used for string, number, or composed objects:
25
Chapter 2 Get Started with Jest
The last test will fail. For primitives like strings, numbers, and
booleans, you can use toBe to test the equality. While for Objects,
internally jest uses Object.is to check, which is strict and compares
objects by memory address. So if you want to make sure all the fields are
matching, use toEqual.
Sometimes, you might not want an exact match. Say you want a
string to be matching some particular pattern. Then you can use toMatch
instead:
26
Other documents randomly have
different content
The Project Gutenberg eBook of The Luckiest
Man in Denv
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.
Author: C. M. Kornbluth
Illustrator: Ed Emshwiller
Language: English
By SIMON EISNER
Illustrated by EMSH
May's man Reuben, of the eighty-third level, Atomist, knew there was
something wrong when the binoculars flashed and then went
opaque. Inwardly he cursed, hoping that he had not committed
himself to anything. Outwardly he was unperturbed. He handed the
binoculars back to Rudolph's man Almon, of the eighty-ninth level,
Maintainer, with a smile.
"They aren't very good," he said.
Almon put them to his own eyes, glanced over the parapet and swore
mildly. "Blacker than the heart of a crazy Angel, eh? Never mind;
here's another pair."
This pair was unremarkable. Through it, Reuben studied the
thousand setbacks and penthouses, of Denv that ranged themselves
below. He was too worried to enjoy his first sight of the vista from
the eighty-ninth level, but he let out a murmur of appreciation. Now
to get away from this suddenly sinister fellow and try to puzzle it out.
"Could we—?" he asked cryptically, with a little upward jerk of his
chin.
"It's better not to," Almon said hastily, taking the glasses from his
hands. "What if somebody with stars happened to see, you know?
How'd you like it if you saw some impudent fellow peering up at
you?"
"He wouldn't dare!" said Reuben, pretending to be stupid and
indignant, and joined a moment later in Almon's sympathetic
laughter.
"Never mind," said Almon. "We are young. Some day, who knows?
Perhaps we shall look from the ninety-fifth level, or the hundredth."
Though Reuben knew that the Maintainer was no friend of his, the
generous words sent blood hammering through his veins; ambition
for a moment.
He pulled a long face and told Almon: "Let us hope so. Thank you for
being my host. Now I must return to my quarters."
He left the windy parapet for the serene luxury of an eighty-ninth-
level corridor and descended slow moving stairs through gradually
less luxurious levels to his own Spartan floor. Selene was waiting,
smiling, as he stepped off the stairs.
She was decked out nicely—too nicely. She wore a steely hued
corselet and a touch of scent; her hair was dressed long. The
combination appealed to him, and instantly he was on his guard. Why
had she gone to the trouble of learning his tastes? What was she up
to? After all, she was Griffin's woman.
"Coming down?" she asked, awed. "Where have you been?"
"The eighty-ninth, as a guest of that fellow Almon. The vista is
immense."
"I've never been...." she murmured, and then said decisively: "You
belong up there. And higher. Griffin laughs at me, but he's a fool.
Last night in chamber we got to talking about you, I don't know how,
and he finally became quite angry and said he didn't want to hear
another word." She smiled wickedly. "I was revenged, though."
Blank-faced, he said: "You must be a good hand at revenge, Selene,
and at stirring up the need for it."
The slight hardening of her smile meant that he had scored and he
hurried by with a rather formal salutation.
Burn him for an Angelo, but she was easy enough to take! The
contrast of the metallic garment with her soft, white skin was
disturbing, and her long hair suggested things. It was hard to think of
her as scheming something or other; scheming Selene was displaced
in his mind by Selene in chamber.
But what was she up to? Had she perhaps heard that he was to be
elevated? Was Griffin going to be swooped on by the Maintainers?
Was he to kill off Griffin so she could leech onto some rising third
party? Was she perhaps merely giving her man a touch of the lash?
He wished gloomily that the binoculars-problem and the Selene-
problem had not come together. That trickster Almon had spoken of
youth as though it were something for congratulation; he hated being
young and stupid and unable to puzzle out the faulty binoculars and
the warmth of Griffin's woman.
The Atomist and the general climbed out from under the table; May's
secretary popped through the door. The general waved him out again
and leaned heavily on the table, his arms quivering. Reuben hastily
brought a chair.
"A glass of water," said May.
The Atomist brought it. He saw the general wash down what looked
like a triple dose of XXX—green capsules which it was better to leave
alone.
May said after a moment: "That's better. And don't look so shocked,
youngster; you don't know the strain we're under. It's only a
temporary measure which I shall discontinue as soon as things ease
up a bit. I was saying that perhaps my good friend Rudolph plans to
substitute one of his men for one of mine. Tell me, how long has this
fellow Almon been a friend of yours?"
"He struck up an acquaintance with me only last week. I should have
realized—"
"You certainly should have. One week. Time enough and more. By
now you've been photographed, your fingerprints taken, your voice
recorded and your gait studied without your knowledge. Only the
retinascope is difficult, but one must risk it for a real double. Have
you killed your man, Reuben?"
He nodded; It had been a silly brawl two years ago over precedence
at the refectory; he disliked being reminded of it.
"Good," said May grimly. "The way these things are done, your
double kills you in a secluded spot, disposes of your body and takes
over your role. We shall reverse it. You will kill the double and take
over his role."
The powerful, methodical voice ticked off possibilities and
contingencies, measures, and countermeasures. Reuben absorbed
them and felt his awe return. Perhaps May had not really been
frightened under the table; perhaps it had been he reading his own
terror in the general's face. May was actually talking to him of
backgrounds and policies. "Up from the eighty-third level!" he swore
to himself as the great names were uttered.
"My good friend Rudolph, of course, wants the five stars. You would
not know this, but the man who wears the stars is now eighty years
old and failing fast. I consider myself a likely candidate to replace
him. So, evidently, must Rudolph. No doubt he plans to have your
double perpetrate some horrible blunder on the eve of the election,
and the discredit would reflect on me. Now what you and I must do
—"
You and I—May's man Reuben and May—up from the eighty-third! Up
from the bare corridors and cheerless bedrooms to marble halls and
vaulted chambers! From the clatter of the crowded refectory to small
and glowing restaurants where you had your own table and servant
and where music came softly from the walls! Up from the scramble to
win this woman or that, by wit or charm or the poor bribes you could
afford, to the eminence from which you could calmly command your
pick of the beauty of Denv! From the moiling intrigue of tripping your
fellow Atomist and guarding against him tripping you to the heroic
thrust and parry of generals!
Up from the eighty-third!
Then May dismissed him with a speech whose implications were
deliriously exciting. "I need an able man and a young one, Reuben.
Perhaps I've waited too long looking for him. If you do well in this
touchy business, I'll consider you very seriously for an important task
I have in mind."
It was 2349. Reuben sprang from bed and stood by the door, his
pistol silenced and ready. At 2350 a naked man slipped swiftly into
the room, heading for the bed as he raised a ten-centimeter
poignard. He stopped in dismay when he realized that the bed was
empty.
Reuben killed him with a bullet through the throat.
Deck One was firing. One, two, three, four, five, six. One, two, three,
four, five, six. One, two, three, four, five, six.
People turned to one another and shook hands, laughed and slapped
shoulders heartily. Eighteen missiles were racing through the
stratosphere, soon to tumble on Ellay. With any luck, one or two
would slip through the first wall of interceptors and blast close
enough to smash windows and topple walls in the crazy city by the
ocean. It would serve the lunatics right.
Five minutes later an exultant voice filled most of Denv.
"Recon missile report," it said. "Eighteen launched, eighteen perfect
trajectories. Fifteen shot down by Ellay first-line interceptors, three
shot down by Ellay second-line interceptors. Extensive blast damage
observed in Griffith Park area of Ellay!"
There were cheers.
And eight Full Maintainers marched into the refectory silently, and
marched out with Reuben.
He knew better than to struggle or ask futile questions. Any question
you asked of a Maintainer was futile. But he goggled when they
marched him onto an upward-bound stairway.
They rode past the eighty-ninth level and Reuben lost count, seeing
only the marvels of the upper reaches of Denv. He saw carpets that
ran the entire length of corridors, and intricate fountains, and mosaic
walls, stained-glass windows, more wonders than he could recognize,
things for which he had no name.
He was marched at last into a wood-paneled room with a great
polished desk and a map behind it. He saw May, and another man
who must have been a general—Rudolph?—but sitting at the desk
was a frail old man who wore a circlet of stars on each khaki
shoulder.
The old man said to Reuben: "You are an Ellay spy and saboteur."
Reuben looked at May. Did one speak directly to the man who wore
the stars, even in reply to such an accusation?
"Answer him, Reuben," May said kindly.
"I am May's man Reuben, of the eighty-third level, an Atomist," he
said.
"Explain," said the other general heavily, "if you can, why all eighteen
of the warheads you procured today failed to fire."
"But they did!" gasped Reuben. "The Recon missile report said there
was blast damage from the three that got through and it didn't say
anything about the others failing to fire."
The other general suddenly looked sick and May looked even kindlier.
The man who wore the stars turned inquiringly to the chief of the
Maintainers, who nodded and said: "That was the Recon missile
report, sir."
The general snapped: "What I said was that he would attempt to
sabotage the attack. Evidently he failed. I also said he is a faulty
double, somehow slipped with great ease into my good friend May's
organization. You will find that his left thumb print is a clumsy forgery
of the real Reuben's thumb print and that his hair has been artificially
darkened."
The old man nodded at the chief of the Maintainers, who said: "We
have his card, sir."
Reuben abruptly found himself being fingerprinted and deprived of
some hair.
"The f.p.s check, sir," one Maintainer said. "He's Reuben."
"Hair's natural, sir," said another.
The general began a rear-guard action: "My information about his
hair seems to have been inaccurate. But the fingerprint means only
that Ellay spies substituted his prints for Reuben's prints in the files
—"
"Enough, sir," said the old man with the stars. "Dismissed. All of you.
Rudolph, I am surprised. All of you, go."
Updated editions will replace the previous one—the old editions will
be renamed.
ebookmasss.com