<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ed SSemuwemba's Blog]]></title><description><![CDATA[Ed SSemuwemba's Blog]]></description><link>https://blog.edssemuwemba.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 13 May 2026 19:58:12 GMT</lastBuildDate><atom:link href="https://blog.edssemuwemba.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to work with PostgreSQL on Render]]></title><description><![CDATA[Introduction
Render offers PostgreSQL for free accounts, but the database is deleted after one month.If the data matters to you, the solution is to back it up and recover it.
How to backup
Follow these steps;

Run this command in the terminal to back...]]></description><link>https://blog.edssemuwemba.com/how-to-work-with-postgresql-on-render</link><guid isPermaLink="true">https://blog.edssemuwemba.com/how-to-work-with-postgresql-on-render</guid><category><![CDATA[PostgreSQL]]></category><category><![CDATA[postgres]]></category><category><![CDATA[render]]></category><category><![CDATA[pg_dump]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 10 Jan 2025 14:42:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/t5V1rup9DCY/upload/5e550dd5e005f658934e4483a0573e2f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Render offers PostgreSQL for free accounts, but the database is deleted after one month.<br />If the data matters to you, the solution is to back it up and recover it.</p>
<h2 id="heading-how-to-backup">How to backup</h2>
<p>Follow these steps;</p>
<ol>
<li><p>Run this command in the terminal to backup the PostgreSQL DB:</p>
<pre><code class="lang-sql"> pg_dump -h dpg-cn9if6fsc6pc74fh6pd0-a.oregon-postgres.render.com -U mysite mysite_d75u -n public <span class="hljs-comment">--no-owner &gt; database_dump.sql</span>
</code></pre>
</li>
<li><p>What each of the values in <code>1</code> above means can be found in <code>6</code> below</p>
</li>
<li><p>You will be prompted to input a password. The password can be obtained by following the steps described in <code>7</code> below.</p>
</li>
<li><p>In case your system <code>pg_dump</code> doesn’t match the server version, you might get the error below;</p>
<pre><code class="lang-bash"> pg_dump: error: server version: 16.4 (Debian 16.4-1.pgdg120+2); pg_dump version: 14.13 (Homebrew)
 pg_dump: error: aborting because of server version mismatch
</code></pre>
</li>
<li><p>To resolve this error, use the <code>pg_dump</code> that matches the server’s. Something like so;</p>
<pre><code class="lang-sql"> /opt/homebrew/opt/postgresql@16/bin/pg_dump -h dpg-cn9if6fsc6pc73fd6pc0-a.oregon-postgres.render.com -U mysitte mysite_d75u -n public <span class="hljs-comment">--no-owner &gt; database_dump.sql</span>
</code></pre>
</li>
<li><p>Replace the relevant values with the ones that match yours as described in the render dashboard;</p>
<ol>
<li><p><code>dpg-cn9if6fsc6pc74fh6pd0-a</code> : your Hostname</p>
</li>
<li><p><a target="_blank" href="http://oregon-postgres.render.com"><code>oregon-postgres.render.com</code></a>: your database region</p>
</li>
<li><p><code>mysite</code> : your database_username</p>
</li>
<li><p><code>mysite_d75u</code> : your database_name</p>
</li>
</ol>
</li>
<li><p>The values are obtained by the following steps;</p>
<ol>
<li><p>Log into render</p>
</li>
<li><p>Go to <code>projects</code></p>
</li>
<li><p>Under <code>services</code>, click PostgreSQL <code>service name</code></p>
</li>
<li><p>The details will be under the <code>connections</code> above <code>Access Control</code></p>
</li>
</ol>
</li>
</ol>
<h2 id="heading-how-to-drop-the-db">How to drop the DB</h2>
<p>Follow these steps;</p>
<ol>
<li><p>Run this command to drop the PostgreSQL DB:</p>
<pre><code class="lang-sql"> /opt/homebrew/opt/postgresql@16/bin/dropdb -h dpg-cn9if6fsc6pc73fd6pc0-a.oregon-postgres.render.com -U mysite mysite_d75u
</code></pre>
</li>
<li><p>You will be prompted to input the password.</p>
</li>
</ol>
<h2 id="heading-how-to-create-and-restore-the-db">How to create and restore the DB</h2>
<p>Follow these steps;</p>
<ol>
<li><p>Run this command to create a new PostgreSQL DB:</p>
<pre><code class="lang-sql"> /opt/homebrew/opt/postgresql@16/bin/createdb dpg-cn9if6fsc6pc73fd6pc0-a.oregon-postgres.render.com -U mysite mysite_d75u
</code></pre>
</li>
<li><p>Run this to restore your PostgreSQL DB from the backup</p>
<pre><code class="lang-sql"> psql -h dpg-cn9if6fsc6pc73fd6pc0-a.oregon-postgres.render.com -U mysite mysite_d75u &lt; database_dump.sql
</code></pre>
</li>
<li><p>You will be prompted to input the password</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Shout out to <a target="_blank" href="https://x.com/silumesii?s=21">Silumesii</a> who greatly assisted with this.<br />With this guide, you can back up, delete and restore your PostgreSQL DB on render.<br />I plan to explore a way of automating this process.</p>
]]></content:encoded></item><item><title><![CDATA[How to deploy a Rails 7 app to Render]]></title><description><![CDATA[Introduction
Heroku no longer has a free tier. This blog post lists the reasons why.Heroku used to be my go-to service for experimenting with new frameworks. I would generate the starter app, and then deploy it to Heroku.Then I would continue to incr...]]></description><link>https://blog.edssemuwemba.com/how-to-deploy-a-rails-7-app-to-render</link><guid isPermaLink="true">https://blog.edssemuwemba.com/how-to-deploy-a-rails-7-app-to-render</guid><category><![CDATA[Rails 7.1]]></category><category><![CDATA[render]]></category><category><![CDATA[Rails]]></category><category><![CDATA[deployment]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 31 May 2024 09:58:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/mcCAFvlzZFQ/upload/32f56e0a4d54bdc0f3e7618f93d08b54.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>Heroku no longer has a free tier. <a target="_blank" href="https://blog.heroku.com/next-chapter">This</a> blog post lists the reasons why.<br />Heroku used to be my go-to service for experimenting with new frameworks. I would generate the starter app, and then deploy it to Heroku.<br />Then I would continue to incrementally build on what had been deployed.</p>
<p>I searched for options and came across <a target="_blank" href="https://render.com/">Render</a> and <a target="_blank" href="https://fly.io">Fly.io</a>.<br />I was particularly interested in a service that could host a Ruby on Rails app and a PostgreSQL database.<br />I decided to experiment with Render.</p>
<h1 id="heading-adding-the-necessary-files">Adding the necessary files</h1>
<p>The following files are necessary as a prerequisite to make the deployment possible;</p>
<ol>
<li><p><code>render.yaml</code></p>
</li>
<li><p><code>render-build.sh</code></p>
</li>
</ol>
<p><code>render.yaml</code> is added to the root</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">databases:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">rumblr</span>
     <span class="hljs-attr">databaseName:</span> <span class="hljs-string">rumblr</span>
     <span class="hljs-attr">user:</span> <span class="hljs-string">root</span>
     <span class="hljs-attr">plan:</span> <span class="hljs-string">free</span>

 <span class="hljs-attr">services:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">web</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">rumblr</span>
     <span class="hljs-attr">runtime:</span> <span class="hljs-string">ruby</span>
     <span class="hljs-attr">plan:</span> <span class="hljs-string">free</span>
     <span class="hljs-attr">buildCommand:</span> <span class="hljs-string">"./bin/render-build.sh"</span>
     <span class="hljs-comment"># preDeployCommand: "./bin/rails db:migrate" # preDeployCommand only available on paid instance types</span>
     <span class="hljs-attr">startCommand:</span> <span class="hljs-string">"./bin/rails server"</span>
     <span class="hljs-attr">envVars:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">key:</span> <span class="hljs-string">DATABASE_URL</span>
         <span class="hljs-attr">fromDatabase:</span>
           <span class="hljs-attr">name:</span> <span class="hljs-string">rumblr</span>
           <span class="hljs-attr">property:</span> <span class="hljs-string">connectionString</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">key:</span> <span class="hljs-string">RAILS_MASTER_KEY</span>
         <span class="hljs-attr">sync:</span> <span class="hljs-literal">false</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">key:</span> <span class="hljs-string">WEB_CONCURRENCY</span>
         <span class="hljs-attr">value:</span> <span class="hljs-number">2</span> <span class="hljs-comment"># sensible default</span>
</code></pre>
<p><code>render-build.sh</code> is added to <code>bin</code> directory</p>
<pre><code class="lang-bash"> <span class="hljs-comment">#!/usr/bin/env bash</span>
 <span class="hljs-comment"># exit on error</span>
 <span class="hljs-built_in">set</span> -o errexit

 bundle install
 ./bin/rails assets:precompile
 ./bin/rails assets:clean
 ./bin/rails db:migrate
</code></pre>
<h1 id="heading-deployment">Deployment</h1>
<h2 id="heading-sign-in-with-github">Sign in with GitHub</h2>
<p>An account is required to access Render services.<br />I created one using Github.</p>
<h2 id="heading-create-an-instance">Create an instance</h2>
<p>In the Render Dashboard;</p>
<ol>
<li><p>Click on Blueprints</p>
</li>
<li><p>Then click on the New Blueprint instance</p>
</li>
<li><p>Select your repository</p>
</li>
</ol>
<h2 id="heading-deploy-the-app">Deploy the app</h2>
<p>In the deploy window;</p>
<ol>
<li><p>Set the value of <code>RAILS_MASTER_KEY</code> to the contents of <code>config/master.key</code></p>
</li>
<li><p>Then click, <code>Approve</code></p>
</li>
<li><p>Give the deployment process some time to complete</p>
</li>
<li><p>The deployed app should be accessible via: <code>https://app_name.onrender.com</code></p>
</li>
</ol>
<h1 id="heading-conclusion">Conclusion</h1>
<h3 id="heading-what-i-liked-about-render">What I liked about Render</h3>
<ol>
<li><p>The ease of connecting easily to GitHub and selecting the target repo</p>
</li>
<li><p>The fact that new changes to the repo are detected and deployment takes place automatically is awesome.</p>
</li>
</ol>
<h3 id="heading-what-i-didnt-like-about-render">What I didn't like about Render</h3>
<ol>
<li><p>The official render tutorial for deployment didn't specify that we needed to add <code>bin/rails db:migrate</code> to the <code>bin/</code><a target="_blank" href="http://render-build.sh"><code>render-build.sh</code></a> script.</p>
</li>
<li><p>They were not clear on how to handle the Postgres database after the trial period other than stating that I had to upgrade.</p>
</li>
<li><p>Sometimes, I forgot to click sync when new changes were pushed to the GitHub repo, resulting in the deployment not happening automatically.</p>
</li>
</ol>
<p>Shout out to <a target="_blank" href="https://twitter.com/silumesii">Silumesii</a> for the pairing sessions to make this happen and for the idea for this blog post.</p>
]]></content:encoded></item><item><title><![CDATA[Common development issues part 1]]></title><description><![CDATA[Introduction
I usually face specific issues that always come up. I always find myself checking Google for the solution over and over.
I thought that checking on Google over and over was inefficient and to save me and probably others, some time, I wil...]]></description><link>https://blog.edssemuwemba.com/common-development-issues-part-1</link><guid isPermaLink="true">https://blog.edssemuwemba.com/common-development-issues-part-1</guid><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Databases]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 21 Jul 2023 08:57:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/j4ocWYAP_cs/upload/11a1bb3e8c506af2d16c9a8d6439dac4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>I usually face specific issues that always come up. I always find myself checking Google for the solution over and over.</p>
<p>I thought that checking on Google over and over was inefficient and to save me and probably others, some time, I will document some of the issues that I face.</p>
<p>For context, I happen to use an M1 Macbook for development.<br />You might wanna consider your specific situation.<br />Nevertheless, I hope this will be helpful.</p>
<h2 id="heading-postgres-stopping-to-work">Postgres stopping to work</h2>
<p>I am not familiar with how this issue comes up.<br />My database of choice is usually Postgres.<br />But once in a while, when I am testing a Rails app on the development machine, I get this error;</p>
<pre><code class="lang-bash">connection to server on socket <span class="hljs-string">"/tmp/.s.PGSQL.5432"</span> 
failed: No such file or directory 
Is the server running locally and accepting connections on that socket?
</code></pre>
<h3 id="heading-the-solution-to-this-issue">The solution to this issue</h3>
<ol>
<li><p>Open the file <code>/opt/homebrew/var/log/postgres.log</code> to identify the problem. I used homebrew to install <code>postgres</code> so this it's location.</p>
<pre><code class="lang-bash"> 27645 2023-06-22 11:54:14.111 EAT [21939] HINT:  Is another postmaster (PID 776) running <span class="hljs-keyword">in</span> data directory <span class="hljs-string">"/opt/homebrew/var/postgres"</span>?
 27646 2023-06-22 11:54:24.161 EAT [21946] FATAL:  lock file <span class="hljs-string">"postmaster.pid"</span> already exists
 27647 2023-06-22 11:54:24.161 EAT [21946] HINT:  Is another postmaster (PID 776) running <span class="hljs-keyword">in</span> data directory <span class="hljs-string">"/opt/homebrew/var/postgres"</span>?
 27648 2023-06-22 11:54:34.206 EAT [21960] FATAL:  lock file <span class="hljs-string">"postmaster.pid"</span> already exists
 27649 2023-06-22 11:54:34.206 EAT [21960] HINT:  Is another postmaster (PID 776) running <span class="hljs-keyword">in</span> data directory <span class="hljs-string">"/opt/homebrew/var/postgres"</span>?
 27650 2023-06-22 11:54:44.250 EAT [21975] FATAL:  lock file <span class="hljs-string">"postmaster.pid"</span> already exists
</code></pre>
</li>
<li><p>Sure enough, as indicated on lines <code>27648</code>, and <code>2749</code> the error is clear.</p>
</li>
<li><p>Deleting the <code>postmater.pid</code> file in the <code>/opt/homebrew/var/postgres</code> directory should solve this issue.</p>
</li>
<li><p>Delete the <code>postmaster.pid</code> file using: <code>rm -rf /opt/homebrew/var/postgres/postmaster.pid</code></p>
</li>
<li><p>Restart <code>postgres</code> by running: <code>brew services restart postgresql@14</code></p>
</li>
<li><p>Now everything should work fine.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope that this is helpful.<br />Take the time to read and understand the problem.</p>
]]></content:encoded></item><item><title><![CDATA[Valuable insights from the Shape Up book]]></title><description><![CDATA[Introduction
The Shape Up Book details how the folks at 37 Signals handle project management, shipping new products and adding new features and everything else in between.
What I learnt

Experiment to find out what works best for you.

Once you have ...]]></description><link>https://blog.edssemuwemba.com/valuable-insights-from-the-shape-up-book</link><guid isPermaLink="true">https://blog.edssemuwemba.com/valuable-insights-from-the-shape-up-book</guid><category><![CDATA[Productivity]]></category><category><![CDATA[project management]]></category><category><![CDATA[books]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 14 Apr 2023 09:00:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/OXmym9cuaEY/upload/cc4b5249af05834c847f5dee8fb8b948.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>The <a target="_blank" href="https://basecamp.com/shapeup">Shape Up Book</a> details how the folks at 37 Signals handle project management, shipping new products and adding new features and everything else in between.</p>
<h2 id="heading-what-i-learnt">What I learnt</h2>
<ol>
<li><p>Experiment to find out what works best for you.</p>
</li>
<li><p>Once you have determined what methods are effective for you, increase the frequency of using them and make the necessary modifications.</p>
</li>
<li><p>While traditional and well-known systems may sound appealing and get a lot of attention, it's important to consider whether they actually work for you in your daily life.</p>
</li>
</ol>
<h2 id="heading-major-takeaways">Major takeaways</h2>
<ol>
<li><p>To successfully ship a product, it is necessary to make tough choices about what to include and what to leave out.</p>
</li>
<li><p>Trying to fix everything before shipping is impossible.</p>
</li>
<li><p>Prioritizing unknown problems should take precedence.</p>
</li>
<li><p>It's important to acknowledge that there will always be more work than time.</p>
</li>
<li><p>Meeting deadlines means accepting some level of imperfection in the final product.</p>
</li>
</ol>
<h2 id="heading-what-is-being-used-day-to-day">What is being used day-to-day</h2>
<p>A slightly modified idea of "scoping the work" is being used.<br />In <a target="_blank" href="https://github.com/Esseme/rumblr">Rumblr</a>, only one feature is worked on at a time.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The book was full of insights.<br />It will be useful as a reference.</p>
]]></content:encoded></item><item><title><![CDATA[How to setup GitHub Actions CI in a Rails 7 app]]></title><description><![CDATA[What is GitHub Actions
For the uninitiated, GitHub Actions helps automate certain aspects of a software project's build, test and deployment aspects. If your project is already on Github, it makes sense to utilise what GitHub Actions has to offer.The...]]></description><link>https://blog.edssemuwemba.com/how-to-setup-github-actions-ci-in-a-rails-7-app</link><guid isPermaLink="true">https://blog.edssemuwemba.com/how-to-setup-github-actions-ci-in-a-rails-7-app</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[GitHub Actions]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[rails7]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 17 Mar 2023 09:05:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/HpMihL323k0/upload/1534e03fde05c99b167edb8724c56c34.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-what-is-github-actions">What is GitHub Actions</h1>
<p>For the uninitiated, GitHub Actions helps automate certain aspects of a software project's build, test and deployment aspects. If your project is already on Github, it makes sense to utilise what GitHub Actions has to offer.<br />The focus of this write-up is the CI aspect of GitHub Actions.</p>
<h1 id="heading-why-i-did-this">Why I did this</h1>
<p>I set out to familiarise myself with how to use GitHub Actions for CI. I wanted to automate the running of the system tests in <a target="_blank" href="https://github.com/Esseme/rumblr">Rumblr</a>.<br />I precisely wanted the CI to run every time I push to a new branch or the main branch and every time a new Pull Request is made.</p>
<h1 id="heading-how-i-achieved-it">How I achieved it</h1>
<p>To get the CI to build, new changes needed to be made and new files needed to be added.</p>
<p>A new file: <code>.env.test</code> had to be created. Below are the contents of the file;</p>
<pre><code class="lang-ruby">EMAIL_RECIPIENTS=test@test.com
FROM_EMAIL=sample@test.com
HONEYBADGER_API_KEY=honeybadger
</code></pre>
<p>A new file for the workflow needed to be added.<br />Below are the contents of the actual CI file which is located via: <code>.github/workflows/config.yml</code></p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">CI</span>

 <span class="hljs-attr">on:</span> [<span class="hljs-string">push</span>,<span class="hljs-string">pull_request</span>]
 <span class="hljs-attr">jobs:</span>
   <span class="hljs-attr">test:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">Tests</span>
     <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
     <span class="hljs-attr">services:</span>
       <span class="hljs-attr">postgres:</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">postgres:12.7</span>
         <span class="hljs-attr">env:</span>
           <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">rumblr</span>
           <span class="hljs-attr">POSTGRES_DB:</span> <span class="hljs-string">rumblr_test</span>
           <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">password</span>
         <span class="hljs-attr">ports:</span> [<span class="hljs-string">"5432:5432"</span>]
         <span class="hljs-attr">options:</span> <span class="hljs-string">&gt;-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
</span>
     <span class="hljs-attr">steps:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">code</span>
         <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>

       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Ruby</span> <span class="hljs-string">and</span> <span class="hljs-string">install</span> <span class="hljs-string">gems</span>
         <span class="hljs-attr">uses:</span> <span class="hljs-string">ruby/setup-ruby@v1</span>
         <span class="hljs-attr">with:</span>
           <span class="hljs-attr">bundler-cache:</span> <span class="hljs-literal">true</span>

       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">postgres</span> <span class="hljs-string">client</span>
         <span class="hljs-attr">run:</span> <span class="hljs-string">sudo</span> <span class="hljs-string">apt-get</span> <span class="hljs-string">install</span> <span class="hljs-string">libpq-dev</span>

       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">test</span> <span class="hljs-string">database</span>
         <span class="hljs-attr">env:</span>
           <span class="hljs-attr">RAILS_ENV:</span> <span class="hljs-string">test</span>
           <span class="hljs-attr">POSTGRES_HOST:</span> <span class="hljs-string">localhost</span>
           <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">rumblr</span>
           <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">password</span>
         <span class="hljs-attr">run:</span> <span class="hljs-string">|
           bin/rails db:setup
</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">tests</span>
         <span class="hljs-attr">env:</span>
           <span class="hljs-attr">RAILS_ENV:</span> <span class="hljs-string">test</span>
           <span class="hljs-attr">POSTGRES_HOST:</span> <span class="hljs-string">localhost</span>
           <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">rumblr</span>
           <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">password</span>
         <span class="hljs-attr">run:</span> <span class="hljs-string">|
           bundle exec rake assets:precompile
           bundle exec rspec</span>
</code></pre>
<p>Some changes needed to be made to the <code>database.yml</code> file. The changes are below;</p>
<pre><code class="lang-yaml"><span class="hljs-attr">test:</span>
   <span class="hljs-string">&lt;&lt;:</span> <span class="hljs-meta">*default</span>
   <span class="hljs-attr">database:</span> <span class="hljs-string">rumblr_test</span>
   <span class="hljs-attr">host:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'POSTGRES_HOST'</span>,  <span class="hljs-string">'localhost'</span>) </span>%&gt;
   <span class="hljs-attr">username:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'POSTGRES_USER'</span>, <span class="hljs-literal">nil</span>) </span>%&gt;
   <span class="hljs-attr">password:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'POSTGRES_PASSWORD'</span>, <span class="hljs-literal">nil</span>) </span>%&gt;
   <span class="hljs-attr">port:</span> &lt;%=<span class="ruby"> ENV.fetch(<span class="hljs-string">'POSTGRES_PORT'</span>, <span class="hljs-number">5432</span>) </span>%&gt;
</code></pre>
<p>These changes were done to the <code>test</code> portion of the database configuration.</p>
<h1 id="heading-challenges-faced">Challenges faced</h1>
<p>Some challenges (as expected) were faced while attempting this task.<br />Consider this <a target="_blank" href="https://github.com/Esseme/rumblr/commit/150a355bff8c9e28809055594489683e0f983ec3">git change log</a> for the challenges that were faced.</p>
<h3 id="heading-the-envtest-file">The <code>.env.test</code> file</h3>
<p>This file had to be included and the suggestion came from a <a target="_blank" href="https://twitter.com/purinkle">colleague</a>.<br />The official Github guides were only partly helpful to assist in setting this up.<br />Otherwise, the build kept on failing and the error didn't make a lot of sense.</p>
<h3 id="heading-the-changes-to-the-test-section-of-the-db-config">The changes to the <code>test</code> section of the DB config</h3>
<p>Consider the <code>config/database.yml</code> file in the <a target="_blank" href="https://github.com/Esseme/rumblr/commit/150a355bff8c9e28809055594489683e0f983ec3">change log</a>.<br />All that had to be added as well for the build to happen successfully.</p>
<h1 id="heading-references">References</h1>
<p>The links below were helpful in achieving this task;</p>
<ol>
<li><p><a target="_blank" href="https://boringrails.com/articles/building-a-rails-ci-pipeline-with-github-actions/">Boring Rails Article</a></p>
</li>
<li><p><a target="_blank" href="https://andycroll.com/ruby/github-actions-ci-for-rails-with-postgresql/">Andy Croll Article</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/a/68258327/2257815">This Stack Overflow answer</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@OwenTran/github-workflow-for-rails-ci-34209a53d19e">Medium Article</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/rails/tailwindcss-rails/issues/153#issuecomment-1191022279">Github Tailwind CSS Issue</a></p>
</li>
</ol>
<h1 id="heading-conclusion">Conclusion</h1>
<p>This is included in the Rumblr project which can be found <a target="_blank" href="https://github.com/Esseme/rumblr">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Learning TDD With RSpec Part 3]]></title><description><![CDATA[This is part 3 (the last) in this series.
Introduction:
In part 2, this was achieved;

Scanning of each of the items, A, B, C, and D was done
The corresponding test was written for each

In part 3, this is going to be handled;

Some house cleaning 
C...]]></description><link>https://blog.edssemuwemba.com/learning-tdd-with-rspec-part-3</link><guid isPermaLink="true">https://blog.edssemuwemba.com/learning-tdd-with-rspec-part-3</guid><category><![CDATA[Ruby]]></category><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[#rspec]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 07 Oct 2022 10:38:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/w0H4K148PGw/upload/v1661522400740/CyU2XYgxC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is part 3 (the last) in this series.</p>
<h3 id="heading-introduction">Introduction:</h3>
<p>In <a href="https://blog.edssemuwemba.com/learning-tdd-with-rspec-part-2">part 2</a>, this was achieved;</p>
<ol>
<li>Scanning of each of the items, A, B, C, and D was done</li>
<li>The corresponding test was written for each</li>
</ol>
<p>In part 3, this is going to be handled;</p>
<ol>
<li>Some house cleaning </li>
<li>Changing <code>CheckOut</code> Spec</li>
<li>Adding <code>PricingRules</code> Spec</li>
<li>Adding <code>PricingRules</code> Class</li>
<li>Adding pricing rules</li>
</ol>
<h3 id="heading-some-house-cleaning">Some House Cleaning:</h3>
<p>The code in the <code>ChecKOut</code> class needs to be included in a separate file under <code>lib/checkout.rb</code></p>
<p>Below is the <code>checkout.rb</code> file:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
    @total = <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    @total
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">'A'</span>
      @total = <span class="hljs-number">50</span>
    <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'B'</span>
      @total = <span class="hljs-number">30</span>
    <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'C'</span>
      @total = <span class="hljs-number">20</span>
    <span class="hljs-keyword">else</span>
      @total = <span class="hljs-number">15</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>The <code>checkout</code> spec needs to included in a separate file under <code>spec/checkout_spec.rb</code></p>
<p>Below is the <code>checkout_spec.rb</code> file:</p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">'checkout'</span>

 RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
   context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">0</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'A'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">50</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when B has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of B'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'B'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">30</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when C has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of C'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'C'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">20</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when D has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of D'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'D'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">15</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-changing-checkout-spec">Changing <code>CheckOut</code> Spec:</h3>
<p>This is the new <code>checkout_spec.rb</code> file:</p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">'checkout'</span>
<span class="hljs-keyword">require</span> <span class="hljs-string">'pricing_rules'</span>

RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
  context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows total of zero'</span> <span class="hljs-keyword">do</span>
      pricing_rules = <span class="hljs-symbol">:Rule</span>
      checkout = CheckOut.new(pricing_rules)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">0</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>·
    it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(
        <span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>})
      checkout = CheckOut.new(pricing_rules)
      checkout.scan(<span class="hljs-string">'A'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">50</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when B has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows the price of B'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(
        <span class="hljs-string">"B"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">30</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">45</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">2</span>})
      checkout = CheckOut.new(pricing_rules)
      checkout.scan(<span class="hljs-string">'B'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">30</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when C has been scanned'</span> <span class="hljs-keyword">do</span>·
    it <span class="hljs-string">'shows the price of C'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(<span class="hljs-string">"C"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">20</span>})
      checkout = CheckOut.new(pricing_rules)
      checkout.scan(<span class="hljs-string">'C'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">20</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when D has been scanned'</span> <span class="hljs-keyword">do</span>·
    it <span class="hljs-string">'shows the price of D'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(<span class="hljs-string">"D"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">15</span>})
      checkout = CheckOut.new(pricing_rules)
      checkout.scan(<span class="hljs-string">'D'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">15</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>This is the new <code>checkout.rb</code> file:</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
     @pricing_rules = pricing_rules
     @items_count = Hash.new(<span class="hljs-number">0</span>)·
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
     @items_count[item] += <span class="hljs-number">1</span>
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
     @items_count.inject(<span class="hljs-number">0</span>) <span class="hljs-keyword">do</span> <span class="hljs-params">|total, (item, count)|</span>
       <span class="hljs-keyword">if</span> item == <span class="hljs-string">'B'</span> <span class="hljs-params">||</span> item == <span class="hljs-string">'A'</span>
         total += @pricing_rules.price_for(item, count)
       <span class="hljs-keyword">else</span>
         total += count*@pricing_rules.unit_price(item)
       <span class="hljs-keyword">end</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-adding-pricingrules-spec">Adding <code>PricingRules</code> Spec:</h3>
<p>This is the <code>pricing_rules_spec.rb</code> file;</p>
<pre><code class="lang-ruby"> <span class="hljs-keyword">require</span> <span class="hljs-string">"pricing_rules"</span>

 RSpec.describe PricingRules <span class="hljs-keyword">do</span>
   describe <span class="hljs-string">"#unit_price"</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">"fetches the unit price for the item"</span> <span class="hljs-keyword">do</span>
       pricing_rules = PricingRules.new(<span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>})

       unit_price = pricing_rules.unit_price(<span class="hljs-string">"A"</span>)

       expect(unit_price).to eq <span class="hljs-number">50</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>

   describe <span class="hljs-string">"#discount_price"</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">"fetches the discount price for the item"</span> <span class="hljs-keyword">do</span>
       pricing_rules = PricingRules.new(<span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>})

       discount_price = pricing_rules.discount_price(<span class="hljs-string">"A"</span>)

       expect(discount_price).to eq <span class="hljs-number">130</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>

   describe <span class="hljs-string">"#discount_count"</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">"fetches the discount count of the item"</span> <span class="hljs-keyword">do</span>
       pricing_rules = PricingRules.new(<span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>})

       discount_count = pricing_rules.discount_count(<span class="hljs-string">"A"</span>)

       expect(discount_count).to eq <span class="hljs-number">3</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>

   describe <span class="hljs-string">"#price_for"</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">"calculates the price for a number of items"</span> <span class="hljs-keyword">do</span>

       pricing_rules = PricingRules.new(
         <span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>})

       price = pricing_rules.price_for(<span class="hljs-string">"A"</span>, <span class="hljs-number">3</span>)

      expect(price).to eq <span class="hljs-number">130</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  describe <span class="hljs-string">"#has_dicount_price"</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">"checks if an item has a discount price"</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(<span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>})

      has_discount = pricing_rules.has_discount_price(<span class="hljs-string">"A"</span>)

      expect(has_discount).to be(<span class="hljs-literal">true</span>)
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-adding-pricingrules-class">Adding <code>PricingRules</code> Class:</h3>
<p>This is the <code>pricing_rules.rb</code> file:</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PricingRules</span>·</span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(rules)</span></span>
     @rules = rules
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">unit_price</span><span class="hljs-params">(item)</span></span>
     @rules[item][<span class="hljs-symbol">:unit_price</span>]
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">discount_price</span><span class="hljs-params">(item)</span></span>
     @rules[item][<span class="hljs-symbol">:discount_price</span>]
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">discount_count</span><span class="hljs-params">(item)</span></span>
     @rules[item][<span class="hljs-symbol">:discount_count</span>]
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">price_for</span><span class="hljs-params">(item, count)</span></span>
     count/discount_count(item) * discount_price(item) +·
     count% discount_count(item) * unit_price(item)·
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">has_discount_price</span><span class="hljs-params">(item)</span></span>
     @rules[item].has_key?(<span class="hljs-symbol">:discount_price</span>)
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>When the <code>pricing_rules_spec</code> tests are run, they pass successfully;</p>
<pre><code class="lang-ruby">./bin/rspec spec/pricing_rules_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">3</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/pricing_rules_spec.rb"</span>=&gt;[<span class="hljs-number">3</span>]}}

Randomized with seed <span class="hljs-number">46467</span>

PricingRules
  <span class="hljs-comment">#has_dicount_price</span>
    checks <span class="hljs-keyword">if</span> an item has a discount price
  <span class="hljs-comment">#price_for</span>
    calculates the price <span class="hljs-keyword">for</span> a number of items
  <span class="hljs-comment">#discount_price</span>
    fetches the discount price <span class="hljs-keyword">for</span> the item
  <span class="hljs-comment">#discount_count</span>
    fetches the discount count of the item
  <span class="hljs-comment">#unit_price</span>
    fetches the unit price <span class="hljs-keyword">for</span> the item

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">0013</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05617</span> seconds to load)
<span class="hljs-number">5</span> examples, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">46467</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h3 id="heading-adding-pricing-rules">Adding Pricing Rules:</h3>
<p>Edit the <code>checkout.rb</code> file to include <code>pricing_rules</code> in the <code>initialize</code> method.</p>
<p>The <code>checkout.rb</code> file changes to:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
    @pricing_rules = pricing_rules
    @total = <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    @total
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">'A'</span>
      @total = <span class="hljs-number">50</span>
    <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'B'</span>
      @total = <span class="hljs-number">30</span>
    <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'C'</span>
      @total = <span class="hljs-number">20</span>
    <span class="hljs-keyword">else</span>·
      @total = <span class="hljs-number">15</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Make certain that written tests still pass and they do as shown below:</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">13654</span>
.....

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00245</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05355</span> seconds to load)
<span class="hljs-number">5</span> examples, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">13654</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>Edit the <code>chekout.rb</code> file further to this;</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
    @pricing_rules = pricing_rules
    @items_count = Hash.new(<span class="hljs-number">0</span>)·
  <span class="hljs-keyword">end</span>
··
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
    @items_count[item] += <span class="hljs-number">1</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    @items_count.inject(<span class="hljs-number">0</span>) <span class="hljs-keyword">do</span> <span class="hljs-params">|total, (item, count)|</span>
      <span class="hljs-keyword">if</span> item == <span class="hljs-string">'B'</span> <span class="hljs-params">||</span> item == <span class="hljs-string">'A'</span>
        total += @pricing_rules.price_for(item, count)
      <span class="hljs-keyword">else</span>
        total += count*@pricing_rules.unit_price(item)
      <span class="hljs-keyword">end</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>This was done to take into account the <code>pricing_rules</code> and <code>items_count</code></p>
<p>Edit the <code>checkout_spec.rb</code> file to gradually include pricing rules information</p>
<h4 id="heading-adding-pricing-rules-to-a">Adding Pricing Rules To A</h4>
<p>Include <code>pricing_rules</code> for the context <code>'when A has been scanned'</code>:</p>
<pre><code class="lang-ruby">context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>
    pricing_rules = PricingRules.new(
      <span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>})
    checkout = CheckOut.new(pricing_rules)

    checkout.scan(<span class="hljs-string">'A'</span>)
    total = checkout.total

    expect(total).to eq <span class="hljs-number">50</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>When the test is run, it passes successfully:</p>
<pre><code class="lang-ruby">./bin/rspec spec/checkout_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">16</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/checkout_spec.rb"</span>=&gt;[<span class="hljs-number">16</span>]}}

Randomized with seed <span class="hljs-number">64567</span>

checkout
  <span class="hljs-keyword">when</span> A has been scanned
    shows the price of A

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00064</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">040</span>95 seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">64567</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h4 id="heading-adding-pricing-rules-to-the-rest-of-the-items">Adding Pricing Rules to the rest of the items:</h4>
<pre><code class="lang-ruby">   context <span class="hljs-string">'when B has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of B'</span> <span class="hljs-keyword">do</span>
       pricing_rules = PricingRules.new(
         <span class="hljs-string">"B"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">30</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">45</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">2</span>})
       checkout = CheckOut.new(pricing_rules)
       checkout.scan(<span class="hljs-string">'B'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">30</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>

   context <span class="hljs-string">'when C has been scanned'</span> <span class="hljs-keyword">do</span>·
     it <span class="hljs-string">'shows the price of C'</span> <span class="hljs-keyword">do</span>
       pricing_rules = PricingRules.new(<span class="hljs-string">"C"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">20</span>})
       checkout = CheckOut.new(pricing_rules)
       checkout.scan(<span class="hljs-string">'C'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">20</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>

   context <span class="hljs-string">'when B, A and then D have been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the total price of B, A and D'</span> <span class="hljs-keyword">do</span>
       pricing_rules = PricingRules.new(
         <span class="hljs-string">"B"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">30</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">45</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">2</span>},
         <span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>},
         <span class="hljs-string">"D"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">15</span>}
       )
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'B'</span>)
       checkout.scan(<span class="hljs-string">'A'</span>)
       checkout.scan(<span class="hljs-string">'D'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">95</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when D has been scanned'</span> <span class="hljs-keyword">do</span>·
    it <span class="hljs-string">'shows the price of D'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(<span class="hljs-string">"D"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">15</span>})
      checkout = CheckOut.new(pricing_rules)
      checkout.scan(<span class="hljs-string">'D'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">15</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when B, A and another B has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows the total discounted price of B plus price of A'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(
        <span class="hljs-string">"B"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">30</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">45</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">2</span>},
        <span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>},
        <span class="hljs-string">"D"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">15</span>}
      )
      checkout = CheckOut.new(pricing_rules)

      checkout.scan(<span class="hljs-string">'B'</span>)
      checkout.scan(<span class="hljs-string">'A'</span>)
      checkout.scan(<span class="hljs-string">'B'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">95</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  context <span class="hljs-string">'when A, A, and another A have been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows the total discounted price of three A items'</span> <span class="hljs-keyword">do</span>
      pricing_rules = PricingRules.new(
        <span class="hljs-string">"A"</span> =&gt; {<span class="hljs-symbol">unit_price:</span> <span class="hljs-number">50</span>, <span class="hljs-symbol">discount_price:</span> <span class="hljs-number">130</span>, <span class="hljs-symbol">discount_count:</span> <span class="hljs-number">3</span>})
      checkout = CheckOut.new(pricing_rules)

      checkout.scan(<span class="hljs-string">'A'</span>)
      checkout.scan(<span class="hljs-string">'A'</span>)
      checkout.scan(<span class="hljs-string">'A'</span>)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">130</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
</code></pre>
<p>Notice that some new contexts have been added;</p>
<ol>
<li>'when B, A and then D have been scanned'</li>
<li>'when B, A and then D have been scanned'</li>
<li>'when A, A, and another A have been scanned'</li>
</ol>
<p>These new contexts are meant to handle the situations for discounts.</p>
<p>These tests run successfully;</p>
<pre><code class="lang-ruby">./bin/rspec spec/checkout_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">4</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/checkout_spec.rb"</span>=&gt;[<span class="hljs-number">4</span>]}}

Randomized with seed <span class="hljs-number">1369</span>

checkout
  <span class="hljs-keyword">when</span> B, A <span class="hljs-keyword">and</span> another B has been scanned
    shows the total discounted price of B plus price of A
  <span class="hljs-keyword">when</span> nothing has been scanned
    shows total of zero
  <span class="hljs-keyword">when</span> A has been scanned
    shows the price of A
  <span class="hljs-keyword">when</span> D has been scanned
    shows the price of D
  <span class="hljs-keyword">when</span> B has been scanned
    shows the price of B
  <span class="hljs-keyword">when</span> A, A, <span class="hljs-keyword">and</span> another A have been scanned
    shows the total discounted price of three A items
  <span class="hljs-keyword">when</span> C has been scanned
    shows the price of C
  <span class="hljs-keyword">when</span> B, A <span class="hljs-keyword">and</span> <span class="hljs-keyword">then</span> D have been scanned
    shows the total price of B, A <span class="hljs-keyword">and</span> D

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00125</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05214</span> seconds to load)
<span class="hljs-number">8</span> examples, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">1369</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h3 id="heading-conclusion">Conclusion:</h3>
<p>This concludes the series.</p>
<p>Shout out to <a href="https://twitter.com/purinkle">Rob</a> for his immense assistance on this and making it easy to comprehend.</p>
<p>The final project can be found <a href="https://github.com/Esseme/checkout_kata">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Learning TDD With RSpec Part 2]]></title><description><![CDATA[This is part 2 of a planned 3 part series
Introduction:
In part 1, this was achieved;

Initialising project
Writing a test for when nothing has been scanned

In part 2, this is going to be handled;

Scanning of A
Scanning of B
Scanning of C
Scanning ...]]></description><link>https://blog.edssemuwemba.com/learning-tdd-with-rspec-part-2</link><guid isPermaLink="true">https://blog.edssemuwemba.com/learning-tdd-with-rspec-part-2</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Testing]]></category><category><![CDATA[#rspec]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 29 Jul 2022 12:59:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/OluDgzgCHp4/upload/v1657877009194/tUmGKQ5l4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is part 2 of a planned 3 part series</p>
<h3 id="heading-introduction">Introduction:</h3>
<p>In <a target="_blank" href="https://blog.edssemuwemba.com/learning-tdd-with-rspec">part 1</a>, this was achieved;</p>
<ol>
<li>Initialising project</li>
<li>Writing a test for when nothing has been scanned</li>
</ol>
<p>In part 2, this is going to be handled;</p>
<ol>
<li>Scanning of A</li>
<li>Scanning of B</li>
<li>Scanning of C</li>
<li>Scanning of D</li>
</ol>
<p>Tests will be run using;</p>
<ol>
<li><code>⎵ + t</code> : run entire test (<code>⎵</code> means the keyboard <code>space bar button</code>)</li>
<li><code>⎵ + l</code> : run last test</li>
<li><code>⎵ + s</code>: run nearest test</li>
</ol>
<h3 id="heading-scanning-of-a">Scanning of A:</h3>
<p>Add another context to check for when <code>A</code> has been scanned. The file changes to this;</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
  context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
      pricing_rules = <span class="hljs-symbol">:Rule</span>
      checkout = CheckOut.new(pricing_rules)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">0</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
  context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>

      expect(total).to eq <span class="hljs-number">50</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Run the test by pressing <code>⎵ + t</code>. We get this error;</p>
<pre><code class="lang-ruby">~
./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">34364</span>
.F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> A has been scanned shows the price of A
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">50</span>

     <span class="hljs-symbol">NameError:</span>
       undefined local variable <span class="hljs-keyword">or</span> method <span class="hljs-string">`total' for #&lt;RSpec::ExampleGroups::Checkout::WhenAHasBeenScanned "shows the price of A" (./spec/check_out_spec.rb:22)&gt;
     # ./spec/check_out_spec.rb:24:in `</span>block (<span class="hljs-number">3</span> levels) <span class="hljs-keyword">in</span> &lt;top (required)&gt;<span class="hljs-string">'

Finished in 0.00256 seconds (files took 0.05539 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/check_out_spec.rb:22 # checkout when A has been scanned shows the price of A

Randomized with seed 34364


shell returned 1

Press ENTER or type command to continue</span>
</code></pre>
<p>Modify the file to add the lines specifying what <code>total</code> is and define <code>pricing_rules</code>;</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
  context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
      pricing_rules = <span class="hljs-symbol">:Rule</span>
      checkout = CheckOut.new(pricing_rules)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">0</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
  context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>
      pricing_rules = <span class="hljs-symbol">:Rule</span>
      checkout = CheckOut.new(pricing_rules)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">50</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>When the test is run, as expected we get the error as shown below;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">5579</span>
.F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> A has been scanned shows the price of A
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">50</span>

       <span class="hljs-symbol">expected:</span> <span class="hljs-number">50</span>
            <span class="hljs-symbol">got:</span> <span class="hljs-number">0</span>

       (compared using ==)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:27:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">0075</span>8 seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">0523</span> seconds to load)
<span class="hljs-number">2</span> examples, <span class="hljs-number">1</span> failure

Failed <span class="hljs-symbol">examples:</span>

rspec ./spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">22</span> <span class="hljs-comment"># checkout when A has been scanned shows the price of A</span>

Randomized with seed <span class="hljs-number">5579</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>A change needs to be made to the spec to include scanning of Item A.
This changes the file to be;</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
     <span class="hljs-number">0</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>

 RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
   context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">0</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'A'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">50</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>When <code>checkout.scan('A')</code> is added, we get this error;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">45438</span>
.F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> A has been scanned shows the price of A
     Failure/<span class="hljs-symbol">Error:</span> checkout.scan(<span class="hljs-string">'A'</span>)

     <span class="hljs-symbol">NoMethodError:</span>
       undefined method <span class="hljs-string">`scan' for #&lt;CheckOut:0x0000000130ca8448&gt;
     # ./spec/check_out_spec.rb:26:in `</span>block (<span class="hljs-number">3</span> levels) <span class="hljs-keyword">in</span> &lt;top (required)&gt;<span class="hljs-string">'

Finished in 0.00187 seconds (files took 0.04966 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/check_out_spec.rb:22 # checkout when A has been scanned shows the price of A

Randomized with seed 45438


shell returned 1

Press ENTER or type command to continue</span>
</code></pre>
<p>Add the method: <code>scan(item)</code> to <code>CheckOut</code> class to fix this error;</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>

  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Now we are back to the previous error when the test is run;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">56370</span>
.F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> A has been scanned shows the price of A
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">50</span>

       <span class="hljs-symbol">expected:</span> <span class="hljs-number">50</span>
            <span class="hljs-symbol">got:</span> <span class="hljs-number">0</span>

       (compared using ==)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:33:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">0076</span>8 seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">04</span>974 seconds to load)
<span class="hljs-number">2</span> examples, <span class="hljs-number">1</span> failure

Failed <span class="hljs-symbol">examples:</span>

rspec ./spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">26</span> <span class="hljs-comment"># checkout when A has been scanned shows the price of A</span>

Randomized with seed <span class="hljs-number">56370</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>To fix this error, we make three changes to the <code>CheckOut</code> class as below;</p>
<pre><code class="lang-ruby">
 <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
     @total = <span class="hljs-number">0</span>
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
     @total
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
     @total = <span class="hljs-number">50</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>Now when the test is run, all the current two tests will pass successfully;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">4857</span>
..

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00201</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">04</span>948 seconds to load)
<span class="hljs-number">2</span> examples, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">4857</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h3 id="heading-scanning-of-b">Scanning of B:</h3>
<p>Add another context to check for when <code>B</code> has been scanned. 
Add the context to the <code>RSpec.describe 'checkout'</code> block.</p>
<p>The file changes to this;</p>
<pre><code class="lang-ruby"> RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
   context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">0</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when A has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of A'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'A'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">50</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
   context <span class="hljs-string">'when B has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of B'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'B'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">30</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>When <code>⎵ + s</code> is pressed on the keyboard to only run this new test, the following error is displayed;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">36</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/check_out_spec.rb"</span>=&gt;[<span class="hljs-number">36</span>]}}

Randomized with seed <span class="hljs-number">53332</span>
F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> B has been scanned shows the price of B
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">30</span>

       <span class="hljs-symbol">expected:</span> <span class="hljs-number">30</span>
            <span class="hljs-symbol">got:</span> <span class="hljs-number">50</span>

       (compared using ==)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:44:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00643</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">0565</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">1</span> failure

Failed <span class="hljs-symbol">examples:</span>

rspec ./spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">37</span> <span class="hljs-comment"># checkout when B has been scanned shows the price of A</span>

Randomized with seed <span class="hljs-number">53332</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>To fix this, make changes to the <code>scan</code> method in the <code>CheckOut</code> class;</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
    @total = <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    @total
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">'A'</span>
      @total = <span class="hljs-number">50</span>
    <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'B'</span>
      @total = <span class="hljs-number">30</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Now when press <code>⎵ + l</code> to run the last test, the test for scanning <code>B</code> now passes as well;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">40</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/check_out_spec.rb"</span>=&gt;[<span class="hljs-number">40</span>]}}

Randomized with seed <span class="hljs-number">59538</span>
.

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">0005</span>9 seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05165</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">59538</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h3 id="heading-scanning-of-c">Scanning of C:</h3>
<p>Add another context to check for when <code>C</code> has been scanned. 
Add the context to the <code>RSpec.describe 'checkout'</code> block.</p>
<p>This is the context;</p>
<pre><code class="lang-ruby">   context <span class="hljs-string">'when C has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of C'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'C'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">20</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
</code></pre>
<p>When <code>+ s</code> is pressed to run this new test, this error results;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">59</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/check_out_spec.rb"</span>=&gt;[<span class="hljs-number">59</span>]}}

Randomized with seed <span class="hljs-number">51710</span>
F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> C has been scanned shows the price of C
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">20</span>

       <span class="hljs-symbol">expected:</span> <span class="hljs-number">20</span>
            <span class="hljs-symbol">got:</span> <span class="hljs-number">0</span>

       (compared using ==)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:59:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00602</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05125</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">1</span> failure

Failed <span class="hljs-symbol">examples:</span>

rspec ./spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">52</span> <span class="hljs-comment"># checkout when C has been scanned shows the price of C</span>

Randomized with seed <span class="hljs-number">51710</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>To fix this, make changes to the <code>CheckOut</code> class.</p>
<p>Do a check for <code>item C</code> like so;</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
     @total = <span class="hljs-number">0</span>
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
     @total
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
     <span class="hljs-keyword">if</span> item == <span class="hljs-string">'A'</span>
       @total = <span class="hljs-number">50</span>
     <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'B'</span>
       @total = <span class="hljs-number">30</span>
     <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'C'</span>
       @total = <span class="hljs-number">20</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>And now when the test is run, it should be pass;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">59</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/check_out_spec.rb"</span>=&gt;[<span class="hljs-number">59</span>]}}

Randomized with seed <span class="hljs-number">2878</span>
.

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">0006</span>8 seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05424</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">2878</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h3 id="heading-scanning-of-d">Scanning of D:</h3>
<p>Add another context to check for when <code>D</code> has been scanned. 
Add the context to the <code>RSpec.describe 'checkout'</code> block.</p>
<p>This is the context;</p>
<pre><code class="lang-ruby">   context <span class="hljs-string">'when D has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows the price of D'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)

       checkout.scan(<span class="hljs-string">'D'</span>)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">15</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
</code></pre>
<p>When <code>+ s</code> is pressed to run this new test, this error results;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">72</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/check_out_spec.rb"</span>=&gt;[<span class="hljs-number">72</span>]}}

Randomized with seed <span class="hljs-number">61671</span>
F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> D has been scanned shows the price of D
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">15</span>

       <span class="hljs-symbol">expected:</span> <span class="hljs-number">15</span>
            <span class="hljs-symbol">got:</span> <span class="hljs-number">0</span>

       (compared using ==)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:72:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00622</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">0561</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">1</span> failure

Failed <span class="hljs-symbol">examples:</span>

rspec ./spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">65</span> <span class="hljs-comment"># checkout when D has been scanned shows the price of D</span>

Randomized with seed <span class="hljs-number">61671</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>To fix this, make changes to the <code>CheckOut</code> class.</p>
<p>Add an <code>else</code> to check for item <code>D</code>;</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>
     @total = <span class="hljs-number">0</span>
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
     @total
   <span class="hljs-keyword">end</span>

   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan</span><span class="hljs-params">(item)</span></span>
     <span class="hljs-keyword">if</span> item == <span class="hljs-string">'A'</span>
       @total = <span class="hljs-number">50</span>
     <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'B'</span>
       @total = <span class="hljs-number">30</span>
     <span class="hljs-keyword">elsif</span> item == <span class="hljs-string">'C'</span>
       @total = <span class="hljs-number">20</span>
     <span class="hljs-keyword">else</span> 
       @total = <span class="hljs-number">15</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>And now when the test is run, it should be pass;</p>
<pre><code class="lang-ruby">./bin/rspec spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">72</span>
Run <span class="hljs-symbol">options:</span> <span class="hljs-keyword">include</span> {<span class="hljs-symbol">:locations=&gt;</span>{<span class="hljs-string">"./spec/check_out_spec.rb"</span>=&gt;[<span class="hljs-number">72</span>]}}

Randomized with seed <span class="hljs-number">38120</span>
.

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">0005</span>9 seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05152</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">38120</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<h3 id="heading-conclusion">Conclusion:</h3>
<p>This concludes part 2.</p>
<p>In part 3, this will handled;</p>
<ol>
<li>refactoring to make the code better.</li>
<li>taking the pricing rules into account</li>
</ol>
<p>Shout out to <a target="_blank" href="https://twitter.com/purinkle">Rob</a>  for his immense assistance on this and making it easy to comprehend.</p>
]]></content:encoded></item><item><title><![CDATA[Learning TDD With RSpec]]></title><description><![CDATA[This is part 1 of a planned 3 part series.
Introduction:
The challenge was to implement the code for a checkout system that handles pricing schemes such as “apples cost 50 cents, three apples cost $1.30.”
The basic guidelines on how to implement the ...]]></description><link>https://blog.edssemuwemba.com/learning-tdd-with-rspec</link><guid isPermaLink="true">https://blog.edssemuwemba.com/learning-tdd-with-rspec</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Testing]]></category><category><![CDATA[#rspec]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 24 Jun 2022 13:22:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/-gkndM1GvSA/upload/v1654759717582/6WvUeWGIH.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is part 1 of a planned 3 part series.</p>
<h3 id="heading-introduction">Introduction:</h3>
<p>The challenge was to implement the code for a checkout system that handles pricing schemes such as “apples cost 50 cents, three apples cost $1.30.”</p>
<p>The basic guidelines on how to implement the kata can be found <a target="_blank" href="http://codekata.com/kata/kata09-back-to-the-checkout/">here</a> </p>
<p>The idea is to use the Red, Green, Refactor approach.</p>
<p>Write a failing test, and then write little code to get the failing test to pass and then clean up the code.</p>
<h3 id="heading-initialising-project">Initialising project:</h3>
<ol>
<li>Navigate to an appropriate directory: <code>~ cd practice</code></li>
<li>Create a new directory &amp; change to it: <code>~ mkdir checkout &amp;&amp; cd $_</code></li>
<li>Create and edit Gemfile: <code>vim Gemfile</code> (vim is being used as the editor for this project)</li>
</ol>
<pre><code class="lang-ruby"><span class="hljs-comment"># frozen_string_literal: true</span>

source <span class="hljs-string">"https://rubygems.org"</span>

git_source(<span class="hljs-symbol">:github</span>) { <span class="hljs-params">|repo_name|</span> <span class="hljs-string">"https://github.com/<span class="hljs-subst">#{repo_name}</span>"</span> }

gem <span class="hljs-string">'rspec'</span>
</code></pre>
<ol>
<li>Press <code>ctrl + z</code> to navigate back to terminal and then type <code>bundle binstubs --all</code> (including <code>binstubs --all</code> after <code>bundle</code> is a shortcut to not use <code>bundle exec</code> when running the <code>rspec</code> command)</li>
<li>Type <code>bin/rspec --init</code> to initialise rspec (a <code>spec</code> folder will be created) </li>
</ol>
<h3 id="heading-writing-the-first-test">Writing the first test:</h3>
<ol>
<li>Create a new file under the spec folder: <code>touch spec/check_out_spec.rb</code></li>
<li><p>Write the first failing test which checks when nothing has been scanned;</p>
<pre><code class="lang-ruby">RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>

    expect(total).to eq <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
</li>
<li>As expected, this test fails when <code>⎵ + t</code> is pressed on the keyboard;</li>
</ol>
<pre><code><span class="hljs-string">./bin/rspec</span> <span class="hljs-string">spec/check_out_spec.rb</span>

<span class="hljs-string">Randomized</span> <span class="hljs-string">with</span> <span class="hljs-string">seed</span> <span class="hljs-number">59413</span>
<span class="hljs-string">F</span>

<span class="hljs-attr">Failures:</span>

  <span class="hljs-number">1</span><span class="hljs-string">)</span> <span class="hljs-string">checkout</span> <span class="hljs-string">when</span> <span class="hljs-string">nothing</span> <span class="hljs-string">has</span> <span class="hljs-string">been</span> <span class="hljs-string">scanned</span> <span class="hljs-string">shows</span> <span class="hljs-string">a</span> <span class="hljs-string">total</span> <span class="hljs-string">of</span> <span class="hljs-string">zero</span>
     <span class="hljs-attr">Failure/Error:</span> <span class="hljs-string">expect(total).to</span> <span class="hljs-string">eq</span> <span class="hljs-number">0</span>

     <span class="hljs-attr">NameError:</span>
       <span class="hljs-string">undefined</span> <span class="hljs-string">local</span> <span class="hljs-string">variable</span> <span class="hljs-string">or</span> <span class="hljs-string">method</span> <span class="hljs-string">`total'</span> <span class="hljs-string">for</span> <span class="hljs-comment">#&lt;RSpec::ExampleGroups::Checkout::WhenNothingHasBeenScanned "shows a total of zero" (./spec/check_out_spec.rb:3)&gt;</span>
     <span class="hljs-comment"># ./spec/check_out_spec.rb:5:in `block (3 levels) in &lt;top (required)&gt;'</span>

<span class="hljs-string">Finished</span> <span class="hljs-string">in</span> <span class="hljs-number">0.00169</span> <span class="hljs-string">seconds</span> <span class="hljs-string">(files</span> <span class="hljs-string">took</span> <span class="hljs-number">0.04863</span> <span class="hljs-string">seconds</span> <span class="hljs-string">to</span> <span class="hljs-string">load)</span>
<span class="hljs-number">1</span> <span class="hljs-string">example,</span> <span class="hljs-number">1</span> <span class="hljs-string">failure</span>

<span class="hljs-attr">Failed examples:</span>

<span class="hljs-string">rspec</span> <span class="hljs-string">./spec/check_out_spec.rb:3</span> <span class="hljs-comment"># checkout when nothing has been scanned shows a total of zero</span>

<span class="hljs-string">Randomized</span> <span class="hljs-string">with</span> <span class="hljs-string">seed</span> <span class="hljs-number">59413</span>


<span class="hljs-string">shell</span> <span class="hljs-string">returned</span> <span class="hljs-number">1</span>

<span class="hljs-string">Press</span> <span class="hljs-string">ENTER</span> <span class="hljs-string">or</span> <span class="hljs-string">type</span> <span class="hljs-string">command</span> <span class="hljs-string">to</span> <span class="hljs-string">continue</span>
</code></pre><ol>
<li><p>Let us incrementally get this test to pass. The feedback loop with TDD is second to none as the error actually tells us what to do next</p>
<pre><code class="lang-ruby">RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
 it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
   pricing_rules = <span class="hljs-symbol">:Rule</span>
   checkout = CheckOut.new(pricing_rules)
   total = checkout.total

   expect(total).to eq <span class="hljs-number">0</span>
 <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>In the above code snippet, two lines have been added; <code>pricing_rules = :Rule</code> and <code>checkout = CheckOut.new(pricing_rules)</code></p>
</li>
</ol>
<p>The error is now different;</p>
<pre><code>~
./bin/rspec spec/check_out_spec.rb

Randomized <span class="hljs-keyword">with</span> <span class="hljs-keyword">seed</span> <span class="hljs-number">59719</span>
F

Failures:

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> <span class="hljs-keyword">nothing</span> has been scanned shows a total <span class="hljs-keyword">of</span> zero
     <span class="hljs-keyword">Failure</span>/<span class="hljs-keyword">Error</span>: checkout = CheckOut.new(pricing_rules)

     NameError:
       uninitialized <span class="hljs-keyword">constant</span> CheckOut
     <span class="hljs-comment"># ./spec/check_out_spec.rb:5:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0.00174</span> <span class="hljs-keyword">seconds</span> (files took <span class="hljs-number">0.04954</span> <span class="hljs-keyword">seconds</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">load</span>)
<span class="hljs-number">1</span> example, <span class="hljs-number">1</span> <span class="hljs-keyword">failure</span>

<span class="hljs-keyword">Failed</span> examples:

rspec ./spec/check_out_spec.rb:<span class="hljs-number">3</span> <span class="hljs-comment"># checkout when nothing has been scanned shows a total of zero</span>

Randomized <span class="hljs-keyword">with</span> <span class="hljs-keyword">seed</span> <span class="hljs-number">59719</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> <span class="hljs-keyword">type</span> command <span class="hljs-keyword">to</span> continue
</code></pre><p>Now we create add a class: <code>CheckOut</code> as the code below;</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>

 <span class="hljs-keyword">end</span>

 RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
   context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">0</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>Now, this is the error returned;</p>
<pre><code>~
./bin/rspec spec/check_out_spec.rb

Randomized <span class="hljs-keyword">with</span> <span class="hljs-keyword">seed</span> <span class="hljs-number">45459</span>
F

Failures:

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> <span class="hljs-keyword">nothing</span> has been scanned shows a total <span class="hljs-keyword">of</span> zero
     <span class="hljs-keyword">Failure</span>/<span class="hljs-keyword">Error</span>: checkout = CheckOut.new(pricing_rules)

     ArgumentError:
       wrong <span class="hljs-built_in">number</span> <span class="hljs-keyword">of</span> arguments (given <span class="hljs-number">1</span>, expected <span class="hljs-number">0</span>)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:9:in `initialize'</span>
     <span class="hljs-comment"># ./spec/check_out_spec.rb:9:in `new'</span>
     <span class="hljs-comment"># ./spec/check_out_spec.rb:9:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0.00264</span> <span class="hljs-keyword">seconds</span> (files took <span class="hljs-number">0.05216</span> <span class="hljs-keyword">seconds</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">load</span>)
<span class="hljs-number">1</span> example, <span class="hljs-number">1</span> <span class="hljs-keyword">failure</span>

<span class="hljs-keyword">Failed</span> examples:

rspec ./spec/check_out_spec.rb:<span class="hljs-number">7</span> <span class="hljs-comment"># checkout when nothing has been scanned shows a total of zero</span>

Randomized <span class="hljs-keyword">with</span> <span class="hljs-keyword">seed</span> <span class="hljs-number">45459</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> <span class="hljs-keyword">type</span> command <span class="hljs-keyword">to</span> continue
</code></pre><p>Now we can write code to solve the above error. It would look something like so;</p>
<pre><code class="lang-ruby"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
   <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

   <span class="hljs-keyword">end</span>

 <span class="hljs-keyword">end</span>

 RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
   context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
     it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
       pricing_rules = <span class="hljs-symbol">:Rule</span>
       checkout = CheckOut.new(pricing_rules)
       total = checkout.total

       expect(total).to eq <span class="hljs-number">0</span>
     <span class="hljs-keyword">end</span>
   <span class="hljs-keyword">end</span>
 <span class="hljs-keyword">end</span>
</code></pre>
<p>For this, we get the undefined method <code>total</code> as the error shows;</p>
<pre><code class="lang-ruby">~
./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">46712</span>
F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> nothing has been scanned shows a total of zero
     Failure/<span class="hljs-symbol">Error:</span> total = checkout.total

     <span class="hljs-symbol">NoMethodError:</span>
       undefined method <span class="hljs-string">`total' for #&lt;CheckOut:0x000000013952bd60&gt;
     # ./spec/check_out_spec.rb:13:in `</span>block (<span class="hljs-number">3</span> levels) <span class="hljs-keyword">in</span> &lt;top (required)&gt;<span class="hljs-string">'

Finished in 0.00174 seconds (files took 0.05301 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/check_out_spec.rb:10 # checkout when nothing has been scanned shows a total of zero

Randomized with seed 46712


shell returned 1

Press ENTER or type command to continue</span>
</code></pre>
<p>To fix the error, add a method: <code>total</code> as shown below;</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>

  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
  context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
      pricing_rules = <span class="hljs-symbol">:Rule</span>
      checkout = CheckOut.new(pricing_rules)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">0</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>We now get another error as shown;</p>
<pre><code class="lang-ruby">~
./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">15684</span>
F

<span class="hljs-symbol">Failures:</span>

  <span class="hljs-number">1</span>) checkout <span class="hljs-keyword">when</span> nothing has been scanned shows a total of zero
     Failure/<span class="hljs-symbol">Error:</span> expect(total).to eq <span class="hljs-number">0</span>

       <span class="hljs-symbol">expected:</span> <span class="hljs-number">0</span>
            <span class="hljs-symbol">got:</span> <span class="hljs-literal">nil</span>

       (compared using ==)
     <span class="hljs-comment"># ./spec/check_out_spec.rb:18:in `block (3 levels) in &lt;top (required)&gt;'</span>

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">00714</span> seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">05137</span> seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">1</span> failure

Failed <span class="hljs-symbol">examples:</span>

rspec ./spec/check_out_spec.<span class="hljs-symbol">rb:</span><span class="hljs-number">13</span> <span class="hljs-comment"># checkout when nothing has been scanned shows a total of zero</span>

Randomized with seed <span class="hljs-number">15684</span>


shell returned <span class="hljs-number">1</span>

Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>Now, to get this to pass, we need to change the <code>total</code> method to return <code>0</code>;</p>
<pre><code class="lang-ruby">
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckOut</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize</span><span class="hljs-params">(pricing_rules)</span></span>

  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">total</span></span>
    <span class="hljs-number">0</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

RSpec.describe <span class="hljs-string">'checkout'</span> <span class="hljs-keyword">do</span>
  context <span class="hljs-string">'when nothing has been scanned'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'shows a total of zero'</span> <span class="hljs-keyword">do</span>
      pricing_rules = <span class="hljs-symbol">:Rule</span>
      checkout = CheckOut.new(pricing_rules)
      total = checkout.total

      expect(total).to eq <span class="hljs-number">0</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Below is the output of the passing test;</p>
<pre><code class="lang-ruby">~
./bin/rspec spec/check_out_spec.rb

Randomized with seed <span class="hljs-number">9210</span>
.

Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>.<span class="hljs-number">001</span>87 seconds (files took <span class="hljs-number">0</span>.<span class="hljs-number">04</span>874 seconds to load)
<span class="hljs-number">1</span> example, <span class="hljs-number">0</span> failures

Randomized with seed <span class="hljs-number">9210</span>


Press ENTER <span class="hljs-keyword">or</span> type command to continue
</code></pre>
<p>This is just one of the tests though. Other tests need to be done i.e. <code>when A has been scanned</code>, <code>when B has been scanned</code>, <code>when C has been scanned</code>, <code>when D has been scanned</code></p>
<p>This concludes part 1.</p>
<p>In part 2, we will tackle how to handle tests for the scanning of A, B, C &amp; D.</p>
<p>In part 3, we will do some refactoring to make the code better.</p>
<p>Shout out to <a target="_blank" href="https://twitter.com/purinkle">Rob</a> for his immense assistance on this and making it easy to comprehend.</p>
]]></content:encoded></item><item><title><![CDATA[My Love-hate relationship with Jaybird]]></title><description><![CDATA[This isn't particularly a post about development but I have found earbuds to be helpful as I zone out and focus on what I'm doing.
I acquired my first Jaybirds in 2016. They were Jaybird X2, there were my first wireless bluetooth earbuds.
They were a...]]></description><link>https://blog.edssemuwemba.com/my-love-hate-relationship-with-jaybird</link><guid isPermaLink="true">https://blog.edssemuwemba.com/my-love-hate-relationship-with-jaybird</guid><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Mon, 08 Nov 2021 07:44:23 GMT</pubDate><content:encoded><![CDATA[<p>This isn't particularly a post about development but I have found earbuds to be helpful as I zone out and focus on what I'm doing.</p>
<p>I acquired my first Jaybirds in 2016. They were Jaybird X2, there were my first wireless bluetooth earbuds.
They were awesome products.
The battery life was as advertised (8 hours)
They were extremely reliable earbuds.
5 years down the road, the wire connecting the individual ear buds had started showing signs of wear and tear.
I knew it was time to retire them.
Meanwhile, after all this time, they would still provide 8 hours. </p>
<p>Fast forward to 2021, I decided to purchase the Jaybird X4. I figured that they would provide the same value for money as the Jaybird X2s had.
Plus they were more features to look forward to.
These are some of the advertised features;</p>
<ol>
<li><p>Ability to connect to two devices at the same time</p>
</li>
<li><p>Companion app to be able to customise sound quality</p>
</li>
</ol>
<p>I was disappointed when the battery wasn't good.
At best I would only get 3 hours out of them.
At times after charging them fully, they would disconnect after connecting and then an audible alert about "battery being low" would be heard.
So, it got a bit frustrating but I wasn't willing to give up yet so I started investigating.</p>
<p>My conclusion is that they have a software issue because when they claim that the battery is slow, it later displays the actual battery level. This wouldn't be an issue if this was the consistent behaviour.
But at times, they just keep disconnecting even after being fully charged.</p>
<p>Later, I saw a review online about this issue.
In hindsight, I should have looked up a review online prior to purchasing them but I was sidelined by the performance of the Jaybird X2s.</p>
<p>Of course, I suppose that Jaybird could push out a software update to solve this issue but I doubt that this a priority.</p>
<p>For now, I am saying goodbye to Jaybird and have my eyes on AirPods Pro.</p>
<p>Moral of the story is: take sometime to look up reviews on a product even when previous generations have been good.</p>
]]></content:encoded></item><item><title><![CDATA[Deploying A Rails 6.0 App To Heroku]]></title><description><![CDATA[This guides assumes Heroku-cli has been installed.Heroku-cli can be installed by running: brew tap heroku/brew && brew install heroku
Bundler Bug
In my case, there was a Bundler bug because I wasn't using Ruby 2.6.0 and above.Make certain that you ar...]]></description><link>https://blog.edssemuwemba.com/deploying-a-rails-60-app-to-heroku</link><guid isPermaLink="true">https://blog.edssemuwemba.com/deploying-a-rails-60-app-to-heroku</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Heroku]]></category><dc:creator><![CDATA[Ed SSemuwemba]]></dc:creator><pubDate>Fri, 06 Aug 2021 16:04:56 GMT</pubDate><content:encoded><![CDATA[<p>This guides assumes Heroku-cli has been installed.<br />Heroku-cli can be installed by running: <code>brew tap heroku/brew &amp;&amp; brew install heroku</code></p>
<h3 id="bundler-bug">Bundler Bug</h3>
<p>In my case, there was a Bundler bug because I wasn't using <code>Ruby 2.6.0</code> and above.<br />Make certain that you are using <code>Ruby Version 2.6.0</code> and above as there is a known bundler bug on <a target="_blank" href="https://devcenter.heroku.com/articles/bundler-version#known-upgrade-issues">Heroku</a></p>
<p>I switched to <code>Ruby 2.6.3</code>.<br />I use <a target="_blank" href="https://rvm.io">RVM</a>, so I run <code>rvm use  2.6.3</code>
Make certain that Ruby 2.6.3 is installed.<br />If it isn’t, install using <code>rvm install 2.6.3</code></p>
<h3 id="precompiling-assets-failed">Precompiling assets failed</h3>
<p>To solve this one, make certain to run: <code>RAILS_ENV=production assets:precompile</code>
Don’t forget to set <code>ENV['RAILS_MASTER_KEY']</code><br />You can the above using <code>heroku config:set RAILS_MASTER_KEY=cat config/master.key --remote production</code><br />I included <code>—remote production</code> because I have two seperate environments (staging and production) setup on Heroku. </p>
<p>Then you are the good to go.<br />The joy of solving these issues is something else.  I can’t trade for anything else.</p>
]]></content:encoded></item></channel></rss>