tutorial.html

来自「perl教程」· HTML 代码 · 共 648 行 · 第 1/4 页

HTML
648
字号
<p>That output isn't terribly descriptive, is it?  When you have two
tests you can figure out which one is #2, but what if you have 102?</p>
<p>Each test can be given a little descriptive name as the second
argument to <code>ok()</code>.</p>
<pre>
    <span class="keyword">use</span> <span class="variable">Test::Simple</span> <span class="string">tests</span> <span class="operator">=&gt;</span> <span class="number">2</span><span class="operator">;</span>
</pre>
<pre>
    <span class="variable">ok</span><span class="operator">(</span> <span class="keyword">defined</span> <span class="variable">$ical</span><span class="operator">,</span>              <span class="string">'new() returned something'</span> <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">isa</span><span class="operator">(</span><span class="string">'Date::ICal'</span><span class="operator">),</span>   <span class="string">"  and it's the right class"</span> <span class="operator">);</span>
</pre>
<p>So now you'd see...</p>
<pre>
    1..2
    ok 1 - new() returned something
    ok 2 -   and it's the right class</pre>
<p>
</p>
<h2><a name="test_the_manual">Test the manual</a></h2>
<p>Simplest way to build up a decent testing suite is to just test what
the manual says it does. [3] Let's pull something out of the 
<a href="../../Date/ICal.html#synopsis">SYNOPSIS in the Date::ICal manpage</a> and test that all its bits work.</p>
<pre>
    <span class="comment">#!/usr/bin/perl -w</span>
</pre>
<pre>
    <span class="keyword">use</span> <span class="variable">Test::Simple</span> <span class="string">tests</span> <span class="operator">=&gt;</span> <span class="number">8</span><span class="operator">;</span>
</pre>
<pre>
    <span class="keyword">use</span> <span class="variable">Date::ICal</span><span class="operator">;</span>
</pre>
<pre>
    <span class="variable">$ical</span> <span class="operator">=</span> <span class="variable">Date::ICal</span><span class="operator">-&gt;</span><span class="variable">new</span><span class="operator">(</span> <span class="string">year</span> <span class="operator">=&gt;</span> <span class="number">1964</span><span class="operator">,</span> <span class="string">month</span> <span class="operator">=&gt;</span> <span class="number">10</span><span class="operator">,</span> <span class="string">day</span> <span class="operator">=&gt;</span> <span class="number">16</span><span class="operator">,</span> 
                             <span class="string">hour</span> <span class="operator">=&gt;</span> <span class="number">16</span><span class="operator">,</span> <span class="string">min</span> <span class="operator">=&gt;</span> <span class="number">12</span><span class="operator">,</span> <span class="string">sec</span> <span class="operator">=&gt;</span> <span class="number">47</span><span class="operator">,</span> 
                             <span class="string">tz</span> <span class="operator">=&gt;</span> <span class="string">'0530'</span> <span class="operator">);</span>
</pre>
<pre>
    <span class="variable">ok</span><span class="operator">(</span> <span class="keyword">defined</span> <span class="variable">$ical</span><span class="operator">,</span>            <span class="string">'new() returned something'</span> <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">isa</span><span class="operator">(</span><span class="string">'Date::ICal'</span><span class="operator">),</span> <span class="string">"  and it's the right class"</span> <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">sec</span>   <span class="operator">==</span> <span class="number">47</span><span class="operator">,</span>       <span class="string">'  sec()'</span>   <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">min</span>   <span class="operator">==</span> <span class="number">12</span><span class="operator">,</span>       <span class="string">'  min()'</span>   <span class="operator">);</span>    
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">hour</span>  <span class="operator">==</span> <span class="number">16</span><span class="operator">,</span>       <span class="string">'  hour()'</span>  <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">day</span>   <span class="operator">==</span> <span class="number">17</span><span class="operator">,</span>       <span class="string">'  day()'</span>   <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">month</span> <span class="operator">==</span> <span class="number">10</span><span class="operator">,</span>       <span class="string">'  month()'</span> <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">year</span>  <span class="operator">==</span> <span class="number">1964</span><span class="operator">,</span>     <span class="string">'  year()'</span>  <span class="operator">);</span>
</pre>
<p>run that and you get:</p>
<pre>
    1..8
    ok 1 - new() returned something
    ok 2 -   and it's the right class
    ok 3 -   sec()
    ok 4 -   min()
    ok 5 -   hour()
    not ok 6 -   day()
    #     Failed test (- at line 16)
    ok 7 -   month()
    ok 8 -   year()
    # Looks like you failed 1 tests of 8.</pre>
<p>Whoops, a failure! [4] Test::Simple helpfully lets us know on what line
the failure occurred, but not much else.  We were supposed to get 17,
but we didn't.  What did we get??  Dunno.  We'll have to re-run the
test in the debugger or throw in some print statements to find out.</p>
<p>Instead, we'll switch from <strong>Test::Simple</strong> to <strong>Test::More</strong>.  <strong>Test::More</strong>
does everything <strong>Test::Simple</strong> does, and more!  In fact, Test::More does
things <em>exactly</em> the way Test::Simple does.  You can literally swap
Test::Simple out and put Test::More in its place.  That's just what
we're going to do.</p>
<p>Test::More does more than Test::Simple.  The most important difference
at this point is it provides more informative ways to say &quot;ok&quot;.
Although you can write almost any test with a generic <code>ok()</code>, it
can't tell you what went wrong.  Instead, we'll use the <code>is()</code>
function, which lets us declare that something is supposed to be the
same as something else:</p>
<pre>
    <span class="comment">#!/usr/bin/perl -w</span>
</pre>
<pre>
    <span class="keyword">use</span> <span class="variable">Test::More</span> <span class="string">tests</span> <span class="operator">=&gt;</span> <span class="number">8</span><span class="operator">;</span>
</pre>
<pre>
    <span class="keyword">use</span> <span class="variable">Date::ICal</span><span class="operator">;</span>
</pre>
<pre>
    <span class="variable">$ical</span> <span class="operator">=</span> <span class="variable">Date::ICal</span><span class="operator">-&gt;</span><span class="variable">new</span><span class="operator">(</span> <span class="string">year</span> <span class="operator">=&gt;</span> <span class="number">1964</span><span class="operator">,</span> <span class="string">month</span> <span class="operator">=&gt;</span> <span class="number">10</span><span class="operator">,</span> <span class="string">day</span> <span class="operator">=&gt;</span> <span class="number">16</span><span class="operator">,</span> 
                             <span class="string">hour</span> <span class="operator">=&gt;</span> <span class="number">16</span><span class="operator">,</span> <span class="string">min</span> <span class="operator">=&gt;</span> <span class="number">12</span><span class="operator">,</span> <span class="string">sec</span> <span class="operator">=&gt;</span> <span class="number">47</span><span class="operator">,</span> 
                             <span class="string">tz</span> <span class="operator">=&gt;</span> <span class="string">'0530'</span> <span class="operator">);</span>
</pre>
<pre>
    <span class="variable">ok</span><span class="operator">(</span> <span class="keyword">defined</span> <span class="variable">$ical</span><span class="operator">,</span>            <span class="string">'new() returned something'</span> <span class="operator">);</span>
    <span class="variable">ok</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">isa</span><span class="operator">(</span><span class="string">'Date::ICal'</span><span class="operator">),</span> <span class="string">"  and it's the right class"</span> <span class="operator">);</span>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">sec</span><span class="operator">,</span>     <span class="number">47</span><span class="operator">,</span>       <span class="string">'  sec()'</span>   <span class="operator">);</span>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">min</span><span class="operator">,</span>     <span class="number">12</span><span class="operator">,</span>       <span class="string">'  min()'</span>   <span class="operator">);</span>    
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">hour</span><span class="operator">,</span>    <span class="number">16</span><span class="operator">,</span>       <span class="string">'  hour()'</span>  <span class="operator">);</span>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">day</span><span class="operator">,</span>     <span class="number">17</span><span class="operator">,</span>       <span class="string">'  day()'</span>   <span class="operator">);</span>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">month</span><span class="operator">,</span>   <span class="number">10</span><span class="operator">,</span>       <span class="string">'  month()'</span> <span class="operator">);</span>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">year</span><span class="operator">,</span>    <span class="number">1964</span><span class="operator">,</span>     <span class="string">'  year()'</span>  <span class="operator">);</span>
</pre>
<p>&quot;Is <code>$ical-&gt;sec</code> 47?&quot;  &quot;Is <code>$ical-&gt;min</code> 12?&quot;  With <code>is()</code> in place,
you get some more information</p>
<pre>
    1..8
    ok 1 - new() returned something
    ok 2 -   and it's the right class
    ok 3 -   sec()
    ok 4 -   min()
    ok 5 -   hour()
    not ok 6 -   day()
    #     Failed test (- at line 16)
    #          got: '16'
    #     expected: '17'
    ok 7 -   month()
    ok 8 -   year()
    # Looks like you failed 1 tests of 8.</pre>
<p>letting us know that <code>$ical-&gt;day</code> returned 16, but we expected 17.  A
quick check shows that the code is working fine, we made a mistake
when writing up the tests.  Just change it to:</p>
<pre>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">$ical</span><span class="operator">-&gt;</span><span class="variable">day</span><span class="operator">,</span>     <span class="number">16</span><span class="operator">,</span>       <span class="string">'  day()'</span>   <span class="operator">);</span>
</pre>
<p>and everything works.</p>
<p>So any time you're doing a &quot;this equals that&quot; sort of test, use <code>is()</code>.
It even works on arrays.  The test is always in scalar context, so you
can test how many elements are in a list this way. [5]</p>
<pre>
    <span class="variable">is</span><span class="operator">(</span> <span class="variable">@foo</span><span class="operator">,</span> <span class="number">5</span><span class="operator">,</span> <span class="string">'foo has 5 elements'</span> <span class="operator">);</span>
</pre>
<p>
</p>
<h2><a name="sometimes_the_tests_are_wrong">Sometimes the tests are wrong</a></h2>
<p>Which brings us to a very important lesson.  Code has bugs.  Tests are
code.  Ergo, tests have bugs.  A failing test could mean a bug in the
code, but don't discount the possibility that the test is wrong.</p>
<p>On the flip side, don't be tempted to prematurely declare a test
incorrect just because you're having trouble finding the bug.
Invalidating a test isn't something to be taken lightly, and don't use
it as a cop out to avoid work.</p>
<p>
</p>
<h2><a name="testing_lots_of_values">Testing lots of values</a></h2>
<p>We're going to be wanting to test a lot of dates here, trying to trick
the code with lots of different edge cases.  Does it work before 1970?
After 2038?  Before 1904?  Do years after 10,000 give it trouble?
Does it get leap years right?  We could keep repeating the code above,
or we could set up a little try/expect loop.</p>
<pre>
    <span class="keyword">use</span> <span class="variable">Test::More</span> <span class="string">tests</span> <span class="operator">=&gt;</span> <span class="number">32</span><span class="operator">;</span>
    <span class="keyword">use</span> <span class="variable">Date::ICal</span><span class="operator">;</span>
</pre>
<pre>
    <span class="keyword">my</span> <span class="variable">%ICal_Dates</span> <span class="operator">=</span> <span class="operator">(</span>
            <span class="comment"># An ICal string     And the year, month, date</span>
            <span class="comment">#                    hour, minute and second we expect.</span>
            <span class="string">'19971024T120000'</span> <span class="operator">=&gt;</span>    <span class="comment"># from the docs.</span>
                                <span class="operator">[</span> <span class="number">1997</span><span class="operator">,</span> <span class="number">10</span><span class="operator">,</span> <span class="number">24</span><span class="operator">,</span> <span class="number">12</span><span class="operator">,</span>  <span class="number">0</span><span class="operator">,</span>  <span class="number">0</span> <span class="operator">]</span><span class="operator">,</span>
            <span class="string">'20390123T232832'</span> <span class="operator">=&gt;</span>    <span class="comment"># after the Unix epoch</span>
                                <span class="operator">[</span> <span class="number">2039</span><span class="operator">,</span>  <span class="number">1</span><span class="operator">,</span> <span class="number">23</span><span class="operator">,</span> <span class="number">23</span><span class="operator">,</span> <span class="number">28</span><span class="operator">,</span> <span class="number">32</span> <span class="operator">]</span><span class="operator">,</span>
            <span class="string">'19671225T000000'</span> <span class="operator">=&gt;</span>    <span class="comment"># before the Unix epoch</span>
                                <span class="operator">[</span> <span class="number">1967</span><span class="operator">,</span> <span class="number">12</span><span class="operator">,</span> <span class="number">25</span><span class="operator">,</span>  <span class="number">0</span><span class="operator">,</span>  <span class="number">0</span><span class="operator">,</span>  <span class="number">0</span> <span class="operator">]</span><span class="operator">,</span>
            <span class="string">'18990505T232323'</span> <span class="operator">=&gt;</span>    <span class="comment"># before the MacOS epoch</span>
                                <span class="operator">[</span> <span class="number">1899</span><span class="operator">,</span>  <span class="number">5</span><span class="operator">,</span>  <span class="number">5</span><span class="operator">,</span> <span class="number">23</span><span class="operator">,</span> <span class="number">23</span><span class="operator">,</span> <span class="number">23</span> <span class="operator">]</span><span class="operator">,</span>
    <span class="operator">);</span>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?