Introduction to Software Testing Paul Ammann instant download
Introduction to Software Testing Paul Ammann instant download
download
https://ebookgate.com/product/introduction-to-software-testing-
paul-ammann/
https://ebookgate.com/product/introduction-to-software-testing-1st-
edition-paul-ammann/
ebookgate.com
https://ebookgate.com/product/software-testing-4th-edition-paul-c-
jorgensen/
ebookgate.com
https://ebookgate.com/product/introduction-to-nondestructive-testing-
a-training-guide-2nd-edition-paul-e-mix/
ebookgate.com
https://ebookgate.com/product/introduction-to-nondestructive-testing-
a-training-guide-second-edition-paul-e-mixauth/
ebookgate.com
Software Testing 1st Edition Ali Mili
https://ebookgate.com/product/software-testing-1st-edition-ali-mili/
ebookgate.com
https://ebookgate.com/product/software-testing-third-edition-brian-
hambling/
ebookgate.com
https://ebookgate.com/product/how-to-reduce-the-cost-of-software-
testing-1st-edition-matthew-heusser/
ebookgate.com
https://ebookgate.com/product/software-testing-interview-questions-
computer-science-1st-edition-s-koirala/
ebookgate.com
https://ebookgate.com/product/well-testing-project-management-paul-j-
nardone/
ebookgate.com
Introduction to Software Testing
Paul Ammann
George Mason University
Jeff Offutt
George Mason University
University Printing House, Cambridge CB2 8BS, United Kingdom
One Liberty Plaza, 20th Floor, New York, NY 10006, USA
477 Williamstown Road, Port Melbourne, VIC 3207, Australia
4843/24, 2nd Floor, Ansari Road, Daryaganj, Delhi – 110002, India
79 Anson Road, #06-04/06, Singapore 079906
www.cambridge.org
Information on this title: www.cambridge.org/9781107172012
DOI: 10.1017/9781316771273
A catalogue record for this publication is available from the British Library.
Part 1 Foundations 1
1 Why Do We Test Software? 3
1.1 When Software Goes Bad 4
1.2 Goals of Testing Software 8
1.3 Bibliographic Notes 17
3 Test Automation 35
3.1 Software Testability 36
3.2 Components of a Test Case 36
v
vi Contents
ix
x List of Figures
xii
List of Tables xiii
Much has changed in the field of testing in the eight years since the first edition was
published. High-quality testing is now more common in industry. Test automation
is now ubiquitous, and almost assumed in large segments of the industry. Agile
processes and test-driven development are now widely known and used. Many
more colleges offer courses on software testing, both at the undergraduate and
graduate levels. The ACM curriculum guidelines for software engineering include
software testing in several places, including as a strongly recommended course
[Ardis et al., 2015].
The second edition of Introduction to Software Testing incorporates new features
and material, yet retains the structure, philosophy, and online resources that have
been so popular among the hundreds of teachers who have used the book.
xiv
Preface to the Second Edition xv
The most obvious, and largest change, is that the introductory chapter 1 from
the first edition has been expanded into five separate chapters. This is a significant
expansion that we believe makes the book much better. The new part 1 grew out
of our lectures. After the first edition came out, we started adding more founda-
tional material to our testing courses. These new ideas were eventually reorganized
into five new chapters. The new chapter 011 has much of the material from the first
edition chapter 1, including motivation and basic definitions. It closes with a discus-
sion of the cost of late testing, taken from the 2002 RTI report that is cited in every
software testing research proposal. After completing the first edition, we realized
that the key novel feature of the book, viewing test design as an abstract activity
that is independent of the software artifact being used to design the tests, implied a
completely different process. This led to chapter 02, which suggests how test criteria
can fit into practice. Through our consulting, we have helped software companies
modify their test processes to incorporate this model.
A flaw with the first edition was that it did not mention JUnit or other test
automation frameworks. In 2016, JUnit is used very widely in industry, and is
commonly used in CS1 and CS2 classes for automated grading. Chapter 03 recti-
fies this oversight by discussing test automation in general, the concepts that make
test automation difficult, and explicitly teaches JUnit. Although the book is largely
technology-neutral, having a consistent test framework throughout the book helps
with examples and exercises. In our classes, we usually require tests to be auto-
mated and often ask students to try other “*-Unit” frameworks such as HttpUnit
as homework exercises. We believe that test organizations cannot be ready to apply
test criteria successfully before they have automated their tests.
Chapter 04 goes to the natural next step of test-driven development. Although
TDD is a different take on testing than the rest of the book, it’s an exciting topic for
test educators and researchers precisely because it puts testing front and center—
the tests become the requirements. Finally, chapter 05 introduces the concept of
test criteria in an abstract way. The jelly bean example (which our students love,
especially when we share), is still there, as are concepts such as subsumption.
Part 2, which is the heart of the book, has changed the least for the second edi-
tion. In 2014, Jeff asked Paul a very simple question: “Why are the four chapters in
part 2 in that order?” The answer was stunned silence, as we realized that we had
never asked which order they should appear in. It turns out that the RIPR model,
1 To help reduce confusion, we developed the convention of using two digits for second edition chapters.
Thus, in this preface, chapter 01 implies the second edition, whereas chapter 1 implies the first.
xvi Preface to the Second Edition
The second edition also has many dozens of corrections (starting with the errata
list from the first edition book website), but including many more that we found
while preparing the second edition. The second edition also has a better index. We
put together the index for the first edition in about a day, and it showed. This time
we have been indexing as we write, and committed time near the end of the process
to specifically focus on the index. For future book writers, indexing is hard work and
not easy to turn over to a non-author!
2 Our MS program is practical in nature, not research-oriented. The majority of students are part-time
students with five to ten years of experience in the software industry. SWE 637 begat this book when
we realized Beizer’s classic text [Beizer, 1990] was out of print.
xviii Preface to the Second Edition
the importance of software quality, and second to get them started with test automa-
tion (we use JUnit at Mason). A second-year course in testing could cover all of
part 1, chapter 06 from part 2, and all or part of part 3. The other chapters in part
2 are probably more than what such students need, but input space partitioning is
a very accessible introduction to structured, high-end testing. A common course in
north American computer science programs is a third-year course on general soft-
ware engineering. Part 1 would be very appropriate for such a course. In 2016 we
are introducing an advanced graduate course on software testing, which will span
cutting-edge knowledge and current research. This course will use some of part
3, the material that we are currently developing for part 4, and selected research
papers.
3 These in-class exercises are not yet a formal part of the book website. But we often draw them from
regular exercises in the text. Interested readers can extract recent versions from our course web pages
with a search engine.
Preface to the Second Edition xix
that students learn more when they work collaboratively (“peer-learning”), they
enjoy it more, and it matches the industrial reality. Very few software engineers
work alone.
Of course, you can use this book in your class as you see fit. We offer these
insights simply as examples for things that work for us. We summarize our current
philosophy of teaching simply: Less talking, more teaching.
Acknowledgments
It is our pleasure to acknowledge by name the many contributers to this text. We
begin with students at George Mason who provided excellent feedback on early
draft chapters from the second edition: Firass Almiski, Natalia Anpilova, Khalid
Bargqdle, Mathew Fadoul, Mark Feghali, Angelica Garcia, Mahmoud Hammad,
Husam Hilal, Carolyn Koerner, Han-Tsung Liu, Charon Lu, Brian Mitchell, Tuan
Nguyen, Bill Shelton, Dzung Tran, Dzung Tray, Sam Tryon, Jing Wu, Zhonghua
Xi, and Chris Yeung.
We are particularly grateful to colleagues who used draft chapters of the sec-
ond edition. These early adopters provided valuable feedback that was extremely
helpful in making the final document classroom-ready. Thanks to: Moataz Ahmed,
King Fahd University of Petroleum & Minerals; Jeff Carver, University of Alabama;
Richard Carver, George Mason University; Jens Hannemann, Kentucky State
University; Jane Hayes, University of Kentucky; Kathleen Keogh, Federation Uni-
versity Australia; Robyn Lutz, Iowa State University; Upsorn Praphamontripong,
George Mason University; Alper Sen, Bogazici University; Marjan Sirjani, Reyk-
javik University; Mary Lou Soffa, University of Virginia; Katie Stolee, North
Carolina State University; and Xiaohong Wang, Salisbury University.
Several colleagues provided exceptional feedback from the first edition: Andy
Brooks, Mark Hampton, Jian Zhou, Jeff (Yu) Lei, and six anonymous review-
ers contacted by our publisher. The following individuals corrected, and in some
cases developed, exercise solutions: Sana’a Alshdefat, Yasmine Badr, Jim Bowring,
Steven Dastvan, Justin Donnelly, Martin Gebert, JingJing Gu, Jane Hayes, Rama
Kesavan, Ignacio Martín, Maricel Medina-Mora, Xin Meng, Beth Paredes, Matt
Rutherford, Farida Sabry, Aya Salah, Hooman Safaee, Preetham Vemasani, and
Greg Williams. The following George Mason students found, and often corrected,
errors in the first edition: Arif Al-Mashhadani, Yousuf Ashparie, Parag Bhagwat,
Firdu Bati, Andrew Hollingsworth, Gary Kaminski, Rama Kesavan, Steve Kinder,
John Krause, Jae Hyuk Kwak, Nan Li, Mohita Mathur, Maricel Medina Mora,
Upsorn Praphamontripong, Rowland Pitts, Mark Pumphrey, Mark Shapiro, Bill
Shelton, David Sracic, Jose Torres, Preetham Vemasani, Shuang Wang, Lance
Witkowski, Leonard S. Woody III, and Yanyan Zhu. The following individuals from
elsewhere found, and often corrected, errors in the first edition: Sana’a Alshde-
fat, Alexandre Bartel, Don Braffitt, Andrew Brooks, Josh Dehlinger, Gordon
Fraser, Rob Fredericks, Weiyi Li, Hassan Mirian, Alan Moraes, Miika Nurmi-
nen, Thomas Reinbacher, Hooman Rafat Safaee, Hossein Saiedian, Aya Salah, and
Markku Sakkinen. Lian Yu of Peking University translated the the first edition into
Mandarin Chinese.
xx Preface to the Second Edition
Foundations
1
The true subject matter of the tester is not testing, but the design of test cases.
The purpose of this book is to teach software engineers how to test. This knowledge
is useful whether you are a programmer who needs to unit test your own software, a
full-time tester who works mostly from requirements at the user level, a manager in
charge of testing or development, or any position in between. As the software indus-
try moves into the second decade of the 21st century, software quality is increasingly
becoming essential to all businesses and knowledge of software testing is becoming
necessary for all software engineers.
Today, software defines behaviors that our civilization depends on in systems
such as network routers, financial calculation engines, switching networks, the Web,
power grids, transportation systems, and essential communications, command, and
control services. Over the past two decades, the software industry has become much
bigger, is more competitive, and has more users. Software is an essential component
of exotic embedded applications such as airplanes, spaceships, and air traffic control
systems, as well as mundane appliances such as watches, ovens, cars, DVD players,
garage door openers, mobile phones, and remote controllers. Modern households
have hundreds of processors, and new cars have over a thousand; all of them running
software that optimistic consumers assume will never fail! Although many factors
affect the engineering of reliable software, including, of course, careful design and
sound process management, testing is the primary way industry evaluates software
during development. The recent growth in agile processes puts increased pressure
on testing; unit testing is emphasized heavily and test-driven development makes
tests key to functional requirements. It is clear that industry is deep into a revolution
in what testing means to the success of software products.
Fortunately, a few basic software testing concepts can be used to design tests
for a large variety of software applications. A goal of this book is to present these
concepts in such a way that students and practicing engineers can easily apply them
to any software testing situation.
This textbook differs from other software testing books in several respects. The
most important difference is in how it views testing techniques. In his landmark
3
4 Foundations
book Software Testing Techniques, Beizer wrote that testing is simple—all a tester
needs to do is “find a graph and cover it.” Thanks to Beizer’s insight, it became evi-
dent to us that the myriad of testing techniques present in the literature have much
more in common than is obvious at first glance. Testing techniques are typically pre-
sented in the context of a particular software artifact (for example, a requirements
document or code) or a particular phase of the lifecycle (for example, require-
ments analysis or implementation). Unfortunately, such a presentation obscures
underlying similarities among techniques.
This book clarifies these similarities with two innovative, yet simplifying,
approaches. First, we show how testing is more efficient and effective by using a clas-
sical engineering approach. Instead of designing and developing tests on concrete
software artifacts like the source code or requirements, we show how to develop
abstraction models, design tests at the abstract level, and then implement actual
tests at the concrete level by satisfying the abstract designs. This is the exact process
that traditional engineers use, except whereas they usually use calculus and algebra
to describe the abstract models, software engineers usually use discrete mathemat-
ics. Second, we recognize that all test criteria can be defined with a very short list
of abstract models: input domain characterizations, graphs, logical expressions, and
syntactic descriptions. These are directly reflected in the four chapters of Part II of
this book.
This book provides a balance of theory and practical application, thereby
presenting testing as a collection of objective, quantitative activities that can be
measured and repeated. The theory is based on the published literature, and pre-
sented without excessive formalism. Most importantly, the theoretical concepts are
presented when needed to support the practical activities that test engineers follow.
That is, this book is intended for all software developers.
Definition 1.2 Software Error: An incorrect internal state that is the manifes-
tation of some fault.
Consider a medical doctor diagnosing a patient. The patient enters the doctor’s
office with a list of failures (that is, symptoms). The doctor then must discover the
1 Why Do We Test Software? 5
fault, or root cause of the symptoms. To aid in the diagnosis, a doctor may order tests
that look for anomalous internal conditions, such as high blood pressure, an irregu-
lar heartbeat, high levels of blood glucose, or high cholesterol. In our terminology,
these anomalous internal conditions correspond to errors.
While this analogy may help the student clarify his or her thinking about faults,
errors, and failures, software testing and a doctor’s diagnosis differ in one cru-
cial way. Specifically, faults in software are design mistakes. They do not appear
spontaneously, but exist as a result of a decision by a human. Medical problems
(as well as faults in computer system hardware), on the other hand, are often
a result of physical degradation. This distinction is important because it limits
the extent to which any process can hope to control software faults. Specifically,
since no foolproof way exists to catch arbitrary mistakes made by humans, we can
never eliminate all faults from software. In colloquial terms, we can make soft-
ware development foolproof, but we cannot, and should not attempt to, make it
damn-foolproof.
For a more precise example of the definitions of fault, error, and failure, we need
to clarify the concept of the state. A program state is defined during execution of a
program as the current value of all live variables and the current location, as given
by the program counter. The program counter (PC) is the next statement in the
program to be executed and can be described with a line number in the file (PC = 5)
or the statement as a string (PC = “if (x > y)”). Most of the time, what we mean by
a statement is obvious, but complex structures such as for loops have to be treated
specially. The program line “for (i=1; i<N; i++)” actually has three statements that
can result in separate states. The loop initialization (“i=1”) is separate from the loop
test (“i<N”), and the loop increment (“i++”) occurs at the end of the loop body. As
an illustrative example, consider the following Java method:
/**
* Counts zeroes in an array
*
* @param x array to count zeroes in
* @return number of occurrences of 0 in x
* @throws NullPointerException if x is null
*/
public static int numZero (int[] x)
{
int count = 0;
for (int i = 1; i < x.length; i++)
{
if (x[i] == 0) count++;
}
return count;
}
6 Foundations
Sidebar
Programming Language Independence
This book strives to be independent of language, and most of the concepts in the book are.
At the same time, we want to illustrate these concepts with specific examples. We choose
Java, and emphasize that most of these examples would be very similar in many other
common languages.
The fault in this method is that it starts looking for zeroes at index 1 instead of
index 0, as is necessary for arrays in Java. For example, numZero ([2, 7, 0]) correctly
evaluates to 1, while numZero ([0, 7, 2]) incorrectly evaluates to 0. In both tests the
faulty statement is executed. Although both of these tests result in an error, only
the second results in failure. To understand the error states, we need to identify the
state for the method. The state for numZero() consists of values for the variables x,
count, i, and the program counter (PC). For the first example above, the state at the
loop test on the very first iteration of the loop is (x = [2, 7, 0], count = 0, i = 1, PC = “i <
x.length”). Notice that this state is erroneous precisely because the value of i should
be zero on the first iteration. However, since the value of count is coincidentally
correct, the error state does not propagate to the output, and hence the software
does not fail. In other words, a state is in error simply if it is not the expected state,
even if all of the values in the state, considered in isolation, are acceptable. More
generally, if the required sequence of states is s 0, s1 , s2 , . . . , and the actual sequence
of states is s 0 , s2 , s 3, . . . , then state s2 is in error in the second sequence. The fault
model described here is quite deep, and this discussion gives the broad view without
going into unneeded details. The exercises at the end of the section explore some of
the subtleties of the fault model.
In the second test for our example, the error state is (x = [0, 7, 2], count = 0, i
= 1, PC = “i < x.length”). In this case, the error propagates to the variable count and
is present in the return value of the method. Hence a failure results.
The term bug is often used informally to refer to all three of fault, error, and
failure. This book will usually use the specific term, and avoid using “bug.” A
favorite story of software engineering teachers is that Grace Hopper found a moth
stuck in a relay on an early computing machine, which started the use of bug as
a problem with software. It is worth noting, however, that the term bug has an
old and rich history, predating software by at least a century. The first use of bug
to generally mean a problem we were able to find is from a quote by Thomas
Edison:
It has been just so in all of my inventions. The first step is an intuition, and comes
with a burst, then difficulties arise–this thing gives out and [it is] then that ‘Bugs’–
as such little faults and difficulties are called–show themselves and months of intense
watching, study and labor are requisite.
— Thomas Edison
A very public failure was the Mars lander of September 1999, which crashed
due to a misunderstanding in the units of measure used by two modules created by
separate software groups. One module computed thruster data in English units and
1 Why Do We Test Software? 7
forwarded the data to a module that expected data in metric units. This is a very
typical integration fault (but in this case enormously expensive, both in terms of
money and prestige).
One of the most famous cases of software killing people is the Therac-25 radi-
ation therapy machine. Software faults were found to have caused at least three
deaths due to excessive radiation. Another dramatic failure was the launch failure
of the first Ariane 5 rocket, which exploded 37 seconds after liftoff in 1996. The
low-level cause was an unhandled floating point conversion exception in an iner-
tial guidance system function. It turned out that the guidance system could never
encounter the unhandled exception when used on the Ariane 4 rocket. That is, the
guidance system function was correct for Ariane 4. The developers of the Ariane 5
quite reasonably wanted to reuse the successful inertial guidance system from the
Ariane 4, but no one reanalyzed the software in light of the substantially differ-
ent flight trajectory of the Ariane 5. Furthermore, the system tests that would have
found the problem were technically difficult to execute, and so were not performed.
The result was spectacular–and expensive!
The famous Pentium bug was an early alarm of the need for better testing,
especially unit testing. Intel introduced its Pentium microprocessor in 1994, and
a few months later, Thomas Nicely, a mathematician at Lynchburg College in Vir-
ginia, found that the chip gave incorrect answers to certain floating-point division
calculations.
The chip was slightly inaccurate for a few pairs of numbers; Intel claimed (proba-
bly correctly) that only one in nine billion division operations would exhibit reduced
precision. The fault was the omission of five entries in a table of 1,066 values (part
of the chip’s circuitry) used by a division algorithm. The five entries should have
contained the constant +2, but the entries were not initialized and contained zero
instead. The MIT mathematician Edelman claimed that “the bug in the Pentium
was an easy mistake to make, and a difficult one to catch,” an analysis that misses
an essential point. This was a very difficult mistake to find during system testing,
and indeed, Intel claimed to have run millions of tests using this table. But the table
entries were left empty because a loop termination condition was incorrect; that is,
the loop stopped storing numbers before it was finished. Thus, this would have been
a very simple fault to find during unit testing; indeed analysis showed that almost
any unit level coverage criterion would have found this multimillion dollar mistake.
The great northeast blackout of 2003 was started when a power line in Ohio
brushed against overgrown trees and shut down. This is called a fault in the power
industry. Unfortunately, the software alarm system failed in the local power com-
pany, so system operators could not understand what happened. Other lines also
sagged into trees and switched off, eventually overloading other power lines, which
then cut off. This cascade effect eventually caused a blackout throughout southeast-
ern Canada and eight states in the northeastern part of the US. This is considered the
biggest blackout in North American history, affecting 10 million people in Canada
and 40 million in the USA, contributing to at least 11 deaths and costing up to $6
billion USD.
Some software failures are felt widely enough to cause severe embarrassment
to the company. In 2011, a centralized students data management system in Korea
miscalculated the academic grades of over 29,000 middle and high school students.
8 Foundations
This led to massive confusion about college admissions and a government inves-
tigation into the software engineering practices of the software vendor, Samsung
Electronics.
A 1999 study commissioned by the U.S. National Research Council and the U.S.
President’s commission on critical infrastructure protection concluded that the cur-
rent base of science and technology is inadequate for building systems to control
critical software infrastructure. A 2002 report commissioned by the National Insti-
tute of Standards and Technology (NIST) estimated that defective software costs
the U.S. economy $59.5 billion per year. The report further estimated that 64% of
the costs were a result of user mistakes and 36% a result of design and development
mistakes, and suggested that improvements in testing could reduce this cost by about
a third, or $22.5 billion. Blumenstyk reported that web application failures lead to
huge losses in businesses; $150,000 per hour in media companies, $2.4 million per
hour in credit card sales, and $6.5 million per hour in the financial services market.
Software faults do not just lead to functional failures. According to a Symantec
security threat report in 2007, 61 percent of all vulnerabilities disclosed were due to
faulty software. The most common are web application vulnerabilities that can be
attacked by some common attack techniques using invalid inputs.
These public and expensive software failures are getting more common and
more widely known. This is simply a symptom of the change in expectations of
software. As we move further into the 21st century, we are using more safety crit-
ical, real-time software. Embedded software has become ubiquitous; many of us
carry millions of lines of embedded software in our pockets. Corporations rely more
and more on large-scale enterprise applications, which by definition have large user
bases and high reliability requirements. Security, which used to depend on cryp-
tography, then database security, then avoiding network vulnerabilities, is now
largely about avoiding software faults. The Web has had a major impact. It fea-
tures a deployment platform that offers software services that are very competitive
and available to millions of users. They are also distributed, adding complexity,
and must be highly reliable to be competitive. More so than at any previous time,
industry desperately needs to apply the accumulated knowledge of over 30 years of
testing research.
Level 2 The purpose of testing is to show that the software does not work.
Level 3 The purpose of testing is not to prove anything specific, but to reduce the
risk of using the software.
Level 4 Testing is a mental discipline that helps all IT professionals develop higher-
quality software.
Level 0 is the view that testing is the same as debugging. This is the view that
is naturally adopted by many undergraduate Computer Science majors. In most CS
programming classes, the students get their programs to compile, then debug the
programs with a few inputs chosen either arbitrarily or provided by the professor.
10 Foundations
This model does not distinguish between a program’s incorrect behavior and a mis-
take within the program, and does very little to help develop software that is reliable
or safe.
In Level 1 testing, the purpose is to show correctness. While a significant step
up from the naive level 0, this has the unfortunate problem that in any but the most
trivial of programs, correctness is virtually impossible to either achieve or demon-
strate. Suppose we run a collection of tests and find no failures. What do we know?
Should we assume that we have good software or just bad tests? Since the goal of
correctness is impossible, test engineers usually have no strict goal, real stopping
rule, or formal test technique. If a development manager asks how much testing
remains to be done, the test manager has no way to answer the question. In fact,
test managers are in a weak position because they have no way to quantitatively
express or evaluate their work.
In Level 2 testing, the purpose is to show failures. Although looking for failures
is certainly a valid goal, it is also inherently negative. Testers may enjoy finding the
problem, but the developers never want to find problems–they want the software to
work (yes, level 1 thinking can be natural for the developers). Thus, level 2 testing
puts testers and developers into an adversarial relationship, which can be bad for
team morale. Beyond that, when our primary goal is to look for failures, we are still
left wondering what to do if no failures are found. Is our work done? Is our software
very good, or is the testing weak? Having confidence in when testing is complete is
an important goal for all testers. It is our view that this level currently dominates the
software industry.
The thinking that leads to Level 3 testing starts with the realization that test-
ing can show the presence, but not the absence, of failures. This lets us accept
the fact that whenever we use software, we incur some risk. The risk may be
small and the consequences unimportant, or the risk may be great and the con-
sequences catastrophic, but risk is always there. This allows us to realize that the
entire development team wants the same thing–to reduce the risk of using the
software. In level 3 testing, both testers and developers work together to reduce
risk. We see more and more companies move to this testing maturity level every
year.
Once the testers and developers are on the same “team,” an organization can
progress to real Level 4 testing. Level 4 thinking defines testing as a mental disci-
pline that increases quality. Various ways exist to increase quality, of which creating
tests that cause the software to fail is only one. Adopting this mindset, test engi-
neers can become the technical leaders of the project (as is common in many other
engineering disciplines). They have the primary responsibility of measuring and
improving software quality, and their expertise should help the developers. Beizer
used the analogy of a spell checker. We often think that the purpose of a spell
checker is to find misspelled words, but in fact, the best purpose of a spell checker
is to improve our ability to spell. Every time the spell checker finds an incorrectly
spelled word, we have the opportunity to learn how to spell the word correctly.
The spell checker is the “expert” on spelling quality. In the same way, level 4 test-
ing means that the purpose of testing is to improve the ability of the developers
1 Why Do We Test Software? 11
to produce high-quality software. The testers should be the experts who train your
developers!
As a reader of this book, you probably start at level 0, 1, or 2. Most software
developers go through these levels at some stage in their careers. If you work in
software development, you might pause to reflect on which testing level describes
your company or team. The remaining chapters in Part I should help you move to
level 2 thinking, and to understand the importance of level 3. Subsequent chapters
will give you the knowledge, skills, and tools to be able to work at level 3. An
ultimate goal of this book is to provide a philosophical basis that will allow read-
ers to become “change agents” in their organizations for level 4 thinking, and test
engineers to become software quality experts. Although level 4 thinking is cur-
rently rare in the software industry, it is common in more mature engineering
fields.
These considerations help us decide at a strategic level why we test. At a more
tactical level, it is important to know why each test is present. If you do not know
why you are conducting each test, the test will not be very helpful. What fact is each
test trying to verify? It is essential to document test objectives and test requirements,
including the planned coverage levels. When the test manager attends a planning
meeting with the other managers and the project manager, the test manager must be
able to articulate clearly how much testing is enough and when testing will complete.
In the 1990s, we could use the “date criterion,” that is, testing is “complete” when
the ship date arrives or when the budget is spent.
Figure 1.1 dramatically illustrates the advantages of testing early rather than
late. This chart is based on a detailed analysis of faults that were detected and fixed
during several large government contracts. The bars marked ‘A’ indicate what per-
centage of faults appeared in that phase. Thus, 10% of faults appeared during the
requirements phase, 40% during design, and 50% during implementation. The bars
marked ‘D’ indicated the percentage of faults that were detected during each phase.
About 5% were detected during the requirements phase, and over 35% during sys-
tem testing. Lastly is the cost analysis. The solid bars marked ‘C’ indicate the relative
cost of finding and fixing faults during each phase. Since each project was different,
this is averaged to be based on a “unit cost.” Thus, faults detected and fixed during
requirements, design, and unit testing were a single unit cost. Faults detected and
fixed during integration testing cost five times as much, 10 times as much during
system testing, and 50 times as much after the software is deployed.
If we take the simple assumption of $1000 USD unit cost per fault, and 100
faults, that means we spend $39,000 to find and correct faults during requirements,
design, and unit testing. During integration testing, the cost goes up to $100,000.
But system testing and deployment are the serious problems. We find more faults
during system testing at ten times the cost, for a total of $360,000. And even though
we only find a few faults after deployment, the cost being 50 X unit means we spend
$250,000! Avoiding the work early (requirements analysis and unit testing) saves
money in the short term. But it leaves faults in software that are like little bombs,
ticking away, and the longer they tick, the bigger the explosion when they finally
go off.
12 Foundations
To put Beizer’s level 4 test maturity level in simple terms, the goal of testing is
to eliminate faults as early as possible. We can never be perfect, but every time we
eliminate a fault during unit testing (or sooner!), we save money. The rest of this
book will teach you how to do that.
EXERCISES
Chapter 1.
1. What are some factors that would help a development organization move
from Beizer’s testing level 2 (testing is to show errors) to testing level 4
(a mental discipline that increases quality)?
2. What is the difference between software fault and software failure?
3. What do we mean by “level 3 thinking is that the purpose of testing is to reduce
risk?” What risk? Can we reduce the risk to zero?
4. The following exercise is intended to encourage you to think of testing in a
more rigorous way than you may be used to. The exercise also hints at the
strong relationship between specification clarity, faults, and test cases 1.
(a) Write a Java method with the signature
public static Vector union (Vector a, Vector b)
The method should return a Vector of objects that are in either of the two
argument Vectors.
(b) Upon reflection, you may discover a variety of defects and ambiguities
in the given assignment. In other words, ample opportunities for faults
exist. Describe as many possible faults as you can. (Note: Vector is a Java
Collection class. If you are using another language, interpret Vector as a list.)
(c) Create a set of test cases that you think would have a reasonable chance of
revealing the faults you identified above. Document a rationale for each
test in your test set. If possible, characterize all of your rationales in some
concise summary. Run your tests against your implementation.
1 Liskov’s Program Development in Java, especially chapters 9 and 10, is a great source for students who
wish to learn more about this.
1 Why Do We Test Software? 13
(d) Rewrite the method signature to be precise enough to clarify the defects
and ambiguities identified earlier. You might wish to illustrate your
specification with examples drawn from your test cases.
5. Below are four faulty programs. Each includes test inputs that result in failure.
Answer the following questions about each program.
/** /**
* Find last index of element * Find last index of zero
* *
* @param x array to search * @param x array to search
* @param y value to look for *
* @return last index of y in x; -1 if absent * @return last index of 0 in x; -1 if absent
* @throws NullPointerException if x is null * @throws NullPointerException if x is null
*/ */
public int findLast (int[] x, int y) public static int lastZero (int[] x)
{ {
for (int i=x.length-1; i > 0; i--) for (int i = 0; i < x.length; i++)
{ {
if (x[i] == y) if (x[i] == 0)
{ {
return i; return i;
} }
} }
return -1; return -1;
} }
// test: x = [2, 3, 5]; y = 2; Expected = 0 // test: x = [0, 1, 0]; Expected = 2
// Book website: FindLast.java // Book website: LastZero.java
// Book website: FindLastTest.java // Book website: LastZeroTest.java
/** /**
* Count positive elements * Count odd or positive elements
* *
* @param x array to search * @param x array to search
* @return count of positive elements in x * @return count of odd/positive values in x
* @throws NullPointerException if x is null * @throws NullPointerException if x is null
*/ */
public int countPositive (int[] x) public static int oddOrPos(int[] x)
{ {
int count = 0; int count = 0;
for (int i=0; i < x.length; i++) for (int i = 0; i < x.length; i++)
{ {
if (x[i] >= 0) if (x[i]%2 == 1 || x[i] > 0)
{ {
count++; count++;
} }
} }
return count; return count;
} }
// test: x = [-4, 2, 0, 2]; Expected = 2 // test: x = [-3, -2, 0, 1, 4]; Expected = 3
// Book website: CountPositive.java // Book website: OddOrPos.java
// Book website: CountPositiveTest.java // Book website: OddOrPosTest.java
14 Foundations
(a) Explain what is wrong with the given code. Describe the fault precisely
by proposing a modification to the code.
(b) If possible, give a test case that does not execute the fault. If not, briefly
explain why not.
(c) If possible, give a test case that executes the fault, but does not result in
an error state. If not, briefly explain why not.
(d) If possible give a test case that results in an error, but not a failure. If not,
briefly explain why not. Hint: Don’t forget about the program counter.
(e) For the given test case, describe the first error state. Be sure to describe
the complete state.
(f) Implement your repair and verify that the given test now produces the
expected output. Submit a screen printout or other evidence that your
new program works.
6. Answer question (a) or (b), but not both, depending on your background.
(a) If you do, or have, worked for a software development company, what
level of test maturity do you think the company worked at? (0: test-
ing=debugging, 1: testing shows correctness, 2: testing shows the program
doesn’t work, 3: testing reduces risk, 4: testing is a mental discipline about
quality).
(b) If you have never worked for a software development company, what
level of test maturity do you think that you have? (0: testing=debugging,
1: testing shows correctness, 2: testing shows the program doesn’t work,
3: testing reduces risk, 4: testing is a mental discipline about quality).
7. Consider the following three example classes. These are OO faults taken
from Joshua Bloch’s Effective Java, Second Edition. Answer the following
questions about each.
{
Object result = super.clone();
// Location "B"
((Truck) result).y = this.y; // throws ClassCastException
return result;
}
// other methods omitted
}
//Test: Truck suv = new Truck (4); Truck co = suv.clone()
// Expected: suv.x = co.x; suv.getClass() = co.getClass()
class Point
{
private int x; private int y;
public Point (int x, int y) { this.x=x; this.y=y; }
(a) Explain what is wrong with the given code. Describe the fault precisely by
proposing a modification to the code.
(b) If possible, give a test case that does not execute the fault. If not, briefly
explain why not.
(c) If possible, give a test case that executes the fault, but does not result in an
error state. If not, briefly explain why not.
(d) If possible give a test case that results in an error, but not a failure. If not,
briefly explain why not. Hint: Don’t forget about the program counter.
(e) In the given code, describe the first error state. Be sure to describe the
complete state.
(f) Implement your repair and verify that the given test now produces the
expected output. Submit a screen printout or other evidence that your new
program works.
Quality Assurance [Beizer, 1984] and Hetzel’s The Complete Guide to Software Test-
ing [Hetzel, 1988] cover various aspects of management and process for software
testing. Several books cover specific aspects of testing [Howden, 1987, Marick, 1995,
Roper, 1994]. The STEP project at Georgia Institute of Technology resulted in a
comprehensive survey of the practice of software testing by Department of Defense
contractors in the 1980s [DeMillo et al., 1987].
The information for the Pentium bug and Mars lander was taken from sev-
eral sources, including by Edelman, Moler, Nuseibeh, Knutson, and Peterson
[Edelman, 1997, Knutson and Carmichael, 2000, Moler, 1995, Nuseibeh, 1997,
Peterson, 1997]. The well-written official accident report [Lions, 1996] is our favorite
source for understanding the details of the Ariane 5 Flight 501 Failure. The infor-
mation for the Therac-25 accidents was taken from Leveson and Turner’s deep
analysis [Leveson and Turner, 1993]. The details on the 2003 Northeast Black-
out was taken from Minkel’s analysis in Scientific American [Minkel, 2008] and
Rice’s book [Rice, 2008]. The information about the Korean education informa-
tion system was taken from two newspaper articles [Min-sang and Sang-soo, 2011,
Korea Times, 2011].
The 1999 study mentioned was published in an NRC / PITAC report
[PITAC, 1999, Schneider, 1999]. The data in Figure 1.1 were taken from a NIST
report that was developed by the Research Triangle Institute [RTI, 2002]. The
figures on web application failures are due to Blumenstyk [Blumenstyk, 2006]. The
figures about faulty software leading to security vulnerabilities are from Symantec
[Symantec, 2007].
Finally, Rick Hower’s QATest website is a good resource for current, elemen-
tary, information about software testing: www.softwareqatest.com.
2
Designers are more efficient and effective if they can raise their level of abstraction.
This chapter introduces one of the major innovations in the second edition of Intro-
duction to Software Testing. Software testing is inherently complicated and our
ultimate goal, completely correct software, is unreachable. The reasons are formal
(as discussed below in section 2.1) and philosophical. As discussed in Chapter 1, it’s
not even clear that the term “correctness” means anything when applied to a piece
of engineering as complicated as a large computer program. Do we expect correct-
ness out of a building? A car? A transportation system? Intuitively, we know that
all large physical engineering systems have problems, and moreover, there is no way
to say what correct means. This is even more true for software, which can quickly
get orders of magnitude more complicated than physical structures such as office
buildings or airplanes.
Instead of looking for “correctness,” wise software engineers try to evaluate soft-
ware’s “behavior” to decide if the behavior is acceptable within consideration of a
large number of factors including (but not limited to) reliability, safety, maintain-
ability, security, and efficiency. Obviously this is more complex than the naive desire
to show the software is correct.
So what do software engineers do in the face of such overwhelming complexity?
The same thing that physical engineers do–we use mathematics to “raise our level of
abstraction.” The Model-Driven Test Design (MDTD) process breaks testing into
a series of small tasks that simplify test generation. Then test designers isolate their
task, and work at a higher level of abstraction by using mathematical engineering
structures to design test values independently of the details of software or design
artifacts, test automation, and test execution.
A key intellectual step in MDTD is test case design. Test case design can be the
primary determining factor in whether tests successfully find failures in software.
Tests can be designed with a “human-based” approach, where a test engineer uses
domain knowledge of the software’s purpose and his or her experience to design
tests that will be effective at finding faults. Alternatively, tests can be designed to sat-
isfy well-defined engineering goals such as coverage criteria. This chapter describes
19
20 Foundations
the task activities and then introduces criteria-based test design. Criteria-based test
design will be discussed in more detail in Chapter 5, then specific criteria on four
mathematical structures are described in Part II. After these preliminaries, the
model-driven test design process is defined in detail. The book website has sim-
ple web applications that support the MDTD in the context of the mathematical
structures in Part II.
Of course the central issue is that for a given fault, not all inputs will “trigger”
the fault into creating incorrect output (a failure). Also, it is often very difficult to
relate a failure to the associated fault. Analyzing these ideas leads to the fault/failure
model, which states that four conditions are needed for a failure to be observed.
Figure 2.1 illustrates the conditions. First, a test must reach the location or loca-
tions in the program that contain the fault (Reachability). After the location is
executed, the state of the program must be incorrect (Infection). Third, the infected
state must propagate through the rest of the execution and cause some output or
final state of the program to be incorrect (Propagation). Finally, the tester must
observe part of the incorrect portion of the final program state (Revealability). If
the tester only observes parts of the correct portion of the final program state, the
failure is not revealed. This is shown in the cross-hatched intersection in Figure 2.1.
Issues with revealing failures will be discussed in Chapter 4 when we present test
automation strategies.
Collectively, these four conditions are known as the fault/failure model, or the
RIPR model.
It is important to note that the RIPR model applies even when the fault is miss-
ing code (so-called faults of omission). In particular, when execution passes through
the location where the missing code should be, the program counter, which is part
of the program state, necessarily has the wrong value.
2 Model-Driven Test Design 21
From a practitioner’s view, these limitations mean that software testing is com-
plex and difficult. The common way to deal with complexity in engineering is to
use abstraction by abstracting out complicating details that can be safely ignored by
modeling the problem with some mathematical structures. That is a central theme
of this book, which we begin by analyzing the separate technical activities involved
in creating good tests.
Test
Manager
n
desig Test instantiate Executable
Designs Tests
Test
Engineer
Test Test
Engineer Engineer
execute
P Computer Output Evaluate
be carried out by one person or by several, and the process is monitored by a test
manager.
One of a test engineer’s most powerful tools is a formal coverage criterion. For-
mal coverage criteria give test engineers ways to decide what test inputs to use
during testing, making it more likely that the tester will find problems in the program
and providing greater assurance that the software is of high quality and reliability.
Coverage criteria also provide stopping rules for the test engineers. The technical
core of this book presents the coverage criteria that are available, describes how
they are supported by tools (commercial and otherwise), explains how they can best
be applied, and suggests how they can be integrated into the overall development
process.
Software testing activities have long been categorized into levels, and the
most often used level categorization is based on traditional software process steps.
Although most types of tests can only be run after some part of the software is
implemented, tests can be designed and constructed during all software devel-
opment steps. The most time-consuming parts of testing are actually the test
design and construction, so test activities can and should be carried out throughout
development.
Requirements Acceptance
Analysis Test Test
Subsystem Integration
Design Test
Detailed Module
Design Test
Implementation Unit
Test
Figure 2.3. Software development activities and testing levels – the “V Model”.
Figure 2.3, often called the “V model,” illustrates a typical scenario for testing
levels and how they relate to software development activities by isolating each step.
Information for each test level is typically derived from the associated development
activity. Indeed, standard advice is to design the tests concurrently with each devel-
opment activity, even though the software will not be in an executable form until the
implementation phase. The reason for this advice is that the mere process of design-
ing tests can identify defects in design decisions that otherwise appear reasonable.
Early identification of defects is by far the best way to reduce their ultimate cost.
Note that this diagram is not intended to imply a waterfall process. The synthesis
and analysis activities generically apply to any development process.
The requirements analysis phase of software development captures the cus-
tomer’s needs. Acceptance testing is designed to determine whether the completed
software in fact meets these needs. In other words, acceptance testing probes
whether the software does what the users want. Acceptance testing must involve
users or other individuals who have strong domain knowledge.
The architectural design phase of software development chooses components
and connectors that together realize a system whose specification is intended to
meet the previously identified requirements. System testing is designed to determine
whether the assembled system meets its specifications. It assumes that the pieces
work individually, and asks if the system works as a whole. This level of testing usu-
ally looks for design and specification problems. It is a very expensive place to find
lower-level faults and is usually not done by the programmers, but by a separate
testing team.
The subsystem design phase of software development specifies the structure and
behavior of subsystems, each of which is intended to satisfy some function in the
overall architecture. Often, the subsystems are adaptations of previously developed
24 Foundations
Although most of the literature emphasizes these levels in terms of when they
are applied, a more important distinction is on the types of faults that we are looking
for. The faults are based on the software artifact that we are testing, and the software
artifact that we derive the tests from. For example, unit and module tests are derived
to test units and modules, and we usually try to find faults that can be found when
executing the units and modules individually.
One final note is that OO software changes the testing levels. OO software blurs
the distinction between units and modules, so the OO software testing literature
has developed a slight variation of these levels. Intra-method testing evaluates indi-
vidual methods. Inter-method testing evaluates pairs of methods within the same
class. Intra-class testing evaluates a single entire class, usually as sequences of calls
to methods within the class. Finally, inter-class testing evaluates more than one class
at the same time. The first three are variations of unit and module testing, whereas
inter-class testing is a type of integration testing.
For the tour of 1892 I was to have the company of Dr. McKean as
long as he could be spared from Chiengmai, which would greatly
enhance the value of the trip. We had also three native evangelist-
assistants, and, last, but not least, we were well supplied with
Scriptures and tracts in the Lāo dialect. Our start was made on
January 5th.
Our first two Sundays and the intervening week we spent in
Wieng Pā Pāo, where we established ourselves in the new chapel
which the people themselves had built since our last tour. We
observed the Week of Prayer with two chapel services daily, and
house-to-house and heart-to-heart work in the intervals. The church
was formally organized with thirty-six adult members and thirty
children, three ruling elders, and two deacons.
From Wieng Pā Pāo we moved on to the village of Mê Kawn, the
centre of our very interesting work of the previous year among the
Mūsô tribe. The Sunday we spent there was a red-letter day in our
missionary life. Of it Dr. McKean writes: “This has been a blessed
day. All [of the Mūsôs] desire baptism. Two boys baptized last year
were admitted to the communion. Eleven other adults and seven
children were baptized, making twenty-two Mūsôs now members of
the visible church. One Lāo girl was received on confession, and
three Lāo children were baptized. Our Christian Mūsôs were out in
full force. A Mūsô officer and others not Christians attended from
another village. Before this we had visited these people in their
homes. We found that they had built a good chapel for their
worship, a better building than either of their own houses. They had
been very diligent in observing the Sabbath, in studying the
catechism, and in worship.”
We could not have been better pleased with our first success. The
exclusion of this little group from the large villages made it possible
and easy for all of them to become Christians. The whole-hearted
zeal with which they entered the church awakened strong hopes for
the conversion of their race. Cha Pū Kaw’s knowledge of the Lāo
tongue was above the average even of their head men. It would be
a long time before we could have another such interpreter and
assistant. And he was nearly, or quite, seventy years old; so that
whatever he was to do in teaching his people must be done soon. It
was, therefore, thought best to make a strong effort through him
and his family during that season.
At our next stopping-place, Nāng Lê, we came near having a
serious casualty. Our boys were out on a deer hunt, and one of them
bethought him of a novel expedient for getting the game. He
climbed a tree, and had the grass fired on the other side of the open
space. The grass was tall and dry, and the wind blew strong towards
him. He became so engrossed in looking for the deer that he forgot
the fire, till it was too late to flee. He could climb beyond the actual
flames; but meanwhile the whole air had become like the breath of a
furnace. When, at last, the fire had swept past him, and he was able
to descend, he was a mass of blisters. The swiftness of the rush of
the fire alone saved his life. Had it been slower, he could not have
escaped suffocation.
From Nāng Lê we visited a very large Mūsô village. It was a steep
foot-climb of four solid hours, and, to make it longer, our guide
missed the way. The first sign of human life we saw was a Mūsô girl
alone watching a clearing. She fled for dear life, till, recognizing Cha
Pū Kaw’s Mūsô speech, she stopped long enough to point the way to
the village. Her fleet steps outran ours, and when we reached the
village, the people were already assembling to see the unwonted
sight of the white foreigners. But the community was greatly
disturbed over another matter. One of their leading officers, it
seemed, was accused of being the abode of a demon that had
caused an epidemic of disease. The authorities were hourly waiting
for an order from the court in Chieng Rāi to expel him and his family
by force from the province. They had heard of Cha Pū Kaw’s
conversion, and were anxious to hear from himself his reasons
therefor—which he gave and enforced till late in the night. They
were expecting, however, on the morrow a regular conflict which
might result in bloodshed, and they evidently preferred that we
should not be there. The head Pū Chān was several days’ journey
distant. They would confer together among themselves and with
him, would let us know the result, and would invite us up again
before we left their neighbourhood.
About midnight a fierce storm of wind and rain broke upon us to
our great discomfort. Our thin tent afforded but poor protection. We
doubled up our bedding over our clothes, and sat upon the pile
under our umbrellas, and laughed at the novelty of our situation and
the poor prospect of a night’s sleep. But later the storm passed off,
and we did get a little sleep. Our visit to that group of Mūsô villages
was evidently not well timed. We took the advice of their officers,
and returned to Nāng Lê.
Two days later we reached Chieng Sên. Here we received a mail
from home, with news that Mrs. McKean was not well, and other
members of the station needed the doctor’s presence. It was
expressed as “the unanimous judgment of the station that he should
return immediately.” We had planned a regular campaign in the
Mūsô districts on both sides of the Mê Kōng—the sort of trip in
which the medical missionary finds his best opportunity. But the
recall was so imperative that it could not be ignored. So I was left to
continue the work alone.
The Mūsô tribe was about equally numerous in the mountain
ranges on both sides of the big river. On the east side there were
eleven villages. It seemed advisable to take that section first,
because they were under Chieng Sên rulers, of whose cordial and
sincere interest in our work we were sure. Sên Chai, the head man
of the large village nearest to the city, was a friend of Nān Suwan,
and was strongly inclined to embrace our religion; but felt the
difficulty of breaking the tribal bond. Before this I had made him a
visit of two or three days, and saw clearly that our only chance of
accomplishing anything was to gain all the head men of the eleven
villages. It was actually easier to win over the whole as a unit than
to win it piecemeal. This was a formidable task to undertake, but
with God’s blessing on the labours of Cha Pū Kaw and Nān Suwan, it
seemed not impossible.
We set out for the first village one morning shortly after ten
o’clock. It was four o’clock when we stopped for rest at the first
cluster of houses on the outskirts of the settlement. The news of our
arrival soon reached the main village. When we started again we
met Sên Chai with a regular serenade-party of men and boys with
native reed instruments, blowing their plaintive dirge-like music, to
welcome us and escort us in. Soon the population was all assembled
—the maidens in their best sarongs, the mothers and grandmothers
each with an urchin strapped to her back by her scarf, the men
coming in from their work, and the inevitable crowd of children. Cha
Pū Kaw was already answering their questions, with Nān Suwan’s
sympathetic aid. They were respectfully shy, but there was no
cringing. Sên Chai invited the local Pū Chān and all the villagers to
assemble after their evening meal to hear the new doctrines. We
first had worship with singing, and prayer by Cha Pū Kaw. It was the
first time they had heard the Great Spirit addressed in their own
Mūsô tongue. There were frequent exclamations of delight that they
were able to understand every word.
And then, before that motley crowd, drinking with them their
native tea from an earthen teapot, the men seated close around, or
reclining as they smoke their pipes, the women and children walking
about or sitting on the ground—we tell of God the great Spirit, the
Creator, and Father of all—the Bible, His message to men—the
incarnation, life, and death of Christ, and redemption through His
blood. Before we get through you will hear man after man say, “I
believe that. It is true.” One man takes up the story from Cha Pū
Kaw’s mouth and repeats it to another—a story that till now he
himself had never heard. Another says, “Nān Suwan has told us this
before, but now we hear it from the father-teacher.”
Before we retired that night Sên Chai said to us, with the approval
of most of his village, “Go on to Sên Bun Yūang and the head men
of the other villages. If they agree, we will all accept Christianity.
One village cannot accept it alone. If we do not ‘kin waw’ with them
—join in their New Year’s feast—we shall be treated as enemies by
the whole tribe.”
So, next morning, we set out to find the great Pū Chān—the
religious head of the province. On our way to his village we fell in
with a man to whom Cha Pū Kaw was speaking with great
earnestness. I found on approaching him that he was not a Mūsô,
but a Kūi—of a tribe which we had planned to visit later. He was the
Pū Chān of his village. He had already invited us through Cha Pū
Kaw to change our plan, and visit his village first. It was nearer than
the village we were intending to visit, and we were already tired
enough with our climb to be willing to stop at the nearest place.
The village was a large one, as mountain villages go—of twenty-
five or thirty houses, and from two hundred and fifty to three
hundred souls—in general not unlike the Mūsô villages we had seen.
The Kūi language also, while different from the Mūsô, is cognate
with it, so that Cha Pū Kaw could still act fairly well as our
interpreter. His talk with the Pū Chān on the way had already laid a
good foundation for our work in the evening, when curiosity and
interest in our errand brought the whole village together to hear Cha
Pū Kaw’s new doctrine from his own lips. The news of his conversion
had already reached them, and he had made a good impression on
the religious head of the village.—And, then, it was something new
to see the Mūsô boys able to read and to sing. Nān Suwan and Cha
Pū Kaw led in prayer, the one in Lāo and the other in Mūsô. Then
our religion was explained in its two leading ideas—rejection of the
spirit-cult, and acceptance of Jesus for the pardon of sin and the life
eternal. Questions were asked and answered.
At last the Pū Chān suggested that, while we continued our
reading and singing with the women and children, he and the men,
with Cha Pū Kaw, withdraw to a neighbouring house and talk the
matter over. It was evident that they would be more at their ease by
themselves, unawed by the presence of the foreign teacher. For
some two hours the debate continued. I could hear their earnest
voices from the neighbouring house, with only now and then a Lāo
word that I could understand. Then they returned to make their
report. With oriental politeness, they expressed their gratitude to the
“great teacher” who had come so far and at such expense, and had
brought with him a fellow-mountaineer of theirs, to teach them,
creatures of the jungle, the way to happiness. They had talked these
matters over, and understood them somewhat, but not fully. Some
were greatly pleased with the teachings, and believed them true. But
they could not yet come as an entire village, and they dared not
separate. Next morning we parted as friends. They were glad that
we had found the way to their village. “Be sure to come again!” That
I thought surely I should do; but this proved to be my only visit.
At the Sên Lūang’s village, where the great Pū Chān lived, we had
the same experience—a good reception, many apparently interested
and anxious to escape their own spirit-worship. A number of the
head men said, “If such and such a village accepts the Jesus-
religion, we will.” But no one could be found to face the clan and
make a start.
Thinking that our native evangelists might get at the heart of the
people all the better if left to do it alone, and being anxious to get
my mail from home, I went down on Saturday to Nān Suwan’s to
spend the Sunday there with the Christians. On Tuesday, to my
disappointment, the evangelists returned to me discouraged. They
were convinced that in the district east of the Mê Kōng River, no
break in the solidarity of the clan could be accomplished that season.
But it was important not to leave these people with the impression
that we had abandoned them. I had left Sên Chai’s village with the
promise to return. So I went up with the Mūsô Christian boys, and
spent a last night with them. The village again assembled, and we
had an interesting evening. The Sên was greatly disappointed that
none of the other villages would join him. But the New Year was at
hand, when the clan must be unbroken. They would wait another
year, and try to get the other villages to join them. On the whole, I
was encouraged. When we left them we were escorted out of the
village to the music of their plaintive flutes, more like a victorious
than a vanquished army.
After a day or two with the Chieng Sên church, we visited the
ridge to the southeast of that city, between it and Chieng Kawng.
Our experience there was but a repetition of that from which we
were just come—cordial receptions, night audiences, manifest
interest, individual believers, anxious consultations, promises for the
next year; but the tribal bond was too strong to be broken.
But Cha Pū Kaw was anxious that we should not pass by his own
mountain villages on the Mê Kok. So we turned southward again
toward Chieng Rāi. This, moreover, was one of those famine years,
such as we have already encountered in our story, and shall
encounter yet again; many people were on the verge of starvation.
In places we could not get food for our own men. And famine was
beginning to be followed by disease and death. This was a serious
obstacle to our work.
Another serious obstacle was the use of opium, which became
more prevalent the further west we went along the Mê Kok range
towards Mûang Fāng. We presently reached villages where the
poppy was cultivated, until, in the last village, men, women, and
boys, and sometimes even girls, were its slaves. Fevers and
dysentery prevail during the rainy season. These people have a very
scanty pharmacopœia, and no antidotes whatever for these
diseases. Opium in some form is probably their surest remedy. Many
persons told me that they began by using it in sickness. As sickness
recurred the habit grew, until they were fast bound in its chains.
These facts largely determined the character of the instruction we
gave, and made our tour a kind of anti-opium crusade. Encouraged
and disappointed at every village, I was still tempted on by visions of
capturing some large village that would prove a more effective
entering wedge for the tribe than Cha Pū Kaw’s poor little hamlet.
The six weeks so spent were at the time the most novel and
exciting, as well as most arduous, of all my missionary experiences
so far.
We took both the old Mūsô men as assistants, and the younger
ones as carriers for our equipment. Our first day’s journey was a fair
sample of what we had to do continually. In many places it would be
a misnomer to speak of the track we travelled as a path. We left the
plain in the morning, and it was half-past two in the afternoon when
we reached the first summit. It was five o’clock when, desperate
with thirst, we came upon a flowing brook. There was, then, still
another hard climb before we saw our long looked-for first village
ahead. And, in general, because of the habit these people have of
planting their villages upon the very highest points where they can
get water, the journey from one of these villages to another in plain
sight, and, apparently, but a short distance away, would take hours
of the hardest travel. Sometimes we would walk weary hours
through rain, or through bushes as wet as rain, to visit a village;
only to walk back again after sitting three hours in wet clothes trying
in vain to awaken some interest in old or young.
One of the most interesting, and, at the same time, one of the
saddest, cases we met was that of Mûn Kamprai, the head man of a
village which clearly bore the impress of his character in the
intelligence and industry of its inhabitants. From opium he had kept
entirely aloof until, only a few years before this time, under the
stress of a severe illness, he began to take it. The poor man now
realized that he was becoming a wreck, but seemed to have no will-
power left to make the effort to break away from the habit. He was
much interested, however, in his two fellow-tribesmen whom I had
brought as my assistants; and Cha Waw’s example seemed to afford
him a faint gleam of hope. If we would stop a week and teach his
people, and would stand by to aid him, he would try. If successful,
he would surely become a Christian—and then his village would be
the one we had been hoping for to free itself from the tribal bond,
and become Christian.
The experiment was, indeed, pathetic. Removing all temptation,
he began with a desperate determination to succeed. We
encouraged him with human sympathy and the hope of divine aid.
We pushed as far as we dared the use of a tonic which Dr. McKean
had given me for such cases; and it aided him perceptibly. He held
out manfully for several days. But, at last, in an evil hour, he could
endure the torture no longer, and before we knew it, he had
resumed the use of the drug. For two nights he had not slept. In his
own expressive language, it was not his eyes, but his heart that
could not sleep. Poor man! his sufferings must have been as near
those of the infernal regions as it is possible to experience in the
body. And then his absolute wreck of mind, and the contempt he felt
for himself when he gave up the struggle as hopeless!
We spared no labour to reach the homes of these people, or their
hearts. We tried to become Mūsôs to the Mūsôs that we might win
them. Sometimes we had to sleep in their huts—on a floor raised
two or three feet from the ground, which the dogs shared with the
family, while the pigs and goats were on the ground beneath. In the
centre was a raised fireplace on which the native teapot always
boiled. Sleeping-mats or thin bedding lay about on the floor, and on
this, before bedtime, some of the inmates would lie down and fall
asleep even while listening to the conversation.—But everywhere the
tribal bond was too strong to be broken.
MŪSÔ PEOPLE AND HUT NEAR CHIENG RAI
By this time the rains had set in. The trails—and the leeches that
infested them—were getting worse and worse. Soon the torrent-
streams would become impassable. We must return while yet we
could. Our six weeks’ wanderings we retraced in four days of
constant tramping. It had been a hard trip for all of us. I myself had
a touch of fever. It seemed good on reaching our camp to have once
more the luxury of a chair and a table. And then to be on the
sadaw’s back travelling homewards, and to meet a good mail on the
way! My three-score and fourth birthday was spent in the forest, and
I reached home safely on the 18th of May, after an absence of
nearly five months.
The scenes reported from Prê were harrowing. I will not pain the
reader by dwelling upon them. One happy result followed the efforts
of the brethren who went to the relief of that district. While
administering to bodily wants, they preached the Gospel, making
such an impression that there was a strong demand for a permanent
station there—which was established the next year, with Dr. and Mrs.
Briggs as pioneer missionaries.
It should be stated that, toward the last, the Siamese government
sent up supplies of rice; but, because of the distance and the
difficulty of transportation, not much reached the suffering people in
time to help them; and much was lost in passing through the hands
of so many officials.
XXXI
ebookgate.com