Sophie

Sophie

distrib > Mageia > 2 > i586 > by-pkgid > 24ac4db6f37cdb581bd43e49530aa7b7 > files > 100

buildbot-doc-0.8.5-2.mga2.noarch.rpm



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Buildbot Coding Style &mdash; Buildbot 0.8.5 documentation</title>
    
    <link rel="stylesheet" href="../_static/agogo.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '0.8.5',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <link rel="shortcut icon" href="../_static/buildbot.ico"/>
    <link rel="top" title="Buildbot 0.8.5 documentation" href="../index.html" />
    <link rel="up" title="Buildbot Development" href="index.html" />
    <link rel="next" title="Master Organization" href="master-overview.html" />
    <link rel="prev" title="Buildbot Development" href="index.html" /> 
  </head>
  <body>
    <div class="header-wrapper">
      <div class="header">
          <p class="logo"><a href="../index.html">
            <img class="logo" src="../_static/header-text-transparent.png" alt="Logo"/>
          </a></p>
        <div class="headertitle"><a
          href="../index.html">Buildbot 0.8.5 documentation</a></div>
        <div class="rel">
          <a href="index.html" title="Buildbot Development"
             accesskey="P">previous</a> |
          <a href="master-overview.html" title="Master Organization"
             accesskey="N">next</a> |
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a>
        </div>
       </div>
    </div>

    <div class="content-wrapper">
      <div class="content">
        <div class="document">
            
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="buildbot-coding-style">
<h1>Buildbot Coding Style<a class="headerlink" href="#buildbot-coding-style" title="Permalink to this headline">¶</a></h1>
<div class="section" id="twisted-idioms">
<h2>Twisted Idioms<a class="headerlink" href="#twisted-idioms" title="Permalink to this headline">¶</a></h2>
<p>Programming with Twisted Python can be daunting.  But sticking to a few
well-defined patterns can help avoid surprises.</p>
<div class="section" id="helpful-twisted-classes">
<h3>Helpful Twisted Classes<a class="headerlink" href="#helpful-twisted-classes" title="Permalink to this headline">¶</a></h3>
<p>Twisted has some useful, but little-known classes.  They are listed here with
brief descriptions, but you should consult the API documentation or source code
for the full details.</p>
<dl class="docutils">
<dt><tt class="xref py py-class docutils literal"><span class="pre">twisted.internet.task.LoopingCall</span></tt></dt>
<dd>Calls an asynchronous function repeatedly at set intervals.</dd>
<dt><tt class="xref py py-class docutils literal"><span class="pre">twisted.application.internet.TimerService</span></tt></dt>
<dd>Similar to <tt class="docutils literal"><span class="pre">t.i.t.LoopingCall</span></tt>, but implemented as a service that will
automatically start and stop the function calls when the service is started and
stopped.</dd>
</dl>
</div>
<div class="section" id="deferredgenerator">
<h3>deferredGenerator<a class="headerlink" href="#deferredgenerator" title="Permalink to this headline">¶</a></h3>
<p><tt class="xref py py-class docutils literal"><span class="pre">twisted.internet.defer.deferredGenerator</span></tt> is a great help to writing
code that makes a lot of asynchronous calls.  Refer to the Twisted
documentation for the details, but the style within Buildbot is as follows:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">defer</span>

<span class="nd">@defer.deferredGenerator</span>
<span class="k">def</span> <span class="nf">mymethod</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
    <span class="n">wfd</span> <span class="o">=</span> <span class="n">defer</span><span class="o">.</span><span class="n">waitForDeferred</span><span class="p">(</span>
            <span class="n">getSomething</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
    <span class="k">yield</span> <span class="n">wfd</span>
    <span class="n">xval</span> <span class="o">=</span> <span class="n">wfd</span><span class="o">.</span><span class="n">getResult</span><span class="p">()</span>

    <span class="k">yield</span> <span class="n">xval</span> <span class="o">+</span> <span class="n">y</span> <span class="c"># return value</span>
</pre></div>
</div>
<p>The key points to notice here:</p>
<ul class="simple">
<li>Always import <tt class="docutils literal"><span class="pre">defer</span></tt> as a module, not the names within it.</li>
<li>Use the decorator form of <tt class="docutils literal"><span class="pre">deferredGenerator</span></tt></li>
<li>For each <tt class="docutils literal"><span class="pre">waitForDeferred</span></tt> call, use the variable <tt class="docutils literal"><span class="pre">wfd</span></tt>, and assign to it
on one line, with the operation returning the Deferred on the next.</li>
<li>While <tt class="docutils literal"><span class="pre">wfd.getResult()</span></tt> can be used in an expression, if that expression is
complex, pull it out into a simple assignment.  This helps reviewers scanning
the code for missing <tt class="docutils literal"><span class="pre">getResult</span></tt> calls.</li>
<li>When <tt class="docutils literal"><span class="pre">yield</span></tt> is used to return a value, add a comment to that effect, since
this can often be missed.</li>
</ul>
<p>As a reminder, Builtbot is compatible with Python-2.4, which does not support
try/finally blocks in generators.</p>
</div>
</div>
<div class="section" id="writing-buildbot-tests">
<h2>Writing Buildbot Tests<a class="headerlink" href="#writing-buildbot-tests" title="Permalink to this headline">¶</a></h2>
<p>In general, we are trying to ensure that new tests are <em>good</em>.  So what makes
a good test?</p>
<div class="section" id="independent-of-time">
<span id="tests-independent-of-time"></span><h3>Independent of Time<a class="headerlink" href="#independent-of-time" title="Permalink to this headline">¶</a></h3>
<p>Tests that depend on wall time will fail. As a bonus, they run very slowly. Do
not use <tt class="xref py py-meth docutils literal"><span class="pre">reactor.callLater</span></tt> to wait &quot;long enough&quot; for something to happen.</p>
<p>For testing things that themselves depend on time, consider using
<tt class="xref py py-class docutils literal"><span class="pre">twisted.internet.tasks.Clock</span></tt>.  This may mean passing a clock instance to
the code under test, and propagating that instance as necessary to ensure that
all of the code using <tt class="xref py py-meth docutils literal"><span class="pre">callLater</span></tt> uses it.  Refactoring code for
testability is difficult, but wortwhile.</p>
<p>For testing things that do not depend on time, but for which you cannot detect
the &quot;end&quot; of an operation: add a way to detect the end of the operation!</p>
</div>
<div class="section" id="clean-code">
<h3>Clean Code<a class="headerlink" href="#clean-code" title="Permalink to this headline">¶</a></h3>
<p>Make your tests readable. This is no place to skimp on comments! Others will
attempt to learn about the expected behavior of your class by reading the
tests. As a side note, if you use a <tt class="xref py py-class docutils literal"><span class="pre">Deferred</span></tt> chain in your test, write
the callbacks as nested functions, rather than using object methods with funny
names:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">testSomething</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">d</span> <span class="o">=</span> <span class="n">doThisFirst</span><span class="p">()</span>
    <span class="k">def</span> <span class="nf">andThisNext</span><span class="p">(</span><span class="n">res</span><span class="p">):</span>
        <span class="k">pass</span> <span class="c"># ...</span>
    <span class="n">d</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="n">andThisNext</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">d</span>
</pre></div>
</div>
<p>This isolates the entire test into one indented block. It is OK to add methods
for common functionality, but give them real names and explain in detail what
they do.</p>
</div>
<div class="section" id="good-name">
<h3>Good Name<a class="headerlink" href="#good-name" title="Permalink to this headline">¶</a></h3>
<p>Your test module should be named after the package or class it tests, replacing
<tt class="docutils literal"><span class="pre">.</span></tt> with <tt class="docutils literal"><span class="pre">_</span></tt> and omitting the <tt class="docutils literal"><span class="pre">buildbot_</span></tt>. For example,
<tt class="file docutils literal"><span class="pre">test_status_web_authz_Authz.py</span></tt> tests the <tt class="xref py py-class docutils literal"><span class="pre">Authz</span></tt> class in
<tt class="file docutils literal"><span class="pre">buildbot/status/web/authz.py</span></tt>. Modules with only one class, or a few
trivial classes, can be tested in a single test module. For more complex
situations, prefer to use multiple test modules.</p>
<p>Test method names should follow the pattern <tt class="samp docutils literal"><span class="pre">test_</span><em><span class="pre">METHOD</span></em><span class="pre">_</span><em><span class="pre">CONDITION</span></em></tt>
where <em>METHOD</em> is the method being tested, and <em>CONDITION</em> is the
condition under which it's tested. Since we can't always test a single
method, this is not a hard-and-fast rule.</p>
</div>
<div class="section" id="assert-only-one-thing">
<h3>Assert Only One Thing<a class="headerlink" href="#assert-only-one-thing" title="Permalink to this headline">¶</a></h3>
<p>Each test should have a single assertion. This may require a little bit of work
to get several related pieces of information into a single Python object for
comparison. The problem with multiple assertions is that, if the first
assertion fails, the remainder are not tested.  The test results then do not
tell the entire story.</p>
<p>If you need to make two unrelated assertions, you should be running two tests.</p>
</div>
<div class="section" id="use-mocks-and-stubs">
<h3>Use Mocks and Stubs<a class="headerlink" href="#use-mocks-and-stubs" title="Permalink to this headline">¶</a></h3>
<p>Mocks assert that they are called correctly. Stubs provide a predictable base
on which to run the code under test. See
<a class="reference external" href="http://en.wikipedia.org/wiki/Mock_object">Mock Object</a> and
<a class="reference external" href="http://en.wikipedia.org/wiki/Method_stub">Method Stub</a>.</p>
<p>Mock objects can be constructed easily using the aptly-named
<a class="reference external" href="http://www.voidspace.org.uk/python/mock/">mock</a> module, which is a
requirement for Buildbot's tests.</p>
<p>One of the difficulties with Buildbot is that interfaces are unstable and
poorly documented, which makes it difficult to design stubs.  A common
repository for stubs, however, will allow any interface changes to be reflected
in only one place in the test code.</p>
</div>
<div class="section" id="small-tests">
<h3>Small Tests<a class="headerlink" href="#small-tests" title="Permalink to this headline">¶</a></h3>
<p>The shorter each test is, the better. Test as little code as possible in each test.</p>
<p>It is fine, and in fact encouraged, to write the code under test in such a way
as to facilitate this. As an illustrative example, if you are testing a new
Step subclass, but your tests require instantiating a BuildMaster, you're
probably doing something wrong! (Note that this rule is almost universally
violated in the existing buildbot tests).</p>
<p>This also applies to test modules.  Several short, easily-digested test modules
are preferred over a 1000-line monster.</p>
</div>
<div class="section" id="isolation">
<h3>Isolation<a class="headerlink" href="#isolation" title="Permalink to this headline">¶</a></h3>
<p>Each test should be maximally independent of other tests. Do not leave files
laying around after your test has finished, and do not assume that some other
test has run beforehand. It's fine to use caching techniques to avoid repeated,
lengthy setup times.</p>
</div>
<div class="section" id="be-correct">
<h3>Be Correct<a class="headerlink" href="#be-correct" title="Permalink to this headline">¶</a></h3>
<p>Tests should be as robust as possible, which at a basic level means using the
available frameworks correctly. All deferreds should have callbacks and be
chained properly. Error conditions should be checked properly. Race conditions
should not exist (see <a class="reference internal" href="#tests-independent-of-time"><em>Independent of Time</em></a>, above).</p>
</div>
<div class="section" id="be-helpful">
<h3>Be Helpful<a class="headerlink" href="#be-helpful" title="Permalink to this headline">¶</a></h3>
<p>Note that tests will pass most of the time, but the moment when they are most
useful is when they fail.</p>
<p>When the test fails, it should produce output that is helpful to the person
chasing it down. This is particularly important when the tests are run
remotely, in which case the person chasing down the bug does not have access to
the system on which the test fails. A test which fails sporadically with no
more information than &quot;AssertionFailed?&quot; is a prime candidate for deletion if
the error isn't obvious. Making the error obvious also includes adding comments
describing the ways a test might fail.</p>
</div>
<div class="section" id="mixins">
<h3>Mixins<a class="headerlink" href="#mixins" title="Permalink to this headline">¶</a></h3>
<p>Do not define setUp and tearDown directly in a mixin. This is the path to
madness. Instead, define a <tt class="xref py py-func docutils literal"><span class="pre">myMixinNameSetUp</span></tt> and
<tt class="xref py py-func docutils literal"><span class="pre">myMixinNameTearDown</span></tt>, and call them explicitly from the subclass's
<tt class="xref py py-meth docutils literal"><span class="pre">setUp</span></tt> and <tt class="xref py py-meth docutils literal"><span class="pre">tearDown</span></tt>. This makes it perfectly clear what is being
set up and torn down from a simple analysis of the test case.</p>
</div>
<div class="section" id="keeping-state">
<h3>Keeping State<a class="headerlink" href="#keeping-state" title="Permalink to this headline">¶</a></h3>
<p>Python does not allow assignment to anything but the innermost local scope or
the global scope with the <tt class="docutils literal"><span class="pre">global</span></tt> keyword.  This presents a problem when
creating nested functions:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">test_localVariable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">cb_called</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="k">def</span> <span class="nf">cb</span><span class="p">():</span>
        <span class="n">cb_called</span> <span class="o">=</span> <span class="bp">True</span>
    <span class="n">cb</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">assertTrue</span><span class="p">(</span><span class="n">cb_called</span><span class="p">)</span> <span class="c"># will fail!</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">cb_called</span> <span class="pre">=</span> <span class="pre">True</span></tt> assigns to a <em>different variable</em> than
<tt class="docutils literal"><span class="pre">cb_called</span> <span class="pre">=</span> <span class="pre">False</span></tt>.  In production code, it's usually best to work around
such problems, but in tests this is often the clearest way to express the
behavior under test.</p>
<p>The solution is to change something in a common mutable object.  While a simple
list can serve as such a mutable object, this leads to code that is hard to
read.  Instead, use <tt class="xref py py-class docutils literal"><span class="pre">State</span></tt>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">buildbot.test.state</span> <span class="kn">import</span> <span class="n">State</span>

<span class="k">def</span> <span class="nf">test_localVariable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="p">(</span><span class="n">cb_called</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">cb</span><span class="p">():</span>
        <span class="n">state</span><span class="o">.</span><span class="n">cb_called</span> <span class="o">=</span> <span class="bp">True</span>
    <span class="n">cb</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">assertTrue</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">cb_called</span><span class="p">)</span> <span class="c"># passes</span>
</pre></div>
</div>
<p>This is almost as readable as the first example, but it actually works.</p>
</div>
</div>
</div>


          </div>
        </div>
      </div>
        </div>
        <div class="sidebar">
<h3>Table Of Contents</h3>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../tutorial/index.html">Buildbot Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../manual/index.html">Buildbot Manual</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Buildbot Development</a><ul class="current">
<li class="toctree-l2 current"><a class="current reference internal" href="">Buildbot Coding Style</a><ul class="simple">
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="master-overview.html">Master Organization</a></li>
<li class="toctree-l2"><a class="reference internal" href="config.html">Buildbot Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="utils.html">Utilities</a></li>
<li class="toctree-l2"><a class="reference internal" href="database.html">The Buildbot Database</a></li>
<li class="toctree-l2"><a class="reference internal" href="results.html">Build Result Codes</a></li>
<li class="toctree-l2"><a class="reference internal" href="formats.html">File Formats</a></li>
<li class="toctree-l2"><a class="reference internal" href="webstatus.html">Web Status</a></li>
<li class="toctree-l2"><a class="reference internal" href="master-slave.html">Master-Slave API</a></li>
<li class="toctree-l2"><a class="reference internal" href="encodings.html">String Encodings</a></li>
<li class="toctree-l2"><a class="reference internal" href="metrics.html">Metrics</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html">Classes</a></li>
</ul>
</li>
</ul>

          <h3 style="margin-top: 1.5em;">Search</h3>
          <form class="search" action="../search.html" method="get">
            <input type="text" name="q" />
            <input type="submit" value="Go" />
            <input type="hidden" name="check_keywords" value="yes" />
            <input type="hidden" name="area" value="default" />
          </form>
          <p class="searchtip" style="font-size: 90%">
            Enter search terms or a module, class or function name.
          </p>
        </div>
        <div class="clearer"></div>
      </div>
    </div>

    <div class="footer-wrapper">
      <div class="footer">
        <div class="left">
          <a href="index.html" title="Buildbot Development"
             >previous</a> |
          <a href="master-overview.html" title="Master Organization"
             >next</a> |
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |
          <a href="../genindex.html" title="General Index"
             >index</a>
            <br/>
            <a href="../_sources/developer/style.txt"
               rel="nofollow">Show Source</a>
        </div>

        <div class="right">
          
    <div class="footer">
        &copy; Copyright Buildbot Team Members.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.
    </div>
        </div>
        <div class="clearer"></div>
      </div>
    </div>

  </body>
</html>