    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Professionalism in Programming #10</title>
        <link>https://members.accu.org/index.php/articles/1137</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Professionalism in Programming, from CVu journal + CVu Journal Vol 13, #5 - Oct 2001</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c184/">Journal Columns</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c182/">Professionalism</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c118/">135</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c182-118/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c182+118/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Professionalism in Programming #10</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 05 October 2001 13:15:47 +01:00 or Fri, 05 October 2001 13:15:47 +01:00</p>
<p><strong>Summary:</strong>&nbsp;<p>Software testing</p></p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e22" id="d0e22"></a></h2>
</div>
<p>You can write as much code as you like, there's one thing you
can be sure of: it won't work perfectly first time, no matter how
long you sit down and carefully specify it beforehand. Software
faults have this creepy ability to work their way into any
software. The more code you write, the more faults you'll
introduce. The faster you write, the more you'll introduce. I've
yet to meet a really prolific coder who created anything near
bug-free code.</p>
<p>So what do we do about this? We <span class=
"emphasis"><em>test</em></span> the code. We do this to find the
problems that exist, and once we've fixed them we use the tests to
give us confidence in the quality of the code we've created.</p>
<p>If you were a car manufacturer, you'd be obliged to physically
crash your new products in various manners to measure and ensure
applicable safety standards are met. We do something like that with
our software (although on the whole, we try not to crash it!)
Perhaps a great cause of the problems with contemporary software
development and deployment is that there are no relevant &quot;safety
standards&quot; which we should adhere to.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e33" id="d0e33"></a>The
<span class="emphasis"><em>what</em></span> and <span class=
"emphasis"><em>why</em></span> of testing</h2>
</div>
<p>Such simple questions as 'What is testing?' and 'Why do we have
to test?' seem almost too obvious to answer. Yet all too often
adequate software testing is not performed - or it is not performed
at the appropriate stage of production. Getting your testing
procedures correct is a skill. Actually having testing procedures
is even more significant. The mere mention of the term testing
procedure is enough to bring some engineers out in hives.</p>
<p>During the lifetime of a software development process various
articles get tested. A large number of <span class=
"emphasis"><em>documents</em></span> will go through a testing
stage (more commonly known as a <span class=
"emphasis"><em>review</em></span> process). Doing this ensures, for
example, that the requirements specification correctly models the
customer's needs, the functional specification implements the
requirements specification, the various sub system specifications
are complete enough to fulfil the functional specification, and so
on.</p>
<p>Naturally then, the implementation code gets tested. It gets
tested at several levels too, ranging from on the developer's
machine (possibly outside of the target environment in which it
will run), at an integration level where the code is glued together
with the other parts of the system, to a product level where the
entire end-product is validated. The <span class=
"emphasis"><em>product</em></span> as a whole is clearly another
testing target. Whilst this latter level of testing will (or
'should') indirectly test all the code components developed that is
not the focus of the tests at this level.</p>
<p>In the rest of this article we will focus entirely on how as
software developers we test the <span class=
"emphasis"><em>code</em></span> we write.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e62" id="d0e62"></a>Effective
testing</h2>
</div>
<p>For our software testing to be effective we need to be clear why
we're testing and what we're trying to do. As software developers
our testing procedure exists for two reasons (this is the
<span class="emphasis"><em>why</em></span>):</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>To help us to find faults and fix them, then</p>
</li>
<li>
<p>To ensure the faults don't reappear in later versions.</p>
</li>
</ol>
</div>
<p>To understand what we're doing we need to be clear exactly what
software we're testing and the method we're using to test (there
are several). Finally, one of the hardest and most important
questions to answer is: when do we know when we've finished
testing?</p>
<p>Once we're satisfied we've tested thoroughly and have removed
all the faults we can consider our software bullet
proof<sup>[<a name="d0e81" href="#ftn.d0e81" id=
"d0e81">1</a>]</sup>. Of course, your confidence in the software is
only as good as your tests. If you haven't tested your software at
all, any confidence you have in it running correctly is clearly
unfounded (unless, perhaps, it is the simplest of one-line &quot;hello
world&quot; programs). The more separate tests you run, the more you can
have confidence that your code is correct. The higher the quality
of the tests (and just how do we measure this?), again, the higher
your level confidence.</p>
<p>In order to do this, then, what form do our tests take? When we
write software we create individual functions at the lowest level,
then classes, then whole systems (for example, a reusable
component, program, device driver or shared library). Each level
should be tested thoroughly. And each level requires a different
sort of test.</p>
<p>Tests can generally only ensure that the correct output is
generated for the right set of inputs. They also need to ensure
that the correct failure cases are generated for a small set of the
possible invalid inputs<sup>[<a name="d0e89" href="#ftn.d0e89" id=
"d0e89">2</a>]</sup>. This is hard, and we'll see why below.</p>
<p>Sadly we have to accept that we still can't produce fault free
software - some errors will get through even the most 'exhaustive'
testing. With this in mind, for effective testing we need to focus
on the key tests that will likely capture the majority of software
defects.</p>
<p>Testing mustn't be put off for too long - experience shows us
that the maintenance and testing phases of software development are
at least as big as the development phase. Some studies show that
typically more than 50% percent of the development time is spent in
testing. Real testing is really hard. We need to start as soon as
possible - even during (or perhaps before) serious software
development.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e100" id="d0e100"></a>Why is
testing hard?</h2>
</div>
<p>If a particular piece of code needs to be tested we said above
that we need to ensure it generates correct output for the set of
all good input values and produces the correct failure cases for
the set of all invalid inputs. That sounds innocuous enough but for
all but the simplest function (with no reliance on any external
part of the system) it is just plain impossible to test
exhaustively.</p>
<p>For example, this is a fairly easy C++ function to test:</p>
<pre class="programlisting">
bool logical_not(bool b)
{
  if (b)
    return false;
  else
    return true;
}
</pre>
<p>The set of inputs is of size two. However, what about the
following function (let's not consider its elegance at the moment)
- it has a very large set of inputs and multiple paths of
execution. How do you exhaustively test it?</p>
<pre class="programlisting">
bool is_prime(int val)
{
  for (int i = 2; i*i = val; ++i)
  {
    int remainder = val - ((val/i)*i);
    if(remainder == 0)
      return false;
  }
  return true;
}
</pre>
<p>And that's just for a single small function. When software
components get glued together, and start relying on each other the
complexity of the software expands exponentially. It becomes not
just difficult, but technically infeasible to test the software
exhaustively. The time and resources do not exist to generate the
test data and run the software over all sets of inputs and stimuli.
Software is inherently complex and can fail in a multitude of
exciting and bizarre ways. You don't just have invalid output to
contend with - there's also crashes, GPFs, and more to guard
against.</p>
<p>Now this isn't the only reason software testing is hard.
Software evolves. This evolution tends to break tests. If the
requirements are not pinned down early on, your tests early on in
the project will probably be invalid because by the time you come
to deliver, the APIs have changed, the functionality is completely
different and the full set of tests have not been created because
development never stood still long enough. If external interfaces
are not stable we can't test.</p>
<p>Bugs can be caused by both errors in software and also in
hardware. When working in embedded environments you are generally
more likely to run into hardware error. Hardware faults can
sometimes be an order of magnitude more difficult to diagnose and
fix.</p>
<p>So good testing is just plain hard. That's why it's often not
done at all properly - leading to the release of code that is
simply not suitable or saleable. The more complicated a code base
becomes the harder it is to test properly, and the easier it is to
ignore this. Programmers tend to leave their developmental testing
and rely on the company's QA<sup>[<a name="d0e121" href=
"#ftn.d0e121" id="d0e121">3</a>]</sup> department to find their
bugs for them. This is not just wrong, it is downright dangerous.
&quot;The single most important rule of testing is to do it.&quot; [<a href=
"#Kernighan-">Kernighan-</a>]</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e128" id="d0e128"></a>How do you
test?</h2>
</div>
<p>So if we can't test exhaustively what do we do? We need to test
as effectively and as fully as we can<sup>[<a name="d0e133" href=
"#ftn.d0e133" id="d0e133">4</a>]</sup>. This kind of testing is
more than just debugging. We write a suite of tests to run - the
tests are extra software<sup>[<a name="d0e140" href="#ftn.d0e140"
id="d0e140">5</a>]</sup>. The question is what goes into this test
suite and how do we determine what tests are necessary? Presume
that the 'simple stuff' - running memory checkers, static code
validators and the like - has already been done during development
(almost as a part of debugging). Having some test cases in for
memory leaks is not by any means unnecessary - however this may not
be the main focus.</p>
<p>What tests are required is naturally dependant on the software
you are writing. The focus may be on timely execution, correct
memory usage, certainly on correct outputs for correct inputs - and
often all of the above. The complexity of the test suite grows
incredibly quickly as the software under test gains a more complex
and convoluted API.</p>
<p>Now we're not going to take a textbook approach to describing
testing as much as a practical approach. There is a lot of theory
behind various types of testing. This article will not replace a
good study of the real background material. There are some links at
the end that provide good jumping points for further
investigation.</p>
<p>We do, though, need to get the nomenclature straight - people
differ in their definitions of the terms bug, error, fault and
defect. They are all precise and important. Generally a fault
exists in our software that leads to it exhibiting a defect or
error. The term bug is a colloquialism: according to folklore, the
first computer bug was an actual bug. It was discovered by Admiral
Grace Hopper in 1945 at Harvard. A moth trapped between two
electrical relays of the Mark II Aiken Relay Calculator caused the
whole machine to shut down.</p>
<p>Tests are easier when the code is written thoughtfully. If a
single section of code is self-contained and doesn't have endless
undocumented and tenuous dependencies on the outside world then it
will be much easier to test. For example, if a function relies
heavily on global variables before running a test you have to
ensure that all these variables are set to a particular state.
However, if the variables accessed are gathered in a state
structure that is passed as a parameter, then the environment of
the test is much better defined. The test can be written with a
much higher degree of confidence. You don't want a test to succeed
one day and then fail the next depending on which way the wind is
blowing.</p>
<p>Good code should be designed from the outset to be testable. It
is a general rule that when you structure your code for testability
you will generally be structuring it in a sensible, understandable
and maintainable way. That can't be a bad thing.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e154" id="d0e154"></a>Different
sorts of tests</h2>
</div>
<p>There are a number of different kinds of testing, each cover
different considerations, each can catch different sets of faults.
All are needed. This is a whistle stop tour of the world of
testing.</p>
<p>There are two main approaches to devising tests, and several
testing scenarios. First we'll look at the two approaches,
<span class="emphasis"><em>black box</em></span> and <span class=
"emphasis"><em>white box</em></span> testing.</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p><span class="bold"><b>Black box testing</b></span></p>
<p>This is also known as <span class="emphasis"><em>functional
testing</em></span>. It is testing from point of view of the user,
not designer. Black box testing compares actual functionality
against intended functionality. It deals with problems in a
fault-based approach.</p>
<p>Black box testing is concerned only with meeting the software's
specification - not that all parts of implementation are tested.
Therefore without clear specs it is very hard to implement the
tests. The internal workings of the code are not known by the
tester, it is seen as a black box. This means that the test is
unbiased - the designer and tester are (or should be) independent
of one another. How often they are is another matter.</p>
<p>Black box test cases can be designed as soon as the software
specification is complete. Since testing every possible input
stream is fairly unrealistic many program paths may go untested.
The tester will have no idea what kind of code coverage they have
achieved when the tests are complete.</p>
<p>Black box testing does rely on the specification being correct
in the first place, and on it not being radically altered after the
tests have been devised.</p>
</li>
<li>
<p><span class="bold"><b>White box testing</b></span></p>
<p>This is also known as <span class="emphasis"><em>structural
testing</em></span>. It is a code-coverage based approach. If black
box testing is concerned with faults of omission, white box testing
discovers faults of commission. Each line of code is scrutinised
systematically to ensure correctness. Where you couldn't see into
the 'black box' beforehand, you now can and do. For this reason
white box testing is sometimes called <span class=
"emphasis"><em>glass box</em></span> testing. It is really only
concerned with testing the software produced and doesn't guarantee
it meets the specification in the same way as black box.</p>
<p>There are static and dynamic methods of white box testing. In
the static method the code is not run, it is inspected and walked
through to ensure that it does in fact represent a valid solution.
The dynamic method is largely concerned with path and branch
testing - running the code in such a way as to execute every line,
and every possible decision.</p>
<p>White box testing is much more expensive that black box, and is
correspondingly done a lot less. It needs the source code to have
been written before the white box tests can be planned. Black box
testing will typically have been done beforehand. It is laborious.
The consequence of a failure at this stage can be much more
expensive. You'd have to code the fix, black box test again, then
redesign and run white box tests.</p>
<p>White box testing aims at some degree of exhaustion; in
statement coverage (we should have executed every line at least
once), and branch coverage (we should have traversed every branch
option, but not necessarily every permutation of the branch
options). It can require modification to the code to force it to go
down certain paths, rather than engineer test cases when it will.
Without tool support white box testing can make your head
explode.</p>
<p>If you do modify the source code, then you're not actually
testing the final executable, which is not always a good thing. It
can also be hard to make work because in large code bases with
third party libraries, sometimes not all the source is
available.</p>
<p>There are a number of source-patching test tools available. For
example, Rational Purify (<a href="www.rational.com" target=
"_top">www.rational.com</a>), and BugTrapper from Mutek (<a href=
"www.mutek.com" target="_top">www.mutek.com</a>).</p>
</li>
</ul>
</div>
<p>Along with these approaches to testing, there is a set of
different test scenarios. They correspond to the different stages
of software development. The relevant tests can be developed in a
black or white box method.</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p><span class="bold"><b>Unit testing</b></span></p>
<p>The term unit test is commonly used to mean testing a &quot;module&quot;
of code (a library, driver, stack layer), but really describes
testing the atomic structures, each class or function. Each
untrusted unit that the code interfaces with is replaced with a
stub or simulator - this ensures we will only trap bugs in this
unit, not bugs caused by outside influences. Unit testing is
performed in strict isolation.</p>
</li>
<li>
<p><span class="bold"><b>Component testing</b></span></p>
<p>This validates the combination of one or more units into a full
component - often this is what people mean by 'unit test'. They are
tested together, all stubs and simulators are replaced with the
real things.</p>
</li>
<li>
<p><span class="bold"><b>Integration testing</b></span></p>
<p>This is testing the combination of components - ensuring that
they interconnect properly and function as a whole according to
specification.</p>
</li>
<li>
<p><span class="bold"><b>Regression testing</b></span></p>
<p>This is re-testing after fixes or modifications are made to the
software or its environment. You regression test to ensure the
software is still working as well as it did before, and that in
making a modification you haven't broken something else. When you
work with brittle software a change in one place can cause a
strange fault to appear elsewhere. Regression testing guards
against this.</p>
<p>It can be difficult to determine how much re-testing is needed,
especially near the end of the development cycle. Automated testing
tools can be especially useful for this type of testing.</p>
</li>
</ul>
</div>
<p>This is still not the end of the story. There are other forms of
testing which we don't have the space to delve into fully. You may
need to run <span class="emphasis"><em>performance
tests</em></span> - if it is a requirement of your product. Maybe
<span class="emphasis"><em>volume test</em></span> to ensure that
your code can handle a huge amount of data. This can unearth
problems related to efficiency of a system (e.g. incorrect buffer
sizes, too much memory required). <span class="emphasis"><em>Stress
testing</em></span> throws a huge amount of data at the code within
a short space of time and is similar to volume testing, it is often
used for high availability systems. <span class=
"emphasis"><em>Recovery testing</em></span> ensures that data can
be recovered after a system breakdown, and that it is still
correct. This can be a priority for high reliability systems. There
are various forms of end-user tests, often performed in 'usability
labs' under very controlled and scripted conditions, as well as
field trials.</p>
<p>What about 'alpha-tests' and 'beta tests'? In reality these
terms mean nothing, and are largely employed as milestones on a
development schedule. Each company will have their own definition
of what they mean by software in an <span class=
"emphasis"><em>alpha</em></span> or <span class=
"emphasis"><em>beta</em></span> state. 'Alpha' usually implies most
of the functionality is present but may be completely unreliable.
In a 'beta' state the software should be mostly usable with very
few remaining problems - beta testing is used in the run up to
final release candidates.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e262" id="d0e262"></a>What is
required for good testing?</h2>
</div>
<p>We're going to be spending a long time testing. We need to make
sure we're not wasting our time. How do we ensure it's effective?
If we want our testing to have maximum impact (and minimum pain):
<span class="emphasis"><em>test early</em></span>, <span class=
"emphasis"><em>test often</em></span>. This is embodied in the
Extreme Programming approach by writing the test cases first of
all, before <span class="emphasis"><em>any</em></span> production
code. I've never done this but I can see that it gives a real
confidence in the code being written<sup>[<a name="d0e276" href=
"#ftn.d0e276" id="d0e276">6</a>]</sup>.</p>
<p>For good testing we need to ensure test cases are exhaustive (or
more realistically 'as complete as possible'). How do we ensure
test cases are exhaustive? It's even fairly hard to define what
exhaustive means. Perhaps it means that you've covered the
execution of every line of code (in a large code base that's quite
an undertaking - and what if some lines have been written that can
never be reached). Perhaps it means that every API has been
exercised in the most common environments. Perhaps it's feeding the
software every set of possible input, good and bad (quite a brute
force method, and often far too resource intensive to be a
realistic approach).</p>
<p>Good test cases often go hand-in-hand with the generation of
good test data. If you can automatically generate the test data
then this can be very handy. Any form of automation will increase
the speed at which you can test, therefore allowing you to test
harder in the same period of time - increasing the likelihood of
improving your software quality.</p>
<p>How do we determine what test data to generate? If we can't
cover every single possible input we need to select a handful of
pertinent inputs. More often than not this will be:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>A certain number of well chosen good inputs to ensure that the
software works properly in the 'normal' case.</p>
</li>
<li>
<p>A certain number of well chosen bad inputs - checks just the
reverse. It ensures the software is robust.</p>
</li>
<li>
<p><span class="emphasis"><em>All</em></span> the boundary cases -
identify the highest and lowest inputs that are valid (or whatever
the natural boundaries are). For each of these test the boundary on
the 'good' side and the 'bad' side to ensure the software works at
the extremes and fails exactly when expected.</p>
</li>
<li>
<p>Test randomly generated sets of data, to eliminate guesswork -
this can be a surprisingly effective test strategy.</p>
</li>
<li>
<p>If numeric data is the input, always test for zero cases.
Programmers always seem to fail to think properly about zero for
some reason.</p>
</li>
<li>
<p>If appropriate, then perform stress testing. Overload the
program with inputs to determine its capacity. This is especially
pertinent in threaded or real time systems.</p>
</li>
</ul>
</div>
<p>In order to foster good testing in a development organisation
there must be a culture of concrete specifications being written up
front. This allows test specifications to be created and worked
with. It is also vital to develop good working relationships twixt
the QA department and the software developers. All too often there
is a rivalry where the testing department is seen as a bunch of
people who aim to get in the way of developers and hinder the path
to release, rather than a team who help to build a stable
product.</p>
<p>How do you know when to stop testing? The task is potentially
endless. The end point can be difficult to determine. Many modern
software applications are so complex, and run in such an
interdependent environment, that complete testing can never be
done. Common factors in deciding when to stop are:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>Deadlines (release deadlines, testing deadlines, etc.),</p>
</li>
<li>
<p>Test cases completed with certain percentage passed (and no
major <span class="emphasis"><em>show-stoppers</em></span>
remaining),</p>
</li>
<li>
<p>Test budget depleted (a very sad criteria for stopping),</p>
</li>
<li>
<p>Coverage of code/functionality/requirements reaches a specified
point,</p>
</li>
<li>
<p>Exhibited bug rate falls below a certain level,</p>
</li>
<li>
<p>Beta or alpha testing period ends.</p>
</li>
</ul>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e333" id="d0e333"></a>Test
harnesses</h2>
</div>
<p>We said that automating the software testing process is a Good
Thing. The common and effective way of doing this is to use a
<span class="emphasis"><em>test harness</em></span>. This is a
scaffold in which to place the tests we write in order to marshal
the test execution and gather the results of the testing in a
single place. The harness monitors which tests have been done (and
the more complex ones maintain a history of test results over
time).</p>
<p>Testing is costly and automation cuts down time and cost.
Clearly though, not all tests can be automated. End-user testing
can be hard to automate, for example how do you emulate mouse
clicks or ensure that the correct sound clip is playing?</p>
<p>A high level of automation comes into its own when regression
testing. If you make a later modification to the code and want to
ensure that you haven't broken it in any way you can just run the
set of tests over it automatically; out at the end pops a
<span class="emphasis"><em>yes</em></span> or <span class=
"emphasis"><em>no</em></span>. Of course the regression test result
is only as good as the tests put into the harness.</p>
<p>Many software companies have developed their own test harnesses.
There are also a number of commercial and free harnesses available
which merit a look. Some of these are listed in the 'Resources'
section at the end. There is a huge benefit in using a company
standard (or other standard) test harness. Rather than spell it
out, I'll leave that as an exercise for the reader.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e353" id=
"d0e353"></a>Conclusion</h2>
</div>
<p>We have seen the necessity, problems with, approaches to and
practical ways to test. Are we performing the full level of testing
for which we are responsible? Do we even know for sure what level
of testing we are responsible for? Do we have full confidence in
the quality of our code, and if not what steps can we take to
rectify this?</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e358" id=
"d0e358"></a>Resources</h2>
</div>
<p>Here are a selection of links to material on the internet that
are useful.</p>
<div class="variablelist">
<dl>
<dt><span class="term">Software Testing (from CMU)</span></dt>
<dd>
<p><a href="www-2.cs.cmu.edu/~koopman/des_s99/sw_testing/" target=
"_top">www-2.cs.cmu.edu/~koopman/des_s99/sw_testing/</a></p>
</dd>
<dt><span class="term">comp.software.testing FAQ</span></dt>
<dd>
<p><a href=
"www.faqs.org/faqs/software-eng/testing-faq/preamble.html" target=
"_top">www.faqs.org/faqs/software-eng/testing-faq/preamble.html</a></p>
</dd>
<dt><span class="term">Software QA and Testing</span></dt>
<dd>
<p><a href="www.softwareqatest.com/" target=
"_top">www.softwareqatest.com/</a></p>
</dd>
</dl>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e385" id="d0e385"></a>Test
harnesses</h2>
</div>
<div class="variablelist">
<dl>
<dt><span class="term">CppUnit</span></dt>
<dd>
<p><a href="cppunit.sourceforge.net" target=
"_top">cppunit.sourceforge.net</a></p>
</dd>
<dt><span class="term">JUnit</span></dt>
<dd>
<p><a href="www.junit.org" target="_top">www.junit.org</a></p>
</dd>
<dt><span class="term">Jtest and C++Test from Parasoft</span></dt>
<dd>
<p><a href="www.parasoft.com" target=
"_top">www.parasoft.com</a></p>
</dd>
<dt><span class="term">liveCODE from Applied
Microsystems</span></dt>
<dd>
<p><a href="www.applied-microsystems.com" target=
"_top">www.applied-microsystems.com</a></p>
</dd>
<dt><span class="term">Aprobe from OC Systems</span></dt>
<dd>
<p><a href="www.ocsystems.com" target=
"_top">www.ocsystems.com</a></p>
</dd>
</dl>
</div>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e425" id="d0e425"></a>References</h2>
</div>
<div class="bibliomixed"><a name="Kernighan-" id="Kernighan-"></a>
<p class="bibliomixed">[Kernighan-] Brian Kernighan and Rob Pike.
<span class="citetitle"><i class="citetitle">The Practice of
Programming</i></span>. 1999, Addison Wesley, Inc. ISBN:
0-201-61586-X.</p>
</div>
</div>
<div class="footnotes"><br>
<hr class="c3" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e81" href="#d0e81" id=
"ftn.d0e81">1</a>]</sup> dly, in the real world testing will rarely
ensure that software is bullet proof - merely that it is adequate.
As we'll see later testing is hard and we can only do as much as we
can afford.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e89" href="#d0e89" id=
"ftn.d0e89">2</a>]</sup> The set of invalid inputs is almost always
<span class="emphasis"><em>much</em></span> larger than the set of
valid inputs.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e121" href="#d0e121" id=
"ftn.d0e121">3</a>]</sup> 'Quality Assurance' - the name often
given to the group of people who perform software testing and have
the final sign-off on whether or not it is of a sufficiently high
quality for release.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e133" href="#d0e133" id=
"ftn.d0e133">4</a>]</sup> We're more likely to if we are made
accountable for our testing. This is a major plus point for
<span class="emphasis"><em>testing specifications</em></span>. They
ensure the visibility of the test procedure, but are often scorned
because they are seen to 'add work'.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e140" href="#d0e140" id=
"ftn.d0e140">5</a>]</sup> You'll get a headache if you start
thinking about testing the testing code.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e276" href="#d0e276" id=
"ftn.d0e276">6</a>]</sup> early you can only be writing black box
tests here.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
