<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Do. Reflect. Learn. Repeat!</title>
    <link>http://blog.zsoldosp.eu</link>
    <description>Excercises in public learning</description>
    <pubDate>Mon, 18 Apr 2016 12:32:00 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>CITCON Cluj 2016</title>
      <link>http://blog.zsoldosp.eu/2016/04/18/citcon-cluj-2016/</link>
      <pubDate>Mon, 18 Apr 2016 12:32:00 CEST</pubDate>
      <category><![CDATA[citcon]]></category>
      <category><![CDATA[conferences]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">Ak8DsCUnbn3-fj05vbRCp36P4OI=</guid>
      <description>CITCON Cluj 2016</description>
      <content:encoded><![CDATA[
          <style type="text/css">
.post img {
   width: 100%;
   height: auto;
}
</style>

<div class="toc">
<ul>
<li><a href="#monorepos">Monorepos</a></li>
<li><a href="#is-there-a-limit-to-self-organization">Is there a limit to self organization?</a></li>
<li><a href="#randomized-testingrandom-data-generation">Randomized testing/random data generation</a></li>
<li><a href="#continuous-deliverydeploymnet-side-effects">Continuous Delivery/Deploymnet side effects</a></li>
<li><a href="#how-do-you-test-your-organization">How do you test your organization?</a></li>
<li><a href="#elephant-carpaccio">Elephant Carpaccio</a></li>
<li><a href="#summary">Summary</a></li>
<li><a href="#books-of-citcon-cluj">Books of CITCON Cluj</a></li>
</ul>
</div>
<p>Cluj was the seventh CITCON I attended, and it's the second CITCON organized by people who first attended the conference series in Budapest (which I organized :)). But it's not about reunion of old friends, it's a super open and welcoming event, where I still keep learning, so without further ado, here are my learnings from the sessions I've attended.</p>
<h2 id="monorepos">Monorepos</h2>
<p>(It was a lunch session, which I didn't attend, but we've talked about it Friday evening)</p>
<p><a href="https://twitter.com/ivanrmoore">Ivan Moore</a> suggested (and has done so in his past project(s)) not to break up your team's repo into different repos, but just have a single one and keep modules separated. Essentially he suggests a single repo per team.</p>
<p>The benefit of this is that you save a lot of time by not having to deal with a bunch of things, especially in the build, packaging and dependency versioning/management area - the compatible versions are always kept together.</p>
<p>It's recommended that you CD the artifacts, but it's actually not a requirement.</p>
<p>We disagreed whether the physical separation  of repos is a better tool to teach people proper modularization, Ivan argued that it should be addressed on a team dynamic/process level (reviews, pairing, etc.), and not make delivery (and refactoring) harder. Note on refactoring: in Java, the equivalent of <code>pip install -e &lt;folder|git url&gt;</code> is much less practical than in Python.</p>
<h2 id="is-there-a-limit-to-self-organization">Is there a limit to self organization?</h2>
<p>It turns out that the team I work with is quite self organizing, but only within the unit of the team. <a href="https://twitter.com/jtf">@Jtf</a> suggested to rephrase the question as <em>Is there a limit to self organization or only to how big the self is?</em>.</p>
<p>I also learned that one should be careful with terminology - the question of who owns the solution and who owns the goal is totally orthogonal to how any given team is organizes work.</p>
<p>At <a href="https://twitter.com/jtf">@Jtf</a>'s company they run something similar to how <a href="http://www.valvesoftware.com/jobs/index.html">Valve</a> operates - there is an internal project fair, where PO(s) propose projects, and then developers sign up for them - and it's perfectly OK if a project gets no signups.</p>
<p>To address the divide between who owns the goal and who the solution, properly cross functional teams can be the answer, i.e.: the PO should be part of the team and should really own goals and priorization of the goals.</p>
<p>There was a rather interesting quote from Alistair Cockburn that <a href="http://alistair.cockburn.us/Self-organization+means+mutiny">"Self organization is mutiny"</a>, because self organizing will inevitebly be pushing the boundaries.</p>
<p>The technique called <a href="http://blog.jeffreyfredrick.com/2016/04/08/coherence-busting-explained/">Coherence Busting</a> was suggested, which in high level translates to empathy/understanding where people's actions are coming from, i.e.: What has to be true for this behavior to make sense. But if you can, just ask directly :)</p>
<h2 id="randomized-testingrandom-data-generation">Randomized testing/random data generation</h2>
<p>On the train ride to Cluj, I was <a href="https://github.com/zsoldosp/spike-pytest-fixtures">playing around with py.test's test fixtures</a> and how one can combine that, e.g.: in a shopping cart, how can one specify in a test that "I need an order for an electroncics items that is sold to an end user who paid by credit card and who used a fixed amount coupon". I've found that generating all combinations is rather easy, but to filter out the scenarios I need for a given test is hard if I don't want to write a lot of specific fixtures (e.g.: <code>electronics_item_for_end_user_with_creditcard_with_fixed_discount</code>), which could get out of hand fast.</p>
<p>One possibility could be to do some (model driven) code generation to generate all these specific fixtures, but I had the impression it might become unmaintainable/hard to understand quickly.</p>
<p>During the session, I used the analogy that "as if I was writing a SQL query to select the test scenarios I need", which - with the input from the other participants led to the realization that I could separate the generation of scenarios from the selection of scenarios, i.e.: I could generate all possible combinations, serialize the results somewhere before running the tests, and then inside the tests I could just query the generated ones and load them. Certainly something to experiment with further!</p>
<h2 id="continuous-deliverydeploymnet-side-effects">Continuous Delivery/Deploymnet side effects</h2>
<p>This session was run by <a href="http://www.pauljulius.com/">PJ</a>, CTO of an online advertising firm, who described their one year journey to CD, and the kind of interesting side effects he has observed.</p>
<p>He has mapped out the full process from idea to profit, and looked where they could speed it up. As a CTO, he started in the domain under his control, i.e.: from commit to released to production, though as it turned out, that's quite a small slice of the full process. Later when he showed the chart to fellow executives, they were surprised by the complexity of the project. Most likely it was the result of organic growth that comes from the human/firm behavior that when one encounters a problem/road block, often the solution to fix it is to add more process to it. Quickly there was buyin to automate a solution to the root causes for which the processes were introduced.</p>
<p><img alt="Paul Julius describing an ideas path from idea to profit" src="/img/citcon-cluj/pj-cd-side-effects.jpg" /></p>
<p>PJ told the engineers to spend the bulk of their coding time refactoring. Which people initially didn't. So he then <em>required that 50% of the time was to be spent on refactoring, as well as 50% of the time should be pair programming</em>. The business did protest initially (this was before the full value map), but the results quickly proved it was worth it. Before this change, it took 12.5 days to from a time the story made it to the implementation backlog to production down to 3.5 days (average), which led to happy stakeholders.</p>
<p>They achieved this by:</p>
<ul>
<li>integrating devs, testers, operations, etc. into a mixed teams, now everyone's title is "Software Creator"</li>
<li>slicing stories smaller</li>
<li>ship the done story when it's done, and not the end of the two weeks iteration</li>
<li>to fill out the refactoring time, they've actually reduced the pure build time from 90 minutes to 3 minutes, and the commit to build ready feedback cycle from 2.5 hours (due to pending builds) to just under a cup of coffeee</li>
</ul>
<p>PJ's observation is that if you give people metrics to strive for, they will game the system to achieve it, so if you give the right targets, great things will happen (note: it's not always easy to get the right targets :))</p>
<p>The refactoring eliminated the fear people had before to change the codebase.</p>
<p>Once they got to the time where it took 3 minutes to deploy, and 1 minute to roll back, the team actually decided to get rid of the slow end to end tests, as they could get faster feedback from production than the time it took to run those tests. However, as an online ad agency, they do have 1000s of events per second (or minutes), so they have enough data. We couldn't pin down an exact formula when exactly one can switch to production monitoring to replace their end to end tests, but the ratio of the time the team needs to go from change idea to deploy in production (<code>i2p</code>, idea to production) and the time the team needs to get feedback whether the change was good once it was deployed (<code>p2f</code>, production to feedback) is a useful one to consider where to invest your time. E.g.: if <code>i2p</code> = 30 mins and <code>p2f</code> is 3 minutes, optimizing <code>i2p</code> could make sense. But if <code>i2p</code> is an hour, and <code>p2f</code> is a day, maybe it doesn't. If anyone knows of some mathematics that could help here, please let me know!</p>
<p>As they dropped their end to end tests tests, unit tests did skyrocket in number too.</p>
<p>Also, just to emphasize, while in retrospect and in this presentation it could sound like smooth sailing, it wasn't, there were many mistakes. But that quickly teaches the team to focus on resiliency and recovery, i.e.: they changed there processes around to reduce the cost of an error (fine-grained feature flags (on off, enable for only some groups, etc.), rolling out to a few servers and then to the whole cluster, etc.). </p>
<p>Apparently New Relic supports a/b testing with monitoring, so one could compare the new release against the old one, so that's something to look into.</p>
<h2 id="how-do-you-test-your-organization">How do you test your organization?</h2>
<p><img alt="Andy Parker's notes from the session" src="/img/citcon-cluj/ap-testing-your-org.jpg" /></p>
<p><a href="https://twitter.com/aparker42">Andy Parker</a> is an engineering manager in a self organizing organization, so the question arose: what exactly should a manager do there? His answer is to gather data that could be an additional input into the kaizen (continuous improvement).</p>
<p>When one joins the organization, it helps to map out the company - look at the org chart, as well as how actually work gets done. Who are the key communicators? Who are people actually working with (usually across the hierarchy, even whent he only common manager they have is the CEO). This is easy to do when one is starting out, but should be remembered an actualized even when one is already part of the "daily mill". See also: static vs. dynamic org. situation</p>
<p>Before one starts out collecting organization, one should always start with a hypothesis (as per the scientific method). This can be the null hypothesis, i.e.: there is nothing interesting here, so observing it I'll find that everything is OK and I will just confirm that.</p>
<p>Some tools to do this is</p>
<ul>
<li>take notes - raw data when possible, even though you can't be an impartial observer of course</li>
<li>beware that observation changes things, but that in itself can be valuable information. E.g.: oh, people are pairing there, let's see what they are working on! Hmm, now that I observe them, they stopped pairing and went back to working alone. Why is that?</li>
<li>(with permission), record conversations and re-listen to them</li>
<li>
<p>in a meeting, draw a communication matrix -</p>
</li>
<li>
<p>who talks to whom</p>
</li>
<li>are they making statements or questions?</li>
<li>
<p>how long do they talk?</p>
</li>
<li>
<p>interview team members - what is your responsibility in the team? what is others' responsibility? You can find that not everyone has the same understaning</p>
</li>
<li>one, especially developers/engineers, should be careful to start with qualitative analysis, and not quantitative</li>
</ul>
<h2 id="elephant-carpaccio">Elephant Carpaccio</h2>
<p>It's a workshop that was <a href="http://alistair.cockburn.us/Elephant+carpaccio">originally run by Alistair Cockburn</a>, but <a href="http://douglassquirrel.com/">Douglas Squirrel</a> has adopted it to fit the one hour session limit.</p>
<p>As we've walked into the room, everyone was required to add a single feature to the drawing of an elephant (which started out as with a circle (head) and 4 lines (body, two legs, and the trump)). Surely we didn't create the masterpiece, but it started to resemble the elephant more and more, and as Squirrel observed, it was looking like an elephant throughout the whole process, it was just getting better/more detailed with each iteration.</p>
<p><img alt="Squirrel showing the original and final elphants" src="/img/citcon-cluj/squirrel-elephants.jpg" /></p>
<p>His client is working with a simple kanban board that has the following columns: idea, dev working on it, testing, and live. Their goal is (which they meet more often than not) to go from idea to live in a single developer day for a story.</p>
<p>E.g.: their app shows graphs, and they've introduced the color picker to allow users to choose the color of the lines of their graph via the following cards:</p>
<ul>
<li>behind a feature toggle, release a UI button for the color picker (to learn whether or not people will actually click on it)</li>
<li>when clicked, pop up a static image (to learn whether people just close the dialog, or actually click on a color)</li>
<li>a functional color picker widget, which allows choosing a color, but the selected value is not used anywhere (to do UX testing with real users over the phone)</li>
<li>actually persist the selected color and display that on the graph (done)</li>
</ul>
<p>In each step, they've implemented a slice which either provided value or provided fast feedback. One benefit of fast feedback is that you can discover early enough if you are working on a feature noone needs, and can concentrate your efforts elsewhere. As opposed to layered development, where first the data storage is implemented, then the backend is implemented, and finally something is shown to the users. It's important to slice the elephant not parallel to the ground, but vertically along the line from its trump to it tail, so that it keeps looking like an elephant.</p>
<p>Slices work even if you only release them internally or to selected users only.</p>
<p>It's important how you slice - e.g.: one could say we start with a single (or two) color(s) color picker, but that would require us to implement a rather thick slice.</p>
<p>There is a nice <a href="http://agileforall.com/wp-content/uploads/2012/01/Story-Splitting-Flowchart.pdf">flowchart to decide on how to slice stories</a>.</p>
<p>In Squirrel's experience people don't tend to slice too thin, but rather they often slice the wrong way</p>
<p>There can be tension and tradeoff in slicing whether we take the smallest next slice to implement or we take the thing that gets us to market/money fastest. That's why the slicing session happens together with the PO and the devs.</p>
<p>The benefit of this approach is that estimation is eliminated, and delivery becomes more predicatable (each card is one dev day).</p>
<p>Usually they only plan ahead like a week or so, so they can respond to feedback without too much rework.</p>
<p>Context: his client is a startup still getting to the proper product - market fit.</p>
<p>After this overview, we did a slicing/planning session for a price calculator (each drink has a price, and there is vat, which varies from country to country).</p>
<p>The following cards were derived:</p>
<ul>
<li>calculate price on command line, in ireland only, for 1 pint of beer with a fixed price and fixed percent tax</li>
<li>for <code>N</code> beers</li>
<li>at a variable price (coming from the user)</li>
<li>move from the command line to a (web) API (assume CD infrastructure is present already)</li>
<li>and whisky and  wine, but calculation can only be done for a single type at a time</li>
<li>multiple types per calculation</li>
<li>expand to have the UK prices/taxes too</li>
</ul>
<h2 id="summary">Summary</h2>
<p>CITCON Cluj was a blast, I've learned way more than what I squeezed into this blog post, so many thanks to Adina and the local organizers for finding a great venue and making the event happen! </p>
<p>Hope to see you at a CITCON next year!</p>
<h2 id="books-of-citcon-cluj">Books of CITCON Cluj</h2>
<p>These are books that were recommended either during the sessions or conversations around the conf, in no particular order</p>
<ul>
<li><a href="http://www.strategy-business.com/article/00344?gko=10921">The Future Of Management Is Teal</a></li>
<li>Why we can't learn anything from Google / Toyota (???)</li>
<li><a href="http://www.amazon.com/Jonathan-Lethem-Author-Occasional-Music/dp/B0036YCMOE/">Gun, with Occassional Music</a></li>
<li><a href="http://www.amazon.com/Research-Methods-Anthropology-Qualitative-Quantitative/dp/0759108692/">Research methods in anthropolgy - qualitative and quantitative approaches</a></li>
</ul>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2016/04/18/citcon-cluj-2016/">CITCON Cluj 2016</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>warnings.warn - some DeprecationWarning gotchas</title>
      <link>http://blog.zsoldosp.eu/2016/02/01/warnings-warn-some-deprecationwarning-gotchas/</link>
      <pubDate>Mon, 01 Feb 2016 11:17:00 CET</pubDate>
      <category><![CDATA[deprecation]]></category>
      <category><![CDATA[executable documentation]]></category>
      <category><![CDATA[gotcha]]></category>
      <category><![CDATA[python]]></category>
      <category><![CDATA[software]]></category>
      <category><![CDATA[til]]></category>
      <category><![CDATA[warnings]]></category>
      <guid isPermaLink="false">bQ24ZuZG1n9rOMCSVN81UBv0wpU=</guid>
      <description>warnings.warn - some DeprecationWarning gotchas</description>
      <content:encoded><![CDATA[
          <h2 id="deprecationwarnings"><code>DeprecationWarning</code>s</h2>
<p>It's a good practice to gradually deprecate one's library's API, so that 
users get advance warning of coming changes. The built in way to
do so is Python's <a href="https://docs.python.org/3.5/library/warnings.html"><code>warnings</code> module</a></p>
<pre><code>import warnings

if __name__ == '__main__':
    warnings.warn('deprecation', DeprecationWarning)
</code></pre>
<h2 id="by-default-they-are-not-reported">By default, they are not reported!</h2>
<p>However, if I run this code, there is no output.</p>
<pre><code>$ python3.5 demo.py
$ echo $?
0
</code></pre>
<p>The <a href="https://docs.python.org/3.5/library/warnings.html#default-warning-filters">documentation on default warning filters</a> explains: </p>
<blockquote>
<p>By default, Python installs several warning filters, which can be overridden by the command-line 
options passed to <code>-W</code> and calls to <code>filterwarnings()</code>.</p>
<ul>
<li><code>DeprecationWarning</code> and <code>PendingDeprecationWarning</code>, and <code>ImportWarning</code> are ignored.</li>
<li><code>BytesWarning</code> is ignored unless the <code>-b</code> option is given once or twice; in this case
   this warning is either printed (<code>-b</code>) or turned into an exception (<code>-bb</code>).</li>
<li><code>ResourceWarning</code> is ignored unless Python was built in debug mode.
</li>
</ul>
</blockquote>
<h2 id="forcing-defaults-from-the-command-line-makes-them-reported">Forcing defaults from the command line makes them reported</h2>
<p>However, if we force the <a href="https://docs.python.org/3.5/using/cmdline.html#cmdoption-W"><em>default</em> warning behavior from the command line</a>,
we get the warnings - even though theoretically we only specified <em>how often</em> the warnings
should be reported, not <em>which</em> warnings to be reported!</p>
<pre><code>$ python3.5 -W d demo.py
demo.py:4: DeprecationWarning: deprecation
  warnings.warn('warning', DeprecationWarning)
$ echo $?
0
</code></pre>
<p>Before reading the docs, I suspected the operating system maintainers didn't want to 'spam'
the end users of their systems with python library warnings while going about their daily 
tasks, but apparently this is built into python itself.</p>
<h2 id="so-how-should-i-deprecate-things">So how should I deprecate things?</h2>
<p>I'm a big fan of <a href="/2010/08/executable-documentation.html">executable documentation</a>, but this might be one of those cases
where good old fashioned documentation might be more effective, as we can't expect users of
our library to run with warnings enabled.</p>
<p>I would still leave in these deprecations for the project's developers as well as for the
pedant users of the library.</p>
<h2 id="checking-against-deprecations-of-our-dependencies">Checking against deprecations of our dependencies</h2>
<p>That's easier, as we own that code. I would run my builds and tests with <code>-W d</code> at the very
least, but I would like to try to run with <code>-W error</code>. Except that I don't want to fail the
build if one of my dependencies is using deprecated apis, so probably I would just have a
custom <code>main.py</code> where I would explicitly set and reset my warning filters. E.g.: updating
the above demo code would give me the following:</p>
<pre><code>import warnings
import os

if os.environ.get('TEST', '0') == '1':
    warnings.filterwarnings(module='.*', action='ignore')
    warnings.filterwarnings(module=__name__, action='error')

if __name__ == '__main__':
    warnings.warn('deprecation', DeprecationWarning)
</code></pre>
<p>&nbsp;</p>
<pre><code>$ TEST=1 python3.5 demo.py
Traceback (most recent call last):
  File "demo.py", line 8, in &lt;module&gt;
    warnings.warn('deprecation', DeprecationWarning)
DeprecationWarning: deprecation
$ echo $?
1
</code></pre>
<p>I yet have to test how feasible it is when our library supports multiple versions of a 
dependent library, e.g.: <a href="https://www.djangoproject.com/">Django</a>, but my gut feeling is that it should be doable</p>
<h3 id="beware-of-the-ordering-of-warning-filters">Beware of the ordering of warning filters</h3>
<p>If in the above example we got the order reversed, then our own <code>DeprecationWarning</code>s would
be ignored too!</p>
<pre><code>if os.environ.get('TEST', '0') == '1':
    warnings.filterwarnings(module=__name__, action='error')
    warnings.filterwarnings(module='.*', action='ignore')
</code></pre>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2016/02/01/warnings-warn-some-deprecationwarning-gotchas/">warnings.warn - some DeprecationWarning gotchas</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>A few thoughts on BDDon't</title>
      <link>http://blog.zsoldosp.eu/2015/12/09/a-few-thoughts-on-bddon-t/</link>
      <pubDate>Wed, 09 Dec 2015 23:00:00 CET</pubDate>
      <category><![CDATA[bdd]]></category>
      <category><![CDATA[behave]]></category>
      <category><![CDATA[cucumber]]></category>
      <category><![CDATA[gherkin]]></category>
      <category><![CDATA[python]]></category>
      <category><![CDATA[software]]></category>
      <category><![CDATA[testing]]></category>
      <guid isPermaLink="false">i_P3Vr2QhglZzxeTvlHSfb_4o6w=</guid>
      <description>A few thoughts on BDDon't</description>
      <content:encoded><![CDATA[
          <p><strong>Note</strong>: apparently I wrote this blog post, but forgot to publish it
back in december. I will publish it nonetheless together with the 
<a href="/2016/02/01/warnings-warn-some-deprecationwarning-gotchas/">python warnings</a> post, and keep the publish/create date the 
original from last year.</p>
<hr />
<p>Kevin Dishman wrote an article titled <a href="https://www.thoughtworks.com/p2magazine/issue12/bdd-dont/">BDDon't</a>, in which he
raises a few objections against issues common with the tools and common
practices of them. As recently at the <a href="https://www.softwerkskammer.org/">Softwerkskammer</a> Nuremberg
user group we've just talked about Gherkin style testing after my 
<a href="https://github.com/zsoldosp/polytesting-taskboard">polytesting talk</a>, I'm now doubly prompted to blog some
thoughts.</p>
<div class="toc">
<ul>
<li><a href="#contextdisclaimer">Context/Disclaimer</a></li>
<li><a href="#i-agree-with-kevins-problem-statements">I agree with Kevin's problem statements</a></li>
<li><a href="#despite-that-i-still-like-gherkin-tools">Despite that, I still like Gherkin tools</a><ul>
<li><a href="#it-forces-separation-of-test-test-glue-and-app-code">It forces separation of test, test glue, and app code</a></li>
<li><a href="#gherkin-docs-can-be-useful-beyond-dev">Gherkin docs can be useful beyond dev</a></li>
<li><a href="#dont-have-to-test-things-on-the-full-stack-level">Don't have to test things on the full stack level</a></li>
</ul>
</li>
<li><a href="#reduce-the-pain-for-gherkin">Reduce the pain for Gherkin</a><ul>
<li><a href="#regular-expression-mapping-parameter-variance">Regular-expression mapping - Parameter variance</a><ul>
<li><a href="#different-abstraction-levels">Different abstraction levels</a></li>
<li><a href="#relying-on-the-applications-own-defaults">Relying on the application's own defaults</a></li>
<li><a href="#using-step-tables-beware-this-is-defaults-in-disguise">Using step tables (beware, this is defaults in disguise!)</a></li>
</ul>
</li>
<li><a href="#global-state">Global state</a></li>
</ul>
</li>
</ul>
</div>
<h2 id="contextdisclaimer">Context/Disclaimer</h2>
<ul>
<li>I've only used <a href="https://github.com/behave/behave">behave</a>, so it's entirely possible it has
  different behavior from the tool implementation(s) Kevin used</li>
<li>I don't run the behave tests on the selenium level</li>
<li>I have never worked for an airline, though flew enough times already.
  But to be consistent with Kevin's examples, I will use this domain to
  illustrate points</li>
<li>I don't exclusively use only BDD tests</li>
</ul>
<h2 id="i-agree-with-kevins-problem-statements">I agree with Kevin's problem statements</h2>
<ul>
<li>Regular-expression mapping can become complex and error prone
  and should be avoided</li>
<li>Global state and step interdependencies are also error prone
  and should be avoided</li>
<li>
<blockquote>
<p>If the business is really interested in participating in test
specification, this would be a great opportunity for them to
pair with someone familiar and comfortable with the test suites the
team has created.</p>
</blockquote>
</li>
</ul>
<h2 id="despite-that-i-still-like-gherkin-tools">Despite that, I still like Gherkin tools</h2>
<h3 id="it-forces-separation-of-test-test-glue-and-app-code">It forces separation of test, test glue, and app code</h3>
<p>Writing readable tests are hard. While on a team with a great culture
and strong discipline this isn't a challenge, on teams that are not yet
experts in testing I find this constraint really helpful.</p>
<h3 id="gherkin-docs-can-be-useful-beyond-dev">Gherkin docs can be useful beyond dev</h3>
<p>As stated above, I've found that motivated stakeholders, BAs, etc. will
be fine reading Java, Ruby, Python test code. However, other people can
find value from an existing - and filterable/navigable (!) - Gherkin
documents, e.g.: tech/customer support people could appreciate
<a href="/2010/08/executable-documentation.html">living documents</a>. A new support person would need the same
info as a new developer making changes in that area! Or imagine if your
processes need to be audited - persuading an auditor to read natural
text might be easier than getting them to navigate codebases.</p>
<h3 id="dont-have-to-test-things-on-the-full-stack-level">Don't have to test things on the full stack level</h3>
<p>Even if Gherkin is used for acceptance testing, some
algorithms/calculations can be tested on the unit/component level, never
even touching the UI to provide the confidence the developers (business)
need(s). As time goes on, it's even possible to transition tests up and
down the test pyramid (thanks to <a href="https://twitter.com/clepce">Stefan Clepce</a> for bringing
<a href="http://pythonhosted.org/behave/new_and_noteworthy_v1.2.5.html#test-stages">behave stages</a> to my attention)!</p>
<h2 id="reduce-the-pain-for-gherkin">Reduce the pain for Gherkin</h2>
<h3 id="regular-expression-mapping-parameter-variance">Regular-expression mapping - Parameter variance</h3>
<h4 id="different-abstraction-levels">Different abstraction levels</h4>
<p>The problem of complex test data isn't unique to BDD tools - integrated
tests written in any tool will face the same problem. And the solutions
are similar - in the tests where I care about the concrete values, I
specify all the test values explicitly, and in tests where I don't care
about those details and operate at a higher level abstraction, I create
sample (random) data for that - a'la <a href="http://pytest.org/latest/fixture.html">pytest fixtures</a></p>
<p>E.g.: instead of </p>
<p><code>Given I have booked 2 flights</code></p>
<p>I might say</p>
<pre><code>Given I booked a valid flight
And I booked another valid flight
</code></pre>

<p>both these steps can match to the same step implementation - whether via
regex, multiple methods calling the same actual implementation, or via
some other way. Here I quite like <a href="https://github.com/behave/behave">behave</a>'s annotations, i.e.:
I can say </p>
<pre><code>@given('I booked a valid flight')
@given('I booked another valid flight')
def booked_a_valid_flight(context):
    ....
</code></pre>

<p>Or I might even test things in isolation, not even sharing step
implementations - I might test that the OLTP model gets translated 
to the correct reporting model, and for the report I only test things
on the report data model (see step tables below).</p>
<h4 id="relying-on-the-applications-own-defaults">Relying on the application's own defaults</h4>
<p>I have never booked a flight for an unaccompanied minor. Until reading
Kevin's article, it hasn't even occurred to me that is a use case to
consider, yet I've booked quite a number of flights.</p>
<p>I'm sure there is an option to specify that. However, that option by
default is not check in the application for the checkout - the customer
explicitly has to request it to be able to specify such a scenario.</p>
<p>Thus for such a scenario, I likely would include an explicit step for
booking with an unaccompanied minor.</p>
<h4 id="using-step-tables-beware-this-is-defaults-in-disguise">Using step tables (beware, this is defaults in disguise!)</h4>
<p><a href="https://github.com/behave/behave">Behave</a> supports <a href="http://pythonhosted.org/behave/gherkin.html#table">step table data</a></p>
<pre><code>Given I have booked a flight
   | type                     | return |
   | with unaccompanied minor | true   |
</code></pre>

<p><em>technically, the above would need a header, but in the step implementation,
the header could be treated as the first row, if that aids readability.</em></p>
<p>This can cause more complex test code, but if each step corresponds to
an actual action in the application (a'la <a href="https://pragprog.com/magazines/2010-08/page-objects-in-python">Page Object</a>), then
there should be no extra logic in the step handler - each line here
corresponds to a form input (or HTTP POST) entry.</p>
<h3 id="global-state">Global state</h3>
<p>In <a href="https://github.com/behave/behave">behave</a>, each step implementation method receives a
<a href="https://github.com/behave/behave/blob/11757e7/behave/runner.py#L33">Context</a> object to store its state (changes) in,</p>
<blockquote>
<p>This object is a place to store information related to the tests you're
running. You may add arbitrary attributes to it of whatever value you need.</p>
<p>During the running of your tests the object will have additional layers of
namespace added and removed automatically. There is a "root" namespace and
additional namespaces for features and scenarios.</p>
</blockquote>
<p>This is unlike it is implemented e.g.: in <a href="https://cucumber.io/docs/reference/jvm#java">cucumber-jvm</a>, and
maybe that's why I haven't run into this issue (though external global
state, such as a database can still be shared).</p>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2015/12/09/a-few-thoughts-on-bddon-t/">A few thoughts on BDDon't</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>The Power of (Open Source) Blueprints</title>
      <link>http://blog.zsoldosp.eu/2015/12/05/the-power-of-open-source-blueprints/</link>
      <pubDate>Sat, 05 Dec 2015 13:41:00 CET</pubDate>
      <category><![CDATA[change]]></category>
      <category><![CDATA[citcon]]></category>
      <category><![CDATA[coderetreat]]></category>
      <category><![CDATA[community]]></category>
      <category><![CDATA[organizing]]></category>
      <category><![CDATA[software]]></category>
      <category><![CDATA[teaching]]></category>
      <guid isPermaLink="false">TmQscoJEA-SD6hw3sIe4T-DcJt4=</guid>
      <description>The Power of (Open Source) Blueprints</description>
      <content:encoded><![CDATA[
          <h2 id="what-are-blueprints">What are blueprints</h2>
<p>As per Wikipedia, a <a href="https://en.wikipedia.org/wiki/Blueprint">blueprint</a> is something that <em>allowed
rapid and accurate reproduction of documents</em>. I have heard it used (and
used myself) for processes too.</p>
<p>They are powerful because they allow me or anyone else to recreate
someone else's tried and tested idea, which in turn allows the idea
to spread (scale) to unimaginable numbers and reach places (and provide
benefits to) the original inventor could have never dreamed of.</p>
<p>It allows a complete novice to the field to organize a successful event.
Think of it like a <a href="https://en.wikipedia.org/wiki/Franchising">franchise</a>. You yourself do put in the
work, and your success benefits the franchise as well as yourself.
However, you don't have to start from scratch; you have a process you
follow, that has been proven to work. When advertising your event, there
is the social proof that the brand exists that makes it easier to sell
it.</p>
<h2 id="examples">Examples</h2>
<p>Some such blueprints I've come across and worked with are</p>
<ul>
<li>the <a href="http://citconf.com/">CITCON</a> meta wiki about <a href="http://citconf.com/wiki/index.php?title=ConferencePlanning">organizing the open space
  conference</a> - and <a href="http://citconf.com/archive/budapest2012//">CITCON Budapest</a> was
  quite a success, which I couldn't have pulled off without having
  the process to follow</li>
<li><a href="http://coderetreat.org/">Coderetreats</a> - I've participated and facilitated in
  public &amp; firm-internal events. The educational sessions and the superb
  detailed documentation the coderetreat community provides make it
  almost too easy to run such an event - no surprise that in 2015 there
  were <a href="http://coderetreat.org/events/event/listByType?type=gdcr15">at least 158 events</a> on a single day!</li>
<li><a href="https://djangogirls.org/">Django Girls</a> - it started in June 2014 in Berlin, and
  by now it already took place on all continents - simply because they 
  have a wonderfully detailed tutorial on how to organize such an event!</li>
<li>the <a href="http://alistair.cockburn.us/Elephant+carpaccio">Elephant Carpaccio</a> also has a super detailed
  <a href="https://docs.google.com/document/d/1TCuuu-8Mm14oxsOnlk8DqfZAA1cvtYu9WGv67Yj_sSk/pub">facilitation guide</a></li>
</ul>
<p>... but I'm sure there are many more out there.</p>
<h2 id="benefits">Benefits</h2>
<p>If you are trying to bring change in your company/team, but you haven't
done it before, you don't have to necessarily invent workshops yourself
(of course, if you want, you can), but can simply take off established
ones "from the shelf".</p>
<p><em>Caution</em>: while you could theoretically run an event just from the
tutorials, it might be beneficial to have attended such a workshop
before running it. I've cooked my first <a href="https://en.wikipedia.org/wiki/Paella"><em>paella</em></a> from a 
cookbook, without ever having eaten one before. While everyone agreed
I've cooked something delicious, later we had to acknowledge it had 
little to do with a real paella :)</p>
<h2 id="if-you-are-already-organizing-something">If you are already organizing something</h2>
<p>If you can afford it, I highly suggest you publicly document it (and
license it openly), so others have a chance to do the same. E.g.: many
user groups struggle finding speakers or sponsors - it would be great to
have a handbook on your sponsor/speaker attraction tactics. It won't
take away from the success of your event or the benefits to your
reputation, you simply just enable more people elsewhere to do the same!</p>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2015/12/05/the-power-of-open-source-blueprints/">The Power of (Open Source) Blueprints</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>Facilitating the Global Day of Coderetreat Zagreb (and a little Nuremberg) 2015</title>
      <link>http://blog.zsoldosp.eu/2015/11/15/facilitating-the-global-day-of-coderetreat-zagreb-and-a-little-nuremberg-2015/</link>
      <pubDate>Sun, 15 Nov 2015 12:30:00 CET</pubDate>
      <category><![CDATA[code]]></category>
      <category><![CDATA[code retreat]]></category>
      <category><![CDATA[community]]></category>
      <category><![CDATA[facilitating]]></category>
      <category><![CDATA[organizing]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">7Wh3mKRL5MoalaxX7WlvFFplBkw=</guid>
      <description>Facilitating the Global Day of Coderetreat Zagreb (and a little Nuremberg) 2015</description>
      <content:encoded><![CDATA[
          <p>This was the second Zagreb <a href="http://coderetreat.org">coderetreat</a>, and this year we actually managed to
organize it to take place the same day as the rest of the world :) Thanks to 
the sponsors <a href="http://toptal.com">Toptal</a>, <a href="http://goodcode.io">Good Code</a>, <a href="http://floatingpoint.io">Floating Point</a> and
the hosts <a href="https://twitter.com/zeljkofilipin">Zeljko</a> and <a href="https://twitter.com/maljosa">Aljosa</a> for making it happen!</p>
<p><img alt="the team working on the game of life" src="/img/gdcr2015zag/whole-team.jpg" /></p>
<p>Due to our last minute advertising, the participants were Ruby heavy, but 
still, the eight people coded in Ruby, Python, C#, Haskell, JavaScript, and
R throughout the day - quite a feat if you consider that two attendees were 
not professional programmers!</p>
<p>Due to a late start and time constraint we only had 5 sessions with the
following constraints:</p>
<ol>
<li>no extra constraints, just exploring pairing, TDD, 4 rules of simple design,
    and the game of life</li>
<li>evil ping pong pairing</li>
<li>void methods only + remote pairing with Nuremberg (Germany)</li>
<li>maximum 3 lines per method</li>
<li>no conditionals (later restricted to no booleans)</li>
</ol>
<h1 id="remote-pairing-with-nuremberg">Remote pairing with Nuremberg</h1>
<p><img alt="remote pairing from zagreb" src="/img/gdcr2015zag/remote02.jpg" /></p>
<p>As I've known <a href="https://twitter.com/marcoemmrich">Marco</a> from before, a few days before the GDCR we had 
a video call where we tested out the feasibility  of remote pairing (we've
tried <a href="http://tmate.io">tmate.io</a> and <a href="http://floobits.com">FlooBits</a>), and
deemed it feasible for a coderetreat (i.e.: can be set up during the lunchbreak).</p>
<p><em>Aside</em>: Planning is everything, but no plan survives first contact with 
the enemy. All pairs used <a href="http://teamviewer.com">TeamViewer</a>
and VisualStudio in the end.</p>
<p>We used the lunchbreak to pair people up using a direct videocall between
me and <a href="https://twitter.com/marcoemmrich">Marco</a>, but that is a cumbersome process and we'll try to
come up with a better one for next time (maybe use a Google spreadsheet
where each location can put down the interested parties' language, tooling
and communication preferences before?), but nonetheless all remote pairs 
reported having had fun!</p>
<p>Facilitating remote pairs is surprisingly easy, but only when the pairs use
the headphones which can be shared between two people - one bud in each person's
ear.</p>
<p>While it does require some prior coordination between the hosts (sync session 
start times, agree on the same constraint for the session, etc.), I do suggest
you try it out if you have the chance, especially if you haven't remote paired
before!</p>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2015/11/15/facilitating-the-global-day-of-coderetreat-zagreb-and-a-little-nuremberg-2015/">Facilitating the Global Day of Coderetreat Zagreb (and a little Nuremberg) 2015</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>Podcasts I Listen To</title>
      <link>http://blog.zsoldosp.eu/2014/03/19/podcasts-i-listen-to/</link>
      <pubDate>Wed, 19 Mar 2014 08:30:00 CET</pubDate>
      <category><![CDATA[outdoors]]></category>
      <category><![CDATA[podcasts]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">LZVxlPekUBiw_pI1RaC0HDD6pkk=</guid>
      <description>Podcasts I Listen To</description>
      <content:encoded><![CDATA[
          <p>Initially I started listening to podcasts to keep up with news in
the software development space, but it has expanded way beyond that.
Recently <a href="https://twitter.com/zeljkofilipin/status/444052979172507648">Zeljko has asked for podcast recommendations</a>,
so instead of shooting a private email I thought I would share the
casts I listen to publicly in a post.</p>
<p>Note it's a <em>long</em> list - but I don't hesitate to skip/delete an episode
based on its description or its first few minutes (caveat: some casts
by their structure are less exciting in the first few minutes).</p>
<p>I've grouped the list, but of course there are many of them that would
fit multiple categories - no taxonomy ever is perfect.</p>
<p>Hope you find something you'll like!</p>
<h2 id="software-development">Software Development</h2>
<ul>
<li><a href="http://dotnetrocks.com/">.NET Rocks</a> was one of the first podcasts I've listened to. As the
  name suggests, it's focused on the Microsoft development space, but the hosts
  are critical enough when needed, and many episodes are tech agnostic. Disclaimer:
  I'm a happy owner of a .NET Rocks mug</li>
<li><a href="http://thetabletshow.com/">The Tablet Show</a> - the sister show to .NET Rocks, with focus on mobile
  and tablets. The Microsoft focus doesn't come through that heavily
  (though it's there)</li>
<li><a href="http://devopscafe.org/">DevOps Cafe</a> - there are some great interviews on here, though the format 
  (sound quality?) took me some getting used to. It exposes me to topics I'm
  a total n00b about, whether its security or networking.</li>
<li>
<p><a href="http://hanselminutes.com/">Hanselminutes</a> - Scott started this with the tagline "the podcast that doesn't
  waste your time". The episodes are limited to around half an hour, and while
  the topics stay around tech, they also touch on the social/human side, such as</p>
<ul>
<li>Scott interviewing his wife about how it is to live with a geek</li>
<li>interviews with developers from publicly underrepresented developer
  groups (women, world class climbers, you name it :)</li>
</ul>
</li>
<li>
<p><a href="http://rubyrouges.com/">Ruby Rogues</a> - a panel discussion about things Ruby related, but many of
  the discussions are applicable to other programming languages, or at the very
  least inspire one to learn how the thing discussed works in the listener's 
  language. Add on top of this they bring up cultural topics that should be
  discussed in the software development community.</p>
</li>
<li><a href="http://javaposse.com/">The Java Posse</a> - it used to be a mix of panel discussion of java/scala programmers,
  and recordings of sessions from the yearly open spaces conferences of 
  the same name, but lately it's just the conference stuff. So great for learning, but
  I miss the chat shows.</li>
<li><a href="http://theshipshow.com/">The Ship Show</a> - build and release engineering, devops, and everything else in 
  between. Panel discussions, news and views, listener questions, as well as 
  interviews. It definitely fills a niche.</li>
<li><a href="http://cognitect.com/podcast">ThinkRelevance/CogniCast</a> - anything and everything related to Clojure or Datomic,
  produced professionally by the company where Rich Hickey works. Sometimes 
  it's too Clojure heavy for me (though you might find that a good thing), but it
  has blown my mind a few times.</li>
</ul>
<h2 id="pop-science">(Pop-)Science</h2>
<ul>
<li><a href="http://www.bbc.co.uk/programmes/b00srz5b">A Brief History of Mathematics</a> - a former BBC Radio4 programme archived in podcast
  form. Short episodes on the various influential people in mathematics. I'm planning
  to re-listen to this series soon.</li>
<li><a href="http://www.bbc.co.uk/programmes/b006qshd">More or Less</a> - Statistical CSI :) Produced by (among others) Tim Harford, 
  this show takes a look at public statistical claims from any aspect of life, 
  and go after digging up sources for these claims as well as verifying them
  and the methodology used. Listener topic suggestions are encouraged!</li>
<li><a href="http://www.npr.org/templates/story/story.php?storyId=127413729">NPR Planet Money</a> - Awesome economics podcast, with short and entertaining 
  episodes. They have provided the best economics coverage of the EU debt crisis
  for laymen like me.</li>
</ul>
<h2 id="social-politics">Social, Politics</h2>
<ul>
<li><a href="http://www.bbc.co.uk/podcasts/series/analysis">Analysis</a> - another BBC Radio 4 programme. Each episode presents one person's
  research and conclusion/opinion of a given topic. Expect lot of source 
  interviews.</li>
<li><a href="http://www.bbc.co.uk/programmes/b010q0n0">Four Thought</a> - personal speeches about personal experiences, delivered to a live
  audience, followed by a few questions and answers. It keeps reminding me how
  little I know about the world and people.</li>
<li><a href="http://www.bbc.co.uk/programmes/b006qk11">Moral Maze</a> - a panel hearing out witnesses on moral questions, arguing with
  the witnesses and with themselves, exploring different these difficult topics, which
  usually don't have clearcut answers. Great topics, great points, and some
  heated debate.</li>
<li><a href="http://www.npr.org/series/6263392/intelligence-squared-u-s">Intelligence Squared</a> - recording of live, superbly moderated debates, published
  as podcasts. The structure (uninterrupted opening statements, Q &amp; A, uninterrupted 
  closing statements, voting) is wonderful, and the moderator is on top of his game. The
  topics are timely and interesting, the debaters are amazingly authentic, and the
  voting results do show that people can change their minds.</li>
<li><a href="http://www.onbeing.org/">On Being with Krista Tippett</a> - exploring open and tolerant faith. Whether by interviewing
  atheists, the translator of the Dalai Lama, a marine biologist, civil right movement
  participants, or marketing guru Seth Godin. Superb audio quality and Krista does have
  a voice which in itself makes it worth listening to any episode - not to mention the
  positive thinking that radiates from the talks.</li>
<li><a href="http://www.bbc.co.uk/programmes/b006qy05">Thinking Allowed</a> - short BBC Radio4 programme reporting on recent papers or books
  in the field of sociology on various subjects.</li>
</ul>
<h2 id="outdoors">Outdoors</h2>
<ul>
<li><a href="http://www.theoutdoorsstation.co.uk/">The Outdoors Station</a> - an irregular podcast. I tend to skip the product episodes,
  and prefer the interview ones. While irregular, the archive does hold quite a 
  few gems - if you are into outdoor stories.</li>
</ul>
<h2 id="business-chatting">Business, chatting</h2>
<ul>
<li><a href="http://www.startupsfortherestofus.com/">Startups for the Rest Of Us</a> - if you ever wanted to understand how small software business 
  owners and marketers think, and need an occasional reminder that we as software
  people are there to deliver solutions, not to write software, it's a great one. On
  top of this, there is a bunch of practical advice if you are trying yourself out 
  in internet marketing. And you can follow Mike and Rob as they develop their respective
  businesses</li>
<li><a href="http://techzinglive.com/">techzing</a> - while lately it has become more of a weekly recorded talk of two friends, 
  which presents new listeners with a steep learning curve during the first few episodes,
  in the past they had wonderful interviews - and even now their hobbies are exciting
  and inspiring enough to listen to (have you ever considered coaching your children's
  school's math team? They actually do that).</li>
</ul>
<h2 id="career">Career</h2>
<ul>
<li><a href="http://manager-tools.com/">Career tools, Manager Tools</a> - I would say this is mandatory listening to anyone who
  wants to make progress in an enterprise environment. Especially if you want to 
  become an executive. Their advice is quite prescriptive (they are ex-military after
  all), but they present their reasoning in (sometimes too) much detail. </li>
<li><a href="http://www.kalzumeus.com/category/podcasts/">Kalzumeus Software</a> - the once-in-a-rare-while podcast of Patrick McKenzie (a.k.a.: patio11).
  There is everything from living in Japan to superb advice to furthering your career,
  especially if you are a freelancer. Since there aren't too many episodes, you can go back 
  and listen to all of them!</li>
</ul>
<h2 id="reference">Reference</h2>
<p>These casts I don't regularly listen to anymore, but have them
bookmarked in case I would want to dive deeper in the topics they
address, for the episodes I've listened to convinced me of its
quality.</p>
<ul>
<li><a href="http://beingtheworst.com/">Being the Worst</a> - for event sourcing and Domain Driven Design</li>
<li><a href="http://marketingforfounders.com/">Marketing for Founders</a> - Feels like marketing 10x-20x lectures.
  Not super exciting to listen to if you don't do this, but probably
  superb to pick up the basic ideas fast.</li>
</ul>
<h2 id="and-the-best-podcasts-theme-music-award-goes-to">And the Best Podcasts Theme Music Award Goes To...</h2>
<p>Hard to tell. Obviously, the Cognicast has the advantage that guests 
choose their own intro and exit music... So I have to disqualify it :)
From the rest, I can narrow it down to the Ruby Rogues and The Ship Show,
but not any further...</p>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2014/03/19/podcasts-i-listen-to/">Podcasts I Listen To</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>Adding New Quality Checks to the Build</title>
      <link>http://blog.zsoldosp.eu/2014/03/07/adding-new-quality-checks-to-the-build/</link>
      <pubDate>Fri, 07 Mar 2014 18:17:00 CET</pubDate>
      <category><![CDATA[continuous integration]]></category>
      <category><![CDATA[monitoring]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">HCF28j7b4oOFWdUd2ZzJi66jW7s=</guid>
      <description>Adding New Quality Checks to the Build</description>
      <content:encoded><![CDATA[
          <p><small><strong>update</strong> (2014-03-08): added reference to podcast time segments
and clarified ambiguity </small></p>
<p>I just got around to listening to <a href="http://theshipshow.com/2014/02/scaling-your-self-service-as-a-service/">The Ship Show #37</a>, and
one of the topics they've discussed (47:00-48:00, 49:30-50:00) was
adding new quality checks to the build. Or to be more precise, they've
<strike>discussed</strike> talked about a case which exhibits the
anti-pattern way of adding new checks to the build, namely:</p>
<ol>
<li>Find a new quality check (e.g.: let's not have compiler warnings)</li>
<li>Get team buy in </li>
<li>Modify the build to fail on these violations</li>
<li>Have a broken build for the coming months - and have developers
   ignore <strong>real</strong> build failures (<em>ah, it's broken only due to the new
   checks!</em>)</li>
<li>Abandon this new quality check so that a failed build actually
   means the build is actually broken</li>
</ol>
<p>One way to avoid the above scenario is to focus on gradual improvement,
i.e.: after steps #1 and #2 (which shouldn't be skipped!), in step #3, 
instead of a <em>zero-tolerance</em> policy, you <strong>set the limit for the new check 
violations at the current level</strong> - i.e.: the team commits to not making the
situation any worse, and trying to improve it. Exceeding this limit will 
make the build fail, and thus there are no more false alarms - all build 
failures have to be taken seriously.</p>
<p>If your monitoring/build tool doesn't support "continuously decreasing limits"
out of the box, you'll have to adjust this limit manually, let's say every morning.
Be careful to only ever <em>lower</em> the limit though!</p>
<p>And there are other <a href="/2014/01/19/green-build-surprises/">things you should be monitoring about your build</a>
too!</p>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2014/03/07/adding-new-quality-checks-to-the-build/">Adding New Quality Checks to the Build</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>Unit Testing In Elixir</title>
      <link>http://blog.zsoldosp.eu/2014/03/05/unit-testing-in-elixir/</link>
      <pubDate>Wed, 05 Mar 2014 19:30:00 CET</pubDate>
      <category><![CDATA[elixir]]></category>
      <category><![CDATA[programming languages]]></category>
      <category><![CDATA[software]]></category>
      <category><![CDATA[testing]]></category>
      <guid isPermaLink="false">0o-82cbUaxJeza1AWri2hAjNJqg=</guid>
      <description>Unit Testing In Elixir</description>
      <content:encoded><![CDATA[
          <div class="document">
<p><em>Note that all of this was written at the time of Elixir
0.12.5-dev, so things might have changed since.</em></p>
<p>Since the <a class="reference external" href="http://elixir-lang.org/getting_started/ex_unit/1.html">tutorial</a>
covers the mechanics pretty well, this post is more about my
impressions of Elixir's approach to this topic.</p>
<div class="section" id="built-in">
<h1>Built-in</h1>
<p>Unit testing is built into the language and the tools, as well as the
tutorial - I love this approach. When you create a new project with
<tt class="docutils literal">mix</tt>, this is the output you get:</p>
<pre class="code bash literal-block">
$ mix new myproject
...
Your mix project was created successfully.
You can use mix to compile it, <span class="name builtin">test</span> it, and more:

    <span class="name builtin">cd</span> myproject
    mix compile
    mix <span class="name builtin">test</span>

Run <span class="literal string backtick">`</span>mix <span class="name builtin">help</span><span class="literal string backtick">`</span> <span class="keyword">for</span> more information.
</pre>
</div>
<div class="section" id="the-test-skeleton-is-not-beginner-friendly">
<h1>The test skeleton is not beginner friendly</h1>
<p>The skeleton unit test suffers the same problems like the <a class="reference external" href="http://djangoproject.com">Django</a>
equivalent - it is aimed at those who get unit testing already. If you
are new to automated testing, seeing code like</p>
<pre class="code elixir literal-block">
<span class="keyword declaration">defmodule</span><span class="whitespace"> </span><span class="name class">FooTest</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">
  </span><span class="keyword namespace">use</span><span class="whitespace"> </span><span class="name class">ExUnit.Case</span><span class="whitespace">

  </span><span class="name">test</span><span class="whitespace"> </span><span class="literal string double">&quot;the truth&quot;</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">
    </span><span class="name">assert</span><span class="punctuation">(</span><span class="name constant">true</span><span class="punctuation">)</span><span class="whitespace">
  </span><span class="keyword">end</span><span class="whitespace">
</span><span class="keyword">end</span>
</pre>
<p>won't really make you say <em>&quot;yes, this makes me understand and love testing!&quot;</em>.
Granted, the whole Elixir tutorial is aimed at people who can already
program.</p>
</div>
<div class="section" id="simplified-yet-flexible-assertions">
<h1>Simplified, yet flexible assertions</h1>
<p>Unlike classic unit testing frameworks, which come bundled with
numerous <tt class="docutils literal">assertWhatever</tt> and <tt class="docutils literal">assertNotWhatever</tt> etc. methods,
(various overloads for each type), ExUnit mostly only uses <tt class="docutils literal">assert</tt> and
<tt class="docutils literal">assert_raise</tt> (though there are some more - see
<a class="reference external" href="http://elixir-lang.org/docs/stable/ExUnit.Assertions.html">ExUnit.Assertions</a>).
Rather, it relies on pattern matching and the assert macro being
smart enough to figure out how to provide a good (enough) failure
message - in this aspect, it reminds me of <a class="reference external" href="http://pytest.org/latest/">py.test</a></p>
<p>I'm curious to see whether it will stay this way - custom assertions
are superb for writing DSL-like code that experts can read (e.g.:
<a class="reference external" href="http://hamcrest.org/">Hamcrest</a>), and I really like the protocol-based extensibility
model used in Elixir elsewhere.</p>
</div>
<div class="section" id="constraint-of-the-failure-messages">
<h1>Constraint of the failure messages</h1>
<p>Your opinion of this feature might differ from mine, but it's worth
pointing this out. While the assertions are pretty flexible,
the actual error message will become the <strong>values</strong> on the left- and right
hand side of the pattern matching. This takes away the information of
exactly which method was called with what parameters, which
I have grown to rely on in Python. Consider the following tests and
the resulting failure messages - which one is more helpful?</p>
<p><a class="reference external" href="/snippets/unit_testing_with_elixir_gofl.exs">Elixir</a>:</p>
<pre class="code elixir literal-block">
<span class="whitespace">    </span><span class="name">test</span><span class="whitespace"> </span><span class="literal string double">&quot;survival - a living cell with 2 or 3 neighbours survives&quot;</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">
        </span><span class="name">assert</span><span class="whitespace"> </span><span class="name class">Gofl.Rules</span><span class="operator">.</span><span class="name">next_state</span><span class="punctuation">(</span><span class="literal string symbol">:alive</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal number integer">2</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="operator">==</span><span class="whitespace"> </span><span class="literal string symbol">:alive</span><span class="whitespace">
        </span><span class="name">assert</span><span class="whitespace"> </span><span class="name class">Gofl.Rules</span><span class="operator">.</span><span class="name">next_state</span><span class="punctuation">(</span><span class="literal string symbol">:alive</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal number integer">3</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="operator">==</span><span class="whitespace"> </span><span class="literal string symbol">:alive</span><span class="whitespace">
        </span><span class="name">assert</span><span class="whitespace"> </span><span class="name class">Gofl.Rules</span><span class="operator">.</span><span class="name">next_state</span><span class="punctuation">(</span><span class="literal string symbol">:dead</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal number integer">3</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="operator">==</span><span class="whitespace"> </span><span class="literal string symbol">:alive</span><span class="whitespace">
        </span><span class="name">assert</span><span class="whitespace"> </span><span class="name class">Gofl.Rules</span><span class="operator">.</span><span class="name">next_state</span><span class="punctuation">(</span><span class="literal string symbol">:dead</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal number integer">2</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="operator">==</span><span class="whitespace"> </span><span class="literal string symbol">:dead</span><span class="whitespace">
    </span><span class="keyword">end</span>
</pre>
<pre class="code bash literal-block">
  <span class="literal number">1</span><span class="operator">)</span> <span class="name builtin">test</span> survival - a living cell with <span class="literal number">2</span> or <span class="literal number">3</span> neighbours survives <span class="operator">(</span>GoflRulesTest<span class="operator">)</span>
     ** <span class="operator">(</span>ExUnit.ExpectationError<span class="operator">)</span>
                  expected: :alive
       to be equal to <span class="operator">(==)</span>: :dead
     at unit_testing_with_elixir_gofl.exs:18



Finished <span class="keyword">in</span> <span class="literal number">0</span>.05 seconds <span class="operator">(</span><span class="literal number">0</span>.04s on load, <span class="literal number">0</span>.01s on tests<span class="operator">)</span>
<span class="literal number">1</span> tests, <span class="literal number">1</span> failures
</pre>
<p><a class="reference external" href="/snippets/unit_testing_with_elixir_gofl.py">Python</a>:</p>
<pre class="code python literal-block">
    <span class="keyword">def</span> <span class="name function">test_survival_a_living_cell_with_2_or_3_neighbours_survives</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">):</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="name">ALIVE</span><span class="punctuation">,</span> <span class="name">cell_next_state</span><span class="punctuation">(</span><span class="name">curr_state</span><span class="operator">=</span><span class="name">ALIVE</span><span class="punctuation">,</span> <span class="name">live_neighbour_cnt</span><span class="operator">=</span><span class="literal number integer">2</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="name">ALIVE</span><span class="punctuation">,</span> <span class="name">cell_next_state</span><span class="punctuation">(</span><span class="name">curr_state</span><span class="operator">=</span><span class="name">ALIVE</span><span class="punctuation">,</span> <span class="name">live_neighbour_cnt</span><span class="operator">=</span><span class="literal number integer">3</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="name">ALIVE</span><span class="punctuation">,</span> <span class="name">cell_next_state</span><span class="punctuation">(</span><span class="name">curr_state</span><span class="operator">=</span><span class="name">DEAD</span><span class="punctuation">,</span> <span class="name">live_neighbour_cnt</span><span class="operator">=</span><span class="literal number integer">3</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="name">DEAD</span><span class="punctuation">,</span> <span class="name">cell_next_state</span><span class="punctuation">(</span><span class="name">curr_state</span><span class="operator">=</span><span class="name">DEAD</span><span class="punctuation">,</span> <span class="name">live_neighbour_cnt</span><span class="operator">=</span><span class="literal number integer">2</span><span class="punctuation">))</span>
</pre>
<pre class="code bash literal-block">
<span class="name variable">F</span>
<span class="operator">======================================================================</span>
FAIL: test_survival_a_living_cell_with_2_or_3_neighbours_survives <span class="operator">(</span>__main__.GoflRulesTest<span class="operator">)</span>
----------------------------------------------------------------------
Traceback <span class="operator">(</span>most recent call last<span class="operator">)</span>:
  File <span class="literal string double">&quot;unit_testing_with_elixir_gofl.py&quot;</span>, line <span class="literal number">22</span>, <span class="keyword">in</span> test_survival_a_living_cell_with_2_or_3_neighbours_survives
    self.assertEquals<span class="operator">(</span>DEAD, cell_next_state<span class="operator">(</span><span class="name variable">curr_state</span><span class="operator">=</span>DEAD, <span class="name variable">live_neighbour_cnt</span><span class="operator">=</span><span class="literal number">2</span><span class="operator">))</span>
AssertionError: False !<span class="operator">=</span> True

----------------------------------------------------------------------
Ran <span class="literal number">1</span> <span class="name builtin">test</span> <span class="keyword">in</span> <span class="literal number">0</span>.000s

FAILED <span class="operator">(</span><span class="name variable">failures</span><span class="operator">=</span><span class="literal number">1</span><span class="operator">)</span>
</pre>
<p>Granted, Python is unique in this regard, IIRC I wouldn't get such
useful stacktraces in C# or Java either, but since I've been mostly
working in Python lately, it certainly was a surprise - not necessarily
for discouraging multiple assertions per test (it's a valid approach),
but more the hiding of the call site information.</p>
<p>However, since <tt class="docutils literal">assert</tt> itself is a macro, its technically possible
to change the assertion - added to my list of things to try :)</p>
</div>
<div class="section" id="async">
<h1>:async</h1>
<p>Test isolation is almost always hard, and these issues tend to only come
out from hiding once tests need to run in parallel for speed - good things
never come alone :) So having concurrent test running built in from the
start is a great way to have the one big (future) problem broken into
many minor inconveniences.</p>
<p>I also like that instead of a test runner command line switch, it is
declared on the TestCase level whether it's OK to run it in parallel
- giving finer control to the test author.</p>
<pre class="code elixir literal-block">
<span class="keyword declaration">defmodule</span><span class="whitespace"> </span><span class="name class">GoflRulesTest</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">
    </span><span class="keyword namespace">use</span><span class="whitespace"> </span><span class="name class">ExUnit.Case</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string symbol">async</span><span class="punctuation">:</span><span class="whitespace"> </span><span class="name constant">true</span>
</pre>
<p>I just wish it was true by default!</p>
</div>
<div class="section" id="cool-things-i-would-like-to-explore-further">
<h1>Cool things I would like to explore further</h1>
<ol class="arabic simple">
<li><dl class="first docutils">
<dt>This short exploration hasn't allowed me figure what kind of</dt>
<dd><strong>differences</strong> there are <strong>between</strong> testing <strong>functional</strong>-
and <strong>object oriented</strong> programs. My gut feeling is there
shouldn't be many: black box, transformation (state) based should
be the same. Interaction testing (mocking) seems an odd fit, however
it might just turn out to be as easy as passing in a &quot;mock&quot; function
as an argument.</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt><strong>Property-based testing</strong> has been on my radar for a while to be</dt>
<dd>tried - and its use seems to be more common in functional programming,
and it's appropriate I should try it in a context where it's set up
to succeed. This is when I'm thankful for Elixir being
built/run on top of a mature platform - otherwise there wouldn't yet
be an available library.</dd>
</dl>
</li>
</ol>
</div>
</div>

          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2014/03/05/unit-testing-in-elixir/">Unit Testing In Elixir</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>End-to-End Testing - A Code Example</title>
      <link>http://blog.zsoldosp.eu/2014/02/15/end-to-end-testing-a-code-example/</link>
      <pubDate>Sat, 15 Feb 2014 17:15:00 CET</pubDate>
      <category><![CDATA[code]]></category>
      <category><![CDATA[django]]></category>
      <category><![CDATA[end-to-end]]></category>
      <category><![CDATA[software]]></category>
      <category><![CDATA[testing]]></category>
      <guid isPermaLink="false">VQdt1K4VFfD0lxpX8wRk-1HuUSE=</guid>
      <description>End-to-End Testing - A Code Example</description>
      <content:encoded><![CDATA[
          <div class="document">
<dl class="docutils">
<dt>Prior posts in <a class="reference external" href="/category/end-to-end/">this series</a>:</dt>
<dd><ul class="first last simple">
<li><a class="reference external" href="/2013/10/23/a-new-look-at-end-to-end-testing-polymorphic-and-fast/">A New Look At End-to-End Testing - Polymorphic and Fast</a></li>
<li><a class="reference external" href="/2013/10/28/going-beyond-regression-what-other-benefits-could-end-to-end-testing-provide/">Going Beyond Regression - What Other Benefits could End-to-End Testing Provide?</a></li>
</ul>
</dd>
</dl>
<p>Abstract concepts are always easier to learn with concrete examples.
This is the first code-heavy post in the series, and it is intended to
illustrate the mechanics of the concept, not yet how it is applied to
the problem domain. For this reason, I use the example of <a class="reference external" href="https://en.wikipedia.org/wiki/Fibonacci_number">Fibonacci
Numbers</a>, with a naive
implementation - the business logic is not the emphasis here, but how we
test them on multiple levels.</p>
<p>I chose <a class="reference external" href="https://www.djangoproject.com/">Django</a> to write the code,
in because of its lovely built in end-to-end testing support, but
knowing that not everyone is a Django developer (yet!), I chose <em>not</em>
to use any of the more idiomatic <a class="reference external" href="https://docs.djangoproject.com/en/1.6/topics/class-based-views/">Django class based views</a>,
since the purpose of this post is not to teach idiomatic Django.</p>
<p>Enough of the disclaimers, on to the code!</p>
<div class="section" id="the-specs-for-the-app">
<h1>The Specs for the App</h1>
<pre class="code python literal-block">
<span class="keyword">class</span> <span class="name class">FibonacciCalculatorTests</span><span class="punctuation">:</span>

    <span class="keyword">def</span> <span class="name function">test_cannot_calculate_sequence_elements_less_than_one</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">):</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="name">n</span><span class="operator">=-</span><span class="literal number integer">1</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="name">n</span><span class="operator">=</span><span class="literal number integer">0</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_can_calculate</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">test_currently_we_cannot_calculate_numbers_greater_than_10</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">):</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_can_calculate</span><span class="punctuation">(</span><span class="literal number integer">10</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="literal number integer">11</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="literal number integer">7895</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">test_can_calculate_the_first_ten_fibonacci_numbers</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">):</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">3</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">3</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">4</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">5</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">5</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">8</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">6</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">13</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">7</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">21</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">8</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">34</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">9</span><span class="punctuation">))</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal number integer">55</span><span class="punctuation">,</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="literal number integer">10</span><span class="punctuation">))</span>

    <span class="keyword">def</span> <span class="name function">test_can_only_calculate_fibonacci_for_integers</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">):</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="literal number float">3.14</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="literal string single">'not a number'</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assert_cannot_calculate</span><span class="punctuation">(</span><span class="keyword constant">None</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">assert_can_calculate</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">result</span> <span class="operator">=</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertIsNotNone</span><span class="punctuation">(</span><span class="name">result</span><span class="punctuation">)</span>
</pre>
<p>We'll get to the implementation of <strong>assert_cannot_calculate</strong> next.</p>
</div>
<div class="section" id="the-business-logic">
<h1>The Business Logic</h1>
<p>Let's add the actual test implementation</p>
<pre class="code python literal-block">
<span class="keyword namespace">from</span> <span class="name namespace">django.test</span> <span class="keyword namespace">import</span> <span class="name">TestCase</span>
<span class="keyword namespace">from</span> <span class="name namespace">simple_fibonacci</span> <span class="keyword namespace">import</span> <span class="name">calculator</span><span class="punctuation">,</span> <span class="name">urls</span>


<span class="keyword">class</span> <span class="name class">InMemory</span><span class="punctuation">(</span><span class="name">FibonacciCalculatorTests</span><span class="punctuation">,</span> <span class="name">TestCase</span><span class="punctuation">):</span>

    <span class="keyword">def</span> <span class="name function">assert_cannot_calculate</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="keyword">with</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertRaises</span><span class="punctuation">(</span><span class="name exception">ValueError</span><span class="punctuation">):</span>
            <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">get_fibonacci</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="keyword">return</span> <span class="name">calculator</span><span class="operator">.</span><span class="name">fibonacci</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>
</pre>
<p>Followed by the calculator fibonacci logic</p>
<pre class="code python literal-block">
<span class="keyword">def</span> <span class="name function">fibonacci</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">):</span>
    <span class="comment single"># don't do this in production</span>
    <span class="comment single"># use https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression</span>
    <span class="keyword">if</span> <span class="name">n</span> <span class="operator">&lt;</span> <span class="literal number integer">1</span><span class="punctuation">:</span>
        <span class="keyword">raise</span> <span class="name exception">ValueError</span><span class="punctuation">(</span><span class="literal string single">'value (</span><span class="literal string interpol">%r</span><span class="literal string single">) too low'</span> <span class="operator">%</span> <span class="name">n</span><span class="punctuation">)</span>
    <span class="keyword">if</span> <span class="name">n</span> <span class="operator">&gt;</span> <span class="literal number integer">10</span><span class="punctuation">:</span>
        <span class="keyword">raise</span> <span class="name exception">ValueError</span><span class="punctuation">(</span><span class="literal string single">'value (</span><span class="literal string interpol">%r</span><span class="literal string single">) too high'</span> <span class="operator">%</span> <span class="name">n</span><span class="punctuation">)</span>
    <span class="keyword">if</span> <span class="name">n</span> <span class="operator word">in</span> <span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span> <span class="literal number integer">2</span><span class="punctuation">):</span>
        <span class="keyword">return</span> <span class="literal number integer">1</span>
    <span class="keyword">return</span> <span class="name">fibonacci</span><span class="punctuation">(</span><span class="name">n</span> <span class="operator">-</span> <span class="literal number integer">1</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="name">fibonacci</span><span class="punctuation">(</span><span class="name">n</span> <span class="operator">-</span> <span class="literal number integer">2</span><span class="punctuation">)</span>
</pre>
</div>
<div class="section" id="this-is-a-webservice-let-s-test-the-json-api">
<h1>This is a webservice, let's test the JSON API!</h1>
<p>You can probably guess, this is where we add the second implementation
for the FibonacciCaulcatorTests:</p>
<pre class="code python literal-block">
<span class="keyword namespace">import</span> <span class="name namespace">simple_fibonacci</span>
<span class="keyword namespace">from</span> <span class="name namespace">django.test.client</span> <span class="keyword namespace">import</span> <span class="name">Client</span>
<span class="keyword namespace">from</span> <span class="name namespace">django.core.urlresolvers</span> <span class="keyword namespace">import</span> <span class="name">reverse</span>
<span class="keyword namespace">import</span> <span class="name namespace">json</span>


<span class="keyword">class</span> <span class="name class">JsonHttpResponse</span><span class="punctuation">(</span><span class="name">FibonacciCalculatorTests</span><span class="punctuation">,</span> <span class="name">TestCase</span><span class="punctuation">):</span>

    <span class="name">urls</span> <span class="operator">=</span> <span class="name">simple_fibonacci</span><span class="operator">.</span><span class="name">urls</span>

    <span class="keyword">def</span> <span class="name function">assert_cannot_calculate</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">data</span> <span class="operator">=</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci_parsed_json_response</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertFalse</span><span class="punctuation">(</span><span class="literal string single">'result'</span> <span class="operator word">in</span> <span class="name">data</span><span class="punctuation">,</span> <span class="name">data</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal string single">'ERROR'</span><span class="punctuation">,</span> <span class="name">data</span><span class="punctuation">[</span><span class="literal string single">'status'</span><span class="punctuation">])</span>

    <span class="keyword">def</span> <span class="name function">get_fibonacci</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">data</span> <span class="operator">=</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci_parsed_json_response</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertFalse</span><span class="punctuation">(</span><span class="literal string single">'error'</span> <span class="operator word">in</span> <span class="name">data</span><span class="punctuation">,</span> <span class="name">data</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal string single">'OK'</span><span class="punctuation">,</span> <span class="name">data</span><span class="punctuation">[</span><span class="literal string single">'status'</span><span class="punctuation">],</span> <span class="name">data</span><span class="punctuation">)</span>
        <span class="keyword">return</span> <span class="name">data</span><span class="punctuation">[</span><span class="literal string single">'result'</span><span class="punctuation">]</span>

    <span class="keyword">def</span> <span class="name function">get_fibonacci_parsed_json_response</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">client</span> <span class="operator">=</span> <span class="name">Client</span><span class="punctuation">()</span>
        <span class="name">url</span> <span class="operator">=</span> <span class="name">reverse</span><span class="punctuation">(</span><span class="literal string single">'fibonacci'</span><span class="punctuation">)</span>
        <span class="name">response</span> <span class="operator">=</span> <span class="name">client</span><span class="operator">.</span><span class="name">post</span><span class="punctuation">(</span><span class="name">url</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal string single">'n'</span><span class="punctuation">:</span> <span class="name">n</span><span class="punctuation">},</span> <span class="name">HTTP_ACCEPT</span><span class="operator">=</span><span class="literal string single">'application/json'</span><span class="punctuation">)</span>
        <span class="name">data</span> <span class="operator">=</span> <span class="name">json</span><span class="operator">.</span><span class="name">loads</span><span class="punctuation">(</span><span class="name">response</span><span class="operator">.</span><span class="name">content</span><span class="punctuation">)</span>
        <span class="name">allowed_keys</span> <span class="operator">=</span> <span class="name builtin">set</span><span class="punctuation">([</span><span class="literal string single">'status'</span><span class="punctuation">,</span> <span class="literal string single">'n'</span><span class="punctuation">,</span> <span class="literal string single">'error'</span><span class="punctuation">,</span> <span class="literal string single">'result'</span><span class="punctuation">])</span>
        <span class="name">data_keys</span> <span class="operator">=</span> <span class="name builtin">set</span><span class="punctuation">(</span><span class="name">data</span><span class="operator">.</span><span class="name">keys</span><span class="punctuation">())</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="name builtin">set</span><span class="punctuation">([]),</span> <span class="name">data_keys</span> <span class="operator">-</span> <span class="name">allowed_keys</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="name">unicode</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">),</span> <span class="name">data</span><span class="punctuation">[</span><span class="literal string single">'n'</span><span class="punctuation">])</span>
        <span class="keyword">return</span> <span class="name">data</span>
</pre>
<p>As you can see, on top of the assertions in the base class, I've added
a few additional assertions, for the api contract (invariants) - this
api shouldn't return extra fields, or if it does, I should be notified
and then decided whether that's a bug that needs correction or a feature,
in which case I'll adjust the <strong>allowed_keys</strong> variable</p>
<p>And here is the implementation:</p>
<pre class="code python literal-block">
<span class="keyword namespace">from</span> <span class="name namespace">django.views.generic</span> <span class="keyword namespace">import</span> <span class="name">View</span>
<span class="keyword namespace">import</span> <span class="name namespace">json</span>
<span class="keyword namespace">from</span> <span class="name namespace">django.http</span> <span class="keyword namespace">import</span> <span class="name">HttpResponse</span>
<span class="keyword namespace">from</span> <span class="name namespace">simple_fibonacci</span> <span class="keyword namespace">import</span> <span class="name">calculator</span>


<span class="keyword">class</span> <span class="name class">FibonacciView</span><span class="punctuation">(</span><span class="name">View</span><span class="punctuation">):</span>

    <span class="keyword">def</span> <span class="name function">post</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">request</span><span class="punctuation">):</span>
        <span class="name">n</span> <span class="operator">=</span> <span class="name">request</span><span class="operator">.</span><span class="name">POST</span><span class="punctuation">[</span><span class="literal string single">'n'</span><span class="punctuation">]</span>
        <span class="name">error</span> <span class="operator">=</span> <span class="keyword constant">None</span>
        <span class="name">result</span> <span class="operator">=</span> <span class="keyword constant">None</span>
        <span class="keyword">try</span><span class="punctuation">:</span>
            <span class="name">result</span> <span class="operator">=</span> <span class="name">calculator</span><span class="operator">.</span><span class="name">fibonacci</span><span class="punctuation">(</span><span class="name builtin">int</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">))</span>
        <span class="keyword">except</span> <span class="name exception">ValueError</span> <span class="keyword">as</span> <span class="name">e</span><span class="punctuation">:</span>
            <span class="name">error</span> <span class="operator">=</span> <span class="name">unicode</span><span class="punctuation">(</span><span class="name">e</span><span class="punctuation">)</span>
        <span class="name">content</span><span class="punctuation">,</span> <span class="name">content_type</span> <span class="operator">=</span> \
            <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_response_content_and_type_function</span><span class="punctuation">(</span><span class="name">request</span><span class="punctuation">)(</span>
                <span class="name">n</span><span class="punctuation">,</span> <span class="name">error</span><span class="punctuation">,</span> <span class="name">result</span>
            <span class="punctuation">)</span>
        <span class="keyword">return</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">to_response</span><span class="punctuation">(</span><span class="name">content</span><span class="punctuation">,</span> <span class="name">content_type</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">get_response_content_and_type_function</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">request</span><span class="punctuation">):</span>
        <span class="keyword">return</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">json_response</span>

    <span class="keyword">def</span> <span class="name function">json_response</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">,</span> <span class="name">error</span><span class="punctuation">,</span> <span class="name">result</span><span class="punctuation">):</span>
        <span class="name">response_data</span> <span class="operator">=</span> <span class="punctuation">{</span><span class="literal string single">'n'</span><span class="punctuation">:</span> <span class="name">n</span><span class="punctuation">}</span>
        <span class="keyword">if</span> <span class="name">error</span> <span class="operator word">is</span> <span class="operator word">not</span> <span class="keyword constant">None</span><span class="punctuation">:</span>
            <span class="name">response_data</span><span class="punctuation">[</span><span class="literal string single">'status'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal string single">'ERROR'</span>
        <span class="keyword">else</span><span class="punctuation">:</span>
            <span class="name">response_data</span><span class="punctuation">[</span><span class="literal string single">'status'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal string single">'OK'</span>
            <span class="name">response_data</span><span class="punctuation">[</span><span class="literal string single">'result'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">result</span>
        <span class="keyword">return</span> <span class="punctuation">(</span><span class="name">json</span><span class="operator">.</span><span class="name">dumps</span><span class="punctuation">(</span><span class="name">response_data</span><span class="punctuation">),</span> <span class="literal string single">'application/json'</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">to_response</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">content</span><span class="punctuation">,</span> <span class="name">content_type</span><span class="punctuation">):</span>
        <span class="name">response</span> <span class="operator">=</span> <span class="name">HttpResponse</span><span class="punctuation">(</span><span class="name">content</span><span class="punctuation">)</span>
        <span class="name">response</span><span class="punctuation">[</span><span class="literal string single">'Content-Type'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">content_type</span>
        <span class="keyword">return</span> <span class="name">response</span>
</pre>
</div>
<div class="section" id="let-s-expose-this-feature-to-normal-user-as-html">
<h1>Let's expose this feature to normal user as HTML!</h1>
<p>The order of the events is sometimes the other way around, but sooner
or later the point comes when the same functionality must be exposed
through a different channel - whether it's a simplified/more efficient
power user interface for your internal support people as opposed to
your first time customers through the public web shop, or adding a
mobile app for your web service, it will happen. And it's nice to know
we can execute the same set of tests against all implementations.</p>
<p>Let's update the tests first:</p>
<pre class="code python literal-block">
<span class="keyword namespace">import</span> <span class="name namespace">re</span>


<span class="keyword">class</span> <span class="name class">HtmlUserFriendlyHttpResponse</span><span class="punctuation">(</span><span class="name">FibonacciCalculatorTests</span><span class="punctuation">,</span> <span class="name">TestCase</span><span class="punctuation">):</span>

    <span class="name">urls</span> <span class="operator">=</span> <span class="name">urls</span>

    <span class="keyword">def</span> <span class="name function">assert_cannot_calculate</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">response</span> <span class="operator">=</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci_response</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertContains</span><span class="punctuation">(</span><span class="name">response</span><span class="operator">=</span><span class="name">response</span><span class="punctuation">,</span> <span class="name">text</span><span class="operator">=</span><span class="literal string single">'&lt;p class=&quot;error&quot;&gt;'</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertNotContains</span><span class="punctuation">(</span><span class="name">response</span><span class="operator">=</span><span class="name">response</span><span class="punctuation">,</span> <span class="name">text</span><span class="operator">=</span><span class="literal string single">'&lt;p class=&quot;success&quot;&gt;'</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">get_fibonacci</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">response</span> <span class="operator">=</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_fibonacci_response</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertContains</span><span class="punctuation">(</span><span class="name">response</span><span class="operator">=</span><span class="name">response</span><span class="punctuation">,</span> <span class="name">text</span><span class="operator">=</span><span class="literal string single">'&lt;p class=&quot;success&quot;&gt;'</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertNotContains</span><span class="punctuation">(</span><span class="name">response</span><span class="operator">=</span><span class="name">response</span><span class="punctuation">,</span> <span class="name">text</span><span class="operator">=</span><span class="literal string single">'&lt;p class=&quot;error&quot;&gt;'</span><span class="punctuation">)</span>
        <span class="keyword">return</span> <span class="name builtin">int</span><span class="punctuation">(</span>
            <span class="name">re</span><span class="operator">.</span><span class="name">search</span><span class="punctuation">(</span>
                <span class="literal string affix">r</span><span class="literal string single">'&lt;span id=&quot;result&quot;&gt;(\d+)&lt;/span&gt;'</span><span class="punctuation">,</span> <span class="name">response</span><span class="operator">.</span><span class="name">content</span>
            <span class="punctuation">)</span> <span class="operator">.</span><span class="name">groups</span><span class="punctuation">()[</span><span class="literal number integer">0</span><span class="punctuation">])</span>

    <span class="keyword">def</span> <span class="name function">get_fibonacci_response</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">):</span>
        <span class="name">client</span> <span class="operator">=</span> <span class="name">Client</span><span class="punctuation">()</span>
        <span class="name">url</span> <span class="operator">=</span> <span class="name">reverse</span><span class="punctuation">(</span><span class="literal string single">'fibonacci'</span><span class="punctuation">)</span>
        <span class="name">client</span><span class="operator">.</span><span class="name">get</span><span class="punctuation">(</span><span class="name">url</span><span class="punctuation">,</span> <span class="name">HTTP_ACCEPT</span><span class="operator">=</span><span class="literal string single">'text/html'</span><span class="punctuation">)</span>  <span class="comment single"># as the user, we first load the page</span>
        <span class="name">post_response</span> <span class="operator">=</span> <span class="name">client</span><span class="operator">.</span><span class="name">post</span><span class="punctuation">(</span>
            <span class="name">url</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal string single">'n'</span><span class="punctuation">:</span> <span class="name">n</span><span class="punctuation">},</span> <span class="name">HTTP_ACCEPT</span><span class="operator">=</span><span class="literal string single">'text/html'</span><span class="punctuation">)</span>
        <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">assertEquals</span><span class="punctuation">(</span><span class="literal string single">'text/html'</span><span class="punctuation">,</span> <span class="name">post_response</span><span class="punctuation">[</span><span class="literal string single">'Content-Type'</span><span class="punctuation">])</span>
        <span class="keyword">return</span> <span class="name">post_response</span>
</pre>
<p>And update our implementation:</p>
<pre class="code python literal-block">
<span class="keyword namespace">from</span> <span class="name namespace">django.views.generic</span> <span class="keyword namespace">import</span> <span class="name">View</span>
<span class="keyword namespace">import</span> <span class="name namespace">json</span>
<span class="keyword namespace">from</span> <span class="name namespace">django.http</span> <span class="keyword namespace">import</span> <span class="name">HttpResponse</span>
<span class="keyword namespace">from</span> <span class="name namespace">simple_fibonacci</span> <span class="keyword namespace">import</span> <span class="name">calculator</span>


<span class="keyword">class</span> <span class="name class">FibonacciView</span><span class="punctuation">(</span><span class="name">View</span><span class="punctuation">):</span>

    <span class="keyword">def</span> <span class="name function">post</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">request</span><span class="punctuation">):</span>
        <span class="name">n</span> <span class="operator">=</span> <span class="name">request</span><span class="operator">.</span><span class="name">POST</span><span class="punctuation">[</span><span class="literal string single">'n'</span><span class="punctuation">]</span>
        <span class="name">error</span> <span class="operator">=</span> <span class="keyword constant">None</span>
        <span class="name">result</span> <span class="operator">=</span> <span class="keyword constant">None</span>
        <span class="keyword">try</span><span class="punctuation">:</span>
            <span class="name">result</span> <span class="operator">=</span> <span class="name">calculator</span><span class="operator">.</span><span class="name">fibonacci</span><span class="punctuation">(</span><span class="name builtin">int</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">))</span>
        <span class="keyword">except</span> <span class="name exception">ValueError</span> <span class="keyword">as</span> <span class="name">e</span><span class="punctuation">:</span>
            <span class="name">error</span> <span class="operator">=</span> <span class="name">unicode</span><span class="punctuation">(</span><span class="name">e</span><span class="punctuation">)</span>
        <span class="name">content</span><span class="punctuation">,</span> <span class="name">content_type</span> <span class="operator">=</span> \
            <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">get_response_content_and_type_function</span><span class="punctuation">(</span><span class="name">request</span><span class="punctuation">)(</span>
                <span class="name">n</span><span class="punctuation">,</span> <span class="name">error</span><span class="punctuation">,</span> <span class="name">result</span>
            <span class="punctuation">)</span>
        <span class="keyword">return</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">to_response</span><span class="punctuation">(</span><span class="name">content</span><span class="punctuation">,</span> <span class="name">content_type</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">get_response_content_and_type_function</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">request</span><span class="punctuation">):</span>
        <span class="keyword">return</span> <span class="name builtin pseudo">self</span><span class="operator">.</span><span class="name">json_response</span>

    <span class="keyword">def</span> <span class="name function">json_response</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">n</span><span class="punctuation">,</span> <span class="name">error</span><span class="punctuation">,</span> <span class="name">result</span><span class="punctuation">):</span>
        <span class="name">response_data</span> <span class="operator">=</span> <span class="punctuation">{</span><span class="literal string single">'n'</span><span class="punctuation">:</span> <span class="name">n</span><span class="punctuation">}</span>
        <span class="keyword">if</span> <span class="name">error</span> <span class="operator word">is</span> <span class="operator word">not</span> <span class="keyword constant">None</span><span class="punctuation">:</span>
            <span class="name">response_data</span><span class="punctuation">[</span><span class="literal string single">'status'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal string single">'ERROR'</span>
        <span class="keyword">else</span><span class="punctuation">:</span>
            <span class="name">response_data</span><span class="punctuation">[</span><span class="literal string single">'status'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal string single">'OK'</span>
            <span class="name">response_data</span><span class="punctuation">[</span><span class="literal string single">'result'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">result</span>
        <span class="keyword">return</span> <span class="punctuation">(</span><span class="name">json</span><span class="operator">.</span><span class="name">dumps</span><span class="punctuation">(</span><span class="name">response_data</span><span class="punctuation">),</span> <span class="literal string single">'application/json'</span><span class="punctuation">)</span>

    <span class="keyword">def</span> <span class="name function">to_response</span><span class="punctuation">(</span><span class="name builtin pseudo">self</span><span class="punctuation">,</span> <span class="name">content</span><span class="punctuation">,</span> <span class="name">content_type</span><span class="punctuation">):</span>
        <span class="name">response</span> <span class="operator">=</span> <span class="name">HttpResponse</span><span class="punctuation">(</span><span class="name">content</span><span class="punctuation">)</span>
        <span class="name">response</span><span class="punctuation">[</span><span class="literal string single">'Content-Type'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">content_type</span>
        <span class="keyword">return</span> <span class="name">response</span>
</pre>
<hr class="docutils" />
<p>That's the concept. The <a class="reference external" href="/category/end-to-end/">series</a> will
continue with me developing an app, and sharing relevant snippets
and lessons learned from that project. Stay tuned!</p>
</div>
</div>

          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2014/02/15/end-to-end-testing-a-code-example/">End-to-End Testing - A Code Example</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>What Elixir Taught Me About Java - Method Overloading Is Just a Convention</title>
      <link>http://blog.zsoldosp.eu/2014/02/08/what-elixir-taught-me-about-java-method-overloading-is-just-a-convention/</link>
      <pubDate>Sat, 08 Feb 2014 15:10:00 CET</pubDate>
      <category><![CDATA[elixir]]></category>
      <category><![CDATA[oop]]></category>
      <category><![CDATA[programming languages]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">4mQOP4Y091_HZpmnEdjhq0LThyc=</guid>
      <description>What Elixir Taught Me About Java - Method Overloading Is Just a Convention</description>
      <content:encoded><![CDATA[
          <div class="document">
<p>I was struggling to understand <a class="reference external" href="http://stackoverflow.com/questions/18011784/why-are-there-two-kinds-of-functions-in-elixir/18023790#18023790">the differences between anonymous
and named functions</a>
in Elixir - only to eventually realize that a lot of it is due
to the incorrect mental model I had about <a class="reference external" href="https://en.wikipedia.org/wiki/Method_overloading">method overloading</a>
from before.</p>
<p>As the saying goes, <em>&quot;for every hard problem, there is a logical, yet
completely wrong explanation&quot;</em>.</p>
<div class="section" id="examples-of-function-arity-overloading">
<h1>Examples of function arity overloading</h1>
<p><em>Arity is just the term used to refer to the number of arguments the
function has.</em></p>
<p><strong>Java</strong></p>
<pre class="code java literal-block">
<span class="keyword declaration">public</span><span class="whitespace"> </span><span class="keyword declaration">class</span> <span class="name class">MethodOverloadingArity</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">

    </span><span class="keyword declaration">public</span><span class="whitespace"> </span><span class="keyword declaration">static</span><span class="whitespace"> </span><span class="name">String</span><span class="whitespace"> </span><span class="name function">join</span><span class="punctuation">(</span><span class="name">String</span><span class="whitespace"> </span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">String</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
        </span><span class="keyword">return</span><span class="whitespace"> </span><span class="name">join</span><span class="punctuation">(</span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string">&quot; &quot;</span><span class="punctuation">);</span><span class="whitespace">
    </span><span class="punctuation">}</span><span class="whitespace">

    </span><span class="keyword declaration">public</span><span class="whitespace"> </span><span class="keyword declaration">static</span><span class="whitespace"> </span><span class="name">String</span><span class="whitespace"> </span><span class="name function">join</span><span class="punctuation">(</span><span class="name">String</span><span class="whitespace"> </span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">String</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">String</span><span class="whitespace"> </span><span class="name">sep</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
        </span><span class="keyword">return</span><span class="whitespace"> </span><span class="name">String</span><span class="punctuation">.</span><span class="name attribute">format</span><span class="punctuation">(</span><span class="literal string">&quot;%s%s%s&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">sep</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">);</span><span class="whitespace">
    </span><span class="punctuation">}</span><span class="whitespace">
</span><span class="punctuation">}</span>
</pre>
<p><strong>Elixir</strong></p>
<pre class="code elixir literal-block">
<span class="keyword declaration">defmodule</span><span class="whitespace"> </span><span class="name class">MethodOverloadingArity</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">

    </span><span class="keyword declaration">def</span><span class="whitespace"> </span><span class="name">join</span><span class="punctuation">(</span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">
        </span><span class="name">join</span><span class="punctuation">(</span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string double">&quot; &quot;</span><span class="punctuation">)</span><span class="whitespace">
    </span><span class="keyword">end</span><span class="whitespace">

    </span><span class="keyword declaration">def</span><span class="whitespace"> </span><span class="name">join</span><span class="punctuation">(</span><span class="name">a</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">b</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">sep</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="keyword">do</span><span class="whitespace">
        </span><span class="name">a</span><span class="whitespace"> </span><span class="operator">&lt;&gt;</span><span class="whitespace"> </span><span class="name">sep</span><span class="whitespace"> </span><span class="operator">&lt;&gt;</span><span class="whitespace"> </span><span class="name">b</span><span class="whitespace">  </span><span class="comment single"># string concatenation</span><span class="whitespace">
    </span><span class="keyword">end</span><span class="whitespace">

</span><span class="keyword">end</span>
</pre>
</div>
<div class="section" id="my-wrong-mental-model">
<h1>My wrong mental model</h1>
<p>I was thinking that since in interviews, tutorials, etc. method
overloading always comes up, there must be something special about it.
It makes for dynamic dispatch - which gets bound at compile time in
regular Java, but when invoked dynamically, it will resolve to the
appropriate overload. I.e.: the following pseudocode would be valid:</p>
<pre class="code elixir literal-block">
<span class="name">foo</span><span class="whitespace"> </span><span class="operator">=</span><span class="whitespace"> </span><span class="name class">MethodOverloadingArity</span><span class="operator">.</span><span class="name">join</span><span class="whitespace">
</span><span class="name">foo</span><span class="operator">.</span><span class="punctuation">(</span><span class="literal string double">&quot;a&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string double">&quot;b&quot;</span><span class="punctuation">)</span><span class="whitespace">
</span><span class="name">foo</span><span class="operator">.</span><span class="punctuation">(</span><span class="literal string double">&quot;a&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string double">&quot;b&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string double">&quot; - &quot;</span><span class="punctuation">)</span>
</pre>
<p>You can tell just from the heading that of course, it's is not valid.
And this is what we get from Elixir:</p>
<pre class="literal-block">
** (UndefinedFunctionError) undefined function: MethodOverloadingArity.join/0
    MethodOverloadingArity.join()
    MethodOverloadingArity.exs:13: (file)
    (elixir) src/elixir_lexical.erl:17: :elixir_lexical.run/2
    (elixir) lib/code.ex:301: Code.require_file/2


</pre>
<p>In the language, the functions are only unique with the combination of
the function name and the number of arguments - it fails because it
cannot find an overload which takes 0 arguments. Thus at the time I
store a reference to it in a variable, I have to resolve the arity.</p>
<p>Initially I thought it's just a special behavior for Elixir (Erlang),
so I set out to explore how it works in Java</p>
<pre class="code java literal-block">
<span class="keyword namespace">import</span><span class="whitespace"> </span><span class="name namespace">java.lang.reflect.Method</span><span class="punctuation">;</span><span class="whitespace">
</span><span class="keyword namespace">import</span><span class="whitespace"> </span><span class="name namespace">java.lang.IllegalArgumentException</span><span class="punctuation">;</span><span class="whitespace">

</span><span class="keyword declaration">public</span><span class="whitespace"> </span><span class="keyword declaration">class</span> <span class="name class">MethodOverloadingMain</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">

    </span><span class="keyword declaration">public</span><span class="whitespace"> </span><span class="keyword declaration">static</span><span class="whitespace"> </span><span class="keyword type">void</span><span class="whitespace"> </span><span class="name function">main</span><span class="punctuation">(</span><span class="name">String</span><span class="operator">[]</span><span class="whitespace"> </span><span class="name">args</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="keyword declaration">throws</span><span class="whitespace"> </span><span class="name">Exception</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
        </span><span class="name">Class</span><span class="operator">&lt;?&gt;</span><span class="whitespace"> </span><span class="name">c</span><span class="whitespace"> </span><span class="operator">=</span><span class="whitespace"> </span><span class="name">Class</span><span class="punctuation">.</span><span class="name attribute">forName</span><span class="punctuation">(</span><span class="literal string">&quot;MethodOverloadingArity&quot;</span><span class="punctuation">);</span><span class="whitespace">
        </span><span class="name">Method</span><span class="operator">[]</span><span class="whitespace"> </span><span class="name">declaredMethods</span><span class="whitespace"> </span><span class="operator">=</span><span class="whitespace"> </span><span class="name">c</span><span class="punctuation">.</span><span class="name attribute">getDeclaredMethods</span><span class="punctuation">();</span><span class="whitespace">
        </span><span class="keyword">for</span><span class="punctuation">(</span><span class="name">Method</span><span class="whitespace"> </span><span class="name">method</span><span class="whitespace"> </span><span class="punctuation">:</span><span class="whitespace"> </span><span class="name">declaredMethods</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
            </span><span class="keyword">if</span><span class="whitespace"> </span><span class="punctuation">(</span><span class="name">method</span><span class="punctuation">.</span><span class="name attribute">getName</span><span class="punctuation">()</span><span class="whitespace"> </span><span class="operator">!=</span><span class="whitespace"> </span><span class="literal string">&quot;join&quot;</span><span class="punctuation">)</span><span class="whitespace">
                </span><span class="keyword">continue</span><span class="punctuation">;</span><span class="whitespace">
            </span><span class="name">System</span><span class="punctuation">.</span><span class="name attribute">out</span><span class="punctuation">.</span><span class="name attribute">println</span><span class="punctuation">(</span><span class="name">method</span><span class="punctuation">.</span><span class="name attribute">toString</span><span class="punctuation">());</span><span class="whitespace">
            </span><span class="keyword">try</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
                </span><span class="name">Object</span><span class="whitespace"> </span><span class="name">result</span><span class="whitespace"> </span><span class="operator">=</span><span class="whitespace"> </span><span class="name">method</span><span class="punctuation">.</span><span class="name attribute">invoke</span><span class="punctuation">(</span><span class="name">c</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string">&quot;first&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string">&quot;second&quot;</span><span class="punctuation">);</span><span class="whitespace">
                </span><span class="name">System</span><span class="punctuation">.</span><span class="name attribute">out</span><span class="punctuation">.</span><span class="name attribute">format</span><span class="punctuation">(</span><span class="literal string">&quot;... invocation result (2 args): %s\n&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">result</span><span class="punctuation">);</span><span class="whitespace">
            </span><span class="punctuation">}</span><span class="whitespace"> </span><span class="keyword">catch</span><span class="punctuation">(</span><span class="name">IllegalArgumentException</span><span class="whitespace"> </span><span class="name">e</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
                </span><span class="name">System</span><span class="punctuation">.</span><span class="name attribute">out</span><span class="punctuation">.</span><span class="name attribute">format</span><span class="punctuation">(</span><span class="literal string">&quot;... (2 args) %s\n&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">e</span><span class="punctuation">);</span><span class="whitespace">
            </span><span class="punctuation">}</span><span class="whitespace">
            </span><span class="keyword">try</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
                </span><span class="name">Object</span><span class="whitespace"> </span><span class="name">result</span><span class="whitespace"> </span><span class="operator">=</span><span class="whitespace"> </span><span class="name">method</span><span class="punctuation">.</span><span class="name attribute">invoke</span><span class="punctuation">(</span><span class="name">c</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string">&quot;first&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string">&quot;second&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="literal string">&quot; - &quot;</span><span class="punctuation">);</span><span class="whitespace">
                </span><span class="name">System</span><span class="punctuation">.</span><span class="name attribute">out</span><span class="punctuation">.</span><span class="name attribute">format</span><span class="punctuation">(</span><span class="literal string">&quot;... invocation result (3 args): %s\n&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">result</span><span class="punctuation">);</span><span class="whitespace">
            </span><span class="punctuation">}</span><span class="whitespace"> </span><span class="keyword">catch</span><span class="punctuation">(</span><span class="name">IllegalArgumentException</span><span class="whitespace"> </span><span class="name">e</span><span class="punctuation">)</span><span class="whitespace"> </span><span class="punctuation">{</span><span class="whitespace">
                </span><span class="name">System</span><span class="punctuation">.</span><span class="name attribute">out</span><span class="punctuation">.</span><span class="name attribute">format</span><span class="punctuation">(</span><span class="literal string">&quot;... (3 args) %s\n&quot;</span><span class="punctuation">,</span><span class="whitespace"> </span><span class="name">e</span><span class="punctuation">);</span><span class="whitespace">
            </span><span class="punctuation">}</span><span class="whitespace">
        </span><span class="punctuation">}</span><span class="whitespace">
    </span><span class="punctuation">}</span><span class="whitespace">
</span><span class="punctuation">}</span>
</pre>
<p>(<em>Yes, it reminds me how much more elegant metaprogramming is in Python.
But Python has no method overloading</em>)</p>
<p>To my surprise (though in retrospect, it's obvious), arity also plays a
role in identifying methods in Java - notice how there are two methods
returned:</p>
<pre class="literal-block">
public static java.lang.String MethodOverloadingArity.join(java.lang.String,java.lang.String)
... invocation result (2 args): first second
... (3 args) java.lang.IllegalArgumentException: wrong number of arguments
public static java.lang.String MethodOverloadingArity.join(java.lang.String,java.lang.String,java.lang.String)
... (2 args) java.lang.IllegalArgumentException: wrong number of arguments
... invocation result (3 args): first - second

</pre>
<p>So in Java function overloading works the exact same way as it does in
Elixir (and based on my quick hallway research, in most other languages)
- an actual method is only identified by its name and arity (and in typed
languages, by type). Thus there is no dynamic method invocation based on
just its name.</p>
<p>So method overloading is just a convention, or if you wish to call it, a
hack.  I wish I learned of name and arity instead of method overloading
first!</p>
<p><em>This is yet another example why learning other languages benefits you even
if you won't end up using the new language in your day job!</em></p>
<p>With regardso to using method overloading, I think I prefer the Ruby/Python
approach - one name, one function, period. For most usecases, default argument
values allow for enough flexibility, and prevent abuse of this convention
(giving two wildly different implementations for the various overloads).</p>
<p><em>Disclaimer</em>: of course, I might still be entirely wrong. If so, please let
me know!</p>
<p>Also, I would like to thank <em>chrismccord</em>, <em>josevalim</em>, and <em>ericmj</em> from
the <cite>#elixir-lang</cite> IRC channel for patiently putting up with me and
helping me understand all this.</p>
</div>
</div>

          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2014/02/08/what-elixir-taught-me-about-java-method-overloading-is-just-a-convention/">What Elixir Taught Me About Java - Method Overloading Is Just a Convention</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
  </channel>
</rss>
