Added cabal and vim dir
This commit is contained in:
539
cabal/share/x86_64-osx-ghc-7.10.1/HUnit-1.2.5.2/doc/Guide.html
Normal file
539
cabal/share/x86_64-osx-ghc-7.10.1/HUnit-1.2.5.2/doc/Guide.html
Normal file
@@ -0,0 +1,539 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.w3.org/MarkUp/SCHEMA/xhtml11.xsd" xml:lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta name="Author" content="Dean Herington"/>
|
||||
<meta name="KeyWords" content="HUnit, unit testing, test-first development, Haskell, JUnit"/>
|
||||
<title>HUnit 1.0 User's Guide</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>HUnit 1.2 User's Guide</h1>
|
||||
|
||||
<p>HUnit is a unit testing framework for Haskell, inspired by the JUnit tool for Java. This
|
||||
guide describes how to use HUnit, assuming you are familiar with Haskell, though not
|
||||
necessarily with JUnit. You can obtain HUnit, including this guide, at <a
|
||||
href="http://code.haskell.org/HUnit">http://code.haskell.org/HUnit</a>.</p>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>A test-centered methodology for software development is most effective when tests are
|
||||
easy to create, change, and execute. The <a href="http://www.junit.org">JUnit</a> tool
|
||||
pioneered support for test-first development in <a href="http://java.sun.com">Java</a>.
|
||||
HUnit is an adaptation of JUnit to Haskell, a general-purpose, purely functional
|
||||
programming language. (To learn more about Haskell, see <a href="http://www.haskell.org"
|
||||
>http://www.haskell.org</a>.)</p>
|
||||
|
||||
<p>With HUnit, as with JUnit, you can easily create tests, name them, group them into
|
||||
suites, and execute them, with the framework checking the results automatically. Test
|
||||
specification in HUnit is even more concise and flexible than in JUnit, thanks to the
|
||||
nature of the Haskell language. HUnit currently includes only a text-based test
|
||||
controller, but the framework is designed for easy extension. (Would anyone care to
|
||||
write a graphical test controller for HUnit?)</p>
|
||||
|
||||
<p>The next section helps you get started using HUnit in simple ways. Subsequent sections
|
||||
give details on <a href="#WritingTests">writing tests</a> and <a href="#RunningTests"
|
||||
>running tests</a>. The document concludes with a section describing HUnit's <a
|
||||
href="#ConstituentFiles">constituent files</a> and a section giving <a
|
||||
href="#References">references</a> to further information.</p>
|
||||
|
||||
<h2 id="GettingStarted">Getting Started</h2>
|
||||
|
||||
<p>In the Haskell module where your tests will reside, import module <tt>Test.HUnit</tt>:</p>
|
||||
<pre>
|
||||
import Test.HUnit
|
||||
</pre>
|
||||
<p>Define test cases as appropriate:</p>
|
||||
<pre>
|
||||
test1 = TestCase (assertEqual "for (foo 3)," (1,2) (foo 3))
|
||||
test2 = TestCase (do (x,y) <- partA 3
|
||||
assertEqual "for the first result of partA," 5 x
|
||||
b <- partB y
|
||||
assertBool ("(partB " ++ show y ++ ") failed") b)
|
||||
</pre>
|
||||
<p>Name the test cases and group them together:</p>
|
||||
<pre>
|
||||
tests = TestList [TestLabel "test1" test1, TestLabel "test2" test2]
|
||||
</pre>
|
||||
<p>Run the tests as a group. At a Haskell interpreter prompt, apply the function
|
||||
<tt>runTestTT</tt> to the collected tests. (The "<tt>TT</tt>" suggests
|
||||
<strong>T</strong>ext orientation with output to the <strong>T</strong>erminal.)</p>
|
||||
<pre>
|
||||
> runTestTT tests
|
||||
Cases: 2 Tried: 2 Errors: 0 Failures: 0
|
||||
>
|
||||
</pre>
|
||||
<p>If the tests are proving their worth, you might see:</p>
|
||||
<pre>
|
||||
> runTestTT tests
|
||||
### Failure in: 0:test1
|
||||
for (foo 3),
|
||||
expected: (1,2)
|
||||
but got: (1,3)
|
||||
Cases: 2 Tried: 2 Errors: 0 Failures: 1
|
||||
>
|
||||
</pre>
|
||||
<p>Isn't that easy?</p>
|
||||
|
||||
<p>You can specify tests even more succinctly using operators and overloaded functions that
|
||||
HUnit provides:</p>
|
||||
<pre>
|
||||
tests = test [ "test1" ~: "(foo 3)" ~: (1,2) ~=? (foo 3),
|
||||
"test2" ~: do (x, y) <- partA 3
|
||||
assertEqual "for the first result of partA," 5 x
|
||||
partB y @? "(partB " ++ show y ++ ") failed" ]
|
||||
</pre>
|
||||
<p>Assuming the same test failures as before, you would see:</p>
|
||||
<pre>
|
||||
> runTestTT tests
|
||||
### Failure in: 0:test1:(foo 3)
|
||||
expected: (1,2)
|
||||
but got: (1,3)
|
||||
Cases: 2 Tried: 2 Errors: 0 Failures: 1
|
||||
>
|
||||
</pre>
|
||||
|
||||
<h2 id="WritingTests">Writing Tests</h2>
|
||||
|
||||
<p>Tests are specified compositionally. <a href="#Assertions">Assertions</a> are combined to
|
||||
make a <a href="#TestCase">test case</a>, and test cases are combined into <a
|
||||
href="#Tests">tests</a>. HUnit also provides <a href="#AdvancedFeatures">advanced
|
||||
features</a> for more convenient test specification.</p>
|
||||
|
||||
<h3 id="Assertions">Assertions</h3>
|
||||
|
||||
<p>The basic building block of a test is an <b>assertion</b>.</p>
|
||||
<pre>
|
||||
type Assertion = IO ()
|
||||
</pre>
|
||||
<p>An assertion is an <tt>IO</tt> computation that always produces a void result. Why is an
|
||||
assertion an <tt>IO</tt> computation? So that programs with real-world side effects can
|
||||
be tested. How does an assertion assert anything if it produces no useful result? The
|
||||
answer is that an assertion can signal failure by calling <tt>assertFailure</tt>.</p>
|
||||
<pre>
|
||||
assertFailure :: String -> Assertion
|
||||
assertFailure msg = ioError (userError ("HUnit:" ++ msg))
|
||||
</pre>
|
||||
<p><tt>(assertFailure msg)</tt> raises an exception. The string argument identifies the
|
||||
failure. The failure message is prefixed by "<tt>HUnit:</tt>" to mark it as an HUnit
|
||||
assertion failure message. The HUnit test framework interprets such an exception as
|
||||
indicating failure of the test whose execution raised the exception. (Note: The details
|
||||
concerning the implementation of <tt>assertFailure</tt> are subject to change and should
|
||||
not be relied upon.)</p>
|
||||
|
||||
<p><tt>assertFailure</tt> can be used directly, but it is much more common to use it
|
||||
indirectly through other assertion functions that conditionally assert failure.</p>
|
||||
<pre>
|
||||
assertBool :: String -> Bool -> Assertion
|
||||
assertBool msg b = unless b (assertFailure msg)
|
||||
|
||||
assertString :: String -> Assertion
|
||||
assertString s = unless (null s) (assertFailure s)
|
||||
|
||||
assertEqual :: (Eq a, Show a) => String -> a -> a -> Assertion
|
||||
assertEqual preface expected actual =
|
||||
unless (actual == expected) (assertFailure msg)
|
||||
where msg = (if null preface then "" else preface ++ "\n") ++
|
||||
"expected: " ++ show expected ++ "\n but got: " ++ show actual
|
||||
</pre>
|
||||
<p>With <tt>assertBool</tt> you give the assertion condition and failure message separately.
|
||||
With <tt>assertString</tt> the two are combined. With <tt>assertEqual</tt> you provide a
|
||||
"preface", an expected value, and an actual value; the failure message shows the two
|
||||
unequal values and is prefixed by the preface. Additional ways to create assertions are
|
||||
described later under <a href="#AdvancedFeatures">Advanced Features</a>.</p>
|
||||
|
||||
<p>Since assertions are <tt>IO</tt> computations, they may be combined--along with other
|
||||
<tt>IO</tt> computations--using <tt>(>>=)</tt>, <tt>(>>)</tt>, and the <tt>do</tt>
|
||||
notation. As long as its result is of type <tt>(IO ())</tt>, such a combination
|
||||
constitutes a single, collective assertion, incorporating any number of constituent
|
||||
assertions. The important features of such a collective assertion are that it fails if
|
||||
any of its constituent assertions is executed and fails, and that the first constituent
|
||||
assertion to fail terminates execution of the collective assertion. Such behavior is
|
||||
essential to specifying a test case.</p>
|
||||
|
||||
<h3 id="TestCase">Test Case</h3>
|
||||
|
||||
<p>A <b>test case</b> is the unit of test execution. That is, distinct test cases are
|
||||
executed independently. The failure of one is independent of the failure of any other.</p>
|
||||
|
||||
<p>A test case consists of a single, possibly collective, assertion. The possibly multiple
|
||||
constituent assertions in a test case's collective assertion are <b>not</b> independent.
|
||||
Their interdependence may be crucial to specifying correct operation for a test. A test
|
||||
case may involve a series of steps, each concluding in an assertion, where each step
|
||||
must succeed in order for the test case to continue. As another example, a test may
|
||||
require some "set up" to be performed that must be undone ("torn down" in JUnit
|
||||
parlance) once the test is complete. In this case, you could use Haskell's
|
||||
<tt>IO.bracket</tt> function to achieve the desired effect.</p>
|
||||
|
||||
<p>You can make a test case from an assertion by applying the <tt>TestCase</tt> constructor.
|
||||
For example, <tt>(TestCase (return ()))</tt> is a test case that never
|
||||
fails, and
|
||||
<tt>(TestCase (assertEqual "for x," 3 x))</tt>
|
||||
is a test case that checks that the value of <tt>x</tt> is 3. Additional ways
|
||||
to create test cases are described later under <a href="#AdvancedFeatures">Advanced
|
||||
Features</a>.</p>
|
||||
|
||||
<h3 id="Tests">Tests</h3>
|
||||
|
||||
<p>As soon as you have more than one test, you'll want to name them to tell them apart. As
|
||||
soon as you have more than several tests, you'll want to group them to process them more
|
||||
easily. So, naming and grouping are the two keys to managing collections of tests.</p>
|
||||
|
||||
<p>In tune with the "composite" design pattern [<a href="#DesignPatterns">1</a>], a
|
||||
<b>test</b> is defined as a package of test cases. Concretely, a test is either a single
|
||||
test case, a group of tests, or either of the first two identified by a label.</p>
|
||||
<pre>
|
||||
data Test = TestCase Assertion
|
||||
| TestList [Test]
|
||||
| TestLabel String Test
|
||||
</pre>
|
||||
<p>There are three important features of this definition to note:</p>
|
||||
<ul>
|
||||
<li>A <tt>TestList</tt> consists of a list of tests rather than a list of test cases.
|
||||
This means that the structure of a <tt>Test</tt> is actually a tree. Using a
|
||||
hierarchy helps organize tests just as it helps organize files in a file system.</li>
|
||||
<li>A <tt>TestLabel</tt> is attached to a test rather than to a test case. This means
|
||||
that all nodes in the test tree, not just test case (leaf) nodes, can be labeled.
|
||||
Hierarchical naming helps organize tests just as it helps organize files in a file
|
||||
system.</li>
|
||||
<li>A <tt>TestLabel</tt> is separate from both <tt>TestCase</tt> and <tt>TestList</tt>.
|
||||
This means that labeling is optional everywhere in the tree. Why is this a good
|
||||
thing? Because of the hierarchical structure of a test, each constituent test case
|
||||
is uniquely identified by its path in the tree, ignoring all labels. Sometimes a
|
||||
test case's path (or perhaps its subpath below a certain node) is a perfectly
|
||||
adequate "name" for the test case (perhaps relative to a certain node). In this
|
||||
case, creating a label for the test case is both unnecessary and inconvenient.</li>
|
||||
</ul>
|
||||
<p>The number of test cases that a test comprises can be computed with
|
||||
<tt>testCaseCount</tt>.</p>
|
||||
<pre>
|
||||
testCaseCount :: Test -> Int
|
||||
</pre>
|
||||
<p>As mentioned above, a test is identified by its <b>path</b> in the test hierarchy.</p>
|
||||
<pre>
|
||||
data Node = ListItem Int | Label String
|
||||
deriving (Eq, Show, Read)
|
||||
|
||||
type Path = [Node] -- Node order is from test case to root.
|
||||
</pre>
|
||||
<p>Each occurrence of <tt>TestList</tt> gives rise to a <tt>ListItem</tt> and each
|
||||
occurrence of <tt>TestLabel</tt> gives rise to a <tt>Label</tt>. The <tt>ListItem</tt>s
|
||||
by themselves ensure uniqueness among test case paths, while the <tt>Label</tt>s allow
|
||||
you to add mnemonic names for individual test cases and collections of them.</p>
|
||||
|
||||
<p>Note that the order of nodes in a path is reversed from what you might expect: The first
|
||||
node in the list is the one deepest in the tree. This order is a concession to
|
||||
efficiency: It allows common path prefixes to be shared.</p>
|
||||
|
||||
<p>The paths of the test cases that a test comprises can be computed with
|
||||
<tt>testCasePaths</tt>. The paths are listed in the order in which the corresponding
|
||||
test cases would be executed.</p>
|
||||
<pre>
|
||||
testCasePaths :: Test -> [Path]
|
||||
</pre>
|
||||
|
||||
<p>The three variants of <tt>Test</tt> can be constructed simply by applying
|
||||
<tt>TestCase</tt>, <tt>TestList</tt>, and <tt>TestLabel</tt> to appropriate arguments.
|
||||
Additional ways to create tests are described later under <a href="#AdvancedFeatures"
|
||||
>Advanced Features</a>.</p>
|
||||
|
||||
<p>The design of the type <tt>Test</tt> provides great conciseness, flexibility, and
|
||||
convenience in specifying tests. Moreover, the nature of Haskell significantly augments
|
||||
these qualities:</p>
|
||||
<ul>
|
||||
<li>Combining assertions and other code to construct test cases is easy with the
|
||||
<tt>IO</tt> monad.</li>
|
||||
<li>Using overloaded functions and special operators (see below), specification of
|
||||
assertions and tests is extremely compact.</li>
|
||||
<li>Structuring a test tree by value, rather than by name as in JUnit, provides for more
|
||||
convenient, flexible, and robust test suite specification. In particular, a test
|
||||
suite can more easily be computed "on the fly" than in other test frameworks.</li>
|
||||
<li>Haskell's powerful abstraction facilities provide unmatched support for test
|
||||
refactoring.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="AdvancedFeatures">Advanced Features</h3>
|
||||
|
||||
<p>HUnit provides additional features for specifying assertions and tests more conveniently
|
||||
and concisely. These facilities make use of Haskell type classes.</p>
|
||||
|
||||
<p>The following operators can be used to construct assertions.</p>
|
||||
<pre>
|
||||
infix 1 @?, @=?, @?=
|
||||
|
||||
(@?) :: (AssertionPredicable t) => t -> String -> Assertion
|
||||
pred @? msg = assertionPredicate pred >>= assertBool msg
|
||||
|
||||
(@=?) :: (Eq a, Show a) => a -> a -> Assertion
|
||||
expected @=? actual = assertEqual "" expected actual
|
||||
|
||||
(@?=) :: (Eq a, Show a) => a -> a -> Assertion
|
||||
actual @?= expected = assertEqual "" expected actual
|
||||
</pre>
|
||||
<p>You provide a boolean condition and failure message separately to <tt>(@?)</tt>, as for
|
||||
<tt>assertBool</tt>, but in a different order. The <tt>(@=?)</tt> and <tt>(@?=)</tt>
|
||||
operators provide shorthands for <tt>assertEqual</tt> when no preface is required. They
|
||||
differ only in the order in which the expected and actual values are provided. (The
|
||||
actual value--the uncertain one--goes on the "?" side of the operator.)</p>
|
||||
|
||||
<p>The <tt>(@?)</tt> operator's first argument is something from which an assertion
|
||||
predicate can be made, that is, its type must be <tt>AssertionPredicable</tt>.</p>
|
||||
<pre>
|
||||
type AssertionPredicate = IO Bool
|
||||
|
||||
class AssertionPredicable t
|
||||
where assertionPredicate :: t -> AssertionPredicate
|
||||
|
||||
instance AssertionPredicable Bool
|
||||
where assertionPredicate = return
|
||||
|
||||
instance (AssertionPredicable t) => AssertionPredicable (IO t)
|
||||
where assertionPredicate = (>>= assertionPredicate)
|
||||
</pre>
|
||||
<p>The overloaded <tt>assert</tt> function in the <tt>Assertable</tt> type class constructs
|
||||
an assertion.</p>
|
||||
<pre>
|
||||
class Assertable t
|
||||
where assert :: t -> Assertion
|
||||
|
||||
instance Assertable ()
|
||||
where assert = return
|
||||
|
||||
instance Assertable Bool
|
||||
where assert = assertBool ""
|
||||
|
||||
instance (ListAssertable t) => Assertable [t]
|
||||
where assert = listAssert
|
||||
|
||||
instance (Assertable t) => Assertable (IO t)
|
||||
where assert = (>>= assert)
|
||||
</pre>
|
||||
<p>The <tt>ListAssertable</tt> class allows <tt>assert</tt> to be applied to <tt>[Char]</tt>
|
||||
(that is, <tt>String</tt>).</p>
|
||||
<pre>
|
||||
class ListAssertable t
|
||||
where listAssert :: [t] -> Assertion
|
||||
|
||||
instance ListAssertable Char
|
||||
where listAssert = assertString
|
||||
</pre>
|
||||
<p>With the above declarations, <tt>(assert ())</tt>,
|
||||
<tt>(assert True)</tt>, and <tt>(assert "")</tt> (as well as
|
||||
<tt>IO</tt> forms of these values, such as <tt>(return ())</tt>) are all
|
||||
assertions that never fail, while <tt>(assert False)</tt> and
|
||||
<tt>(assert "some failure message")</tt> (and their
|
||||
<tt>IO</tt> forms) are assertions that always fail. You may define additional
|
||||
instances for the type classes <tt>Assertable</tt>, <tt>ListAssertable</tt>, and
|
||||
<tt>AssertionPredicable</tt> if that should be useful in your application.</p>
|
||||
|
||||
<p>The overloaded <tt>test</tt> function in the <tt>Testable</tt> type class constructs a
|
||||
test.</p>
|
||||
<pre>
|
||||
class Testable t
|
||||
where test :: t -> Test
|
||||
|
||||
instance Testable Test
|
||||
where test = id
|
||||
|
||||
instance (Assertable t) => Testable (IO t)
|
||||
where test = TestCase . assert
|
||||
|
||||
instance (Testable t) => Testable [t]
|
||||
where test = TestList . map test
|
||||
</pre>
|
||||
<p>The <tt>test</tt> function makes a test from either an <tt>Assertion</tt> (using
|
||||
<tt>TestCase</tt>), a list of <tt>Testable</tt> items (using <tt>TestList</tt>), or
|
||||
a <tt>Test</tt> (making no change).</p>
|
||||
|
||||
<p>The following operators can be used to construct tests.</p>
|
||||
<pre>
|
||||
infix 1 ~?, ~=?, ~?=
|
||||
infixr 0 ~:
|
||||
|
||||
(~?) :: (AssertionPredicable t) => t -> String -> Test
|
||||
pred ~? msg = TestCase (pred @? msg)
|
||||
|
||||
(~=?) :: (Eq a, Show a) => a -> a -> Test
|
||||
expected ~=? actual = TestCase (expected @=? actual)
|
||||
|
||||
(~?=) :: (Eq a, Show a) => a -> a -> Test
|
||||
actual ~?= expected = TestCase (actual @?= expected)
|
||||
|
||||
(~:) :: (Testable t) => String -> t -> Test
|
||||
label ~: t = TestLabel label (test t)
|
||||
</pre>
|
||||
<p><tt>(~?)</tt>, <tt>(~=?)</tt>, and <tt>(~?=)</tt> each make an assertion, as for
|
||||
<tt>(@?)</tt>, <tt>(@=?)</tt>, and <tt>(@?=)</tt>, respectively, and then a test case
|
||||
from that assertion. <tt>(~:)</tt> attaches a label to something that is
|
||||
<tt>Testable</tt>. You may define additional instances for the type class
|
||||
<tt>Testable</tt> should that be useful.</p>
|
||||
|
||||
<h2 id="RunningTests">Running Tests</h2>
|
||||
|
||||
<p>HUnit is structured to support multiple test controllers. The first subsection below
|
||||
describes the <a href="#TestExecution">test execution</a> characteristics common to all
|
||||
test controllers. The second subsection describes the <a href="#Text-BasedController"
|
||||
>text-based controller</a> that is included with HUnit.</p>
|
||||
|
||||
<h3 id="TestExecution">Test Execution</h3>
|
||||
|
||||
<p>All test controllers share a common test execution model. They differ only in how the
|
||||
results of test execution are shown.</p>
|
||||
|
||||
<p>The execution of a test (a value of type <tt>Test</tt>) involves the serial execution (in
|
||||
the <tt>IO</tt> monad) of its constituent test cases. The test cases are executed in a
|
||||
depth-first, left-to-right order. During test execution, four counts of test cases are
|
||||
maintained:</p>
|
||||
<pre>
|
||||
data Counts = Counts { cases, tried, errors, failures :: Int }
|
||||
deriving (Eq, Show, Read)
|
||||
</pre>
|
||||
<ul>
|
||||
<li><tt>cases</tt> is the number of test cases included in the test. This number is a
|
||||
static property of a test and remains unchanged during test execution.</li>
|
||||
<li><tt>tried</tt> is the number of test cases that have been executed so far during the
|
||||
test execution.</li>
|
||||
<li><tt>errors</tt> is the number of test cases whose execution ended with an unexpected
|
||||
exception being raised. Errors indicate problems with test cases, as opposed to the
|
||||
code under test.</li>
|
||||
<li><tt>failures</tt> is the number of test cases whose execution asserted failure.
|
||||
Failures indicate problems with the code under test.</li>
|
||||
</ul>
|
||||
<p>Why is there no count for test case successes? The technical reason is that the counts
|
||||
are maintained such that the number of test case successes is always equal to
|
||||
<tt>(tried - (errors + failures))</tt>. The
|
||||
psychosocial reason is that, with test-centered development and the expectation that
|
||||
test failures will be few and short-lived, attention should be focused on the failures
|
||||
rather than the successes.</p>
|
||||
|
||||
<p>As test execution proceeds, three kinds of reporting event are communicated to the test
|
||||
controller. (What the controller does in response to the reporting events depends on the
|
||||
controller.)</p>
|
||||
<ul>
|
||||
<li><i>start</i> -- Just prior to initiation of a test case, the path of the test case
|
||||
and the current counts (excluding the current test case) are reported.</li>
|
||||
<li><i>error</i> -- When a test case terminates with an error, the error message is
|
||||
reported, along with the test case path and current counts (including the current
|
||||
test case).</li>
|
||||
<li><i>failure</i> -- When a test case terminates with a failure, the failure message is
|
||||
reported, along with the test case path and current counts (including the current
|
||||
test case).</li>
|
||||
</ul>
|
||||
<p>Typically, a test controller shows <i>error</i> and <i>failure</i> reports immediately
|
||||
but uses the <i>start</i> report merely to update an indication of overall test
|
||||
execution progress.</p>
|
||||
|
||||
<h3 id="Text-BasedController">Text-Based Controller</h3>
|
||||
|
||||
<p>A text-based test controller is included with HUnit.</p>
|
||||
<pre>
|
||||
runTestText :: PutText st -> Test -> IO (Counts, st)
|
||||
</pre>
|
||||
<p><tt>runTestText</tt> is generalized on a <i>reporting scheme</i> given as its first
|
||||
argument. During execution of the test given as its second argument, the controller
|
||||
creates a string for each reporting event and processes it according to the reporting
|
||||
scheme. When test execution is complete, the controller returns the final counts along
|
||||
with the final state for the reporting scheme.</p>
|
||||
|
||||
<p>The strings for the three kinds of reporting event are as follows.</p>
|
||||
<ul>
|
||||
<li>A <i>start</i> report is the result of the function <tt>showCounts</tt> applied to
|
||||
the counts current immediately prior to initiation of the test case being started.</li>
|
||||
<li>An <i>error</i> report is of the form
|
||||
"<tt>Error in: <i>path</i>\n<i>message</i></tt>",
|
||||
where <i>path</i> is the path of the test case in error, as shown by
|
||||
<tt>showPath</tt>, and <i>message</i> is a message describing the error. If the path
|
||||
is empty, the report has the form "<tt>Error:\n<i>message</i></tt>".</li>
|
||||
<li>A <i>failure</i> report is of the form
|
||||
"<tt>Failure in: <i>path</i>\n<i>message</i></tt>", where
|
||||
<i>path</i> is the path of the test case in error, as shown by
|
||||
<tt>showPath</tt>, and <i>message</i> is the failure message. If the path is empty,
|
||||
the report has the form "<tt>Failure:\n<i>message</i></tt>".</li>
|
||||
</ul>
|
||||
|
||||
<p>The function <tt>showCounts</tt> shows a set of counts.</p>
|
||||
<pre>
|
||||
showCounts :: Counts -> String
|
||||
</pre>
|
||||
<p>The form of its result is
|
||||
"<tt>Cases: <i>cases</i> Tried: <i>tried</i> Errors: <i>errors</i> Failures: <i>failures</i></tt>"
|
||||
where <i>cases</i>, <i>tried</i>, <i>errors</i>, and <i>failures</i> are the count
|
||||
values.</p>
|
||||
|
||||
<p>The function <tt>showPath</tt> shows a test case path.</p>
|
||||
<pre>
|
||||
showPath :: Path -> String
|
||||
</pre>
|
||||
<p>The nodes in the path are reversed (so that the path reads from the root down to the test
|
||||
case), and the representations for the nodes are joined by '<tt>:</tt>' separators. The
|
||||
representation for <tt>(ListItem <i>n</i>)</tt> is <tt>(show n)</tt>. The representation
|
||||
for <tt>(Label <i>label</i>)</tt> is normally <i>label</i>. However, if <i>label</i>
|
||||
contains a colon or if <tt>(show <i>label</i>)</tt> is different from <i>label</i>
|
||||
surrounded by quotation marks--that is, if any ambiguity could exist--then <tt>(Label
|
||||
<i>label</i>)</tt> is represented as <tt>(show <i>label</i>)</tt>.</p>
|
||||
|
||||
<p>HUnit includes two reporting schemes for the text-based test controller. You may define
|
||||
others if you wish.</p>
|
||||
<pre>
|
||||
putTextToHandle :: Handle -> Bool -> PutText Int
|
||||
</pre>
|
||||
<p><tt>putTextToHandle</tt> writes error and failure reports, plus a report of the final
|
||||
counts, to the given handle. Each of these reports is terminated by a newline. In
|
||||
addition, if the given flag is <tt>True</tt>, it writes start reports to the handle as
|
||||
well. A start report, however, is not terminated by a newline. Before the next report is
|
||||
written, the start report is "erased" with an appropriate sequence of carriage return
|
||||
and space characters. Such overwriting realizes its intended effect on terminal devices.</p>
|
||||
<pre>
|
||||
putTextToShowS :: PutText ShowS
|
||||
</pre>
|
||||
<p><tt>putTextToShowS</tt> ignores start reports and simply accumulates error and failure
|
||||
reports, terminating them with newlines. The accumulated reports are returned (as the
|
||||
second element of the pair returned by <tt>runTestText</tt>) as a <tt>ShowS</tt>
|
||||
function (that is, one with type <tt>(String -> String)</tt>) whose
|
||||
first argument is a string to be appended to the accumulated report lines.</p>
|
||||
|
||||
<p>HUnit provides a shorthand for the most common use of the text-based test controller.</p>
|
||||
<pre>
|
||||
runTestTT :: Test -> IO Counts
|
||||
</pre>
|
||||
<p><tt>runTestTT</tt> invokes <tt>runTestText</tt>, specifying <tt>(putTextToHandle stderr
|
||||
True)</tt> for the reporting scheme, and returns the final counts from the test
|
||||
execution.</p>
|
||||
|
||||
|
||||
<h2 id="References">References</h2>
|
||||
|
||||
<dl>
|
||||
|
||||
<dt id="DesignPatterns">[1] Gamma, E., et al. Design Patterns: Elements of Reusable
|
||||
Object-Oriented Software, Addison-Wesley, Reading, MA, 1995.</dt>
|
||||
<dd>The classic book describing design patterns in an object-oriented context.</dd>
|
||||
|
||||
<dt>
|
||||
<a href="http://www.junit.org">http://www.junit.org</a>
|
||||
</dt>
|
||||
<dd>Web page for JUnit, the tool after which HUnit is modeled.</dd>
|
||||
|
||||
<dt>
|
||||
<a href="http://junit.sourceforge.net/doc/testinfected/testing.htm">
|
||||
http://junit.sourceforge.net/doc/testinfected/testing.htm</a>
|
||||
</dt>
|
||||
<dd>A good introduction to test-first development and the use of JUnit.</dd>
|
||||
|
||||
<dt>
|
||||
<a href="http://junit.sourceforge.net/doc/cookstour/cookstour.htm">
|
||||
http://junit.sourceforge.net/doc/cookstour/cookstour.htm</a>
|
||||
</dt>
|
||||
<dd>A description of the internal structure of JUnit. Makes for an interesting
|
||||
comparison between JUnit and HUnit.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p>The HUnit software and this guide were written by Dean Herington (<a
|
||||
href="mailto:heringto@cs.unc.edu">heringto@cs.unc.edu</a>).</p>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user