1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
<html xmlns="http://www.w3.org/1999/xhtml">
4
<title>Chapter 14. Behaviour-Driven Development</title>
5
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
<link rel="stylesheet" href="docbook.css" type="text/css"></link>
11
<h1>PHPUnit Manual</h1>
14
<li><a href="index.html" class="active">PHPUnit 3.4 <span><small>English</small></span></a></li><li><a href="http://www.phpunit.de/manual/3.3/en/index.html">PHPUnit 3.3 <span><small>English</small></span></a></li><li><a href="http://www.phpunit.de/manual/3.4/ja/index.html">PHPUnit 3.4 <span><small>Japanese</small></span></a></li><li><a href="http://www.phpunit.de/manual/3.3/ja/index.html">PHPUnit 3.3 <span><small>Japanese</small></span></a></li>
17
<div class="colmask leftmenu">
20
<table border="0" width="100%">
22
<td align="left"><a accesskey="p" href="test-driven-development.html">Prev</a></td>
23
<td align="right"><a accesskey="n" href="code-coverage-analysis.html">Next</a></td>
26
<div class="chapter" title="Chapter 14. Behaviour-Driven Development"><div class="titlepage"><div><div><h2 class="title"><a id="behaviour-driven-development"></a>Chapter 14. Behaviour-Driven Development</h2></div></div></div><p>
27
<a id="id2569236" class="indexterm"></a>
28
<a id="id2569165" class="indexterm"></a>
30
In <a class="xref" href="appendixes.bibliography.html#Astels2006" title="A New Look at Test-Driven Development">[<abbr class="abbrev">Astels2006</abbr>]</a>, Dave Astels makes the following points:
31
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
32
<a class="ulink" href="http://en.wikipedia.org/wiki/Extreme_Programming" target="_top">Extreme Programming</a>
33
originally had the rule to test everything that could possibly break.
34
</p></li><li class="listitem"><p>
35
Now, however, the practice of testing in Extreme Programming has evolved
36
into <a class="ulink" href="http://en.wikipedia.org/wiki/Test-driven_development" target="_top">Test-Driven Development</a>
37
(see <a class="xref" href="test-driven-development.html" title="Chapter 13. Test-Driven Development">Chapter 13</a>).
38
</p></li><li class="listitem"><p>
39
But the tools still force developers to think in terms of tests and
40
assertions instead of specifications.
41
</p></li></ul></div><div class="blockquote" title="So if it's not about testing, what's it about?"><table border="0" width="100%" cellspacing="0" cellpadding="0" class="blockquote" summary="Block quote"><tr><td width="10%" valign="top"> </td><td width="80%" valign="top"><div class="blockquote-title"><p><b>So if it's not about testing, what's it about?</b></p></div><p>
42
It's about figuring out what you are trying to do before you run off
43
half-cocked to try to do it. You write a specification that nails down a
44
small aspect of behaviour in a concise, unambiguous, and executable form.
45
It's that simple. Does that mean you write tests? No. It means you write
46
specifications of what your code will have to do. It means you specify the
47
behaviour of your code ahead of time. But not far ahead of time. In fact,
48
just before you write the code is best because that's when you have as
49
much information at hand as you will up to that point. Like well done TDD,
50
you work in tiny increments... specifying one small aspect of behaviour at
51
a time, then implementing it.
53
When you realize that it's all about specifying behaviour and not writing
54
tests, your point of view shifts. Suddenly the idea of having a Test class
55
for each of your production classes is ridiculously limiting. And the
56
thought of testing each of your methods with its own test method (in a 1-1
57
relationship) will be laughable.
58
</p></td><td width="10%" valign="top"> </td></tr><tr><td width="10%" valign="top"> </td><td colspan="2" align="right" valign="top">--<span class="attribution">Dave Astels</span></td></tr></table></div><p>
59
<a id="id2570321" class="indexterm"></a>
60
<a id="id2570328" class="indexterm"></a>
62
The focus of <a class="ulink" href="http://en.wikipedia.org/wiki/Behavior_driven_development" target="_top">Behaviour-Driven Development</a>
63
is "the language and interactions used in the process of software development.
64
Behavior-driven developers use their native language in combination with the
65
ubiquitous language of <a class="ulink" href="http://en.wikipedia.org/wiki/Domain_driven_design" target="_top">Domain-Driven Design</a>
66
to describe the purpose and benefit of their code. This allows the developers
67
to focus on why the code should be created, rather than the technical details,
68
and minimizes translation between the technical language in which the code
69
is written and the domain language spoken by the" domain experts.
71
<a id="id2570360" class="indexterm"></a>
73
The <code class="literal">PHPUnit_Extensions_Story_TestCase</code> class adds a story
74
framework that faciliates the definition of a
75
<a class="ulink" href="http://en.wikipedia.org/wiki/Domain-specific_programming_language" target="_top">Domain-Specific Language</a>
76
for Behaviour-Driven Development. Inside a <span class="emphasis"><em>scenario</em></span>,
77
<code class="literal">given()</code>, <code class="literal">when()</code>, and
78
<code class="literal">then()</code> each represent a <span class="emphasis"><em>step</em></span>.
79
<code class="literal">and()</code> is the same kind as the previous step. The following
80
methods are declared <code class="literal">abstract</code> in
81
<code class="literal">PHPUnit_Extensions_Story_TestCase</code> and need to be
83
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">runGiven(&$world, $action, $arguments)</code></p><p>...</p></li><li class="listitem"><p><code class="literal">runWhen(&$world, $action, $arguments)</code></p><p>...</p></li><li class="listitem"><p><code class="literal">runThen(&$world, $action, $arguments)</code></p><p>...</p></li></ul></div><div class="section" title="BowlingGame Example"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="behaviour-driven-development.bowlinggame-example"></a>BowlingGame Example</h2></div></div></div><p>
84
In this section, we will look at the example of a class that calculates
85
the score for a game of bowling. The rules for this are as follows:
86
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>The game consists of 10 frames.</p></li><li class="listitem"><p>In each frame the player has two opportunities to knock down 10 pins.</p></li><li class="listitem"><p>The score for a frame is the total number of pins knocked down, plus bonuses for strikes and spares.</p></li><li class="listitem"><p>A spare is when the player knocks down all 10 pins in two tries.</p><p>The bonus for that frame is the number of pins knocked down by the next roll.</p></li><li class="listitem"><p>A strike is when the player knocks down all 10 pins on his first try.</p><p>The bonus for that frame is the value of the next two balls rolled.</p></li></ul></div><p>
87
<a class="xref" href="behaviour-driven-development.html#behaviour-driven-development.bowlinggame-example.examples.BowlingGameSpec.php" title="Example 14.1: Specification for the BowlingGame class">Example 14.1</a>
88
shows how the above rules can be written down as specification scenarios
89
using <code class="literal">PHPUnit_Extensions_Story_TestCase</code>.
90
</p><div class="example"><a id="behaviour-driven-development.bowlinggame-example.examples.BowlingGameSpec.php"></a><p class="title"><b>Example 14.1: Specification for the BowlingGame class</b></p><div class="example-contents"><pre class="programlisting"><code><span class="default"><?php</span><br /><span class="keyword">require_once</span><span class="default"> </span><span class="string">'PHPUnit/Extensions/Story/TestCase.php'</span><span class="keyword">;</span><br /><span class="keyword">require_once</span><span class="default"> </span><span class="string">'BowlingGame.php'</span><span class="keyword">;</span><br /><span class="default"> </span><br /><span class="keyword">class</span><span class="default"> </span><span class="default">BowlingGameSpec</span><span class="default"> </span><span class="keyword">extends</span><span class="default"> </span><span class="default">PHPUnit_Extensions_Story_TestCase</span><br /><span class="keyword">{</span><br /><span class="default"> </span><span class="comment">/**</span><br /><span class="comment"> * @scenario</span><br /><span class="comment"> */</span><br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">scoreForGutterGameIs0</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">given</span><span class="keyword">(</span><span class="string">'New game'</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">then</span><span class="keyword">(</span><span class="string">'Score should be'</span><span class="keyword">,</span><span class="default"> </span><span class="default">0</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="comment">/**</span><br /><span class="comment"> * @scenario</span><br /><span class="comment"> */</span><br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">scoreForAllOnesIs20</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">given</span><span class="keyword">(</span><span class="string">'New game'</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">when</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">1</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">then</span><span class="keyword">(</span><span class="string">'Score should be'</span><span class="keyword">,</span><span class="default"> </span><span class="default">20</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="comment">/**</span><br /><span class="comment"> * @scenario</span><br /><span class="comment"> */</span><br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">scoreForOneSpareAnd3Is16</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">given</span><span class="keyword">(</span><span class="string">'New game'</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">when</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">5</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">5</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">3</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">then</span><span class="keyword">(</span><span class="string">'Score should be'</span><span class="keyword">,</span><span class="default"> </span><span class="default">16</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="comment">/**</span><br /><span class="comment"> * @scenario</span><br /><span class="comment"> */</span><br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">scoreForOneStrikeAnd3And4Is24</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">given</span><span class="keyword">(</span><span class="string">'New game'</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">when</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">3</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">4</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">then</span><span class="keyword">(</span><span class="string">'Score should be'</span><span class="keyword">,</span><span class="default"> </span><span class="default">24</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="comment">/**</span><br /><span class="comment"> * @scenario</span><br /><span class="comment"> */</span><br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">scoreForPerfectGameIs300</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">given</span><span class="keyword">(</span><span class="string">'New game'</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">when</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">and</span><span class="keyword">(</span><span class="string">'Player rolls'</span><span class="keyword">,</span><span class="default"> </span><span class="default">10</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">-></span><span class="default">then</span><span class="keyword">(</span><span class="string">'Score should be'</span><span class="keyword">,</span><span class="default"> </span><span class="default">300</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">runGiven</span><span class="keyword">(</span><span class="keyword">&</span><span class="default">$world</span><span class="keyword">,</span><span class="default"> </span><span class="default">$action</span><span class="keyword">,</span><span class="default"> </span><span class="default">$arguments</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">switch</span><span class="keyword">(</span><span class="default">$action</span><span class="keyword">)</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="keyword">case</span><span class="default"> </span><span class="string">'New game'</span><span class="keyword">:</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'game'</span><span class="keyword">]</span><span class="default"> </span><span class="keyword">=</span><span class="default"> </span><span class="keyword">new</span><span class="default"> </span><span class="default">BowlingGame</span><span class="keyword">;</span><br /><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'rolls'</span><span class="keyword">]</span><span class="default"> </span><span class="keyword">=</span><span class="default"> </span><span class="default">0</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">break</span><span class="keyword">;</span><br /><span class="default"> </span><br /><span class="default"> </span><span class="keyword">default</span><span class="keyword">:</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="keyword">return</span><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">notImplemented</span><span class="keyword">(</span><span class="default">$action</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">runWhen</span><span class="keyword">(</span><span class="keyword">&</span><span class="default">$world</span><span class="keyword">,</span><span class="default"> </span><span class="default">$action</span><span class="keyword">,</span><span class="default"> </span><span class="default">$arguments</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">switch</span><span class="keyword">(</span><span class="default">$action</span><span class="keyword">)</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="keyword">case</span><span class="default"> </span><span class="string">'Player rolls'</span><span class="keyword">:</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'game'</span><span class="keyword">]</span><span class="keyword">-></span><span class="default">roll</span><span class="keyword">(</span><span class="default">$arguments</span><span class="keyword">[</span><span class="default">0</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'rolls'</span><span class="keyword">]</span><span class="keyword">++</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">break</span><span class="keyword">;</span><br /><span class="default"> </span><br /><span class="default"> </span><span class="keyword">default</span><span class="keyword">:</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="keyword">return</span><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">notImplemented</span><span class="keyword">(</span><span class="default">$action</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">}</span><br /> <br /><span class="default"> </span><span class="keyword">public</span><span class="default"> </span><span class="keyword">function</span><span class="default"> </span><span class="default">runThen</span><span class="keyword">(</span><span class="keyword">&</span><span class="default">$world</span><span class="keyword">,</span><span class="default"> </span><span class="default">$action</span><span class="keyword">,</span><span class="default"> </span><span class="default">$arguments</span><span class="keyword">)</span><br /><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">switch</span><span class="keyword">(</span><span class="default">$action</span><span class="keyword">)</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="keyword">case</span><span class="default"> </span><span class="string">'Score should be'</span><span class="keyword">:</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">for</span><span class="default"> </span><span class="keyword">(</span><span class="default">$i</span><span class="default"> </span><span class="keyword">=</span><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'rolls'</span><span class="keyword">]</span><span class="keyword">;</span><span class="default"> </span><span class="default">$i</span><span class="default"> </span><span class="keyword"><</span><span class="default"> </span><span class="default">20</span><span class="keyword">;</span><span class="default"> </span><span class="default">$i</span><span class="keyword">++</span><span class="keyword">)</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'game'</span><span class="keyword">]</span><span class="keyword">-></span><span class="default">roll</span><span class="keyword">(</span><span class="default">0</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><br /><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">assertEquals</span><span class="keyword">(</span><span class="default">$arguments</span><span class="keyword">[</span><span class="default">0</span><span class="keyword">]</span><span class="keyword">,</span><span class="default"> </span><span class="default">$world</span><span class="keyword">[</span><span class="string">'game'</span><span class="keyword">]</span><span class="keyword">-></span><span class="default">score</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">break</span><span class="keyword">;</span><br /><span class="default"> </span><br /><span class="default"> </span><span class="keyword">default</span><span class="keyword">:</span><span class="default"> </span><span class="keyword">{</span><br /><span class="default"> </span><span class="keyword">return</span><span class="default"> </span><span class="default">$this</span><span class="keyword">-></span><span class="default">notImplemented</span><span class="keyword">(</span><span class="default">$action</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="default"> </span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?></span><br /></code></pre><pre class="screen"><strong class="userinput"><code>phpunit --story BowlingGameSpec</code></strong>
91
PHPUnit 3.4.2 by Sebastian Bergmann.
94
[x] Score for gutter game is 0
97
Then Score should be 0
99
[x] Score for all ones is 20
122
Then Score should be 20
124
[x] Score for one spare and 3 is 16
130
Then Score should be 16
132
[x] Score for one strike and 3 and 4 is 24
138
Then Score should be 24
140
[x] Score for perfect game is 300
155
Then Score should be 300
157
Scenarios: 5, Failed: 0, Skipped: 0, Incomplete: 0.</pre></div></div><br class="example-break"></br></div></div>
158
<table border="0" width="100%">
160
<td align="left"><a accesskey="p" href="test-driven-development.html">Prev</a></td>
161
<td align="right"><a accesskey="n" href="code-coverage-analysis.html">Next</a></td>
166
<dl><dt><span class="chapter"><a href="automating-tests.html">1. Automating Tests</a></span></dt><dt><span class="chapter"><a href="goals.html">2. PHPUnit's Goals</a></span></dt><dt><span class="chapter"><a href="installation.html">3. Installing PHPUnit</a></span></dt><dt><span class="chapter"><a href="writing-tests-for-phpunit.html">4. Writing Tests for PHPUnit</a></span></dt><dd><dl><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.test-dependencies">Test Dependencies</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers">Data Providers</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.exceptions">Testing Exceptions</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.errors">Testing PHP Errors</a></span></dt></dl></dd><dt><span class="chapter"><a href="textui.html">5. The Command-Line Test Runner</a></span></dt><dt><span class="chapter"><a href="fixtures.html">6. Fixtures</a></span></dt><dd><dl><dt><span class="section"><a href="fixtures.html#fixtures.more-setup-than-teardown">More setUp() than tearDown()</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.variations">Variations</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.sharing-fixture">Sharing Fixture</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.global-state">Global State</a></span></dt></dl></dd><dt><span class="chapter"><a href="organizing-tests.html">7. Organizing Tests</a></span></dt><dd><dl><dt><span class="section"><a href="organizing-tests.html#organizing-tests.filesystem">Composing a Test Suite Using the Filesystem</a></span></dt><dt><span class="section"><a href="organizing-tests.html#organizing-tests.xml-configuration">Composing a Test Suite Using XML Configuration</a></span></dt><dt><span class="section"><a href="organizing-tests.html#organizing-tests.testsuite">Using the TestSuite Class</a></span></dt></dl></dd><dt><span class="chapter"><a href="testcase-extensions.html">8. TestCase Extensions</a></span></dt><dd><dl><dt><span class="section"><a href="testcase-extensions.html#testcase-extensions.output">Testing Output</a></span></dt></dl></dd><dt><span class="chapter"><a href="database.html">9. Database Testing</a></span></dt><dd><dl><dt><span class="section"><a href="database.html#database.datasets">Data Sets</a></span></dt><dd><dl><dt><span class="section"><a href="database.html#database.datasets.flatxml">Flat XML Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.xml">XML Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.csv">CSV Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.replacement">Replacement Data Set</a></span></dt></dl></dd><dt><span class="section"><a href="database.html#database.operations">Operations</a></span></dt><dt><span class="section"><a href="database.html#database.bestpractices">Database Testing Best Practices</a></span></dt></dl></dd><dt><span class="chapter"><a href="incomplete-and-skipped-tests.html">10. Incomplete and Skipped Tests</a></span></dt><dd><dl><dt><span class="section"><a href="incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.incomplete-tests">Incomplete Tests</a></span></dt><dt><span class="section"><a href="incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.skipping-tests">Skipping Tests</a></span></dt></dl></dd><dt><span class="chapter"><a href="test-doubles.html">11. Test Doubles</a></span></dt><dd><dl><dt><span class="section"><a href="test-doubles.html#test-doubles.stubs">Stubs</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.mock-objects">Mock Objects</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.stubbing-and-mocking-web-services">Stubbing and Mocking Web Services</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.mocking-the-filesystem">Mocking the Filesystem</a></span></dt></dl></dd><dt><span class="chapter"><a href="testing-practices.html">12. Testing Practices</a></span></dt><dd><dl><dt><span class="section"><a href="testing-practices.html#testing-practices.during-development">During Development</a></span></dt><dt><span class="section"><a href="testing-practices.html#testing-practices.during-debugging">During Debugging</a></span></dt></dl></dd><dt><span class="chapter"><a href="test-driven-development.html">13. Test-Driven Development</a></span></dt><dd><dl><dt><span class="section"><a href="test-driven-development.html#test-driven-development.bankaccount-example">BankAccount Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="behaviour-driven-development.html" class="active">14. Behaviour-Driven Development</a></span></dt><dd><dl><dt><span class="section"><a href="behaviour-driven-development.html#behaviour-driven-development.bowlinggame-example">BowlingGame Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="code-coverage-analysis.html">15. Code Coverage Analysis</a></span></dt><dd><dl><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.specifying-covered-methods">Specifying Covered Methods</a></span></dt><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.ignoring-code-blocks">Ignoring Code Blocks</a></span></dt><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.including-excluding-files">Including and Excluding Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="other-uses-for-tests.html">16. Other Uses for Tests</a></span></dt><dd><dl><dt><span class="section"><a href="other-uses-for-tests.html#other-uses-for-tests.agile-documentation">Agile Documentation</a></span></dt><dt><span class="section"><a href="other-uses-for-tests.html#other-uses-for-tests.cross-team-tests">Cross-Team Tests</a></span></dt></dl></dd><dt><span class="chapter"><a href="skeleton-generator.html">17. Skeleton Generator</a></span></dt><dd><dl><dt><span class="section"><a href="skeleton-generator.html#skeleton-generator.test">Generating a Test Case Class Skeleton</a></span></dt><dt><span class="section"><a href="skeleton-generator.html#skeleton-generator.class">Generating a Class Skeleton from a Test Case Class</a></span></dt></dl></dd><dt><span class="chapter"><a href="selenium.html">18. PHPUnit and Selenium</a></span></dt><dd><dl><dt><span class="section"><a href="selenium.html#selenium.selenium-rc">Selenium RC</a></span></dt><dt><span class="section"><a href="selenium.html#selenium.seleniumtestcase">PHPUnit_Extensions_SeleniumTestCase</a></span></dt></dl></dd><dt><span class="chapter"><a href="logging.html">19. Logging</a></span></dt><dd><dl><dt><span class="section"><a href="logging.html#logging.xml">Test Results (XML)</a></span></dt><dt><span class="section"><a href="logging.html#logging.tap">Test Results (TAP)</a></span></dt><dt><span class="section"><a href="logging.html#logging.json">Test Results (JSON)</a></span></dt><dt><span class="section"><a href="logging.html#logging.codecoverage">Code Coverage (XML)</a></span></dt></dl></dd><dt><span class="chapter"><a href="build-automation.html">20. Build Automation</a></span></dt><dd><dl><dt><span class="section"><a href="build-automation.html#build-automation.ant">Apache Ant</a></span></dt><dt><span class="section"><a href="build-automation.html#build-automation.maven">Apache Maven</a></span></dt><dt><span class="section"><a href="build-automation.html#build-automation.phing">Phing</a></span></dt></dl></dd><dt><span class="chapter"><a href="continuous-integration.html">21. Continuous Integration</a></span></dt><dd><dl><dt><span class="section"><a href="continuous-integration.html#continuous-integration.atlassian-bamboo">Atlassian Bamboo</a></span></dt><dt><span class="section"><a href="continuous-integration.html#continuous-integration.cruisecontrol">CruiseControl</a></span></dt><dt><span class="section"><a href="continuous-integration.html#continuous-integration.phpUnderControl">phpUnderControl</a></span></dt></dl></dd><dt><span class="chapter"><a href="api.html">22. PHPUnit API</a></span></dt><dd><dl><dt><span class="section"><a href="api.html#api.overview">Overview</a></span></dt><dt><span class="section"><a href="api.html#api.assert">PHPUnit_Framework_Assert</a></span></dt><dd><dl><dt><span class="section"><a href="api.html#api.assert.assertArrayHasKey"><code class="literal">assertArrayHasKey()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertClassHasAttribute"><code class="literal">assertClassHasAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertClassHasStaticAttribute"><code class="literal">assertClassHasStaticAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertContains"><code class="literal">assertContains()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertContainsOnly"><code class="literal">assertContainsOnly()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertEqualXMLStructure"><code class="literal">assertEqualXMLStructure()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertEquals"><code class="literal">assertEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFalse"><code class="literal">assertFalse()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFileEquals"><code class="literal">assertFileEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFileExists"><code class="literal">assertFileExists()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertGreaterThan"><code class="literal">assertGreaterThan()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertGreaterThanOrEqual"><code class="literal">assertGreaterThanOrEqual()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertLessThan"><code class="literal">assertLessThan()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertLessThanOrEqual"><code class="literal">assertLessThanOrEqual()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertNull"><code class="literal">assertNull()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertObjectHasAttribute"><code class="literal">assertObjectHasAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertRegExp"><code class="literal">assertRegExp()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSame"><code class="literal">assertSame()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectCount"><code class="literal">assertSelectCount()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectEquals"><code class="literal">assertSelectEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectRegExp"><code class="literal">assertSelectRegExp()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertStringEndsWith"><code class="literal">assertStringEndsWith()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertStringEqualsFile"><code class="literal">assertStringEqualsFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertStringStartsWith"><code class="literal">assertStringStartsWith()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertTag"><code class="literal">assertTag()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertThat"><code class="literal">assertThat()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertTrue"><code class="literal">assertTrue()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertType"><code class="literal">assertType()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlFileEqualsXmlFile"><code class="literal">assertXmlFileEqualsXmlFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlStringEqualsXmlFile"><code class="literal">assertXmlStringEqualsXmlFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlStringEqualsXmlString"><code class="literal">assertXmlStringEqualsXmlString()</code></a></span></dt></dl></dd><dt><span class="section"><a href="api.html#api.test">PHPUnit_Framework_Test</a></span></dt><dt><span class="section"><a href="api.html#api.testcase">PHPUnit_Framework_TestCase</a></span></dt><dt><span class="section"><a href="api.html#api.testsuite">PHPUnit_Framework_TestSuite</a></span></dt><dt><span class="section"><a href="api.html#api.testresult">PHPUnit_Framework_TestResult</a></span></dt><dt><span class="section"><a href="api.html#api.package-structure">Package Structure</a></span></dt></dl></dd><dt><span class="chapter"><a href="extending-phpunit.html">23. Extending PHPUnit</a></span></dt><dd><dl><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestCase">Subclass PHPUnit_Framework_TestCase</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.Assert">Assert Classes</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Extensions_TestDecorator">Subclass PHPUnit_Extensions_TestDecorator</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_Test">Implement PHPUnit_Framework_Test</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestResult">Subclass PHPUnit_Framework_TestResult</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener">Implement PHPUnit_Framework_TestListener</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.TestRunner">New Test Runner</a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.assertions.html">A. Assertions</a></span></dt><dt><span class="appendix"><a href="appendixes.annotations.html">B. Annotations</a></span></dt><dd><dl><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.assert"><code class="literal">@assert</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.backupGlobals"><code class="literal">@backupGlobals</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.backupStaticAttributes"><code class="literal">@backupStaticAttributes</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.covers"><code class="literal">@covers</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.dataProvider"><code class="literal">@dataProvider</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.depends"><code class="literal">@depends</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.expectedException"><code class="literal">@expectedException</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.group"><code class="literal">@group</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.outputBuffering"><code class="literal">@outputBuffering</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses"><code class="literal">@runTestsInSeparateProcesses</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.runInSeparateProcess"><code class="literal">@runInSeparateProcess</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.test"><code class="literal">@test</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.testdox"><code class="literal">@testdox</code></a></span></dt><dt><span class="section"><a href="appendixes.annotations.html#appendixes.annotations.ticket"><code class="literal">@ticket</code></a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.configuration.html">C. The XML Configuration File</a></span></dt><dd><dl><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.phpunit">PHPUnit</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.testsuites">Test Suites</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.groups">Groups</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.blacklist-whitelist">Including and Excluding Files for Code Coverage</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.logging">Logging</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.test-listeners">Test Listeners</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables">Setting PHP INI settings, Constants and Global Variables</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.selenium-rc">Configuring Browsers for Selenium RC</a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.index.html">D. Index</a></span></dt><dd><dl><dt><span class="index"><a href="appendixes.index.html#appendixes.index.index"></a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.bibliography.html">E. Bibliography</a></span></dt><dt><span class="appendix"><a href="appendixes.copyright.html">F. Copyright</a></span></dt></dl>
171
<p><a href="appendixes.copyright.html">Copyright</a> © 2005-2010 <a href="http://sebastian-bergmann.de/">Sebastian Bergmann</a>.</p>
173
<script type="text/javascript">
174
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
175
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
177
<script type="text/javascript">
179
var pageTracker = _gat._getTracker("UA-68261-7");
180
pageTracker._trackPageview();
181
} catch(err) {}</script>