100% found this document useful (2 votes)
15 views

Test Driven Development in Ruby A Practical Introduction to TDD Using Problem and Solution Domain Analysis Paranj download

The document is a promotional overview of the book 'Test Driven Development in Ruby: A Practical Introduction to TDD Using Problem and Solution Domain Analysis' by Bala Paranj, which provides insights into Test Driven Development (TDD) principles and practices. It includes links to various related books on TDD in different programming languages and methodologies. The content outlines the structure of the book, including chapters on TDD basics, techniques, and practical applications.

Uploaded by

uslanhores0t
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
15 views

Test Driven Development in Ruby A Practical Introduction to TDD Using Problem and Solution Domain Analysis Paranj download

The document is a promotional overview of the book 'Test Driven Development in Ruby: A Practical Introduction to TDD Using Problem and Solution Domain Analysis' by Bala Paranj, which provides insights into Test Driven Development (TDD) principles and practices. It includes links to various related books on TDD in different programming languages and methodologies. The content outlines the structure of the book, including chapters on TDD basics, techniques, and practical applications.

Uploaded by

uslanhores0t
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 60

Test Driven Development in Ruby A Practical

Introduction to TDD Using Problem and Solution


Domain Analysis Paranj download

https://textbookfull.com/product/test-driven-development-in-ruby-
a-practical-introduction-to-tdd-using-problem-and-solution-
domain-analysis-paranj/

Download more ebook from https://textbookfull.com


We believe these products will be a great fit for you. Click
the link to download now, or visit textbookfull.com
to discover even more!

Test Driven Java Development Invoke TDD principles for


end to end application development 2nd Edition Alex
Garcia

https://textbookfull.com/product/test-driven-java-development-
invoke-tdd-principles-for-end-to-end-application-development-2nd-
edition-alex-garcia/

Domain-Driven Laravel: Learn to Implement Domain-Driven


Design Using Laravel Jesse Griffin

https://textbookfull.com/product/domain-driven-laravel-learn-to-
implement-domain-driven-design-using-laravel-jesse-griffin/

iOS Test Driven Development by Tutorials First Edition


Learn Real World Test Driven Development Joshua Greene

https://textbookfull.com/product/ios-test-driven-development-by-
tutorials-first-edition-learn-real-world-test-driven-development-
joshua-greene/

Test-Driven Development in Go: A practical guide to


writing idiomatic and efficient Go tests through real-
world example 1st Edition Adelina Simion

https://textbookfull.com/product/test-driven-development-in-go-a-
practical-guide-to-writing-idiomatic-and-efficient-go-tests-
through-real-world-example-1st-edition-adelina-simion/
Practical Test Automation: Learn to Use Jasmine, RSpec,
and Cucumber Effectively for Your TDD and BDD Panos
Matsinopoulos

https://textbookfull.com/product/practical-test-automation-learn-
to-use-jasmine-rspec-and-cucumber-effectively-for-your-tdd-and-
bdd-panos-matsinopoulos/

Matlab A Practical Introduction to Programming and


Problem Solving Stormy Attaway

https://textbookfull.com/product/matlab-a-practical-introduction-
to-programming-and-problem-solving-stormy-attaway/

MATLAB A Practical Introduction to Programming and


Problem Solving Stormy Attaway

https://textbookfull.com/product/matlab-a-practical-introduction-
to-programming-and-problem-solving-stormy-attaway-2/

Python Testing Cookbook Easy solutions to test your


Python projects using test driven development and
Selenium 2nd Edition Greg L. Turnquist & Bhaskar N. Das

https://textbookfull.com/product/python-testing-cookbook-easy-
solutions-to-test-your-python-projects-using-test-driven-
development-and-selenium-2nd-edition-greg-l-turnquist-bhaskar-n-
das/

Practical Domain-Driven Design in Enterprise Java -


Using Jakarta EE, Eclipse MicroProfile, Spring Boot,
and the Axon Framework 1st Edition Vijay Nair

https://textbookfull.com/product/practical-domain-driven-design-
in-enterprise-java-using-jakarta-ee-eclipse-microprofile-spring-
boot-and-the-axon-framework-1st-edition-vijay-nair/
Test Driven
Development
in Ruby
A Practical Introduction to TDD Using
Problem and Solution Domain Analysis

Bala Paranj
Test Driven
Development in Ruby
A Practical Introduction to TDD Using
Problem and Solution Domain Analysis

Bala Paranj
Test Driven Development in Ruby: A Practical Introduction to TDD Using Problem and Solution
Domain Analysis
Bala Paranj
Atlanta, Georgia, USA
ISBN-13 (pbk): 978-1-4842-2637-7 ISBN-13 (electronic): 978-1-4842-2638-4
DOI 10.1007/978-1-4842-2638-4
Library of Congress Control Number: 2017934648
Copyright © 2017 by Bala Paranj
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are
not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the material
contained herein.
Managing Director: Welmoed Spahr
Editorial Director: Todd Green
Acquisitions Editor: Steve Anglin
Development Editor: Matthew Moodie
Technical Reviewer: Ronald Petty
Coordinating Editor: Mark Powers
Copy Editor: April Rondeau
Compositor: SPi Global
Indexer: SPi Global
Artist: SPi Global
Cover image designed by Freepik.
Distributed to the book trade worldwide by Springer Science+Business Media New York,
233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail
[email protected], or visit www.springeronline.com. Apress Media, LLC is a California LLC
and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM
Finance Inc is a Delaware corporation.
For information on translations, please e-mail [email protected], or visit http://www.apress.com/
rights-permissions.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales web
page at www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub via the book's product page, located at www.apress.com/9781484226377. For more
detailed information, please visit http://www.apress.com/source-code.
Printed on acid-free paper
This book is dedicated to the memory of my father.
Contents at a Glance

About the Author��������������������������������������������������������������������������������������������������� xiii


About the Technical Reviewer���������������������������������������������������������������������������������xv
Foreword���������������������������������������������������������������������������������������������������������������xvii
Acknowledgments��������������������������������������������������������������������������������������������������xix
Introduction������������������������������������������������������������������������������������������������������������xxi


■Chapter 1: The Basics�������������������������������������������������������������������������������������������� 1

■Chapter 2: Katas�������������������������������������������������������������������������������������������������� 57

■Chapter 3: Techniques in TDD���������������������������������������������������������������������������� 125

■Chapter 4: Importance of Test Cases����������������������������������������������������������������� 153

■Chapter 5: Character-to-Number Conversion���������������������������������������������������� 163

■Chapter 6: Conway’s Game of Life��������������������������������������������������������������������� 171

■Chapter 7: Gilded Rose�������������������������������������������������������������������������������������� 221

■Chapter 8: Dealing with Third-Party APIs���������������������������������������������������������� 263

■Chapter 9: Pair Ranking������������������������������������������������������������������������������������ 277

Index��������������������������������������������������������������������������������������������������������������������� 285

v
Contents

About the Author��������������������������������������������������������������������������������������������������� xiii


About the Technical Reviewer���������������������������������������������������������������������������������xv
Foreword���������������������������������������������������������������������������������������������������������������xvii
Acknowledgments��������������������������������������������������������������������������������������������������xix
Introduction������������������������������������������������������������������������������������������������������������xxi


■Chapter 1: The Basics�������������������������������������������������������������������������������������������� 1
Terminology���������������������������������������������������������������������������������������������������������������������� 1
Kata�������������������������������������������������������������������������������������������������������������������������������������������������������� 1
Coding Kata�������������������������������������������������������������������������������������������������������������������������������������������� 2
Domain��������������������������������������������������������������������������������������������������������������������������������������������������� 2
Problem Domain������������������������������������������������������������������������������������������������������������������������������������� 2
Solution Domain������������������������������������������������������������������������������������������������������������������������������������� 2
Domain Expert���������������������������������������������������������������������������������������������������������������������������������������� 2
Domain Knowledge��������������������������������������������������������������������������������������������������������������������������������� 3

Defining the Problem Domain and the Solution Domain�������������������������������������������������� 3


Learning TDD ������������������������������������������������������������������������������������������������������������������� 3
Learning by Coding Kata������������������������������������������������������������������������������������������������������������������������� 3
Learning Retrospective��������������������������������������������������������������������������������������������������������������������������� 4
Intent vs. Implementation������������������������������������������������������������������������������������������������ 4
Intent������������������������������������������������������������������������������������������������������������������������������������������������������ 4
Implementation��������������������������������������������������������������������������������������������������������������������������������������� 4
Intent and Implementation��������������������������������������������������������������������������������������������������������������������� 4
Separate Intent from Implementation����������������������������������������������������������������������������������������������������� 7

vii
■ Contents

Tests Are Executable Documentation��������������������������������������������������������������������������������������������������� 11


Shift in Mental State����������������������������������������������������������������������������������������������������������������������������� 11

Overview of TDD������������������������������������������������������������������������������������������������������������� 12
Test Driven Development���������������������������������������������������������������������������������������������������������������������� 12
The Five Steps of TDD��������������������������������������������������������������������������������������������������������������������������� 13
Separation of Intent from Implementation�������������������������������������������������������������������������������������������� 16
Ping Pong Pair Programming Technique���������������������������������������������������������������������������������������������� 16
Black Box Perspective�������������������������������������������������������������������������������������������������������������������������� 16
Shift in System and Mental States������������������������������������������������������������������������������������������������������� 17
Importance of Discipline����������������������������������������������������������������������������������������������������������������������� 18
Overcoming Difficulty �������������������������������������������������������������������������������������������������������������������������� 18

Problem-Solving Skills��������������������������������������������������������������������������������������������������� 18
Four Phases of Problem Solving����������������������������������������������������������������������������������������������������������� 19
Subskills of Test Driven Development�������������������������������������������������������������������������������������������������� 20
Alternative Representations����������������������������������������������������������������������������������������������������������������� 25
Divide and Conquer Strategy���������������������������������������������������������������������������������������������������������������� 26

Designing Test Cases����������������������������������������������������������������������������������������������������� 26


Sum a List of Numbers������������������������������������������������������������������������������������������������������������������������� 26
Sequence of Test Cases������������������������������������������������������������������������������������������������������������������������ 27

Assertion������������������������������������������������������������������������������������������������������������������������ 28
Test Driving Calculator��������������������������������������������������������������������������������������������������� 30
Canonical Test Structure����������������������������������������������������������������������������������������������������������������������� 30
Arrange, Act, Assert������������������������������������������������������������������������������������������������������������������������������ 30
Calculator��������������������������������������������������������������������������������������������������������������������������������������������� 31
Subtraction������������������������������������������������������������������������������������������������������������������������������������������� 34

Common Mistakes���������������������������������������������������������������������������������������������������������� 37
Common Mistakes in the TDD Cycle����������������������������������������������������������������������������������������������������� 37
Base Conversion����������������������������������������������������������������������������������������������������������������������������������� 38
Code Reflecting Test Data��������������������������������������������������������������������������������������������������������������������� 46
Multiple Assertions������������������������������������������������������������������������������������������������������������������������������� 47

viii
■ Contents

Forgetting to Test the Negative Case���������������������������������������������������������������������������������������������������� 50


Not Testing the Boundary Conditions���������������������������������������������������������������������������������������������������� 50
Not Updating the Tests�������������������������������������������������������������������������������������������������������������������������� 50
Implementation-Aware Tests���������������������������������������������������������������������������������������������������������������� 53

Summary������������������������������������������������������������������������������������������������������������������������ 54

■Chapter 2: Katas�������������������������������������������������������������������������������������������������� 57
Fibonacci Sequence������������������������������������������������������������������������������������������������������� 57
Problem Statement������������������������������������������������������������������������������������������������������������������������������� 58
Problem Domain Analysis��������������������������������������������������������������������������������������������������������������������� 58
Solution Domain Analysis��������������������������������������������������������������������������������������������������������������������� 59
Assumptions����������������������������������������������������������������������������������������������������������������������������������������� 62
Test-Driven Fibonacci��������������������������������������������������������������������������������������������������������������������������� 62

Fizz Buzz������������������������������������������������������������������������������������������������������������������������ 71
Problem Statement������������������������������������������������������������������������������������������������������������������������������� 71
Problem Domain Analysis��������������������������������������������������������������������������������������������������������������������� 71
Solution Domain Analysis��������������������������������������������������������������������������������������������������������������������� 72
Test-Driven FizzBuzz���������������������������������������������������������������������������������������������������������������������������� 72
No if-else Constraint����������������������������������������������������������������������������������������������������������������������������� 77
No if Constraint������������������������������������������������������������������������������������������������������������������������������������� 86
Implementation-Independent Tests������������������������������������������������������������������������������������������������������ 88
Crossing the System Boundary������������������������������������������������������������������������������������������������������������ 90
Mocking as a Design Technique����������������������������������������������������������������������������������������������������������� 90
Abstraction Levels in a System������������������������������������������������������������������������������������������������������������ 94
Testing Random Behavior��������������������������������������������������������������������������������������������������������������������� 95
Testing Time-Dependent Behavior�������������������������������������������������������������������������������������������������������� 96
Simulating User Input��������������������������������������������������������������������������������������������������������������������������� 97
Open Closed Principle������������������������������������������������������������������������������������������������������������������������� 100
Difference Reduction�������������������������������������������������������������������������������������������������������������������������� 102
Defect Localization����������������������������������������������������������������������������������������������������������������������������� 104

ix
■ Contents

Stack���������������������������������������������������������������������������������������������������������������������������� 105
Basic Stack����������������������������������������������������������������������������������������������������������������������������������������� 105
Test Precisely and Concretely������������������������������������������������������������������������������������������������������������� 107
Make Your Code Robust���������������������������������������������������������������������������������������������������������������������� 109

The Sieve of Eratosthenes�������������������������������������������������������������������������������������������� 112


Algorithm�������������������������������������������������������������������������������������������������������������������������������������������� 114

Prime Factors��������������������������������������������������������������������������������������������������������������� 119


Problem Statement����������������������������������������������������������������������������������������������������������������������������� 119
Problem Domain Analysis������������������������������������������������������������������������������������������������������������������� 119
Solution Domain Analysis������������������������������������������������������������������������������������������������������������������� 120

Summary���������������������������������������������������������������������������������������������������������������������� 124

■Chapter 3: Techniques in TDD���������������������������������������������������������������������������� 125
Obvious Implementation���������������������������������������������������������������������������������������������� 125
Fake It Till You Make It�������������������������������������������������������������������������������������������������� 127
Triangulation����������������������������������������������������������������������������������������������������������������� 129
Addition���������������������������������������������������������������������������������������������������������������������������������������������� 129
Sum a List of Numbers����������������������������������������������������������������������������������������������������������������������� 130

Solution Domain Analysis Redux���������������������������������������������������������������������������������� 135


Reduction��������������������������������������������������������������������������������������������������������������������� 136
Problem Statement����������������������������������������������������������������������������������������������������������������������������� 137
Steps to Solve the Problem���������������������������������������������������������������������������������������������������������������� 137
Test-Driven GCD���������������������������������������������������������������������������������������������������������������������������������� 139

Transformation Priority Premise����������������������������������������������������������������������������������� 142


Refactorings and Transformations������������������������������������������������������������������������������������������������������ 143
Transformation List����������������������������������������������������������������������������������������������������������������������������� 143
Counter����������������������������������������������������������������������������������������������������������������������������������������������� 144
Factorial���������������������������������������������������������������������������������������������������������������������������������������������� 149

Summary���������������������������������������������������������������������������������������������������������������������� 152

x
■ Contents


■Chapter 4: Importance of Test Cases����������������������������������������������������������������� 153
Problem Statement������������������������������������������������������������������������������������������������������ 153
Problem Domain Analysis��������������������������������������������������������������������������������������������� 153
Solution Domain Analysis��������������������������������������������������������������������������������������������� 153
Algorithm Description��������������������������������������������������������������������������������������������������� 156
Code����������������������������������������������������������������������������������������������������������������������������� 156
Summary���������������������������������������������������������������������������������������������������������������������� 162

■Chapter 5: Character-to-Number Conversion���������������������������������������������������� 163
Problem Statement������������������������������������������������������������������������������������������������������ 163
Discussion������������������������������������������������������������������������������������������������������������������������������������������ 163

Solution Domain Analysis��������������������������������������������������������������������������������������������� 163


Test Cases�������������������������������������������������������������������������������������������������������������������� 165
Summary���������������������������������������������������������������������������������������������������������������������� 169

■Chapter 6: Conway’s Game of Life��������������������������������������������������������������������� 171
Problem Statement������������������������������������������������������������������������������������������������������ 171
Problem Domain Analysis��������������������������������������������������������������������������������������������� 171
Assumptions��������������������������������������������������������������������������������������������������������������������������������������� 176

Solution Domain Analysis��������������������������������������������������������������������������������������������� 176


Moore Neighborhood�������������������������������������������������������������������������������������������������������������������������� 176

Test Cases�������������������������������������������������������������������������������������������������������������������� 177


Test-Driven Game of Life���������������������������������������������������������������������������������������������� 177
Application Statement������������������������������������������������������������������������������������������������������������������������ 209
Refactor Solution�������������������������������������������������������������������������������������������������������������������������������� 210

Code Review����������������������������������������������������������������������������������������������������������������� 214


Summary���������������������������������������������������������������������������������������������������������������������� 220

■Chapter 7: Gilded Rose�������������������������������������������������������������������������������������� 221
Form vs. Structure������������������������������������������������������������������������������������������������������� 221
Problem Statement������������������������������������������������������������������������������������������������������ 222

xi
■ Contents

Initial Setup������������������������������������������������������������������������������������������������������������������ 223


Form��������������������������������������������������������������������������������������������������������������������������������������������������� 225
Structure��������������������������������������������������������������������������������������������������������������������������������������������� 226
DeMorgan’s Laws������������������������������������������������������������������������������������������������������������������������������� 244
Making Temporal Dependency Explicit����������������������������������������������������������������������������������������������� 245
Improving the Structure���������������������������������������������������������������������������������������������������������������������� 248
Express Intent������������������������������������������������������������������������������������������������������������������������������������� 249
Tell-Don’t-Ask Principle���������������������������������������������������������������������������������������������������������������������� 252
Inheritance������������������������������������������������������������������������������������������������������������������������������������������ 255

Implementing the New Feature������������������������������������������������������������������������������������ 257


Express Domain Concepts������������������������������������������������������������������������������������������������������������������ 258

Retrospective��������������������������������������������������������������������������������������������������������������� 261
Summary���������������������������������������������������������������������������������������������������������������������� 262

■Chapter 8: Dealing with Third-Party APIs���������������������������������������������������������� 263
Subscription Plan��������������������������������������������������������������������������������������������������������� 263
Create a Plan�������������������������������������������������������������������������������������������������������������������������������������� 263
Delete a Plan�������������������������������������������������������������������������������������������������������������������������������������� 264

Stripe Customer����������������������������������������������������������������������������������������������������������� 264


Subscribe a Customer to a Plan����������������������������������������������������������������������������������� 265
Test-Driven Stripe Library�������������������������������������������������������������������������������������������� 266
Integration Tests��������������������������������������������������������������������������������������������������������������������������������� 266
Unit Tests�������������������������������������������������������������������������������������������������������������������������������������������� 268

Make Your Code Robust����������������������������������������������������������������������������������������������� 274


Summary���������������������������������������������������������������������������������������������������������������������� 276

■Chapter 9: Pair Ranking������������������������������������������������������������������������������������ 277
Problem Domain Analysis��������������������������������������������������������������������������������������������� 277
Solution������������������������������������������������������������������������������������������������������������������������ 278
Summary���������������������������������������������������������������������������������������������������������������������� 284

Index��������������������������������������������������������������������������������������������������������������������� 285

xii
About the Author

Bala Paranj has a master’s degree in electrical engineering from Wichita


State University. He has been working in the software industry since 1996.
He started his career as a technical support engineer and later became a
web developer. He most commonly uses Perl, Java, and Ruby. He has
consulted for companies in the United States, Australia, and Jamaica in
finance, telecommunications, and other domains.
He is the founder of the developer training company rubyplus.com.
He publishes podcasts and screencasts in Ruby. He has been organizing
Ruby, Rails and TDD related events since 2007. He also has developed
several open-source gems that were extracted from his side projects.
He lives in Los Altos Hills, California, with his girlfriend and his dog,
Chico. He enjoys hiking, tennis, and tango. You can buy the TDD in Ruby
course at https://rubyplus.com/sales/new?id=11
You can contact the author with any questions about his book at
[email protected].

xiii
About the Technical Reviewer

Ronald Petty, M.B.A., M.S. is the founder of Minimum Distance LLC, a


management consulting firm based in San Francisco. He spends his time
helping technology-based startups do the right thing. He is also an
instructor at UC Berkeley Extension.

xv
Foreword

I have known Bala for more than a decade. In all this time, he has consistently been a leader in the Ruby
community in the San Francisco Bay Area. Bala has mentored many Ruby and Rails developers, including
me. He is very approachable and has a very appealing style of conversation.
Case in point, last week I was waiting for him at the Starbucks near Google’s HQ in Mountain View to
get his opinions on a project I am working on. While I waited, I met a fellow coffee enthusiast who, upon
finding out that I work for Intuit (the TurboTax company), asked me for some career advice. Ten minutes
later, Bala walked in. After a quick introduction to what we were talking about, Bala took the lead on the
mentoring. No more than a minute had passed before the protégé said, “Can I please record this?” Yes, Bala
is that impressive!
Bala thinks differently. He is a genius. In fact, when the above conversation was done, the protégé asked
us for our contact information. Whereas I proceeded to enter my name, number, and email into his phone,
Bala said, “Just go to my website and click on download vCard. Boom.”
Bala’s excellence in communicating rather abstract concepts clearly and concisely is very clear in the
way the lessons and examples are laid out in this book. He builds up the examples one step at a time so that
it is crystal clear what he intends you to learn. He uses various techniques to make sure the concepts stick in
your mind.
My two key takeaways from this book are as follows:
1.
Understanding the problem is the most important part of solving the problem.
2.
Test Driven Development does not magically result in a good design. There is
more to design than just reducing duplication in code.
This is an excellent book, and I highly recommend that you read it if you plan to create great software.

—John Varghese
Devops Evangelist at Intuit

xvii
Acknowledgments

My first thanks go to Steve Anglin, who approached me with the idea of writing a Ruby book. As a first-time
author, I was both petrified and excited at the same time. He was very understanding about my situation and
provided me the freedom to choose the topic and timing of the book.
I would like to thank Rhonda Jezek for pairing with me on most of the examples in this book, and Daniel
Pritchard for believing in me and encouraging me to write the book. I also would like to thank the members
of my Silicon Valley Ruby meetup, who provided valuable feedback about the early material in this book at
the bootcamps and tutorials. Thanks to Emily Bache for providing me with very candid technical feedback,
and Randy Coulman for his inspiring presentations and technical review of one of the chapters. I would also
like to thank Mayank Suri for challenging me and pushing me out of my comfort zone in order to accomplish
bigger goals in my career.
This book builds on top of the work of others like Kent Beck, Robert Martin, Eric Evans, Gerard
Meszaros, Michael Feathers, and others mentioned in the book. I cannot thank Ryan Davis enough for
building a simple and elegant testing framework with a gentle learning curve for beginners.
This book would not have been a reality without Steve Anglin, Mark Powers, and Matthew Moodie. I am
deeply indebted to the Apress team for recognizing my talent and providing me with a channel for my voice.
Last but not least, thanks to Ronald Petty for patiently reviewing my book and pointing out the mistakes.
This book is the result of my search for solutions to overcome the difficulties I faced when I started to
learn TDD. It also distills the design knowledge I have acquired over my career. I sincerely hope that this
book shows empathy for beginners and makes it easier for them to learn TDD.

xix
Introduction

Experience is simply the name we give our mistakes.


—Oscar Wilde

This book is the result of my struggle to learn Test Driven Development. I started documenting the
difficulties that I faced and what I did to overcome them. I started sharing my tips with the members of
my Silicon Valley Ruby meetup and on my blog. You will learn both from my mistakes and from other
developers in this book.

Mistakes are the portals of discovery.


—James Joyce

More importantly, if you document your mistakes and start analyzing them, you too will discover new tips
that you can share with others. Mastering TDD is a journey. I hope you enjoy the journey as much as I have
enjoyed writing this book. Good luck.

xxi
CHAPTER 1

The Basics

This chapter will discuss coding kata, basic terminology, overcoming difficulty in TDD, and how to improve
your TDD skills over time. We will look at the distinction between intent and implementation and its role in
coming up with elegant solutions. We will briefly discuss the basics of Test Driven Development (TDD) and
how problem-solving skills fit into TDD. We will also cover designing test cases, assertion, Canonical Test
Structure, and how to avoid common mistakes.

Terminology
This section will introduce you to the basic terminology required to grasp the material in this book. We will
look at basic terms such as kata, coding kata, domain, problem domain, and solution domain.

Kata
Kata is a Japanese word meaning form. In martial arts, it describes a choreographed pattern of movements
used to train yourself to the level of muscle memory. The focus is on making small improvements during
practice. Figure 1-1 shows a choreographed pattern of movements in martial arts.

Figure 1-1. A choreographed pattern of movements

© Bala Paranj 2017 1


B. Paranj, Test Driven Development in Ruby, DOI 10.1007/978-1-4842-2638-4_1
Chapter 1 ■ The Basics

Coding Kata
A coding kata is a short exercise that is thirty minutes to an hour long. It can be coded in many different
ways. It is likely that coding katas have many solutions. The focus is on learning when you work through
them. The goal is to practice in order to improve your skills, not to achieve perfection.

Domain
What comes to mind when you hear terms such as equity, debt, gross margin, and net income? How about
contour, contrast, opacity, and form? Here’s another example: parallel, ordinate, arc, and angle. A domain is
defined as a specific sphere of activity or knowledge. The first example corresponds to finance. The second
example corresponds to visual communication, and the third corresponds to geometry. Figure 1-2 shows
three different domains—finance, visual communication, and math—consisting of abstractions found in
those domains.

Figure 1-2. Examples of domains

Problem Domain
The problem domain refers to real-world things and concepts related to a problem.

Solution Domain
The solution domain refers to real-world things and concepts related to a solution.

Domain Expert
A domain expert is someone with special knowledge or skill in a particular domain. For instance, an
accountant is an expert in the accounting domain. The development of accounting software requires
knowledge in two different domains, namely accounting and software.

2
Chapter 1 ■ The Basics

Domain Knowledge
Domain knowledge is expertise in a particular problem domain. It is a critical ingredient in coming up with
abstractions that create elegant solutions.

Defining the Problem Domain and the Solution Domain


When you read a problem statement in a textual form, you will find concepts in the problem statement.
You can list the concepts you find and group them to come up with the problem domain name. Figure 1-3
illustrates the process of coming up with the problem domain name from a given problem statement.

Figure 1-3. Process of finding the domain name

Let’s now see an example of problem domain and solution domain. Let’s say you have leaking sink
problem in your kitchen. You search on the Internet for the term leaking sink. The phrase leaking sink is
found in the problem domain. Once you read about the solution to this problem, you learn about things
like: clevis screw, stopper rod, clevis, retaining nut and so on. These terms belong to the solution domain.
You watch a video and find out that you need to buy a retaining nut to fix the leak. You now start using this
term found in the solution domain, retaining nut, to find the nearest store carrying this item. So, the term:
retaining nut belongs to the solution domain.

Learning TDD
Learning by Coding Kata
Why coding Kata? Test Driven Development (TDD) is a difficult but learnable skill. So, in order to answer
this question, we need to look at why TDD is difficult.

TDD is not a testing technique. It’s an analysis technique, a design technique, really a
technique for all activities of development.
—Kent Beck, Test Driven Development by Example

3
Chapter 1 ■ The Basics

By using the small but precise nature of the coding kata to practice these skills separately, you can
move past this difficulty and hone your TDD skills. So, coding kata is the best way to learn TDD. How do you
practice a coding kata? You will work through a coding kata by following the five steps of TDD, which will be
discussed in an upcoming section.

Learning Retrospective
After you complete a coding kata using TDD, reflect on the TDD practice session. Ask yourself the following
questions:
• What went well during the TDD session?
• What went wrong during the TDD session?
• What can I do differently next time to improve?

The answers to these questions will tell you where you need to focus your efforts in your next practice
session so as to improve your skills. It’s a good idea to keep a journal that records the coding kata name and
the answers to these questions for each practice session.

Intent vs. Implementation


In this section, we will discuss the intent and implementation, or the specification and implementation.
We will look at examples to illustrate the differences between intent and implementation, why we need to
separate them, and how to separate them in the code.

Intent
The dictionary definition of intent is determined to do something. If you want to travel in your car, your intent
is to drive your car. You don’t reach into the transmission and pull levers to drive. You can drive without
knowing the details of the car engine. You use the visible parts of the car, such as the steering wheel, gas
pedal, brake, and gears, to drive. You can express your intent by using the public interface of the car. In
programming terms, the intent-revealing drive() method is used. The public interface would consist of
things you can do to a car, such as start, stop, drive, turn, and so on.

Implementation
The things under the hood of the car make up the implementation. Only your car mechanic knows about the
details of the car engine. You may be aware of the 3.0 liter V-6 engine, but you have no idea of how it works.
There could be methods that are internal to the class, such as burn_fuel(), that are not part of the public
interface of the car. This means the user does not directly invoke any private methods of the car.

Intent and Implementation


We will now see three examples of intent and implementation, the difference between them, and why we
need to separate them.

4
Chapter 1 ■ The Basics

Music
Music is composed by music composers. Music composers organize and develop the music to create a
written score that can be interpreted by performers. Performers play the music using different musical
instruments by referring the sheet music. Sheet music is not music. Sheet music is a visual abstraction of
music. To be specific, it is a symbolic abstraction of music that can be read by anyone who knows how to
read music notation. The composers communicate with other musicians across space and time using music
notation. This is the intent, the what, the logical design. Figure 1-4 shows sheet music that communicates
with other musicians.

Figure 1-4. Sheet music is a symbolic abstraction of music

Playing the music with a musical instrument is the implementation, the how, or the physical design.
There are many physical designs for a given logical design. In this example, the same sheet music can be
used to play the music using different musical instruments. Figure 1-5 shows music being performed by a
musical instrument, achieved by interpreting the sheet music.

5
Chapter 1 ■ The Basics

Figure 1-5. Music is played using a musical instrument

Lyrics
A lyricist writes the words for a song by organizing sections into one of the agreed upon structures. This
provides the roadmap for the song. Let’s consider the lyrics for the song “Come Together.” John Lennon
wrote this song. This is the what. The how in this case are the performances by The Beatles, Aerosmith, and
Michael Jackson of the same song, “Come Together.”

Home Plan
An architect gets requirements from the client. A hand-drawn sketch consisting of bubbles, squares,
and rectangles captures the idea of where things are and how they interrelate. This diagram becomes
architecture. Figure 1-6 shows the blueprint of a house that captures the design decisions made by the
architect. This blueprint of a house is the what. It is a visual abstraction of the design. You can build many
houses using the same blueprint.

6
Chapter 1 ■ The Basics

Figure 1-6. Blueprint of a house

Table 1-1 summarizes the intent and implementation of some common, everyday things that you
encounter.

Table 1-1. Intent vs. Implementation

Intent Implementation
Drive a car Internal mechanism of a car that drives
Represent music The process of playing music with a musical instrument
Lyrics of a song The unique way of singing a song by a singer
Plan of a home Houses that conform to the same blueprint but look different

Separate Intent from Implementation


We need to separate the intent from implementation. Why? Because it allows us to change the
implementation without breaking the tests. The intent is the focus of the tests. The implementation is the
focus of the production code. As long as the behavior is the same, the implementation changes should not
break the tests.

7
Chapter 1 ■ The Basics

Sheep Example
So, how do we separate the intent from implementation? We can use Chris Stevenson’s TestDox (https://
en.wikipedia.org/wiki/TestDox). TestDox expresses the subject in the code as part of a sentence. Here is
an example:
• A sheep eats grass.
• A sheep bleats when frightened.
• A sheep produces delicious milk.
• A sheep moves away from sheep dogs.
In this example, the sheep is the subject. Its behavior is expressed in a sentence. This can be
automatically converted to specifications in code. Figure 1-7 shows the behavior of a sheep expressed as
specifications in code.

Figure 1-7. Specifications in ĉode

In this example, we are using the spec style of the Minitest testing framework to describe the behavior of
a sheep. Minitest ships with the Ruby language. When you think about a system from the outside, you focus
on the intent. In this case, what does the sheep do?

Test API Example


For a realistic example, examine Figure 1-8 from the RSpec documentation that shows developers how the
eq() method in RSpec (http://rspec.info) works.

8
Chapter 1 ■ The Basics

Figure 1-8. Specification that shows RSpec API usage example

The example is easy to read and shows how the eq() method can be used to compare two strings that
are equal and not equal. (Source: https://www.relishapp.com/rspec/rspec-expectations/docs/built-
in-matchers/equality-matchers)

Bowling Game Example


Let’s look at an example that uses a bowling game scoring program to illustrate how to discover an
intent-revealing interface.

it 'score is 10 for a strike - knocking down all ten pins' do


  game = BowlingGame.new
  10.times { game.roll(1) }

  assert_equal 10, game.score


end

9
Chapter 1 ■ The Basics

This test does not reveal the intent of rolling ten times. We don’t know why it invokes the roll method
ten times, because the intent is hidden. We can make the intent explicit by asking the question: “What does
it mean to hit all ten pins?” In the bowling game domain, it means a strike. So, we can express it directly in
code as follows:

it 'score is 10 for a strike - knocking down all ten pins' do


  game = BowlingGame.new
  game.strike

  assert_equal 10, game.score


end

The strike method is intent-revealing and expresses the domain concept mentioned in the test name
directly in the code. It clearly communicates the meaning of a strike in a bowling game to other developers.

Precision in Language and Meaning


An infant cries, and you don’t know whether it is hungry or has tummy trouble. If you give it milk, it stops
crying. As it grows, the request “Milk!” becomes “Me Milk!” and later “Please give me some milk to drink.”
Children learn as they grow and their language acquires more precise meaning. Similarly, as the software
grows, the tests acquire more precise meaning.
A proposition in logic is a statement that expresses a concept that can be either true or false. For
instance, we can make valid propositions about the concept of grass, as follows:
• Grass is green.
• Grass is a plant.
• Grass grows.
• Grass is a monocot.
And so on, leading to increased meaning and precision of meaning for the concept of grass. We can
express this as specifications in code similar to the sheep example, as shown in Figure 1-9.

Figure 1-9. Specifications for grass

Now, consider the following:


• It has a wide opening to the water tank.
• It has a marked tank for exact water filling.
• It has two-hour auto-shutoff.

10
Chapter 1 ■ The Basics

• It has a filter basket.


• It has a thermal carafe.
• It is usually in the kitchen.
• It has a sink.
• It maintains the temperature of the drink inside.
What is it? At some point in the sequence, you connected with the pattern and understood it was a
description of a coffee maker. From that point, each statement confirmed your understanding. We can
express these statements as specifications in code that describes the coffee maker. We will discuss this in
more detail in an upcoming section on designing the sequence of test cases.

Tests Are Executable Documentation


Let’s say you installed a gem and need to figure out how to use it. You should be able to look at the tests and
see examples that show you how to use the library. It will answer questions such as:
• Which class should I instantiate?
• How do I instantiate the class?
• Which method should I invoke?
• What parameters does the method need?
And so on. However, you should not read the source code of the gem to figure out the answers to these
questions. The developer of the gem has achieved the desired separation of intent and implementation only
when one can write programs that use that gem by referring only to the tests that come with the gem. Tests
are executable documentation and always tell the truth. Other forms of documentation, such as wiki, source
code commenting, and so on, can get out of sync with the production code.
The tests are a way for the library developer to communicate with other developers about the library.
Tests must be readable and easy to understand for someone who is new to the library.

Shift in Mental State


You focus on specifying what a system should do when you are reading the problem description. This is
analysis. The mental state is the what during this activity. You will be looking at the problem domain. For
what, you must focus on the input and output of the system, as illustrated in Figure 1-10. You will focus on
what is visible outside of a system and ignore what is inside the system. You will ignore the details and treat
the system under test as a black box.

Figure 1-10. Mental focus is on what

11
Chapter 1 ■ The Basics

From what, we move to how. The focus shifts from analysis to design. You will be looking at the solution
domain. Your mental state is how. For how, you will focus on what is inside the system, as illustrated in
Figure 1-11. You will consider the details of the system under test.

Figure 1-11. Mental focus is on how

A professional artist starts to draw a portrait with a general outline that gives the basic shape of the face,
eyes, and so on. At this stage, the attributes of a person, such as eyes and lips, could be those of anyone. They
don’t look unique to the portrait subject. As the artist gradually adds more details and adds depth using
shading, the drawing comes to life and resembles the subject. The final portrait fits the structure provided by
the general outline drawn in the initial stages of the drawing. Software developers work in a similar way in
order to write software to solve a given problem.

Overview of TDD
This section is a brief introduction to Test Driven Development. We will answer questions such as what,
why, and how. We will discuss why we start with a failing test and are minimal when implementing the
production code. We will also see how TDD separates the intent from implementation, how to get all the
benefits of TDD, and, finally, what makes TDD difficult.

Test Driven Development


Test Driven Development is a software development practice where the test is written before the production
code. The goal is clean code that works. It leads to better quality and fewer defects in code. It eliminates the
need to spend days in a debugger to hunt down hard-to-find bugs. Thus, it reduces debugging efforts. Why
have clean code that works as the goal?

Clean code that works gives you a chance to learn all the lessons that the code has to teach
you. If you only slap together the first thing you think of, you never have time to think of a
second, better thing. The intent is to learn and come up with a better solution.
—Kent Beck, Test Driven Development by Example

12
Chapter 1 ■ The Basics

The Five Steps of TDD


Kent Beck is the creator of extreme programming, a software development methodology that avoids rigid
formal specifications for a collaborative and iterative design process. Kent Beck sums up the fives steps of
TDD as follows:
1. Quickly add a test.
2. Run all tests and see the new one fail. Since there is no code yet to make the test
pass, this test will fail.
3. Make a little change to pass the test as quickly as possible.
4. Run all tests and see them all succeed.
5. Refactor to remove duplication.
Figure 1-12 shows how the red-green-refactor steps repeat to form the TDD cycle.

Figure 1-12. The TDD steps repeat to form the TDD cycle

In the first step, we write a test. In the second step, we record a requirement as a test. We also explicitly
design the client API. Designing the API here means answering questions such as the following:
• Does the method name reveal the intent?
• Should this be an instance method or a class method?
• What are the parameters to this method?
• What are the required parameters?
• What are the optional parameters?
• Should this parameter be passed in to the constructor instead of being passed in to
the method?
• Should the parameter have a default value?

13
Another Random Scribd Document
with Unrelated Content
"We didn't fink, mother," pleaded Don, looking up in her face with
such a droll mixture of fun and entreaty in his roguish blue eyes,
that she could not refrain from giving him a kiss and a smile as she
answered, "Ah, my boys must learn to think and not take mother's
things without leave. Now run away to your plays and try to be good
children."
"Mother, I do think you're a little too easy with them," Mildred
said in a slightly vexed tone.
"Perhaps; but if I make a mistake, is it not far better to do so on
the side of mercy than of severity?"
"I suppose so; I shouldn't like to see them whipped."
Then laughingly she told the story of Fan's doings, and as needles
and cord must be replaced, put on her bonnet and sallied forth upon
the errand.
Mildred as one of the prettiest, most accomplished, graceful, and
fascinating young ladies of the place, and belonging to one of the
first families, was a good deal admired, and never lacked attention
at a party, picnic or any sort of gathering of the young people of the
town.
As she left the store where she had made her purchases, Spencer
Hall crossed the street and joined her.
He was the only son of the wealthiest man in the place and,
because of his great expectations, looked upon by most of the
young girls and their mammas as a desirable match.
Mildred, however, was of a different opinion, knowing him to be
idle, purse-proud, vain and conceited.
She therefore returned his greeting rather coldly; heartily wishing
that he had not happened to see her, or that something would occur
to rid her at once of his undesirable company.
Greatly amazed would the young exquisite have been could he
have read her thoughts; for he had no doubt that she felt highly
gratified and honored by his notice. Was he not arrayed in
broadcloth suit, silk hat and immaculate kids, while she wore calico,
cotton gloves and the simplest of straw bonnets? And could not his
father buy hers out ten times over?
His manner was gracious and patronizing as he remarked—
sauntering along by her side, "Why, Miss Mildred, can it be true that
you are going to leave us? I don't see what Lansdale will do without
you."
"It is quite true that we are going, Mr. Hall," she answered, with a
slight curl of the lip; "and I suppose my father and mother will be
missed; but I can not think that my loss will in any way affect the
prosperity of the town or the happiness of the people."
"Some people's it certainly will," he said, with increased
graciousness, exerting himself slightly to keep pace with her, as she
quickened her steps to a very rapid walk. "We don't want to lose
you; might it not be possible to persuade you to remain among us?"
"Certainly not; unless my parents should change their plans and
decide to stay. Of which there is not the least probability."
"Do you know that you are walking very fast, Miss Mildred?" he
said, laughing. "Do let us slacken our pace a little, for who knows
when we may have the pleasure of walking together again."
"You must excuse me; I am in great haste. But there is not the
slightest necessity for your exerting yourself to keep pace with me.
It is broad daylight and I know the way."
"Now don't be sarcastic, my dear young lady. I'd be willing at any
time to make a far greater exertion for the pleasure of your society;
but if we move so rapidly it will shorten our interview considerably."
"I have already explained that I am in haste; there is much to be
done in the few weeks before we leave," the girl answered coldly,
pressing on with accelerated speed.
"Haven't time even for a word with an old friend, eh? Then good-
morning, Miss Keith," and turning about in disgust, he sauntered
leisurely along in another direction while she sped on her way as
before.
"Is it possible! what does the girl mean!" he ejaculated the next
minute, as on turning his head to look after her, he perceived that
Mildred had actually stopped upon the sidewalk—stopped to speak
to a mutual acquaintance, a lad a year or two younger than himself,
who was working his own way in the world, getting an education by
the hardest and helping a widowed, invalid mother.
For Frank Osborne Mildred had the highest respect, though she
looked upon him as a mere boy and was wholly unconscious that to
him she was the embodiment of every virtue and grace; that her
words, looks and smiles were treasured up in his very heart of
hearts; nor did she dream how unhesitatingly he would have laid
down his life to save hers had it been in danger. It was only a boy's
passion, but it was deep and strong.
The news of the intended removal of the Keiths to what, in those
days, seemed a far distant region, had been a great shock to him;
but with the hopefulness of youth he consoled himself with the
resolve to follow and seek her out—when in the course of years he
should earn fame and fortune—though she should be carried to the
ends of the earth.
His eye brightened and his cheek flushed, as on turning a corner,
he came suddenly upon her in her rapid walk, and she stopped and
held out her hand in friendly greeting.
He took it almost reverentially.
"How d'ye do, Frank? and how is your mother to-day?" she was
saying, her bright eyes looking straight into his.
"Better, thank you, Miss Mildred. And you are well? and oh, can it
be true that you are all going so far away?" he asked with a wistful,
longing look.
"Yes; to the land of the Hoosiers, wild Indians and wolves," she
said gayly. "Don't you envy me?"
"I envy those that go with you," he answered, sighing. "You won't
forget old friends, Miss Mildred?"
"No; no, indeed, Frank," she said, heartily. "But good-bye. I must
hurry home," and with a nod and smile she tripped away; to the
satisfaction of Hall who had jealously watched the whole interview.
He was glad it had been no longer, though he could not avoid the
unpleasant consciousness that more favor had been shown to "that
pauper" than to himself, the prospective heir to a comfortable
fortune.
Chapter Third.
"Lessons so dear, so fraught with holy truth
As those her mother's faith shed on her
youth."
"Now," said Mildred, taking up her sewing again, "I must work
fast to make up for lost time, for I've set my heart on finishing this
dress of Ada's to-day."
The words had scarcely left her lips when there came a loud crash
and scream from the hall, followed by a sound of tumbling and
rolling.
Up sprang mother, aunt and sister, scattering scissors, thimbles
and work, and rushed toward the scene of commotion.
They found the stairs, and Fan, who sat weeping half way up,
drenched with water; while at the foot were scattered fragments of
a large pitcher, Cyril lying among them half stunned and with the
blood streaming from a cut in his head; Don gazing down upon him
from the landing and adding his mite to the confusion by screaming,
"Oh! oh! oh! he's deaded! he's deaded!"
"No, he ain't," said Cyril, slowly getting on his feet. "Mother, I
didn't mean to. Please don't let Milly scold us young ones. Oh, stop
this quick!" putting his hand to his head.
"Yes, sonny, as soon as possible," said Mrs. Keith, taking his head
in her hands and holding the lips of the wound together. "A basin of
cold water, Milly, quick! and aunt, there is sticking plaster in the
work-table drawer. Hush Don; don't cry any more, Fan; Cyril isn't
much hurt and mother will soon make it all right."
Her orders were promptly obeyed, the wound skillfully dressed,
Fan's wet clothes changed, and then inquiry was made as to how it
had all happened.
"Why—why," said Cyril, "you see Fan wanted to wash her hands;
'cause she'd been diggin' in her garden and dey was all dirty, and
dere wasn't any water in the pitcher and we brung it down and got it
full and I was carryin' it up and my foot tripped and I fell down with
it and knocked Fan over cause she was behind me. And I couldn't
help it. Could I, Don?"
"No, you touldna help it," assented Don. "And Fan touldn't too."
"And he's dot a bad hurt on his head," put in Fan pityingly.
"Yes, he's punished enough, I think," said the mother, caressing
him; "his intentions seem to have been good; but next time you
want water, dears, come and tell mother or sister Milly."
"There, the morning's gone," said Mildred, as bells and whistles
began their usual announcement; "a full hour of it wasted, too, by
the pranks of those children. I hope they've finished up the business
for to-day!"
Vain hope! inactivity was impossible to those restless spirits: their
surplus energy must be worked off in some way.
They had not been heard from for two hours and Mrs. Keith had
just remarked that she feared it must be some mischief that was
keeping them so quiet, when shrieks and wails from three infantile
voices, coming from the second story, appealed strongly to the
compassion of their relatives in the sitting-room.
The call for help was responded to as promptly as on the previous
occasion. Mother, aunt, and sister flew to the rescue and on entering
the room whence the sounds proceeded, found Fan locked in the
wardrobe and the two boys seated in the lower drawer of the bureau
which their weight had caused to tip so far forward that they could
not get out without assistance. A chair standing so near as to
prevent the bureau from falling entirely to the floor, had probably
saved them from a serious accident; but there they were, bent
nearly double, legs dangling, vociferous screams issuing from their
throats.
It was the work of a moment for the laughing mother and aunt to
lift up the bureau and release the two rogues, while Mildred sprang
to the wardrobe, unlocked it and took the sobbing Fan in her arms.
"You poor dear, who fastened you in there?"
"Cyril did. He said I stealed and must go to jail. And—and I was
'f'aid it would des tumble over; it shaked so when I tried to det out."
"The naughty boy!" cried Mildred, flashing an indignant glance at
him as he and Don crept from the drawer, straightened themselves
and stood up looking very much abashed and ill at ease.
"Mother, I do think Cyril ought to be punished."
"I didn't hurt her," he muttered, hanging his head; "and I was
goin' to let her out 'fore long. And we didn't mean to tumble the
bureau over. Did we Don?"
"No; it dus went yight over its ownse'f," chimed in the little
brother. "Pease, mamma we's doin to be dood boys now."
"You might have been very much hurt if the chair had not been
where it was," she said, composing her features and speaking with
becoming gravity, "I am very thankful for your escape, and you must
never do such things again. Especially never lock each other into a
wardrobe or closet," she added sitting down, drawing Fan to her side
and caressing her tenderly, while Miss Stanhope and Mildred
restored the contents of the bureau drawers, which the boys had
unceremoniously tossed upon the carpet.
"Why, mother?" queried the self-constituted jailor.
"Because it is very dangerous. Your little sister might have been
frightened into a fit or have died for want of air to breathe."
Cyril's eyes dilated, then filled with tears as he seemed to see the
little sister he loved so dearly lying before him white and cold and
dead.
"I won't ever, ever do it again," he said tremulously.
"No, you must be Fan's big brave brother that she can trust to
take care of her and shield her from harm. I don't believe my Cyril
would be such a mean coward as to hurt a little girl or anything
smaller or weaker than himself, except for that naughty 'didn't
think!'"
"But I didn't hurt her, mother."
"Yes, my son, you hurt her feelings very much."
He considered a moment. "Yes, I s'pose that's so," he said slowly,
"Fan, I'll tell you; I'm real sorry; and you may be jailor now and lock
me up in that wardrobe."
"No, no! there must be no more such doings," quickly interposed
mamma.
"Dess I wouldn't do such sing!" said Fan, wiping away her tears
with her chubby little hand.
"What a room!" said Mildred, shutting the last bureau drawer and
turning to look about her; "every chair out of place and turned on its
side, the bed all tumbled and bits of paper scattered over the
carpet."
"Pick them up, children, and try to keep out of mischief for the
rest of the day. I must go back to my sewing," Mrs. Keith said,
following her aunt, who had already left the room.
Mildred staid behind to assist in setting it to rights.
"You naughty children! really I could almost enjoy spanking you
all round," she exclaimed directly, as she came upon the fragments
of a delicate china vase belonging to herself, and a valued letter
from a friend torn into bits.
"Milly," said Cyril solemnly, "s'pose we should get deaded some
day; wouldn't you be sorry?"
"Suppose I should get deaded," she retorted, "wouldn't you be
sorry for spoiling my pretty things?"
She was ashamed of her outburst nevertheless, and the child's
words haunted her all the afternoon.
It was evening; two candles burned on the sitting-room table,
and beside it sat Mildred and her mother still busily plying their
needles.
The rest of the family were in bed and Miss Stanhope and the
seamstress had gone to their own homes hours ago.
"My child, put up your work for to-night," said Mrs. Keith; "You
are looking weary and depressed; and no wonder, for you have had
a hard day."
"A busy day, mother; but not so hard as yours, because I have
had a walk in the fresh air while you have been stitch, stitching from
early morning till now. And if you don't forbid it I shall sit up and
work as long as you do. I consider it one of the eldest daughter's
privileges to share her mother's burdens."
"My dear girl! you are a comfort to me! I thank God for you every
day," the mother said, looking at her with dewy eyes and a beautiful
smile, "but because you are young and growing, you need more rest
and sleep than I do. So go, daughter, and never mind leaving me."
"Mayn't I stay a little longer," pleaded the girl, "I want one of our
nice confidential talks. O mother, I am so disgusted with myself! I
was very angry with Cyril and Don to-day when I found they'd
broken that vase I valued so because you gave it to me as a
birthday present; and it was so pretty too—and torn up that sweet
letter dear Miss Grey wrote me just before she died."
"Indeed! I didn't know they had done such damage and I am very
sorry for your loss, dear!"
"Yes, mother, I knew you would be; my loss of temper, though,
was worse than all. I do wish I knew how you contrive always to be
so patient."
"I'm afraid it's very often all on the outside," the mother
answered with a slight smile. "But I find it a great help in bearing
patiently with the little every day worries, to think of them as sent,
or permitted, by my best Friend—One who never makes a mistake—
for my growth in grace; for you know we grow strong by resistance."
"Well, mother, I am constantly resolving that I will not give way to
my temper, and yet I keep on doing so; and I grow so discouraged
and so disgusted with myself. What shall I do?"
"My child, watch and pray. Our sufficiency is of God. He is our
strength. And do not look at yourself; try to forget self altogether in
'looking unto Jesus;' get your mind and heart full of his lovely image,
so full that there will be no room in it for aught else; and thus shall
you grow into His likeness."
Mildred's eyes shone as she looked up into her mother's earnest
face.
"I am sure that must be the way," she said, low and feelingly,
"and I will try it; for I do long to be like Him, mother; for He is
indeed to me, 'the chiefest among ten thousand and the one
altogether lovely!'"
"Oh, how good He is to me!" ejaculated the mother, glad tears
shining in her eyes: "that you might learn thus to know and love Him
has been the burden of my prayer for you—for each of my dear
children—since they first saw the light."
They worked on in silence for some minutes, then Mildred seeing
a smile playing about her mother's lips, asked what was the thought
that provoked it.
"A reminiscence of some of your infantile pranks," her mother
answered laughing. "You should be forbearing with your little brother
and sisters for you were fully as mischievous as they are.
"Before you could walk I caught you one day seated in the middle
of the table set for tea, your hand in the sugar bowl, your mouth full
and your face well besmeared.
"You were a great climber and it was difficult to keep anything out
of your way; and as soon as Rupert could creep he followed you into
danger and mischief; pulling things about, breaking, tearing, cutting,
climbing fences and trees, and even getting out of windows on to
roofs.
"Besides, you had a perfect mania for tasting everything that
could possibly be eaten or drunk—soap, candles, camphor, lye,
medicines whatever you could lay your hands on—till I was in
constant fear for your lives."
"You poor, dear mother, what a time you must have had with us!"
exclaimed the girl. "We can never hope to repay you for your patient
love and care."
"My child, I have always felt that my darlings paid for their trouble
as they went along; their love has always been so sweet to me,"
Mrs. Keith answered, cheerily. "And I can not tell you how much I
enjoy the sweet society and confidence of my eldest daughter—the
knowledge that she has no secrets from me."
"I have not, indeed," Mildred said, heartily, "as why should I?
knowing as I do that my mother is my best and wisest, as well as
dearest earthly friend."
Then recalling the events of the morning she gave a laughing
account of her interview with Spencer Hall.
"If I could contemplate the possibility of leaving you behind it
would certainly not be in his care," her mother said, joining in her
merriment, "and I am glad you have sense enough not to fancy
him."
"Truly I do not in the least; though many of the girls consider him
a great catch because of his father's wealth," said Mildred. "But
really I don't believe he meant anything, and I felt like showing him
that I understood that very well and resented his trifling; and
wouldn't have been much better pleased if he had been in earnest."
Chapter Fourth.
"And, like some low and mournful spell,
To whisper but one word—farewell."
—Park Benjamin.
One sweet June morning an expectant group gathered in the
shade of the vine-wreathed porch of Miss Stanhope's pretty cottage.
It consisted of that good lady herself Mr. and Mrs. Keith and their
eight children, all attired in neat traveling costume, and awaiting the
coming of the stage coach which was to carry them the first step of
their journey—to the nearest town situate on the Ohio and Erie
Canal.
Mr. and Mrs. Park, the new occupants of the cottage, were there
too, and a few old neighbors and friends who had run in for a last
good-bye.
Mrs. Keith and Mildred turned now and then, a tearful lingering
look upon their deserted home and this other which was equally
familiar, almost equally dear; Miss Stanhope seemed to have some
ado to control her feelings of sadness and anxiety for the future; but
Mr. Keith was in fine spirits in which the children evidently shared
very largely.
Eager to be off, they moved restlessly about asking again and
again, "When will the stage come?" and kept sending out
reconnoitering parties to see if there were any signs of its approach.
At length they espied it and announced the fact with joyful
exclamations as its four prancing steeds came sweeping around the
corner and, swaying and rolling, it dashed up to the gate.
The driver drew rein, the guard sprang from his lofty perch, threw
open the door and let down the steps.
There were hurried embraces and farewells, a hasty stowing away
of bags, bundles, and passengers large and small, in the inside, and
of more bulky baggage in the boot of the coach, the steps were
replaced, the door slammed to, and amid waving of handkerchiefs
and a chorus of good-byes and good wishes, the "toot, toot!" of the
guard's horn, the crack of the coachman's whip, they swept away
down the street, looking, in all probability, their last upon many a
well known object, many a friendly face, nodding and smiling to
them from door or window.
Frank Osborne, at work in his mother's garden, dropped his hoe
to lift his hat and bow as the stage passed, and to gaze after it with
a longing, lingering look.
Spencer Hall, standing, cigar in mouth, on the steps of his father's
mansion, did likewise.
But Mildred had turned her head away, purposely, and did not see
him.
Never before had Lansdale put on so inviting an appearance, or
the surrounding country looked so lovely as to-day, while they rolled
onward through the valley and over the hills now clothed in all the
rich verdure of early summer and basking in the brilliant sunlight
occasionally mellowed and subdued by the flitting shadow of some
soft, white, fleecy like cloud floating in the deep azure of the sky.
A few hours' drive took our travellers to the town where they
were to exchange the stage for the canal boat, the packet Pauline.
She lay at the wharf, and having dined comfortably at a hotel near
by, they went on board, taking with them the luggage brought by
the stage.
Their household goods had been dispatched on the same route
some days before.
Here they were in quarters only less confined than those of the
stage, the Pauline's cabin being so narrow that when the table was
to be set for a meal, most of the passengers had to go on deck to be
out of the way.
All along the side of the cabin ran a cushioned seat; used for that
purpose in the daytime and as a lower berth at night; other shelf-like
berths being then set up over it; all so narrow that the occupant
could scarcely turn upon his couch; and the upper ones so close to
the ceiling that it required some care to avoid striking the head
against it in getting in or out. Also there was an unpleasant
dampness about the bedding.
In the cool of the evening or when the sun was clouded, the deck
was the favorite place of resort; but there a constant lookout for
bridges must be kept, and to escape them it was sometimes
necessary to throw one's self flat upon the deck; not the most
pleasant of alternatives.
The progress of these packets was so slow too, that it took nearly
a week to reach Cleveland from the point where our friends
embarked.
But this mode of travel had its compensations. One was the
almost absolute safety; another the ease with which the voyager
could step ashore when the boat was in a lock and refresh himself
with a brisk walk along the tow-path; boarding her again when the
next lock was reached.
This was done daily by some of the Keith family, even the very
little ones being sometimes allowed the treat when the weather and
walking were fine and the distance was not too great.
Passengers were constantly getting off and on at the locks and
the towns along the route, and often the boat was crowded. It was
so the first night that our friends spent on board; babies cried, older
children fretted and some grown people indulged in loud complaints
of scant and uncomfortable accommodations; altogether the cabin
was a scene of confusion and the young Keiths felt very forlorn.
But mother, aunt and older sister were very patient, soothed,
comforted, and at length succeeded in getting them all to sleep.
Then Aunt Wealthy, saying that she felt disposed to lie down and
rest beside the children, persuaded Mrs. Keith and Mildred to go
upon deck for an hour to enjoy the moonlight and the pleasant
evening breeze with Mr. Keith and Rupert, who had been there ever
since supper.
Mr. Keith helped his wife and daughter up the short flight of steps
that led from the stern to the deck, and found them seats on some
of their own trunks.
There were a number of other passengers sitting about or pacing
to and fro; among the former a burly German who sat flat on the
deck at the stern end of the boat, his long legs dangling over the
edge, his elbow on his knee and his bearded chin in his hand, gazing
out idly over the moonlight landscape, while wreaths of smoke from
a pipe in his mouth, curled slowly up from his lips.
The Pauline glided onward with easy pleasant motion; all had
grown quiet in the cabin below and the song of the bullfrogs, the
dull thud of the horses' hoofs and the gentle rush of the water
against the sides of the boat, were the only sounds that broke the
stillness.
"How nice it is here!" exclaimed Mildred, "the breeze is so
refreshing, the moonlight so bewitching!"
"Yes, the country is looking beautiful," said her mother, "and one
gets a good view of it here; but I feel somewhat apprehensive in
regard to the bridges. We must be on the watch for them and dodge
in time."
"We will," said her husband; "though we may pretty safely trust
to the steersman; it is his duty to be on the lookout and give timely
warning."
"Well, we're facing in the right direction to see them," remarked
Rupert, "but that Dutchman back there is not. I s'pose he's safe
enough, though, with the man at the helm to sing out as we near
them."
With that they fell into talk on other topics, and thought no more
of the smoker.
"Bridge!" sang out the steersman, and down went every head
except that of the German, who sat and smoked on unmoved.
"Bridge!" The cry was repeated in louder, more emphatic tones.
"Yah, pridge, pridge!" responded the German straightening up a
little, nodding his head assentingly, but not looking round.
"Bridge!" sang out the steersman for the third time, "bridge, you
stupid lout! dodge or"—
But the boat was already sweeping under, and the bridge taking
the German across his shoulders threw him with sudden violence to
the platform below, whence he rolled over into the canal, uttering a
half stifled cry for help as the water closed over him.
But he rose again instantly panting and spluttering, and striking
out vigorously for the boat; he presently succeeded in laying hold of
the edge of the platform, and, the steersman lending him a helping
hand, clambered on board, crestfallen and dripping, while the crowd
on deck, seeing him safe, indulged in a hearty laugh at his expense.
"I loss mein bipe," he said ruefully, shrugging his shoulders and
shaking the water from his clothes.
"Well, you got a free bath in exchange and may be thankful you
didn't lose your life," remarked the steersman with a grin. "Next time
I call out bridge I guess you'll duck your head like the rest."
The rain had been falling heavily all night, but the sun shone
brightly, and the clouds were flying before a high wind that blew
fresh and cool from Lake Erie as the Pauline glided quietly into
Cleveland.
"What a beautiful city!" exclaimed the young Keiths as they
stepped ashore. "Do let us walk to the hotel, father, if it is not too
far."
"Just as Aunt Wealthy and your mother say," he replied, taking
the baby from his wife. "I am told it is but a short distance, Marcia; I
will have our heavy baggage carried directly to the steamer which
leaves this afternoon; and Rupert and the girls can take charge of
the satchels and small packages."
The ladies decided in favor of the walk as affording agreeable
exercise and enabling them to see the city to better advantage than
if cooped up in hack or omnibus, and no one regretted their choice:
they found the wide streets so clean, the breeze so refreshing and
exhilarating, and enjoyed so very much gazing upon the tall, elegant
looking houses and the pretty things displayed in the windows of the
large, handsome stores.
After a good dinner at the hotel, Mr. Keith, his wife and older
children, went out for another stroll about the city; Miss Stanhope,
who insisted that she had had exercise enough, and preferred to
stay where she was, taking charge of the little ones in their absence.
On the return of the pedestrians the whole party went on board
the steamer which was to convey them across the lake to Detroit. It
was a fine boat, the cabin large and handsome; staterooms on each
side furnished with berths of far more comfortable size than those of
the canal packets.
The table here was better, too, both in its appointments and the
quality of the food, and was set in a lower saloon, reached from the
upper one by a flight of broad winding stairs.
The children were delighted with the change and wanted to be on
the guards all afternoon, watching the play of the great stern wheel,
admiring the rainbows in the clouds of spray it sent up, looking out
over the wide waste of waters, at the islands and an occasional
passing boat, or racing back and forth.
Mildred and Rupert were given charge of the three little ones and
found great vigilance necessary to prevent Cyril and Don from
putting themselves in peril of their lives. Mildred was more than once
sorely tempted to shake the young rogues who gave her no peace;
but, remembering and acting upon her mother's advice, was able to
restrain herself and treat them with uniform gentleness.
She felt rewarded when, as she was putting them to bed, her
mother being busy with the babe, Don threw his arms impulsively
round her neck and kissing her again and again, said "I loves you,
Milly; you so dood to us naughty chillens."
"That she is!" assented Cyril, heartily, "an' I wish I didn't be so
bad."
"Well, try again to-morrow to be ever so good," Mildred
answered, tucking them in and leaving them with a good-night kiss.
She helped her sisters with their preparations for the night, then
was rewarded with a delightful evening spent with the older
members of the family in the open air, looking out upon the beautiful
wide expanse of waters, now starlit and anon illumined by the silvery
rays of the moon as she rose apparently from the distant eastern
edge of the lake and slowly ascended the azure vault of the
heavens, now shining resplendently and again veiling her fair face
for a moment with a thin floating cloud.
The next morning the steamer lay at anchor in Detroit harbor and
our friends left her for a hotel in what was then the principal street
of the city. Here, too, they walked out to view the land, and passing
the stores and public buildings, found well-shaded streets and
handsome residences with pretty door-yards in front.
Mr. Keith gave his children their choice of passing around the
lakes in a steamer or in the sloop Queen Charlotte. They chose the
latter and the next morning the family and their luggage were
transferred to her decks.
The ladies pointed out the articles they wished carried to their
staterooms and followed in the wake of the bearers.
There was less of show here than on the steamer they had left,
but comfort and convenience had not been overlooked, and though
Mildred's face clouded a little, it brightened again in a moment as
she noted the cheerful content in those of her mother and aunt.
They hurried on deck again where Rupert had been left in charge
of the younger children, to watch the vessel getting under way.
They were lying close to a steamer on whose other side was a
second sloop in quite as close proximity. All seemed hurry and bustle
on board the three.
"I don't see how we are to start," observed Mildred, glancing up
at the sails which hung almost motionless on the masts, "for there's
scarcely a breath of wind."
"Don't you see that they're lashing us and the Milwaukee yonder
fast to the steamboat, one on each side?" said Rupert. "She's to tow
both till the wind gets up."
"Oh, is that the way? she'll have hard work to do it, I should
think."
"She won't growl any way."
"No, I suppose not. Which is the captain, Ru.?"
"That nice jolly looking chap over yonder, that's giving orders in
such a loud peremptory tone, is Captain Wells, master of the ship;
that blue eyed, brown haired, rosy cheeked stripling standing near is
his son, Edward Wells; and they're both English; so don't remind
them that this vessel was taken from the British in the last war."
"Of course not, unless they say something mean or exasperating
about Washington or America."
"In that case I give you leave to twit 'em as hard as you like."
"Who was that nice looking man that helped us on board? I
thought father or somebody called him captain."
"So he is, Captain Jones; but acting as first mate here. That lady,
talking to mother and Aunt Wealthy, is his wife. They're both
Yankees; so you can relieve your mind occasionally on the subject of
the ship, by a little private exultation with them.
"Do you notice the contrast between those two faces?—mother's
and Mrs. Jones'; hers so dark, mother's so beautifully fair and rosy."
"Who could help noticing it? Rupert, I do think our mother has
just the loveliest face in the world!"
"Ditto!" he said, gazing at her with a world of filial love, pride and
chivalric admiration in his handsome eyes.
"I say what's the use? you may just as well set still where you
hare," growled a voice near at hand.
The young people turned involuntarily at the sound, and
perceived that the speaker was a burly, red-faced young
Englishman; the one so politely and kindly addressed, a little meek-
eyed woman of the same nationality, with a chalky complexion, and
washed out appearance generally, who, as they afterward learned,
and suspected at the time, was the wife of his bosom.
"'What a bear!" exclaimed Rupert in an aside to his sister, and
drawing her away as he spoke. "See, we're beginning to move. Let's
go over to the other side where we can have a better view."
"I presume that's what she wanted to do," remarked Mildred,
glancing back at the meek-eyed woman. "And why shouldn't he have
let her?"
"Why, indeed, except that he's a cowardly bully."
"How do you know?"
"Because that's the only kind of man that would speak so to a
decent woman."
Chapter Fifth.
"Hark! to the hurried question of despair:
'Where is my child?' and echo answers
'where?'"
—Byron.
"How did you learn all you've been telling me, Ru.?" asked Mildred
as they stood side by side watching with interest the Queen
Charlotte and her consorts slowly clearing the harbor. "Oh, easily
enough; young Wells and I got into talk while you and the others
were down in the cabin; I asked questions and he answered 'em.
Ah, here he comes," he added looking round, "I'll introduce him for
he's a nice fellow, I'm sure, and it's a good thing to have a friend at
court; in other words to be in favor with the reigning powers; i. e.
the captain and his nearest of kin. My sister, Miss Mildred Keith, Mr.
Wells."
"Happy to make your acquaintance, Miss," said the young sailor,
gallantly, lifting his hat and bowing low. "Hope you'll enjoy your
voyage on the Queen Charlotte. Shall be most happy to do all I can
to make the trip pleasant to you."
"Thank you kindly."
He began at once by finding comfortable seats for them where
they were sheltered from the sun, and had a good view of the
Canada and Michigan shores; and being acquainted with the
localities, and their history, and possessed of a ready command of
language, he added much to the interest of the scene by the
information he imparted; sometimes unsolicited, at others in answer
to questions.
When they had passed through Detroit river and so far out into
Lake St. Clair that little could be seen but water and sky, he offered
to show them over the vessel.
They gladly accepted, enjoyed the tour, and when it was over
rejoined the rest of their party just as the cabin passengers were
summoned to the supper table.
Mildred was seated between Rupert and Edward Wells; opposite
them sat Mr. and Mrs. Sims, the bullying Englishman and his meek-
eyed wife, and a bachelor gentleman of pleasing countenance and
manners, whom Captain Wells addressed as Mr. Carr. Next them
were Captain and Mrs. Jones. There were many more passengers of
both sexes, several nationalities, and a variety of ages from infants
in arms, up to hoary headed grandparents, but with most of them
our story has little or nothing to do.
The two captains, the wife of the one and the son of the other,
were polite and genial, the fare was excellent, and every one
present seemed disposed to contentment and good humor except
Mr. Sims, who turned up his nose at the food, snubbed his wife and
scowled at his opposite neighbors; perchance reading too plainly in
the frank, youthful countenances their disapproval of him.
Mildred so compassionated the long-suffering wife that, in the
course of the evening, seeing her sitting by herself and looking sad
and lonely, she drew near and opened a conversation.
Mrs. Sims responded readily.
"Do sit down, Miss," she said, making room for Mildred by her
side, "I'm so glad to 'ave some one to speak to, for I gets hawful
'omesick at times."
"Ah, that must be a very trying feeling," Mildred said
compassionately. "I know nothing of it myself; for I've never been
away from home or mother for a week at a time."
"Well, Miss, you're fortunate."
"Have you been long in the country?"
"It's barely six months, Miss, since I left me father's 'ouse in
London. We kept an 'otel there; an' that's 'ow I came to know Mr.
Sims; he takin' lodgin' with us while up to London about some
business 'e 'ad with the lawyers."
"And are your own family all still in England?"
"Yes, Miss; hevery one; I left 'em all—father, mother, brothers and
sisters—for 'im," she answered with a tremble in her voice and
wiping her eyes furtively.
"What a shame he should treat you as he does!" was the
indignant exclamation that rose to Mildred's lips, but she checked
herself in time, and changed it for, "Then I think he ought to be very
good to you."
"I 'ope we'll be 'appy, Miss, when we're settled down in a 'ome of
our own," remarked the little woman with a half stifled patient sigh.
"And indeed it's not 'alf so bad as I expected; I've been hastonished,
at finding so many white women in America. I thought when I
landed in New York I'd be the honly white woman there. I s'posed all
the rest would be Injuns or niggers."
"Indeed! how relieved you must have been on discovering your
mistake," remarked Mildred demurely, while her eyes twinkled with
suppressed fun.
"That I was, Miss, as you may well believe; it quite reconciled me
to the country."
The sun rose brightly the next morning and the young Keiths
were early on deck, romping and racing about, fall of the vivacity
and mirth usually incident to extreme youth and perfect health.
They were well watched over by their father, Mildred and Rupert,
or there is no knowing what wild and dangerous pranks might have
been indulged in by Cyril and Don.
The former actually proposed a flying leap from the deck of the
Queen Charlotte to that of the steamer and was not at all pleased by
the decided veto put upon it by his father.
"I think you might let a fellow try, papa," he grumbled, "it would
be such fun and I know I could do it."
"No, you couldna," said Don, peeping over the ship's side, "it's a
big, big place."
"Come over to the other side of the deck, and stay there," said
Mr. Keith, leading them away.
Rupert followed holding Fan by the hand. "What was that? what
were they throwing in?" he asked, stopping suddenly at a sound as
of a heavy body plunging into the water, while at the same instant a
startled cry came from the deck of the Milwaukee.
"A man overboard!"
"A man overboard!" the fearful cry was taken up and repeated on
all sides amid the rush of many feet and the quick, sharp imperative
words of command.
Almost instantly a boat was lowered and strong arms were pulling
with swift, vigorous strokes for the spot, already left far behind,
where the splash of the falling body had been heard, and keen eyes
were eagerly searching the waste of waters; the crews and
passengers of the three vessels crowding the decks and following
their movements in breathless anxiety and suspense.
They pulled backward and forward, calling out to the drowning
one that help was near.
"Ah, yonder he is at last!" cries a woman's voice in exultant
tones; "there he is with his head above water, for I see his hat."
"And they see him too, and are pulling toward him with all their
might!"
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like