<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>DogBiscuit</title>
    <description>... mmm, crunchy!</description>
    <link>http://dogbiscuit.org/mdub/weblog</link>
    <language>en-us</language>
    <generator>EvenYetAnotherWeblog</generator>
    <item>
      <title>Attacking slow-running builds (notes from CITCON)</title>
      <guid>http://dogbiscuit.org/mdub/weblog/Tech/Programming/AttackingSlowRunningBuildsAtCitcon</guid>
      <pubDate>Tue, 01 Jul 2008 22:20:00 +1000</pubDate>
      <description><![CDATA[<p>
Last weekend I went along to <a href='http://www.citconf.com/'>CITCON</a> here in Melbourne.  Which was great fun, by the way.
</p>
<p>
There I ran a session on "Attacking slow-running CI builds".  It was a small group, but an interesting discussion, I think.  Here are my (rough, unedited) notes:
</p>
<h3>
WHAT is the impact of a slow build?
</h3>
<ul>
<li>
fewer checkins
</li>
<li>
more waiting
</li>
<li>
context switching
</li>
<li>
discourages integration
</li>
<li>
discourages writing of additional tests
</li>
<li>
more chance of overlapping checkins
</li>
<li>
more build breakages
</li>
<li>
more time required to get the build fixed
</li>
<li>
reduced productivity
</li>
<li>
WASTE!
</li>
</ul>
<h3>
WHY is the build slow?
</h3>
<ul>
<li>
slow tests (particularly acceptance tests)
</li>
<ul>
<li>
over-testing (testing the same code-paths repeatedly)
</li>
<li>
expensive set-up and tear-down
</li>
<li>
too much testing via the user-interface
</li>
<li>
tests that pause, sleep, or poll (e.g. to deal with AJAX)
</li>
</ul>
<li>
too much I/O!
</li>
<li>
use of slow infrastructure components (database servers, application servers, etc.)
</li>
<li>
slow hardware
</li>
</ul>
<h3>
HOW can we make it faster?
</h3>
<ul>
<li>
faster hardware
</li>
<li>
run tests in parallel
</li>
<li>
distribute tests
</li>
<li>
fail fast
</li>
<ul>
<li>
selective testing: run tests most likely to fail first
</li>
<ul>
<li>
could use dependency-analysis to identify which tests were affected by recent commits
</li>
</ul>
</ul>
<li>
refactor story-based acceptance tests into scenario-based tests
</li>
<ul>
<li>
bigger tests, with more assertions, offsets set-up/tear-down costs
</li>
<ul>
<li>
but makes tests more complex
</li>
</ul>
</ul>
<li>
share test fixtures between a group of tests
</li>
<ul>
<li>
but breaks test isolation
</li>
</ul>
<li>
avoid I/O
</li>
<ul>
<li>
in-memory database
</li>
<li>
in-memory file-store (RAM disk?)
</li>
<li>
stub out infrastructure components
</li>
<ul>
<li>
avoid testing these components by side-effect
</li>
</ul>
</ul>
<li>
populate the database directly, rather than using the user-interface to set-up for a test
</li>
<li>
separate your system into components that can be tested independently
</li>
</ul>
<h2>
Thinking about this later ...
</h2>
<h3>
There are two types ...
</h3>
<p>
The suggestions for improving build times seemed to fall into two categories:
<ol>
<li>
optimise the build/tests
</li>
<li>
throw additional hardware at the problem
</li>
</ol>
</p>
<p>
My problem with the "throw hardware at it" approach is that it typically <u>only helps for the build-server</u> machine; the poor old developers are still left with a slow-running build, and therefore many of the productivity issues still exist.
</p>
<h3>
Another idea
</h3>
<p>
It occurs to me now that we missed a fairly fundamental trick to improve test times: <u>improve the performance of the system-under-test itself</u>.  It's a great excuse to start thinking about  performance earlier in the project.
</p>
<h3>
"Customer Acceptance Test" does not need to mean end-to-end
</h3>
<p>
On all the projects I've been on in recent years, we've ended up with the majority of the tests being either "developer unit tests", which run super-fast, or "customer acceptance tests" which test end-to-end (browser-to-database) and run super-slow.  
</p>
<p>
Methinks it should be less black-and-white.  If we can demonstrate functionality that the customer cares about by calling the underlying logic directly (i.e. at unit-test level), rather than by exercising the user-interface, then what's wrong with that?  (We just need one test to prove that the underlying logic has been properly integrated into the UI.)
</p>
]]></description>
    </item>
  </channel>
</rss>
