<?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>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>Quick script to help reporting bugs for python</title>
      <link>http://blog.zsoldosp.eu/2013/09/11/quick-script-to-help-reporting-bugs-for-python/</link>
      <pubDate>Wed, 11 Sep 2013 17:00:00 CEST</pubDate>
      <category><![CDATA[bash]]></category>
      <category><![CDATA[code]]></category>
      <category><![CDATA[note to self]]></category>
      <category><![CDATA[python]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">-y0sMmjTXW82o3McTP9I6l_Hh4k=</guid>
      <description>Quick script to help reporting bugs for python</description>
      <content:encoded><![CDATA[
          <div class="document">
<p>While poking around the
<a class="reference external" href="https://pypi.python.org/pypi/testrepository/">testrepository</a>
package I ran into the cryptic error message of <strong>'unicodeescape'
codec can't decode bytes in position 56-57: truncated \uXXXX escape</strong>.
I set out to reproduce the bug, but that is of course an iterative
process, like anything else in coding, so I set out to script it. Since
I expect I'll need this again, and someone else might need it too,
I'm recording it here.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>I eventually figured out the problem was that <a class="reference external" href="http://testrepository.readthedocs.org/en/latest/MANUAL.html#python">the recommended
default for testrepository</a>
has a different command line behavior from the built in unittest's
runner:</p>
<blockquote>
<ul class="simple">
<li><tt class="docutils literal">python <span class="pre">-m</span> unittest discover bugrepro</tt></li>
<li><tt class="docutils literal">testr run bugrepro</tt> doesn't get translated to the discover
root, but into <tt class="docutils literal">LISTOPT</tt> variable (<tt class="docutils literal">python <span class="pre">-m</span> subunit.run
discover . $LISTOPT $IDOPTION</tt>)</li>
</ul>
</blockquote>
<p class="last">Sure, a nicer exception message would have been nice.</p>
</div>
<div class="section" id="my-environment">
<h1>My Environment</h1>
<p>While for serious development I use Linux VMs, for explorations/hobbies,
I use the base Windows 7 on my command line from git-bash - it's enough
for basic scripting things, plus I tend to use git anyway, and I don't
like Powershell.</p>
</div>
<div class="section" id="the-script">
<h1>The script</h1>
<pre class="code bash literal-block">
<span class="comment hashbang">#!/bin/sh
</span><span class="keyword">function</span> d<span class="operator">()</span> <span class="operator">{</span>
    <span class="name builtin">echo</span> <span class="literal string double">&quot;\$ </span><span class="name variable">$*</span><span class="literal string double">&quot;</span>
    <span class="name variable">$*</span>
<span class="operator">}</span>

<span class="keyword">function</span> win_info<span class="operator">()</span> <span class="operator">{</span>
    systeminfo <span class="punctuation">|</span> grep <span class="literal string double">&quot;\(OS Name\|OS Manufacturer\|System Type\|Locale\)&quot;</span>
<span class="operator">}</span>

<span class="name variable">REPRO_FOLDER</span><span class="operator">=</span>bugrepro
d win_info
d python --version
d pip freeze
d git --version
d grep ^ -nH <span class="literal string backtick">`</span>find <span class="name variable">$REPRO_FOLDER</span> -name <span class="literal string escape">\*</span>.py<span class="literal string backtick">`</span>
d python -m unittest discover <span class="name variable">$REPRO_FOLDER</span>
d ls .testr* -l
d cat .testr.conf
d testr run <span class="name variable">$REPRO_FOLDER</span>
d testr run
</pre>
<p>Running <tt class="docutils literal">./bugrepro.sh <span class="pre">2&gt;&amp;1</span> | tee bugrepro.txt&nbsp; &gt; /dev/null</tt> produces
the following output (cropped, you can see
<a class="reference external" href="/snippets/bugrepro.txt">the full output here</a>):</p>
<pre class="literal-block">
$ win_info
OS Name:                   Microsoft Windows 7 Professional 
OS Manufacturer:           Microsoft Corporation
System Type:               x64-based PC
System Locale:             en-us;English (United States)
Input Locale:              en-us;English (United States)
$ python --version
Python 2.7.4
$ pip freeze
extras==0.0.3

</pre>
</div>
<div class="section" id="things-i-learned">
<h1>Things I learned</h1>
<p>While this took somewhat longer than expected (and writing this
post wasn't even planned!) and I haven't even reported the actual
bug yet (Yak shaving...), but I don't mind - especially because I
did all this while recovering from a nasty cold :)</p>
<ul class="simple">
<li>for <tt class="docutils literal">cmd.exe</tt>, the <tt class="docutils literal">ver</tt> and <tt class="docutils literal">systeminfo</tt> commands are pretty neat
and <a class="reference external" href="http://www.windows7password.net/all-windows-7-commands-cmd-exe/">there are more commands</a>:
type <tt class="docutils literal">help</tt></li>
<li>wrote my first blog post in
<a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>
since it's a better fit for including snippets (<a class="reference external" href="/2010/08/executable-documentation.html/">executable
documentation</a> is a pet peeve of mine!)</li>
</ul>
<p><strong>Open Questions</strong> (aka: do I want to shave further yaks?!):</p>
<ul>
<li><p class="first"><tt class="docutils literal">cmd.exe /C</tt> doesn't seem to behave as one would expect it when
invoked from git-bash (msysgit, 1.8.1) - it doesn't exit and the
execution to continue requires an <tt class="docutils literal">exit</tt> command!</p>
</li>
<li><p class="first">I always want to do
<a class="reference external" href="/2013/07/25/some-metaprogramming-reflection-in-bash/">metaprogramming in bash</a>
- how could I display
the body of a bash function? I'm thinking of something similar to
what one does with alias</p>
<pre class="code bash literal-block">
$ <span class="name builtin">alias</span> <span class="name variable">foo</span><span class="operator">=</span><span class="literal string single">'echo foo'</span>
$ foo
foo
$ <span class="name builtin">alias</span> foo
<span class="name builtin">alias</span> <span class="name variable">foo</span><span class="operator">=</span><span class="literal string single">'echo foo'</span>
</pre>
</li>
<li><p class="first">is there a better way for passing arguments in bash? I ended up doing
<tt class="docutils literal">grep ^</tt> because I went crazy trying to escape
<tt class="docutils literal"><span class="pre">find...</span> <span class="pre">-exec...\;</span></tt>.
and making the script use <tt class="docutils literal"><span class="pre">#!/bin/bash</span> <span class="pre">-x</span></tt> would be an overkill
here, and I just want to echo back the command that was executed...</p>
</li>
</ul>
</div>
</div>

          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2013/09/11/quick-script-to-help-reporting-bugs-for-python/">Quick script to help reporting bugs for python</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>Own your data (or why did I move away from Blogger and WordPress?)</title>
      <link>http://blog.zsoldosp.eu/2013/08/04/own-your-data-or-why-did-i-move-away-from-blogger-and-wordpress/</link>
      <pubDate>Sun, 04 Aug 2013 14:25:00 CEST</pubDate>
      <category><![CDATA[blog]]></category>
      <category><![CDATA[data]]></category>
      <category><![CDATA[outdoors]]></category>
      <category><![CDATA[ownership]]></category>
      <category><![CDATA[python]]></category>
      <category><![CDATA[software]]></category>
      <guid isPermaLink="false">8UAjTLJV0td1NxR0DNBSZhVVots=</guid>
      <description>Own your data (or why did I move away from Blogger and WordPress?)</description>
      <content:encoded><![CDATA[
          <p>This blog used to be two separate blogs, hosted at 
<a href="http://blogger.com">Blogger</a> and <a href="http://wordpress.com">WordPress.com</a>,
respectively. I've gone through some trouble to migrate their content,
hopefully without breaking urls to this <a href="http://blogofile.com">Blogofile</a> 
based setup. In the process, I have lost a considerable number of 
features and conveniences - so why did I do this?</p>
<h2 id="owning-my-data-and-platform">Owning my data and platform</h2>
<p>As the saying goes, there is no such thing as a free lunch (or put more
bluntly, if you are not paying for it, <em>you</em> are the product being 
sold). A prime example is <a href="http://wordpress.com">WordPress.com</a>, which reserves the
right to display ads on your freely hosted blog, while <a href="http://blogger.com">Blogger</a>
probably enhances their advertisement profile of you - I don't know.</p>
<p>Even if these platforms don't do anything bad at the moment, they can
pretty much change the features available to you, or any other aspects
of their terms of service - remember that story about the 
<a href="http://news.cnet.com/8301-1023_3-57560370-93/instagram-rolls-back-terms-of-service-after-ownership-dustup/">Instagram ToS change regarding commercial use of your photos</a>?
Sure, it turned out to be a misunderstanding and/or they backed down,
but theoretically they can do it.</p>
<p>Of course, this wasn't a concern when I started out with blogging, but 
certainly is something to consider now that I am nearing post #42. </p>
<p>These considerations are of course applicable for other service 
providers beyond blogging, e.g.:</p>
<ul>
<li>(sports) tracking applications - while I have not yet gotten around 
  to building up a website like <a href="http://www.susi-ralf.de/index.html">Suzi &amp; Ralf</a>, but I know 
  eventually I will want to create something with the trails of all the
  places I've been to, whether for fun or for an anniversary gift or
  similar - and most sites make it rather hard to export your data 
  conveniently (<a href="http://endomondo.com">endomondo</a> is particularly annoying, so I'm 
  real grateful for the easy zip-export of <a href="http://runkeeper.com">runkeeper</a>!)</li>
<li>social networks - does <a href="http://linkedin.com">LinkedIn</a>, <a href="http://facebook.com">Facebook</a>, 
  <a href="http://xing.com">Xing</a>, etc. allow you to easily export your contacts and their
  contact details? I would be pretty upset to find myself without a 
  personal copy of that data</li>
</ul>
<p>Of course, I keep using services hosted by others, but I try to make 
sure I use one with a friendly <a href="http://www.dataliberation.org/">data liberation</a>
policy!</p>
<h2 id="other-considerations">Other considerations</h2>
<ul>
<li><strong>backup</strong> - sure, it's almost a repeat of the prior point, but worth 
  noting. It doesn't happen as often as before, but there is always the
  possibility of <a href="http://blog.theoldreader.com/post/56209408824/important-update">data loss or service outage</a></li>
<li><strong>version control</strong> - being a software developer, this is almost 
  second nature to me - it's incredibly liberating to be able to throw
  all my changes away and go back to a previous, known good version of
  a post draft.</li>
<li><strong>offline authoring</strong> - I do a lot of my writing and hobby coding 
  during my train commute, with spotty internet connection at best.
  Working locally on my laptop with my favorite text editor beats any
  online editor widget. </li>
<li><strong>full customizations</strong> - sure, probably there is a WordPress plugin
  for anything I would want to do, but for a lot of the small checks, 
  it takes longer to find, learn, and configure the one I need than
  to implement it in <a href="http://python.org">python</a> - e.g.: checking the site for
  broken links, custom reports, etc. I should probably mention the html
  template customizations here too, though you might be able to tell
  that is not yet the highest priority for me :)</li>
</ul>
          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2013/08/04/own-your-data-or-why-did-i-move-away-from-blogger-and-wordpress/">Own your data (or why did I move away from Blogger and WordPress?)</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
    <item>
      <title>Book Review - Python Testing Cookbook by Greg L. Turnquist</title>
      <link>http://blog.zsoldosp.eu/2011/10/book-review-python-testing-cookbook-by.html</link>
      <pubDate>Sun, 23 Oct 2011 13:24:00 CEST</pubDate>
      <category><![CDATA[book review]]></category>
      <category><![CDATA[python]]></category>
      <category><![CDATA[software]]></category>
      <category><![CDATA[testing]]></category>
      <guid isPermaLink="false">http://blog.zsoldosp.eu/2011/10/book-review-python-testing-cookbook-by.html</guid>
      <description>Book Review - Python Testing Cookbook by Greg L. Turnquist</description>
      <content:encoded><![CDATA[
          
<p>I have been doing (developer) automated testing for years now, but I recently moved from <a href="http://www.microsoft.com/net/">.NET</a> to <a href="http://www.python.org/">Python</a>. Recently, at one point I suggested to collegues that we try <a href="http://concordion.org/">Concordion</a>, only to learn that there is the <a href="http://docs.python.org/library/doctest.html"><code>doctest module</code></a> that could be used to achieve similar result (more about that in a later post). Remembering my own advice: <a href="/2010/12/when-in-rome-do-as-romans-do.html">When In Rome, Do as the Romans Do</a>, I set out looking for a Python specific book about testing - and the <a href="http://www.packtpub.com/python-testing-cookbook/book">Python Testing Cookbook</a> by <a href="http://pythontestingcookbook.posterous.com/">Greg L. Turnquist</a> book seemed to be a good fit <a href="http://streamhacker.com/2011/07/18/python-testing-cookbook-review/">based on reviews</a>.</p><br/><hr/><br/><p>Overall, I liked the book, and it lived up to my expectations - it provided me with a list of tools and some sample code to get started with each of them. </p><br/><p>Beware that it is an entry level book - if, like me, you are already familiar with the testing concepts, and are looking for a book to learn about advanced testing concepts, theories, this book might be too little for you (or just read through the "There is more" sections of the recipies). But it is great for someone new to testing - though discussions with (and code reviews by) someone experienced in testing should accompany the reading.</p><br/><p>Despite the below criticisms, which are meant to be rather a companion to the book than an advice against it (i.e.: probably the only book I wouldn't find anything missing from and nothing to criticise about would be written for me, in real time, based on my immediate needs). The fact that the list is short shows how I found the rest of the book valuable, with great advices that go beyond the cookbook format (why you shouldn't use <code>fail()</code>, why there should be one assert per test, etc.). While I don't see eye to eye on each topic with the book, but just as the book is not written in a "my way or the highway" style, I will not get into minor differrences of opinion.</p><br/><h2>Format of the book</h2><br/><p>Each chapter explores a topic, with multiple specific recipes. Each recipe is relatively self contained, so if we are in a hurry and need to get to the solution of one specific problem without reading the whole book/chapter, it's possible. However, for those reading whole chapters, this results in a bit of repetition - I had to fight the urge to just gloss over the code I (thought) I had seen before. </p><br/><p>Each recepie follows the format of </p><br/><ul><br/><li>stating the problem</li><br/><li>showing code that solves it</li><br/><li>explaining how the code works</li><br/><li>and finally, providing warnings about pitfalls and problems in the code, and some further advice</li><br/></ul><br/><p>While this format is easy to follow, it has a few drawbacks.</p><br/><ul><br/><li>until I got used to this style, I often found myself cursing out loud like the <a href="http://www.osnews.com/story/19266/WTFs_m">code reviewers in this comic</a> while reading the code that will later be explained to be bad/antipattern. </li><br/><li>each recipe has a lot of additional testing insight, potentially unrelated to the tool being demonstrated - but one can miss these, thinking "oh, I know all about doctest, I'll just skip that chapter"</li><br/><li>for people in a hurry, just scanning the cookbook and copying (typing up) the code - there is nothing to indicate in the code that there is an antipattern there, only in the later paragrpahs - which you might not read when in a hurry. Just thinking about the examples where the unit tests have no asserts but only print statements gives me the shivers (and it's even used for illustration in the chapter about Continious Integration!).</li><br/></ul><br/><h2>What was missing from the book</h2><br/><ul><br/><li>About testing legacy code, I was missing two things: <ul><br/><li>a pointer to Michael Feather's classic book, <a href="http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052">Working Effectively with Legacy Code</a></li><br/><li>a warning about a mistake I have seen almost everyone (myself included) make when getting started with testing legacy code: don't write tests just because you can - only add cases for the area you are working on and only add enough to cover your current needs. This is hinted at, but I've found it's important to state it explicitly.</li><br/></ul><br/></li><br/><li>Notes about test maintainability <ul><br/><li>I strongly disagree with the approach of having one test class per physical class, and test methods directly excercising the class's method. I've found these can lead to maintainability problems down the road, so I prefer to introduce helper abstractions (e.g.: <code>assert_roman_numeral_conversion(expected_result, roman_numeral_string)</code> method) for most of my tests, and organize test methods by logical scenarios instead of mirroring code organizational units (on successful login, validating user input, etc.). These abstraction (indirections) makes it easier to update tests after an API change or refactoring. It might sound like an advanced topic, but I think it's a key concept for effective tests, and one that people should be exposed to early (just after they've made the mental jump from throwaway main methods with visual/human assertions to automated tests with automated assertions).</li><br/><li>Acceptance Testing - it is notoriously difficult for us programmers to <a href="http://blog.objectmentor.com/articles/2009/12/07/writing-maintainable-automated-acceptance-tests">write good acceptance tests</a> that are both maintainable and readable by the customers. I'm rather sure that in the example given in the book, the customers would not be interested in knowing which html tag contains the price in the output. </li><br/></ul><br/></li><br/></ul><br/><h2>Minor criticisms</h2><br/><ul><br/><li>there is an inconsistent level of detail and further pointers. E.g.: while <code>optparse</code> is explained in detail, <code>virtualenv</code> and <code>setuptools</code> are glossed over.</li><br/><li>In addition to the assertless test methods, the other thing that shocked me was the example in the doctest module that - to illustrate that the test works - introduced a bug in the test code. While the fact that test is code and thus can be buggy should be emphasized, but that wasn't the case here. This could leave the reader wondering why exactly we introduced the bug in the test code - aren't we testing the application?</li><br/><li>The book is careful not to fall into the trap of elitist speak that might alienate people, but saying that coupling and cohesiveness are subjective terms is just providing gunpowder to unwinnable arguments(*).</li><br/></ul><br/><h2>Interesting notes</h2><br/><ul><br/><li>This might be a cultural thing (I'm coming from .NET), but I've found it rather surprising that such an entry level book talks about test runners, and write custom test runners. It's useful knowledge, just something that I have not seen mentioned in so much detail in the Java/.NET world so early. Maybe it's got to do with IDEs being more widespread, where running a subset of the tests is easy.</li><br/></ul><br/><p>As said, the book lives up to the expectations, so if you would like to get a quick and practical introduction to testing in pytohn - both tools and concepts, I can recommend this one for you.</p><br/><hr/><br/><p>(*) Reminds me of a story from long ago. The team in question has decided to use bind variables for all SQL invocations (I've said it's been some time ago) to prevent SQL Injection. The one programmer wrote a stored procedure that concatenated the SQL command in its body... and argued that this is just a matter of style. At least the procedure was invoked from the application using bind parameters...</p>

          <hr />
          The post <a hef="http://blog.zsoldosp.eu/2011/10/book-review-python-testing-cookbook-by.html">Book Review - Python Testing Cookbook by Greg L. Turnquist</a> first appeared on <a href="http://blog.zsoldosp.eu">http://blog.zsoldosp.eu</a>.
        ]]></content:encoded>
    </item>
  </channel>
</rss>
