Jekyll2023-06-25T00:01:25-04:00https://marklapierre.net/Mark LapierreCognitive science PhD, software and automation engineer, data science aspirant, perennial student.Mark Lapierre[email protected]https://marklapierre.netUsing GitLab CI/CD for Automated Let’s Encrypt Certificate Deployment2018-11-17T10:20:00-05:002018-11-17T10:20:00-05:00https://marklapierre.net/letsencrypt-auto-gitlab-ci<p>I previously wrote about <a href="/gitlab-pages-custom-domain/">setting up this blog on GitLab Pages</a><sup id="autoletsencrypt-fnr1"><a href="#autoletsencrypt-fn1">1</a></sup>. Back then I set up HTTPS <a href="https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/">manually</a>. This post is about how I’ve automated that process using <a href="https://about.gitlab.com/product/continuous-integration/">GitLab CI/CD</a> and <a href="https://github.com/JustinAiken">Justin Aiken’s</a> <a href="https://github.com/JustinAiken/jekyll-gitlab-letsencrypt">jekyll-gitlab-letsencrypt</a> plugin for <a href="http://jekyllrb.com/">Jekyll</a>.</p>
<p>Last time I used <a href="https://github.com/certbot/certbot">certbot-auto</a> (it was called <code class="highlighter-rouge">letsencrypt-auto</code> at the time) to manually obtain and verify my <a href="https://letsencrypt.org/">Lets’s Encrypt</a> certificate. If you have shell access to your webserver you can use <code class="highlighter-rouge">certbot</code> to automatically update your certificate. But I don’t have shell access; GitLab Pages are for static sites. However, all the steps involved in obtaining, installing, and verifying a Let’s Encrypt certificate can be automated as long as you have access to <em>some</em> kind of shell environment, and can publish the static results of the process.</p>
<p>That’s where GitLab CI/CD comes in.</p>
<p>It’s possible to write your own shell script and add it to your <a href="https://docs.gitlab.com/ee/ci/yaml/"><code class="highlighter-rouge">.gitlab-ci.yml</code></a> file, but thankfully other people have already done that work. In this case, in the form of <a href="https://github.com/JustinAiken/jekyll-gitlab-letsencrypt">jekyll-gitlab-letsencrypt</a>.</p>
<p>Configuring it involved <a href="https://gitlab.com/mlapierre/mlapierre.gitlab.io/commit/3decf69503ede8bf4c4901572df20454be0c889b#de3150c01c3a946a6168173c4116741379fe3579_26_26">adding it to my <code class="highlighter-rouge">Gemfile</code></a>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">group</span> <span class="ss">:jekyll_plugins</span> <span class="k">do</span>
<span class="n">gem</span> <span class="s1">'jekyll-gitlab-letsencrypt'</span>
<span class="k">end</span>
</code></pre></div></div>
<p>And then <a href="https://gitlab.com/mlapierre/mlapierre.gitlab.io/commit/3decf69503ede8bf4c4901572df20454be0c889b#cd089ae45ce870c45e434019e8f1ed4f066cd425_178_178">updating my <code class="highlighter-rouge">_config.yml</code></a>:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">gitlab-letsencrypt</span><span class="pi">:</span>
<span class="c1"># Gitlab settings:</span>
<span class="na">gitlab_repo</span><span class="pi">:</span> <span class="s1">'</span><span class="s">mlapierre/mlapierre.gitlab.io'</span> <span class="c1"># Namespaced repository identifier</span>
<span class="c1"># Domain settings:</span>
<span class="na">email</span><span class="pi">:</span> <span class="s1">'</span><span class="s">[email protected]'</span> <span class="c1"># Let's Encrypt email address</span>
<span class="na">domain</span><span class="pi">:</span> <span class="s1">'</span><span class="s">marklapierre.net'</span> <span class="c1"># Domain that the cert will be issued for</span>
<span class="c1"># Jekyll settings:</span>
<span class="na">base_path</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/'</span> <span class="c1"># Where you want the file to go</span>
<span class="na">pretty_url</span><span class="pi">:</span> <span class="no">true</span> <span class="c1"># Add a "/" on the end of the URL</span>
<span class="na">filename</span><span class="pi">:</span> <span class="s1">'</span><span class="s">_pages/letsencrypt_challenge.html'</span>
<span class="c1"># Delay settings:</span>
<span class="na">initial_delay</span><span class="pi">:</span> <span class="m">180</span> <span class="c1"># How long to wait for Gitlab CI to push your changes before it starts checking</span>
</code></pre></div></div>
<p>And then <a href="https://gitlab.com/mlapierre/mlapierre.gitlab.io/commit/10f9a64c5d49b25a3664dd1c2b16a09047dd6372">adding a job to my <code class="highlighter-rouge">.gitlab-ci.yml</code></a>:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">renew-letsencrypt</span><span class="pi">:</span>
<span class="na">stage</span><span class="pi">:</span> <span class="s">build</span>
<span class="na">script</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">bundle install</span>
<span class="pi">-</span> <span class="s">bundle exec jekyll letsencrypt</span>
<span class="na">only</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">schedules</span>
</code></pre></div></div>
<p>Items in <a href="https://docs.gitlab.com/ee/ci/yaml/README.html#only-and-except-simplified"><code class="highlighter-rouge">only</code></a> specify how the <code class="highlighter-rouge">renew-letsencrypt</code> job can be executed. The <a href="https://docs.gitlab.com/ee/user/project/pipelines/schedules.html#using-only-and-except"><code class="highlighter-rouge">schedules</code></a> option allows the job to be run in a schedule.</p>
<p>And here is a scheduled pipeline that runs once a week:</p>
<p><img src="/assets/images/letsencrypt_renew_pipeline.png" alt="Let's Encrypt renew pipeline schedule settings" /></p>
<p>Let’s Encrypt certificates expire after 90 days but you can make the request to renew them as frequently as you like (<a href="https://letsencrypt.org/docs/rate-limits/">within limits that most people wouldn’t reach</a>).</p>
<p>For the plugin to work it needs push access to my blog’s repository on GitLab, and for that it needs a <a href="https://gitlab.com/profile/personal_access_tokens">personal access token</a>. If you want to use <code class="highlighter-rouge">jekyll-gitlab-letsencrypt</code> locally and will never publish your <code class="highlighter-rouge">_config.yml</code> you can provide your personal access token via:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">gitlab-letsencrypt</span><span class="pi">:</span>
<span class="na">personal_access_token</span><span class="pi">:</span> <span class="s1">'</span><span class="s">ENTER</span><span class="nv"> </span><span class="s">SECRET</span><span class="nv"> </span><span class="s">HERE'</span>
</code></pre></div></div>
<p>But if you use GitLab CI/CD you can provide it more securely via an environment variable, <code class="highlighter-rouge">GITLAB_TOKEN</code>. You can do that via Settings -> CI/CD -> <a href="https://docs.gitlab.com/ee/ci/variables/README.html#variables">Variables</a>:</p>
<p><img src="/assets/images/settings_ci-cd_variables.png" alt="GITLAB_TOKEN in CI/CD Variables" /></p>
<p>When the <a href="https://gitlab.com/mlapierre/mlapierre.gitlab.io/-/jobs/119001388">scheduled job executes</a>, the plugin takes care of publishing the challenge file that the Let’s Encrypt service verifies, and then it uses the GitLab API to update my certificate in my GitLab Pages settings:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ bundle exec jekyll letsencrypt
Configuration file: /builds/mlapierre/mlapierre.gitlab.io/_config.yml
Registering [email protected] to https://acme-v01.api.letsencrypt.org/...
Pushing file to Gitlab
Commiting challenge file as _pages/letsencrypt_challenge.html
Done Commiting! Check https://gitlab.com/mlapierre/mlapierre.gitlab.io/commits/master
Going to check http://marklapierre.net/.well-known/acme-challenge/d7D2-lvQqQJSolI42L9RSaOjQYBQrBSQsFWdzYELLJM/ for the challenge to be present...
Waiting 180 seconds before we start checking for challenge..
Got response code 200, file is present!
Requesting verification...
Challenge status = pending
Challenge is valid!
Updating domain marklapierre.net pages setting with new certificates..
Success!
All finished! Don't forget to `git pull` in order to bring your local repo up to date with changes this plugin made.
Job succeeded
</code></pre></div></div>
<p>And now I don’t have to bother manually updating my certificate. Many thanks to <a href="https://justinaiken.com/">Justin</a> and everyone else who did all the hard work!</p>
<hr />
<p style="font-size:12px" id="autoletsencrypt-fn1"><a href="#autoletsencrypt-fnr1">1.</a> In the interest of transparency, I should note that since writing that post <a href="https://about.gitlab.com/company/team/#mdlap" title="Mark Lapierre's team page on GitLab.com">I've started working for GitLab</a>. More on that in another post.
</p>Mark Lapierre[email protected]https://marklapierre.netI previously wrote about setting up this blog on GitLab Pages1. Back then I set up HTTPS manually. This post is about how I’ve automated that process using GitLab CI/CD and Justin Aiken’s jekyll-gitlab-letsencrypt plugin for Jekyll.Pros and Cons of Quarantined Tests2018-06-06T16:10:00-04:002018-06-06T16:10:00-04:00https://marklapierre.net/pros-cons-quarantined-tests<p>Flaky tests, i.e., those that only fail sometimes, are the bane of any end-to-end automated test suite.</p>
<p>Another type of problem test is one that fails every time but which tests something that is deemed not important enough to fix right now. If you have to ignore some of the failed tests sooner or later you’re going to ignore one that you should have paid attention to. Or worse, you might decide to ignore them all because clearly no-one is fixing the bugs.</p>
<p>If a test is broken, fixing it should always be the first course of action, if possible. But what if some other task has a higher priority? If you’re confident that the problem is the test and not the software being tested, it might be reasonable to allow the test to keep failing, at least temporarily.</p>
<p>When you frequently ignore some failing tests, the whole suite is at risk of being seen as unreliable. A common way to prevent that is to quarantine the flaky/failing tests. Quarantine in this context refers to isolating the troublesome tests from the rest of the test suite. Not for fear of contagion, except in the sense of the negative impact they can have on the perception of the rest of the tests.</p>
<p>I think I first came across the concept in <a href="https://martinfowler.com/articles/nonDeterminism.html">an article by Martin Fowler</a>. It’s a great read on the topic of flaky tests and how to identify and resolve the causes of their flakiness. This post isn’t about how to fix them so check out that article if you’re after that kind of info.</p>
<p>More recently, <a href="https://testing.googleblog.com/2016/05/flaky-tests-at-google-and-how-we.html">an article on the Google Testing Blog</a> mentioned the same technique for dealing with the same types of troublesome tests.</p>
<p>Even though quarantining tests can be a good temporary solution, if you don’t fix the tests (or the bugs) you can end up in the situation I mentioned before; a few failing tests create the impression that the entire suite is unreliable, enough so that you might consider them <a href="https://testbitsblog.wordpress.com/2018/04/04/quarantining-failing-tests-is-a-death-sentence/">a death sentence</a>.</p>
<p>My team and try to avoid that death sentence in a few ways:</p>
<ol>
<li>
<p>Report quarantined test results separately from the rest of the test suite.</p>
<p>That way everyone can see the results of the reliable tests and know that a failure there is something that should be looked at immediately. We don’t have to try to identify the “true” failures amongst the flaky ones.</p>
</li>
<li>
<p>Tag quarantined tests with a reason they’re quarantined.</p>
<p>So flaky tests get tagged as such. Failing tests that aren’t going to get fixed for a while get reported and tagged with the issue number. Comments can be added if the tag isn’t sufficient. This isn’t enough to rescue a quarantined test from oblivion, but it can help avoid the potential problem of losing track of why a test was quarantined.</p>
</li>
<li>
<p>Schedule a regular review of quarantined tests.</p>
<p>If it’s not scheduled it’s not likely to happen. Failing tests can be assigned to someone to fix if priorities change, and time can be invested in fixing a flaky test if we decide it’s more important than we first thought.</p>
</li>
<li>
<p>Delete the test</p>
<p>If any test stays in quarantine for a long time it would be worthwhile rethinking the value the test provides. Maybe it turns out that unit tests, or even exploratory tests, provide enough coverage. Or the test might cover a part of the software that rarely changes, or which doesn’t get much use. In that case if there is a regression it’s not a big deal. We might <code class="highlighter-rouge">@Ignore</code> the test and leave a comment explaining why—instead of deleting it—if it seems likely someone might decide to write the test again.</p>
</li>
</ol>
<p>How do you deal with flaky or failing tests that don’t get fixed quickly?</p>Mark Lapierre[email protected]https://marklapierre.netFlaky tests, i.e., those that only fail sometimes, are the bane of any end-to-end automated test suite. Quarantining tests can be a good temporary solution, but if you don't fix them (or the bugs) a few failing tests create the impression that the entire suite is unreliable. So what can you do?Inattentional Blindness and Scripted Tests2018-05-08T17:40:00-04:002018-05-08T17:40:00-04:00https://marklapierre.net/inattentional-blindness-scripted-tests<p>My previous workplace was a large organisation in which many testers were employed to evaluate the quality of the software we developed and maintained. We had a collection of scripted test cases that testers would follow step-by-step. That worked reasonably well, although I was employed to help automate our processes, including testing, which contributed significantly to the quality of our software.</p>
<p>When I started working at my current workplace I found similarly detailed scripted test cases. Part of my responsibilities included manual testing, so I thought I could test the way I was familiar with, and how the rest of my colleagues tested—just follow the test cases. It hasn’t worked well. We find bugs, for sure, but as I’ve grown in experience I’ve found more and more problems with the software that had been there for a long time, through many versions of the software and through many executions of test cases that should have revealed them.</p>
<p>There are at least a few things that I think explain why we, including my past self, failed to identify problems:</p>
<ol>
<li><strong>Out-of-date test cases.</strong> Change happens constantly and we have too many tests with too much detail for our small QA team to keep up with.</li>
<li><strong>Treating test cases like an instruction manual.</strong> It’s relatively easy for an experienced tester to follow the steps of a scripted test case to the letter, assuming the steps are accurate. That was our standard practice. But it’s even easier to miss out on opportunities to reveal bugs if you do that.</li>
<li><strong>Overwhelming detail.</strong> Many test cases are so long, verbose, and complicated that it’s very easy to miss important details in the steps and expected results, especially when you’re under pressure to get the job done quickly.</li>
<li><strong>Unnecessarily specific detail.</strong> Often a test case instructs the tester to use a particular element of the UI in a particular way. E.g., “enter a value in the Account text field and click the Validate button at the bottom of the panel.” That sort of specificity means the other fields are likely to be ignored, as well as ignoring all the other ways that validation could be triggered. And that problem is in addition to making it hard to keep the test case up to date (because sooner or later, that Validate button is going to move, or be removed entirely).</li>
</ol>
<p>The last three points have something in particular in common. They all trigger a cognitive phenomenon called <a href="https://en.wikipedia.org/wiki/Inattentional_blindness">inattentional blindness</a>. It’s something that we all experience, whether we’re aware of it or not<sup id="fnr1"><a href="#fn1">1</a></sup>. A well-known demonstration of the phenomenon comes from a psychological study and you can perform the experiment from the study yourself by watching a video and following the instructions at the start:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/vJG698U2Mvo?rel=0" frameborder="0" allow="encrypted-media" allowfullscreen=""></iframe>
<p><br />
If you haven’t done so already, I strongly recommend you do the experiment first before you read on—this is something you really only get to experience once, although there are <a href="https://www.youtube.com/watch?v=FWSxSQsspiQ">variations</a> of it. Although it’s likely something you’ll experience again and again in real life.</p>
<p><a href="https://doi.org/10.1068/p281059">The study</a> and <a href="https://en.wikipedia.org/wiki/Inattentional_blindness#Experiments">others like it</a> find that half of the time on average, people fail to notice the unexpected element. They’re asked to perform a task and they’re focused so intently on it that they fail to perceive something <em>they’re looking right at</em>. It’s one of the reasons using your phone while driving is so dangerous, even hands-free; if your attention is on the text/app/call it’s not on the road.</p>
<p>That kind of inattentional blindness is exactly what can happen when you follow a scripted test. You focus on the steps you have to follow and the results you have to check for and you fail to notice anything else. The software can behave in unexpected ways, but you might miss it if you’re only paying attention to what the test case says should happen. Even if you’re looking right at the problem. Missing the unexpected becomes more likely the longer you’re doing the task and the more anxious you are about completing it quickly.</p>
<p>I’m certainly not the first to draw the link between inattentional blindness and scripted tests. Michael Bolton, for one, has <a href="http://www.developsense.com/blog/index.php?s=inattentional+blindness">mentioned it a few times on his blog</a>. But it’s particularly relevant to me now as I try to improve our testing practices. Whatever changes we make, we need to be aware of the potential for inattentional blindness.</p>
<p>For now it’s clear to me that the scripted, highly-detailed test cases we’re used to at my workplace are getting in the way of us improving the quality of our software. Part of the solution is a more exploratory approach to testing. <a href="http://www.developsense.com/blog/2018/04/very-short-blog-posts-34-checking-inside-exploration/#comment-294393">One suggestion</a> is that instead of following a test case step-by-step, you could:</p>
<blockquote>
<p>glance over the test case; try to discern the task that’s being modeled or the information that’s being sought; then try to fulfill the task without referring to the test case. That puts the tester in command to try the task and stumble over problems in getting to the goal. Since the end user is not going to be following the test case either, those problems are likely to be bugs.</p>
</blockquote>
<p>For those interested, there is more information about <a href="http://www.scholarpedia.org/article/Inattentional_blindness">inattentional blindness on Scholarpedia</a>, including references to the original research publications.</p>
<p>How do you avoid inattentional blindness while you’re testing? I haven’t set up a commenting system here yet but <a href="https://dev.to/mlapierre/inattentional-blindness-and-scripted-tests-2m24">this article is cross-posted to dev.to</a> and you’re welcome to comment there.</p>
<p style="font-size:12px" id="fn1"><a href="#fnr1">1.</a> Technically, we're never aware of it. That's the <em>inattentional</em> part.
</p>Mark Lapierre[email protected]https://marklapierre.netMy previous workplace was a large organisation in which many testers were employed to evaluate the quality of the software we developed and maintained. We had a collection of scripted test cases that testers would follow step-by-step. That worked reasonably well, although I was employed to help automate our processes, including testing, which contributed significantly to the quality of our software.From GitHub to GitLab pages2018-05-01T19:10:00-04:002018-05-01T19:10:00-04:00https://marklapierre.net/gitlab-pages-custom-domain<p>I started this site on <a href="https://pages.github.com/">GitHub Pages</a> because:</p>
<ol>
<li>I was already using GitHub</li>
<li>I didn’t want to have to deal with hosting</li>
<li>It’s free</li>
</ol>
<p>But I’d been meaning to set up my own domain for a while<sup id="fnr1"><a href="#fn1">1</a></sup> and although GitHub pages supports custom domains it didn’t seem to support HTTPS on custom domains. And there’s no way I’m setting up a web site in 2018 without HTTPS.</p>
<p>It turns out that <a href="https://github.com/isaacs/github/issues/156#issuecomment-377262435">support for HTTPS with custom domains is gradually being rolled out now</a>, and it’s possible to <a href="https://github.com/isaacs/github/issues/156#issuecomment-380159640">set it up yourself</a>. But there’s no mention of this in the documentation, and <a href="https://github.com/isaacs/github/issues/156#issuecomment-366542067">word from GitHub Support</a> doesn’t suggest it’ll be official any time soon. And it hasn’t been rolled out to my account yet.</p>
<p>So I looked into GitLab as an alternative. I liked what I found. Not only is there <a href="https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html">extensive documentation</a>, but there’s also <a href="https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/">an official tutorial</a>.</p>
<p>I won’t say it was easy, but unless something has gone terribly wrong you’re reading this over a secure connection certified by <a href="https://letsencrypt.org/">Let’s Encrypt</a>.</p>
<p>I followed the instructions to <a href="https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html#add-your-custom-domain-to-gitlab-pages-settings">add my domain to my GitLab pages settings</a>, and to <a href="https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html#dns-a-record">configure the DNS records for my domain</a>. There are a few helpful links to how-to pages for specific hosts, but none for my registration service. Fortunately, the instruction provided were sufficient.</p>
<p>Before I delved into HTTPS I wanted to make sure the domain setup was behaving as expected. It was not. When I tried to open a link to my site I got a 404 back. The DNS record was directing the request to the correct server, but the server wasn’t associating the request with my GitLab Pages repository. It was then that I realised the project name still ended in github.com, not gitlab.com. When I imported my GitHub repository, the import function on GitLab copied the original repo’s name, <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/43991"><em>ignoring the new name it allowed me to enter</em></a>. No matter, I thought, there’s an option to change the name. So I did that. But still my site threw up a 404. It seems that I’d only changed the name of my <em>project</em>, i.e., the display name. I had to hunt down the setting to change the name of the repository itself (Settings > Advanced Settings > Rename repository). But once I’d updated that I could finally access my site via <a href="https://marklapierre.net" title="This site">marklapierre.net</a>.</p>
<p>And, finally, the HTTPS configuration. I followed <a href="https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/">the tutorial</a> and ran the <code class="highlighter-rouge">letsencrypt-auto</code> <a href="https://en.wikipedia.org/wiki/Command-line_interface">CLI</a> to set up a challenge response that would confirm for Let’s Encrypt that I control marklapierre.net. Unfortunately, at some point after the instructions were written <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/35853">GitLab Pages and Jekyll stopped accepting permalinks with dots in them</a>. Fortunately, <a href="https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/#comment-3685550418">someone pointed this out in the comments on the tutorial</a> along with the solution—end the permalink with <code class="highlighter-rouge">/</code> not <code class="highlighter-rouge">.html</code>.</p>
<p>So now I have a secure site on my own domain. Huzzah!</p>
<p>[<em>Update: on the same day I published this, <a href="https://blog.github.com/2018-05-01-github-pages-custom-domains-https/">GitHub announced support for HTTPS on custom domains</a>. Nice.</em>]</p>
<p style="font-size:12px" id="fn1"><a href="#fnr1">1.</a> Someone else got <a href="http://marklapierre.com" title="no relation">marklapierre.com</a>. Last update in 2014? C'mon Mark, you're killing me!
</p>Mark Lapierre[email protected]https://marklapierre.netI started this site on GitHub Pages because:Science and software testing2018-04-22T19:31:00-04:002018-04-22T19:31:00-04:00https://marklapierre.net/science-and-software-testing<p>Software testing, particularly manual software testing, is sometimes thought of as nothing more than following a script to confirm that the software does what it was designed to do. From that perspective, testing might seem like a boring and relatively mindless task. And to be honest, that <em>is</em> <a href="https://qacomplete.com/resources/articles/what-is-manual-testing/#manual_testing_as_script_following">the traditional view</a> of testing as part of the Waterfall method of software development in large organisations. Division of labour meant that there were some people who did nothing but follow scripts someone else had written, and report bugs that someone else would fix.</p>
<p>Science, on the other hand, is undeniably interesting and challenging. So if you share the impression that software testing is boring, you might be suprised to know that I find both engaging and worth spending my time and effort on<sup id="fnr1"><a href="#fn1">1</a></sup>. Having worked as a software tester, and having studied a scientific field (cognitive science), I’ve noticed some similarities that help explain why I’m drawn to both pursuits despite their apparent lack of similarity.</p>
<p><a href="https://en.oxforddictionaries.com/definition/science">Science can be defined as</a>:</p>
<blockquote>
<p>“The intellectual and practical activity encompassing the systematic study of the structure and behaviour of the physical and natural world through observation and experiment.”</p>
</blockquote>
<p>That doesn’t seem to describe following testing scripts at all. Even if you swap “the physical and natural world” for “the software under test”, and even if you include the task of writing scripts. But if you consider the entire process of software testing you’ll see similarities emerge. For one thing, test scripts have to be written based on something, and in today’s world of agile software development, than something is usually <em>not</em> requirements handed down from designers, but rather requirements explored, developed, and refined iteratively. <a href="https://qacomplete.com/resources/articles/what-is-manual-testing/#manual_testing_as_script_following">Observation and experiment are a big part of that iterative process</a>. This is especially the case when working on existing software that doesn’t have good documentation—how else could you figure out how the software works except through observation and experiment? Even if you have access to the code, it’s unlikely you could read the code and know exactly how the software will behave. And there isn’t always someone else around to ask.</p>
<p>The reality of software testing is a lot more than following a script. A more complete <a href="http://www.satisfice.com/blog/archives/856">definition of testing</a> is that:</p>
<blockquote>
<p>“Testing is the process of evaluating a product by learning about it through exploration and experimentation, which includes to some degree: questioning, study, modeling, observation, inference, etc.”</p>
</blockquote>
<p>When defined that way, it’s much clearer how testing and science are similar. Questioning, study, modeling, observation, and inference are all core aspects of science and testing.</p>
<p>In testing, we question whether the software does what we expect it to do. We question whether it does what customers want it to do and in the way they want. We question whether a code change has unintended effects. We study how the software behaves under various conditions. We construct models of how we believe the software performs, even if they’re only mental models. We observe how the software responds to input. And ultimately we make inferences about the quality of the software.</p>
<p>Another similarity between science and software testing is that neither process truly has an end. There is always more to discover through science, even at the end of a project that has produced significant insights. And there is always more to learn about any but the simplest software. In the case of science and testing, it’s not meaningful to think of the entire process as having a goal, but it is necessary to define a reasonable milestone as the completion of a project. We don’t finish testing when there are no bugs, because that will never happen, but we can consider testing complete when the software behaves well under a reasonable range of scenarios.</p>
<p>Science is often described as trying to prove things<sup id="fnr2"><a href="#fn2">2</a></sup>. That is not the aim of science, nor is it how science works. <a href="https://undsci.berkeley.edu/article/0_0_0/whatisscience_04">Science is, in part, a way of trying to better understand the world</a>. And science is the knowledge produced by that process. The scientific method involves making a hypothesis and then gathering evidence and analysing data to draw conclusions about whether the hypothesis is supported. It’s possible to find evidence that rules out a hypothesis, but it’s not possible find evidence that a particular hypothesis is <em>the only</em> explanation for the data. This is because other hypotheses might explain that evidence just as well, including hypotheses that no-one has come up with yet. But after carefully analysing the results of many experiments a clearer understanding can begin to emerge (in the form of a theory). In that way you can think of science as showing what doesn’t work until there’s a reasonably solid explanation left. It’s not about being right; it’s about being less wrong.</p>
<p>Similarly, testing isn’t about proving that the software is bug free; it’s about providing evidence that you can use the software without any significant issues, so that what’s left is reasonably solid. It’s also not about proving that the software does exactly what the customer wants, but it is about helping to iteratively improve the customer’s satisfaction with the software. This is an important part of software testing that’s sometimes forgotten—the aim isn’t solely to find bugs, but also to find unexpected, unusual, or confusing behaviour.</p>
<p>On the other hand, there are plenty of ways in which science and testing are different. But I’ll leave that for another post.</p>
<p style="font-size:12px" id="fn1"><a href="#fnr1">1.</a> Not so much manual testing specifically, but a comprehensive approach to testing that includes exploratory testing and automation.
<p style="font-size:12px" id="fn2"><a href="#fnr2">2.</a> Do a search for "<a href="https://www.google.com/search?q=science+proves">science proves</a>". It's enough to make a scientist or philosopher or mathematician cry.
</p></p>Mark Lapierre[email protected]https://marklapierre.netSoftware testing, particularly manual software testing, is sometimes thought of as nothing more than following a script to confirm that the software does what it was designed to do. From that perspective, testing might seem like a boring and relatively mindless task. And to be honest, that is the traditional view of testing as part of the Waterfall method of software development in large organisations. Division of labour meant that there were some people who did nothing but follow scripts someone else had written, and report bugs that someone else would fix.We’re neither rock stars nor impostors2017-11-23T17:36:00-05:002017-11-23T17:36:00-05:00https://marklapierre.net/were-neither-rockstars-nor-imposters<p>Recently, <a href="https://rachsmith.com/2017/i-dont-have-imposter-syndrome">Rach Smith raised some important points about how we tend to talk about impostor syndrome:</a></p>
<blockquote>
<ul>
<li>it minimizes the impact that this experience has on people that really do suffer from it.</li>
<li>we’re labelling what should be considered positive personality traits - humility, an acceptance that we can’t be right all the time, a desire to know more, as a “syndrome” that we need to “deal with”, “get over” or “get past”.</li>
</ul>
</blockquote>
<p>If you haven’t read her post yet I highly recommend you do. The issue came up again during <a href="http://developeronfire.com/podcast/episode-288-rachel-smith-connecting-and-delivering">Rach’s chat with Dave on Developer on Fire</a>.</p>
<p>I can’t truly say I’ve experienced impostor syndrome, although I suspect that’s mostly because I’ve often been in small teams where everyone was similarly skilled. For example, I was once one of two novice web developers in a product development team. We <em>really</em> didn’t know what we were doing. I did feel unqualified, but since there was no one more experienced to compare myself against I didn’t feel like an impostor. But I <em>did</em> suffer from low self-confidence and a huge pile of self-doubt. Fortunately, experience and education has helped me come to grips with the limits of my knowledge and ability. I’m sure that self-awareness has contributed to better performance independently of any increase in my skills.</p>
<p>It all got me thinking about my experience with how jobs are advertised and how interviews are conducted, about the pressure to elevate one’s technical skills, about the growing awareness of the importance of <a href="https://en.wikipedia.org/wiki/Soft_skills">“soft” skills</a>, and about the rock star culture that’s promoted in some parts of the industry.</p>
<p>Rach noted that even highly successful senior developers sometimes experience self-doubt and the awareness of gaps in their knowledge. This is something that is all too often missing from discussions about preparing for interviews, especially for highly sought-after positions. We’re always told to prepare extensively (good advice), and to project confidence (sure, projecting a <em>lack</em> of confidence is understandably unhelpful), but the highest quality advice also points out the importance of awareness of the limits of one’s skills and knowledge so that they can be appropriately managed. Much of the advice I remember from my early days suggested I should do my best to cover up my weaknesses. I don’t believe that did anything but lead to feelings of insecurity and inevitably falling apart when the limits of my knowledge were revealed. Later, I received much better advice; to be able to say “I don’t know,” and then to work through the problem aloud, asking questions to fill in the gaps until I <em>do</em> have enough understanding to give a reasonable answer. And isn’t that more or less how we work each day? If anyone actually had the supreme skills and confidence we’re naively advised to portray during interviews, I’m pretty sure they wouldn’t find the job challenging or interesting enough (and would likely inflict their arrogance and the consequences of their boredom on the rest of us).</p>
<p>Another topic missing from good career advice, fortunately less common these days, is the importance of soft skills. As Rach noted, “the most accomplished developers [have] constant awareness of the ‘gap’ in their knowledge and willingness to work towards closing it.” That sort of awareness is as important a soft skill as general social and communication skills. It’s a key part of <a href="https://en.wikipedia.org/wiki/Metacognition">metacognition</a>. The people I’ve experienced most joy in working with are those who freely admit their limitations and strive daily towards eliminating them. That effort shows in their contributions at work that go above and beyond the explicit requirements of their role. Among the worst people to work with are those who do the minimum work required, without any awareness of the opportunities for improvement that pass them by every day. Even worse are those who perform at a similar level while believing that they are in fact contributing much more and at a much greater degree of competence<sup id="fnrdke"><a href="#fndke">1</a></sup>. The latter type of person is unlikely to experience anything that might be called “impostor syndrome”, although if anyone were truly an impostor, it would be them.</p>
<p>Beyond a growing understanding of the importance of interpersonal soft skills, there are many other non-technical skills that make a solid team member. For example, the O*NET database shows <a href="https://www.onetonline.org/link/details/15-1131.00">active learning towards the top of a list of skills seen as important for a programmer</a><sup id="fnrcomm"><a href="#fncomm">2</a></sup>. And yet typical hiring practices overwhelmingly reflect the prioritisation of immediate technical skills. I’m confident that’s a big part of the reason “rock star” developers are those seen as <em>having</em> the greatest skills rather than being most <em>able</em> to learn or improve. And yet the former doesn’t imply the latter, especially if those great skills lie in one highly specific domain; you can learn to do one thing really well without being able to generalise that skill, nor does it mean you possess other distinct but important skills. Other downsides of specialisation are a topic for another post.</p>
<p>Similarly, the poor attitudes and bad behaviours of some workers are accepted because of their technical skills, despite the negative impact they have on the people around them. I suspect this might be a subtle influence on feeling like an imposter; we provide a perverse incentive for people to behave in ways that no reasonable person wants to. Our industry favours those who promote themselves as the best coder, the most knowledgeable developer, the ideal technical candidate, and we (at least implicitly) discourage people from embracing their range of skills and their ability to improve.</p>
<hr />
<p style="font-size:12px" id="fndke"><a href="#fnrdke">1</a>. <a href="https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect">The Dunning-Kruger effect</a> in effect, so to speak.
<p style="font-size:12px" id="fncomm"><a href="#fnrcomm">2</a>. Although communication skills are <a href="https://www.ziprecruiter.com/blog/job-skills-employers-want/">apparently the #1 requirement</a> in computing-related job ads, other soft skills and transferable technical skills are far less frequently mentioned.
</p></p>Mark Lapierre[email protected]https://marklapierre.netRecently, Rach Smith raised some important points about how we tend to talk about impostor syndrome:Summer of Data Science 2017 - Final Update2017-09-09T16:58:00-04:002017-09-09T16:58:00-04:00https://marklapierre.net/data-science/summer-of-data-science-final-update<p>Ok, so it’s not summer any more. My defence is that I did this work during summer but I’m only <em>writing</em> about it now.</p>
<p>To recap, I’d been working on a smart filter; a system to predict articles I’d like based on articles I’d previously found interesting. I’m calling it my rss-thingy / smart filter / information assistant<sup id="fnr1"><a href="#fn1">1</a></sup>. I’m tempted to call it “theia”, short for “the information assistant” and a play on “the AI”, but it sounds too much like a Siri rip-off. Which it’s not.</p>
<p>Aaaanyway, I’d collected 660 interesting articles and 801 that I didn’t find interesting–fewer than expected, but I had to get rid of some that were too short or weren’t articles (e.g., lists of links, or github repositories). There was also a bit of manual work to make sure none of the ‘misses’ were actually ‘hits’. I.e., I didn’t want interesting articles to turn up as misses, so I skimmed through all the misses to make sure they weren’t coincidentally interesting (there were a few). The hits and misses then went into separate folders, ready to be loaded by scikit-learn.</p>
<p>I used scikit-learn to vectorise the documents as a tf-idf matrix, and then trained a linear support vector machine and a naive bayes classifier. Both showed reasonable precision and recall upon my first attempt, but tests on new articles showed that the classifier tended to categorise articles as misses, even if I did find them interesting. This is not particularly surprising; most articles I’m exposed to are not particularly interesting, and such simple models trained on a relatively small dataset are unlikely to be exceptionally accurate in identifying them. I spent a little time tuning the models without getting very far and decided to take a step sideways before going further.</p>
<p>Eventually I’ll want to group potentially interesting articles, so I wrote up a quick topic analysis of the articles I liked, comparing non-negative matrix factorization with latent dirichlet allocation. They did a reasonable job of identifying common themes, including brain research, health research, science, technology, politics, testing, and, of course, data science.</p>
<p>You can see the code for <a href="https://github.com/mlapierre/SoDS17">this informal experiment</a> on github.</p>
<p>In my next experiment (now, not SoDS18!) I plan to refine the predictions by paying more attention to cleaning and pre-processing the data. And I need to brush up on tuning these models. I’ll also use the trained models to make ranked predictions rather than simple binary classifications. The dataset will be a little bigger now at around 800 interesting articles, and a few thousand not-so-interesting.</p>
<p style="font-size:12px" id="fn1"><a href="#fnr1">1.</a> Given all the trouble I have naming things, I'm really glad I haven't had to do any cache-invalidation yet.</p>Mark Lapierre[email protected]https://marklapierre.netOk, so it’s not summer any more. My defence is that I did this work during summer but I’m only writing about it now.Summer of Data Science 2017 - Update 12017-06-28T17:11:12-04:002017-06-28T17:11:12-04:00https://marklapierre.net/data-science/summer-of-data-science-2017-update-1<p>My dataset/corpus is coming together.</p>
<p>It was relatively easy to create a set of text files from the articles I’d saved to Evernote. It’s taking more time to collect a set of articles that I didn’t find interesting enough to save. I’ll make that easier in the future by automatically saving <em>all</em> the articles that pass through my feed reader, but for now I’m grabbing copies from CommonCrawl. This saves me the trouble of crawling dozens of different websites, but I still have to search the CommonCrawl index to find articles among everything else in the index from each site.</p>
<p>I created a list of all the site I’d saved at least one article from, then I downloaded the CommonCrawl index records for each site from the last two years. Next I filtered the records to include only pages that were likely to be articles (e.g., no ‘about’ or ‘contact’ pages, etc.). I took a random sample of up to 100 of the records remaining for each site and downloaded the WARC records, and then extracted and saved each article’s text. I’ll make all the code available once I’ve polished it a little.</p>
<p>The next step will be to explore the dataset a little before diving into topic analysis.</p>Mark Lapierre[email protected]https://marklapierre.netMy dataset/corpus is coming together.Summer of Data Science 20172017-06-14T17:45:17-04:002017-06-14T17:45:17-04:00https://marklapierre.net/data-science/summer-of-data-science-2017<h2 id="goal-to-launch-my-learned-system-for-coping-with-the-information-firehose">Goal: To launch<sup id="fnr1"><a href="#fn1">*</a></sup> my learn’ed system for coping with the information firehose</h2>
<p>I heard about the <a href="https://www.becomingadatascientist.com/2017/05/29/summer-of-data-science-2017/">Summer of Data Science 2017</a> recently and decided to join in. I like learning by doing so I chose a personal project as the focus of my efforts to enhance my data science skills.</p>
<p>For the past <em>forever</em> I’ve been stopping and starting one side-project in particular. It’s a system that searches and filters many sources of information to provide me with articles/papers/web pages relevant to my interests. It will use NLP and machine learning to model my interests and to predict whether I’m likely to find a new article worthwhile. Like a recommender system but just for me, because I’m selfish. Something like <a href="https://winds.getstream.io/">Winds</a>. The idea is to collect all the articles I read/skim/ignore via an RSS reader, and tag those I find interesting. And to build up a Zotero collection of papers of several degrees of quality and interest. Those tagged and untagged articles and papers will comprise my datasets. There is a lot more to this project, but that’s the core of it.</p>
<p>My first (mis)step was to begin building an RSS reader than could automatically gather data on my reading habits that I could use to infer interest based on my behaviour; whether I clicked a link to the full article, how long I spent reading an article, whether I shared it, etc. Recently I decided that was not the best use of my time, as it would be much easier to start with explicitly tagged articles–I can start gathering those without creating a new tool. So I’m doing that by saving interesting articles to Evernote. Today I have just under 900. I can use CommonCrawl to get all the articles I <em>didn’t</em> find interesting on the relevant sites (i.e., the articles that would have appeared in my RSS reader, but which I didn’t save).</p>
<p>There are many things I’ll need to do before I’m done, but all of those depend on having a dataset I can analyse. So my next step will be to turn those Evernote notes and other articles into a dataset suitable for consumption by NLP tools. Given the tools available for transforming text-based datasets from one format to another, I’m not going to spend much time choosing a particular format. I’ll start with a set of plain-text copies of each article and associated metadata, and take it from there.</p>
<p>I’ve been less consistent in gathering research papers. I’ve been saving the best papers I’ve stumbled across, but I could do much better by approaching it as a research project, i.e., do a literature review. That’s a huge task so I’ll focus on analysing web articles first.</p>
<p style="font-size:12px" id="fn1"><a href="#fnr1">*</a>I was going to write "complete" but really, it'll always be changing and will probably never be complete. But ready for automated capture and analysis? Sure, I can make that happen.</p>Mark Lapierre[email protected]https://marklapierre.netGoal: To launch* my learn’ed system for coping with the information firehose I heard about the Summer of Data Science 2017 recently and decided to join in. I like learning by doing so I chose a personal project as the focus of my efforts to enhance my data science skills.Hello, World!2017-06-13T18:05:00-04:002017-06-13T18:05:00-04:00https://marklapierre.net/hello-world<p>Hello, World!</p>
<p>For a programmer this is a mandatory thing. No apologies.</p>Mark Lapierre[email protected]https://marklapierre.netHello, World!