<?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[Srinivas's Blog]]></title><description><![CDATA[👨🏻‍💻 Software Craftsman at EverestEngineering | ✍🏻 Beginner Blogger | 🕺 Dancer]]></description><link>https://keencoder.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1603977654094/pdQCSDLwB.png</url><title>Srinivas&apos;s Blog</title><link>https://keencoder.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 15 May 2026 23:12:09 GMT</lastBuildDate><atom:link href="https://keencoder.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Unit testing for absolute beginners]]></title><description><![CDATA[Recently at Everest Engineering, I got an opportunity to teach unit testing to our interns. I thought of sharing the content that I prepared for the session with the world so that it may benefit some beginners out there. Read on...
What is Testing?

...]]></description><link>https://keencoder.dev/unit-testing-for-absolute-beginners</link><guid isPermaLink="true">https://keencoder.dev/unit-testing-for-absolute-beginners</guid><category><![CDATA[unit testing]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Testing]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Jest]]></category><dc:creator><![CDATA[Srinivas]]></dc:creator><pubDate>Thu, 03 Aug 2023 16:14:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1690963911522/4f402656-d02b-4c2c-a37a-05774d012c96.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently at <a target="_blank" href="https://everest.engineering/">Everest Engineering</a>, I got an opportunity to teach unit testing to our interns. I thought of sharing the content that I prepared for the session with the world so that it may benefit some beginners out there. Read on...</p>
<h3 id="heading-what-is-testing">What is Testing?</h3>
<blockquote>
<p><strong>In simple terms, its a process of checking something if it does what it intended to do</strong></p>
</blockquote>
<p><strong>example:</strong></p>
<p>Let's say you are given a Bluetooth speaker and asked to test it. What do you do?</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>Keep thinking… brb 🙂</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>Okay, Let me tell you what I do. I will pair the speaker to my mobile phone via Bluetooth and play my favorite songs from my Spotify playlist, and see if the sound is coming from the speaker. If it is coming from the speaker, I will say it works, otherwise, it does not.</p>
<p>If you look at it closely, while you test something, you always have following steps</p>
<ul>
<li><p><strong>Arrange:</strong> You setup it so that it is ready to be tested</p>
<ul>
<li>Pairing the speaker with a phone ( of course you can test whether the Bluetooth is capable of connecting to phones, it is a different use case, let's keep it aside)</li>
</ul>
</li>
<li><p><strong>Act:</strong> You pass some input</p>
<ul>
<li>You play songs</li>
</ul>
</li>
<li><p><strong>Assert:</strong> You expect something of the system that you are testing</p>
<ul>
<li>Sound output from the speaker</li>
</ul>
</li>
</ul>
<h3 id="heading-what-is-unit-testing">What is unit testing?</h3>
<p>Each system has many independent features that can be tested alone</p>
<p>In our case, these are the candidates for units</p>
<ul>
<li><p>Feature that allows us to pair Bluetooth speakers with input devices like speakers, laptops..etc</p>
</li>
<li><p>Feature that plays songs</p>
</li>
<li><p>Feature that lets us control pause the music</p>
</li>
<li><p>Feature that lets us control playing the music</p>
</li>
<li><p>Feature that lets us increase the volume</p>
</li>
<li><p>Feature that lets us decrease the volume</p>
</li>
<li><p>Finally, a feature that allows disconnecting from the input devices</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">👨‍💻</div>
<div data-node-type="callout-text"><strong>Testing these units in an isolated manner without depending on other features is called unit testing</strong></div>
</div>

<p>When it comes to testing software, a unit can be a <em>function</em>, a <em>class and its public API</em> ( <a target="_blank" href="https://softwareengineering.stackexchange.com/questions/380287/why-is-unit-testing-private-methods-considered-as-bad-practice">yes never test private methods <em>directly</em></a> ), or a <em>feature that involves multiple classes</em>. To keep things simple let's take functions, and classes as units, and let's move further.</p>
<h3 id="heading-unit-test">Unit test</h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">👩‍💻</div>
<div data-node-type="callout-text"><strong>A unit test is a piece of code, that invokes some other piece of code and checks its end results against a set of expectations</strong></div>
</div>

<h3 id="heading-lets-write-our-first-unit-test">Let's write our first unit test</h3>
<p>Please download the starter project from <a target="_blank" href="https://github.com/SriNandan33/unit-testing-for-beginners/tree/typescript-starter">this link</a>. It uses <a target="_blank" href="https://www.typescriptlang.org/">Typescript</a> as a programming language, and <a target="_blank" href="https://jestjs.io/">Jest</a> as the testing framework. The starter project is taken from <a target="_blank" href="https://github.com/stemmlerjs/simple-typescript-starter">here</a>. If you are curious about the files inside it, please check <a target="_blank" href="https://khalilstemmler.com/blogs/typescript/node-starter-project/">this blog post</a> out. There are a lot of files, but our main interest is going to on <code>index.ts</code>, <code>index.spec.ts</code> for now. <code>index.ts</code> file is where we write the code, and we write our tests inside <code>index.spec.ts</code> . Come, let's write our first test</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// index.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span></span>): <span class="hljs-title">number</span> </span>{
  <span class="hljs-keyword">return</span> x + y;
}
</code></pre>
<p>Our code is simple, it is just a function that takes two numbers and adds them together, and returns the result. Let's write a test for it</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { add } <span class="hljs-keyword">from</span> <span class="hljs-string">'./index'</span>;

describe(<span class="hljs-string">'test calculator'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'add'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-comment">// Our code at the moment is too simple and does not need any setup</span>

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = add(<span class="hljs-number">10</span>, <span class="hljs-number">1</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toEqual(<span class="hljs-number">11</span>);
  });
});
</code></pre>
<p>Let's run our tests</p>
<pre><code class="lang-plaintext">npm run test
</code></pre>
<p>Your output should look something like this</p>
<pre><code class="lang-plaintext">&gt; jest

 PASS  src/index.spec.ts
  test calculator
    ✓ add (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.038 s, estimated 2 s
Ran all test suites.
</code></pre>
<h3 id="heading-unit-testing-classes">Unit testing classes</h3>
<p>Let's write another program and test it. This time using classes. We are going to write a simple calculator program. Let’s get our hands on the keyboard and code it up</p>
<p>Let’s create a file <code>calculator.ts</code> and add the following class to it</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// calculator.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Calculator {
  <span class="hljs-keyword">public</span> add(x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> x + y;
  }
}
</code></pre>
<p>We have added a class with <code>add</code> function, which is similar to what we had in the earlier example. Let's test it now</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// calculator.spec.ts</span>

<span class="hljs-keyword">import</span> Calculator <span class="hljs-keyword">from</span> <span class="hljs-string">'./calculator'</span>;

describe(<span class="hljs-string">'test calculator'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'test add'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = calc.add(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toBe(<span class="hljs-number">6</span>);
  });
}
</code></pre>
<p>Here we got Arrange step as well, which instantiates the class and stores the reference into the constant variable <code>calc</code></p>
<p>Let's run the tests</p>
<pre><code class="lang-plaintext">npm run test calculator
</code></pre>
<p>Your output should look something like this</p>
<pre><code class="lang-plaintext">PASS  src/calculator.spec.ts
  test calculator
    ✓ test add (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.98 s
Ran all test suites matching /calculator/i.
</code></pre>
<p>Let's finish other methods like <strong>subtraction, multiplication, and division.</strong> Handle zero division as well, throw an Error if the user tries to divide with Zero.</p>
<p>Let's have a look at the finished code and tests</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// calculator.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Calculator {
  <span class="hljs-keyword">public</span> add(x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> x + y;
  }

  <span class="hljs-keyword">public</span> subtract(x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> x - y;
  }

  <span class="hljs-keyword">public</span> multiply(x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> x * y;
  }

  <span class="hljs-keyword">public</span> division(x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">if</span> (y === <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Zero division error'</span>);
    }
    <span class="hljs-keyword">return</span> x / y;
  }
}
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> Calculator <span class="hljs-keyword">from</span> <span class="hljs-string">'./calculator'</span>;

describe(<span class="hljs-string">'test calculator'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'test add'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = calc.add(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toBe(<span class="hljs-number">6</span>);
  });

  test(<span class="hljs-string">'test subtract'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = calc.subtract(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toBe(<span class="hljs-number">8</span>);
  });

  test(<span class="hljs-string">'test subtract from smaller number'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = calc.subtract(<span class="hljs-number">2</span>, <span class="hljs-number">10</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toBe(<span class="hljs-number">-8</span>);
  });

  test(<span class="hljs-string">'test multiply'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = calc.multiply(<span class="hljs-number">2</span>, <span class="hljs-number">10</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toBe(<span class="hljs-number">20</span>);
  });

  test(<span class="hljs-string">'test division'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> result = calc.division(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>);

    <span class="hljs-comment">// Assert</span>
    expect(result).toBe(<span class="hljs-number">5</span>);
  });

  test(<span class="hljs-string">'should not allow dividing with zero'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

    <span class="hljs-comment">// Act &amp; Assert</span>
    expect(<span class="hljs-function">() =&gt;</span> calc.division(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>)).toThrow(<span class="hljs-string">'Zero division error'</span>);
  });
});
</code></pre>
<p>If you see the above solution, we have covered zero division error as well. It is important to test all the critical paths/flows while you write your unit tests. You can use code coverage tools to see if you have any uncovered code. Let's have a look at them now</p>
<h3 id="heading-measuring-code-coverage">Measuring code coverage</h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Code coverage is a metric that can help you understand how much of your source is tested.</div>
</div>

<p>Open your <code>package.json</code> file and add the following line under <code>scripts</code> section</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
<span class="hljs-comment">// ... other commands</span>
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest"</span>,
    <span class="hljs-attr">"test-cov"</span>: <span class="hljs-string">"jest --coverage"</span>
},
</code></pre>
<p>For the sake of this example, please skip the last test that covers zero division error. You can skip a test using <code>test.skip('&lt;name&gt;')</code> syntax</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Calculator.spec.ts</span>

<span class="hljs-comment">// other tests</span>
test.skip(<span class="hljs-string">'should not allow dividing with zero'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Arrange</span>
  <span class="hljs-keyword">const</span> calc = <span class="hljs-keyword">new</span> Calculator();

  <span class="hljs-comment">// Act &amp; Assert</span>
  expect(<span class="hljs-function">() =&gt;</span> calc.division(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>)).toThrow(<span class="hljs-string">'Zero division error'</span>);
});
</code></pre>
<p>Now run <code>npm run test-cov</code></p>
<pre><code class="lang-plaintext">jest --coverage

 PASS  src/index.spec.ts
 PASS  src/wallet.spec.ts
❯ npm run test

&gt; typescript-starter@1.0.0 test
&gt; jest --coverage

 PASS  src/index.spec.ts
 PASS  src/wallet.spec.ts
❯ npm run test-cov

&gt; typescript-starter@1.0.0 test-cov
&gt; jest --coverage

 PASS  src/index.spec.ts
 PASS  src/calculator.spec.ts
 PASS  src/wallet.spec.ts
---------------|---------|----------|---------|---------|-------------------
File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------|---------|----------|---------|---------|-------------------
All files      |      96 |       50 |     100 |      96 |                   
 calculator.ts |   91.66 |        0 |     100 |   91.66 | 16                
 index.ts      |     100 |      100 |     100 |     100 |                   
 wallet.ts     |     100 |      100 |     100 |     100 |                   
---------------|---------|----------|---------|---------|-------------------

Test Suites: 3 passed, 3 total
Tests:       1 skipped, 9 passed, 10 total
Snapshots:   0 total
Time:        1.521 s, estimated 2 s
</code></pre>
<p>You can see that <code>calculator.ts</code> does not have 100% coverage while others have it, because we don’t have the test that executes the <em>if block</em> that handles zero division scenario. When you run the above command, <strong>Jest</strong> creates another directory called <code>coverage</code> in your project, open <code>index.html</code> in your browser and see the beautiful visualization of your coverage output.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690965265838/0f97235b-5cf2-48cb-83e7-d0e54b7d3cb4.png" alt class="image--center mx-auto" /></p>
<p>It should look something like this. One more beautiful thing about this HTML report is that you can see what code has been missed by your tests. Click on <code>calculator.ts</code> and you should see Jest highlighting <em>if block.</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690965288031/369f65c7-ae4a-42ac-87fd-fc3c591306b7.png" alt class="image--center mx-auto" /></p>
<p>That’s awesome, isn’t it :) Now you can remove <code>.skip</code> from your tests, and see 100% coverage for <code>calculator.ts</code></p>
<p>While the coverage tool is good, it often misleading as well. Let me explain you what I mean</p>
<p>Please comment out your <code>expect</code> functions in your test except for the last test which checks for <em>exception</em>, and run <code>npm run test-cov</code> . You should see that Jest says your code is 100% covered even though we commented on all our assertions.</p>
<p>So that is why, you should never rely on coverage report while deciding how much code is being tested. Now let's revisit our definition of code coverage</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Code coverage is a metric that can help you understand how much of your source is <s>tested</s> <em>exercised</em>.</strong></div>
</div>

<div data-node-type="callout">
<div data-node-type="callout-emoji">📣</div>
<div data-node-type="callout-text"><strong>You don’t have to aim for 100% coverage, while it is good to have it may not always be possible. Having said that, it is important to cover all the critical paths in your code so that you have enough confidence on your tests. Use coverage tools as a guiding force to see if you have any uncovered code which is critical rather than aiming at a particular coverage percentage like 85%, 99% ..etc</strong></div>
</div>

<h3 id="heading-state-based-testing">State based testing</h3>
<p>So far you have been calling some functions and asserting the return value. It is called output-based testing. There is another form of testing, which asserts the object's state i.e. instance variables. Let's see how it looks like</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> SomeClassWithState {
  <span class="hljs-keyword">public</span> anInstanceVar: <span class="hljs-built_in">number</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">initVal: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.anInstanceVar = initVal;
  }

  <span class="hljs-keyword">public</span> increaseBy(num: <span class="hljs-built_in">number</span>) {
    <span class="hljs-built_in">this</span>.anInstanceVar += num;
  }

  <span class="hljs-keyword">public</span> getVal(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.anInstanceVar;
  }
}

<span class="hljs-comment">// Test</span>
describe(<span class="hljs-string">'test state based class'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'test with state'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> cls = <span class="hljs-keyword">new</span> SomeClassWithState(<span class="hljs-number">10</span>)

    <span class="hljs-comment">// Act</span>
    cls.increaseBy(<span class="hljs-number">5</span>)

    <span class="hljs-comment">// Assert</span>
    expect(cls.getVal()).toBe(<span class="hljs-number">15</span>)
  })
})
</code></pre>
<p>To practice it, let's Implement a digital wallet program. Write a class that stores user balance as a number, and create <code>add</code>, <code>withdraw</code> methods that adds money to the wallet, and withdraw it respectively</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// wallet.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Wallet {
  <span class="hljs-keyword">private</span> balance: <span class="hljs-built_in">number</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">initialAmount: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.balance = initialAmount;
  }

  <span class="hljs-keyword">public</span> add(amount: <span class="hljs-built_in">number</span>) {
    <span class="hljs-built_in">this</span>.balance += amount;
  }

  <span class="hljs-keyword">public</span> withdraw(amount: <span class="hljs-built_in">number</span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.balance &lt; amount) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Insufficient balance'</span>);
    }
    <span class="hljs-built_in">this</span>.balance -= amount;
  }

  <span class="hljs-keyword">public</span> getBalance(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.balance;
  }
}
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-comment">// wallet.spec.ts</span>

<span class="hljs-keyword">import</span> Wallet <span class="hljs-keyword">from</span> <span class="hljs-string">'./wallet'</span>;

describe(<span class="hljs-string">'Test Wallet'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'test add'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> wallet = <span class="hljs-keyword">new</span> Wallet(<span class="hljs-number">100</span>);

    <span class="hljs-comment">// Act</span>
    wallet.add(<span class="hljs-number">100</span>);

    <span class="hljs-comment">// Assert</span>
    expect(wallet.getBalance()).toBe(<span class="hljs-number">200</span>);
  });

  test(<span class="hljs-string">'test withdraw'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> wallet = <span class="hljs-keyword">new</span> Wallet(<span class="hljs-number">100</span>);

    <span class="hljs-comment">// Act</span>
    wallet.withdraw(<span class="hljs-number">20</span>);

    <span class="hljs-comment">// Assert</span>
    expect(wallet.getBalance()).toBe(<span class="hljs-number">80</span>);
  });

  test(<span class="hljs-string">'should not withdraw if there is no balance '</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> wallet = <span class="hljs-keyword">new</span> Wallet(<span class="hljs-number">100</span>);

    <span class="hljs-comment">// Act &amp; Assert</span>
    expect(<span class="hljs-function">() =&gt;</span> wallet.withdraw(<span class="hljs-number">200</span>)).toThrow(<span class="hljs-string">'Insufficient balance'</span>);
  });
});
</code></pre>
<h3 id="heading-stubs-amp-mocks">Stubs &amp; Mocks</h3>
<p>To explain stubs, and mocks better, I would like to start straight with an example program. Take a look at a following class <code>Encoder</code>, it has a <code>encode</code> method that takes some text as input and encodes it into a different string by shifting the characters by some random positions between 1 and 26 ( equal to the number of alphabets ). For example, if you encode <code>abcz</code> by shifting 5 positions it will become <code>fgge</code> ( you might have already guessed how <code>z</code> became <code>e</code> 😁 )</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// encoder.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Encoder {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> NUMBER_OF_ALPHABETS = <span class="hljs-number">26</span>;
  <span class="hljs-keyword">public</span> encode(text: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
    <span class="hljs-keyword">const</span> source = text.toLowerCase();
    <span class="hljs-keyword">let</span> result = <span class="hljs-string">''</span>;

    <span class="hljs-keyword">const</span> encodeWith: <span class="hljs-built_in">number</span> = <span class="hljs-built_in">this</span>.getASecretNumber();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> idx = <span class="hljs-number">0</span>; idx &lt; text.length; idx++) {
      result += <span class="hljs-built_in">String</span>.fromCharCode(
        ((source.charCodeAt(idx) - <span class="hljs-string">'a'</span>.charCodeAt(<span class="hljs-number">0</span>) + encodeWith) %
          <span class="hljs-built_in">this</span>.NUMBER_OF_ALPHABETS) +
          <span class="hljs-string">'a'</span>.charCodeAt(<span class="hljs-number">0</span>),
      );
    }

    <span class="hljs-keyword">return</span> result;
  }

  <span class="hljs-keyword">private</span> getASecretNumber() {
    <span class="hljs-comment">// generates a random number between 1, 26 ( yes the total number of alphabets :D )</span>
    <span class="hljs-keyword">let</span> min = <span class="hljs-number">1</span>;
    <span class="hljs-keyword">let</span> max = <span class="hljs-number">26</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * (max - min + <span class="hljs-number">1</span>) + min);
  }
}
</code></pre>
<p>Before writing tests for the above program, please run it a couple of times and see the output. Did you notice that it changes every time? Yes, it is because every time we run it we generate a random number between 1, 26 and encode the text. How the hell do we test such code? We can only test if the program’s output is predictable, which means every time we run the program we should get the same result. We can’t test our code otherwise</p>
<p>How can we make the above code testable? To answer that let’s go to the roots of the problem. The issue here is our code is <strong><em>tightly coupled</em></strong> with the random number generator. Let's try to reduce the coupling by hiding our random number generation behind an interface</p>
<p><strong>Step 1:</strong> Create an interface</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// IRandomGen.ts</span>

<span class="hljs-keyword">interface</span> IRandomNumberGenerator {
  random(min: <span class="hljs-built_in">number</span>, max: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span>;
}
</code></pre>
<p><strong>Step 2:</strong> Create a new class and move the random number generator into it, and make sure your class implements the above interface</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// randomGen.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> RandomNumberGenerator <span class="hljs-keyword">implements</span> IRandomNumberGenerator {
  <span class="hljs-keyword">public</span> random(min: <span class="hljs-built_in">number</span>, max: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * (max - min + <span class="hljs-number">1</span>) + min);
  }
}
</code></pre>
<p><strong>Step 3:</strong> Refactor your class to take the random number generator as the constructor argument, but instead of directly depending on the class, depend on <code>IRandomNumberGenerator</code> the interface instead</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Encoder {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> NUMBER_OF_ALPHABETS = <span class="hljs-number">26</span>;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> secretGen: IRandomNumberGenerator;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">secretGen: IRandomNumberGenerator</span>) {
    <span class="hljs-built_in">this</span>.secretGen = secretGen;
  }

  <span class="hljs-keyword">public</span> encode(text: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
    <span class="hljs-keyword">const</span> source = text.toLowerCase();
    <span class="hljs-keyword">let</span> result = <span class="hljs-string">''</span>;

    <span class="hljs-keyword">const</span> encodeWith: <span class="hljs-built_in">number</span> = <span class="hljs-built_in">this</span>.secretGen.random(
      <span class="hljs-number">1</span>,
      <span class="hljs-built_in">this</span>.NUMBER_OF_ALPHABETS,
    );
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> idx = <span class="hljs-number">0</span>; idx &lt; text.length; idx++) {
      result += <span class="hljs-built_in">String</span>.fromCharCode(
        ((source.charCodeAt(idx) - <span class="hljs-string">'a'</span>.charCodeAt(<span class="hljs-number">0</span>) + encodeWith) %
          <span class="hljs-built_in">this</span>.NUMBER_OF_ALPHABETS) +
          <span class="hljs-string">'a'</span>.charCodeAt(<span class="hljs-number">0</span>),
      );
    }
    <span class="hljs-keyword">return</span> result;
  }
}
</code></pre>
<p>That’s it, we decoupled our <code>Encoder</code> class from random generation logic. Now while we implement our real code ( production code ) we can pass an instance of <code>RandomNumberGenerator</code> to our <code>Encoder</code> . While we unit test our code, we can pass a dummy implementation that returns a deterministic number rather than a random number. Let's write our test now…</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// encoder.spec.ts</span>

<span class="hljs-keyword">import</span> Encoder <span class="hljs-keyword">from</span> <span class="hljs-string">'./encoder'</span>;
<span class="hljs-keyword">import</span> IRandomNumberGenerator <span class="hljs-keyword">from</span> <span class="hljs-string">'./IRandomGen'</span>;

<span class="hljs-keyword">class</span> RandomGenStub <span class="hljs-keyword">implements</span> IRandomNumberGenerator {
  <span class="hljs-keyword">private</span> returnVal: <span class="hljs-built_in">number</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">returnVal: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.returnVal = returnVal;
  }

  <span class="hljs-keyword">public</span> random(min: <span class="hljs-built_in">number</span>, max: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.returnVal;
  }
}

describe(<span class="hljs-string">'test encoder'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should encode text correctly'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> stubGen = <span class="hljs-keyword">new</span> RandomGenStub(<span class="hljs-number">5</span>);
    <span class="hljs-keyword">const</span> encoder = <span class="hljs-keyword">new</span> Encoder(stubGen);

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> encoded = encoder.encode(<span class="hljs-string">'abcz'</span>);

    <span class="hljs-comment">//Assert</span>
    expect(encoded).toBe(<span class="hljs-string">'fghe'</span>);
  });
});
</code></pre>
<p>Let me leverage the same example to explain <strong>mocks</strong> as well. To do so, let's introduce a new feature in our Encoder program. The new feature requires us to log the results into a file in <code>&lt;text&gt; is encoded into &lt;encoded text&gt; by shifting &lt;numberOfChar&gt; characters</code> format.</p>
<p>Let’s modify our code accordingly</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Encoder {
  <span class="hljs-comment">// .. code is stripped</span>

  <span class="hljs-keyword">public</span> encode(text: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
    <span class="hljs-comment">// ... code is stripped</span>

    <span class="hljs-built_in">this</span>.writeIntoLog(text, result, encodeWith);
    <span class="hljs-keyword">return</span> result;
  }

  <span class="hljs-keyword">private</span> writeIntoLog(input: <span class="hljs-built_in">string</span>, encoded: <span class="hljs-built_in">string</span>, shiftedBy: <span class="hljs-built_in">number</span>) {
    <span class="hljs-keyword">try</span> {
      fs.appendFileSync(
        <span class="hljs-string">'output.txt'</span>,
        <span class="hljs-string">`<span class="hljs-subst">${input}</span> is encoded into <span class="hljs-subst">${encoded}</span> by shifting <span class="hljs-subst">${shiftedBy}</span> characters`</span>,
      );
    } <span class="hljs-keyword">catch</span> {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'error logging into file'</span>);
    }
  }
}
</code></pre>
<p>If you observe closely, our program output does not really depend on the <code>writeIntoLog</code> function. Should we still test it? The answer is Yes, You should test every business logic. You should never leave a requirement untested. Always think in terms of business requirements rather than in terms of program outputs.</p>
<p>Now the question is, how to test the <code>writeIntoLog</code> function? One way could be, to see if the log text is written into the file during your unit test. That works and runs fast as file system calls faster in general, but what if you are writing into a database that is sitting remotely somewhere else? what if you would like to send the same text as a message to your user? Those requirements involve sending data over the network and making API calls during unit tests making them so slow. Then how do we test such code without actually using real APIs? That is where <strong>Mocks</strong> come into the picture</p>
<p>Just like the random generator problem above, our logic is tightly coupled with the file system to write the log. Lets now make our code and file system loosely coupled using interfaces, and constructor injection ( injecting dependencies using constructor )</p>
<p><strong>Step 1:</strong> Create an interface</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// ILogger.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">interface</span> ILogger {
  log(text: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">void</span>;
}
</code></pre>
<p><strong>Step 2:</strong> Create a new class and move the file system call into it, and make sure it implements the above interface</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// logger.ts</span>

<span class="hljs-keyword">import</span> ILogger <span class="hljs-keyword">from</span> <span class="hljs-string">'./ILogger'</span>;
<span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">'fs'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Logger <span class="hljs-keyword">implements</span> ILogger {
  <span class="hljs-keyword">public</span> log(text: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">try</span> {
      fs.appendFileSync(
        <span class="hljs-string">'output.txt'</span>, <span class="hljs-comment">// Hardcoded for simplicity. Usually take it from some config</span>
        text,
      );
    } <span class="hljs-keyword">catch</span> {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'error logging into file'</span>);
    }
  }
}
</code></pre>
<p><strong>Step 3:</strong> Refactor your encoder class to take logger as a constructor argument, instead of directly depending on the concrete class, depend on the interface</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> Encoder {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> NUMBER_OF_ALPHABETS = <span class="hljs-number">26</span>;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> secretGen: IRandomNumberGenerator;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> logger: ILogger;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">secretGen: IRandomNumberGenerator, logger: ILogger</span>) {
    <span class="hljs-built_in">this</span>.secretGen = secretGen;
    <span class="hljs-built_in">this</span>.logger = logger;
  }

  <span class="hljs-keyword">public</span> encode(text: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
      <span class="hljs-comment">// ... code is stripped</span>

    <span class="hljs-built_in">this</span>.writeIntoLog(text, result, encodeWith);
    <span class="hljs-keyword">return</span> result;
  }

  <span class="hljs-keyword">private</span> writeIntoLog(input: <span class="hljs-built_in">string</span>, encoded: <span class="hljs-built_in">string</span>, shiftedBy: <span class="hljs-built_in">number</span>) {
    <span class="hljs-keyword">const</span> log = <span class="hljs-string">`<span class="hljs-subst">${input}</span> is encoded into <span class="hljs-subst">${encoded}</span> by shifting <span class="hljs-subst">${shiftedBy}</span> characters \\n`</span>;
    <span class="hljs-built_in">this</span>.logger.log(log);
  }
}
</code></pre>
<p>Awesome, we decoupled our Encoder from the file system. Let's now write the tests for it, in fact, we just have to modify our existing one so that, it not only tests for the output but also checks if we are calling the logging functionality correctly</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// encoder.spec.ts</span>

<span class="hljs-keyword">class</span> LoggerMock <span class="hljs-keyword">implements</span> ILogger {
  <span class="hljs-keyword">public</span> called: <span class="hljs-built_in">number</span>;
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.called = <span class="hljs-number">0</span>;
  }
  <span class="hljs-keyword">public</span> log(text: <span class="hljs-built_in">string</span>) {
    <span class="hljs-built_in">this</span>.called += <span class="hljs-number">1</span>;
  }
}

describe(<span class="hljs-string">'test encoder'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should encode text correctly'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> stubGen = <span class="hljs-keyword">new</span> RandomGenStub(<span class="hljs-number">5</span>);
    <span class="hljs-keyword">const</span> loggerMock = <span class="hljs-keyword">new</span> LoggerMock();
    <span class="hljs-keyword">const</span> encoder = <span class="hljs-keyword">new</span> Encoder(stubGen, loggerMock);

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> encoded = encoder.encode(<span class="hljs-string">'abcz'</span>);

    <span class="hljs-comment">//Assert</span>
    expect(encoded).toBe(<span class="hljs-string">'fghe'</span>);
    expect(loggerMock.called).toBe(<span class="hljs-number">1</span>);
  });
});
</code></pre>
<p>Here we created our mock in such a way that it tracks if the function is called. <code>expect(loggerMock.called).toBe(1);</code> checks exactly the same.</p>
<p>But there is one more problem, writing these stubs, mocks every time is a tedious task and time-consuming. To avoid manually writing them, we use Mocking libraries. Jest has an inbuilt mocking library, but I liked a library called <a target="_blank" href="https://www.npmjs.com/package/moq.ts">moq.ts</a>, but you can use your library of choice.</p>
<p>Install moq.ts using npm</p>
<pre><code class="lang-bash">npm install moq.ts --save-dev
</code></pre>
<p>Let's remove stubs, and mocks that are manually written, and let's leverage moq.ts instead. Here is how the refactored tests look like</p>
<pre><code class="lang-typescript">describe(<span class="hljs-string">'test encoder'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should encode text correctly'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Arrange</span>
    <span class="hljs-keyword">const</span> stubGen = <span class="hljs-keyword">new</span> Mock&lt;IRandomNumberGenerator&gt;()
      .setup(<span class="hljs-function">(<span class="hljs-params">randomGen</span>) =&gt;</span> randomGen.random(<span class="hljs-number">1</span>, <span class="hljs-number">26</span>))
      .returns(<span class="hljs-number">5</span>)
      .object();

    <span class="hljs-comment">// const loggerMock = new LoggerMock();</span>
    <span class="hljs-keyword">const</span> loggerMock = <span class="hljs-keyword">new</span> Mock&lt;ILogger&gt;()
      .setup(<span class="hljs-function">(<span class="hljs-params">logger</span>) =&gt;</span> logger.log(It.IsAny()))
      .returns();
    <span class="hljs-keyword">const</span> encoder = <span class="hljs-keyword">new</span> Encoder(stubGen, loggerMock.object());

    <span class="hljs-comment">// Act</span>
    <span class="hljs-keyword">const</span> encoded = encoder.encode(<span class="hljs-string">'abcz'</span>);

    <span class="hljs-comment">//Assert</span>
    expect(encoded).toBe(<span class="hljs-string">'fghe'</span>);
    loggerMock.verify(<span class="hljs-function">(<span class="hljs-params">logger</span>) =&gt;</span> logger.log(It.IsAny()), Times.AtMostOnce());
  });
});
</code></pre>
<p>Thanks for reading :). I know it is a bit unorganized and feel unfinished, but I hope you learned something from it. Keep testing your code if you want some peaceful sleep at night 😁 and happy coding ❤️</p>
<p>You may also enjoy the related article I wrote about writing testable code. It has so much overlap with this post though. Here is the <a target="_blank" href="https://keencoder.dev/beginners-guide-to-writing-testable-code">link</a> if you are interested.</p>
]]></content:encoded></item><item><title><![CDATA[Beginner's guide to writing testable code]]></title><description><![CDATA[Believe it or not, I spent 3 years of my career without knowing what testability really means, in fact, I never really heard that term until lately. I have been working on small-scale applications, writing tests for every feature I had implemented, b...]]></description><link>https://keencoder.dev/beginners-guide-to-writing-testable-code</link><guid isPermaLink="true">https://keencoder.dev/beginners-guide-to-writing-testable-code</guid><category><![CDATA[unit testing]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[design and architecture]]></category><dc:creator><![CDATA[Srinivas]]></dc:creator><pubDate>Thu, 12 May 2022 05:34:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652333214450/OV8_uwpxh.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Believe it or not, I spent 3 years of my career without knowing what testability really means, in fact, I never really heard that term until lately. I have been working on small-scale applications, writing tests for every feature I had implemented, but it took 3 years to realize that the tests I have been writing are integration tests, not unit tests. Let me show you how my code used to look like a few years back</p>
<blockquote>
<p>Snippets in this blog post are written in C# but the concept can be applied to any OOP language. Also please note that I left null checks and error handling to keep things simple and focused.</p>
</blockquote>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WeatherApp</span> {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> WeatherAPIClient _weatherApiClient;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherApp</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> apiKey</span>)</span>
    {
        _weatherApiClient = <span class="hljs-keyword">new</span> WeatherAPIClient(apiKey);
    }


    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">GetAvgTempBetween</span>(<span class="hljs-params">DateTime startDate, DateTime endDate</span>)</span>
    {
        <span class="hljs-keyword">var</span> weatherDataResponse = _weatherApiClient.GetWeatherDataBetween(startDate, endDate);

        <span class="hljs-keyword">var</span> readings = weatherDataResponse[<span class="hljs-string">"forecast"</span>][<span class="hljs-string">"forecastday"</span>];
        <span class="hljs-keyword">var</span> numOfReadings = readings.AsArray().Count;

        <span class="hljs-keyword">double</span> sumOfTemps = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i &lt; numOfReadings; i++){
            sumOfTemps += (<span class="hljs-keyword">double</span>)readings[i][<span class="hljs-string">"day"</span>][<span class="hljs-string">"avgtemp_c"</span>];
        }

        <span class="hljs-keyword">return</span> Math.Round(sumOfTemps/numOfReadings, <span class="hljs-number">2</span>);
    }
}
</code></pre>
<p>Consider, the above <code>WeatherApp</code> class, which is going to be our SUT (Subject Under Test), we are basically calculating the average temperature between two dates. Our SUT depends on the <code>WeatherAPIClient</code> class to get weather data from an external API. <code>WeatherAPIClient</code> just calls the API by sending the required parameters and returns the response. You can find the API client code below. </p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WeatherAPIClient</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">string</span> _apiKey;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherAPIClient</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> apiKey</span>)</span>
    {
        _apiKey = apiKey;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> JsonNode <span class="hljs-title">GetWeatherDataBetween</span>(<span class="hljs-params">DateTime startDate, DateTime endDate</span>)</span>
    {
        <span class="hljs-keyword">var</span> formattedStartDate = startDate.ToString(<span class="hljs-string">"yyyy-MM-dd"</span>);
        <span class="hljs-keyword">var</span> formattedEndDate = endDate.ToString(<span class="hljs-string">"yyyy-MM-dd"</span>);
        <span class="hljs-keyword">var</span> url = <span class="hljs-string">$"https://api.weatherapi.com/v1/history.json?key=<span class="hljs-subst">{_apiKey}</span>&amp;q=Hyderabad&amp;dt=<span class="hljs-subst">{formattedStartDate}</span>&amp;end_dt=<span class="hljs-subst">{formattedEndDate}</span>"</span>;

        <span class="hljs-keyword">var</span> requestMessage = <span class="hljs-keyword">new</span> HttpRequestMessage(HttpMethod.Get, url);
        <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">new</span> HttpClient().Send(requestMessage);

        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> reader = <span class="hljs-keyword">new</span> StreamReader(response.Content.ReadAsStream());
        <span class="hljs-keyword">return</span> JsonNode.Parse(reader.ReadToEnd())!;
    }
}
</code></pre>
<blockquote>
<p>Please note that the city name is hardcoded to Hyderabad </p>
<p>( maybe I was feeling lazy to modify the code :p )</p>
</blockquote>
<p>Now let me show you how I used to test code like above</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TestWeatherApp</span>
    {
        [<span class="hljs-meta">Fact</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">TestAverageTemperatureBetweenTwoDates</span>(<span class="hljs-params"></span>)</span>{
            <span class="hljs-comment">// Arrange</span>
            <span class="hljs-keyword">var</span> startDate = DateTime.Parse(<span class="hljs-string">"2022-05-02"</span>);
            <span class="hljs-keyword">var</span> endDate = DateTime.Parse(<span class="hljs-string">"2022-05-03"</span>);
            <span class="hljs-keyword">var</span> weatherApp = <span class="hljs-keyword">new</span> WeatherApp(<span class="hljs-string">"some-api-key"</span>);

            <span class="hljs-comment">// Act</span>
            <span class="hljs-keyword">var</span> result = weatherApp.GetAvgTempBetween(startDate, endDate);

            <span class="hljs-comment">//Assert</span>
            Assert.Equal(<span class="hljs-number">37</span>, result);
        }
    }
</code></pre>
<p>Everything looks good, right? I wrote some code that works, and I am able to test the code I wrote, so does that mean my code is testable? Before answering that let's revisit the definition of unit test. I liked the following definition from the book <a target="_blank" href="https://www.amazon.com/Unit-Testing-Principles-Practices-Patterns/dp/1617296279">Unit Testing Principles, Practices, and Patterns</a></p>
<blockquote>
<p>A unit test is a test that</p>
<ul>
<li><p>Verifies a single unit of behavior,</p>
</li>
<li><p>Does it quickly,</p>
</li>
<li><p>And does it in isolation from other tests.</p>
</li>
</ul>
<p>A test that doesn’t meet at least one of these three requirements falls into the category of <strong>integration tests</strong></p>
</blockquote>
<p>Our test is <strong><em>verifying a single unit of behavior </em></strong>, there is no shared state between other tests so it is <strong><em>running in isolation from other tests</em></strong>, but what about the second characteristic? does our test <strong><em>run quickly</em></strong>? </p>
<p>The answer is, definitely a <strong>NO</strong>, as we discussed earlier, our SUT depends on <code>WeatherAPIClient</code> which actually makes a network call to get weather data which makes our tests run really slow. Imagine you have so many tests which exercise the code that depends on <em>network</em>, <em>databases</em>, <em>filesystems</em>, <em>caches</em>...etc to get some data, your entire test suite takes several minutes to hours making your feedback loops longer, affecting the time that takes for you to develop, go live.</p>
<blockquote>
<p>Code is said to be <strong>testable</strong>, If it does not cross system boundaries, i.e does not reach out to <em>network</em>, <em>databases</em>, <em>filesystems</em>, <em>caches</em>..etc <strong><em>during unit testing</em></strong></p>
</blockquote>
<p>Since our code is talking to the network, it is not testable. Now let's see where the problem is, what is making our code untestable?
.</p>
<p>.</p>
<p>.</p>
<p>Did you spot it?</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>Alright, let me explain.</p>
<p>It is the <code>new</code> keyword that is making our code untestable, to be precise it is the instantiation of <code>WeatherAPIClient</code> in the constructor. The moment you do that, <code>WeatherApp</code> becomes tightly coupled with <code>WeatherAPIClient</code>. Let's fix it.</p>
<h3 id="heading-refactoring-towards-testable-code">Refactoring towards testable code</h3>
<p>Let's start by removing the instantiation inside the constructor, instead, let's take the <code>WeatherAPIClient</code> instance as the argument to the constructor. It is called <a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_injection#Constructor_injection">constructor injection</a>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WeatherApp</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> WeatherAPIClient _weatherApiClient;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherApp</span>(<span class="hljs-params">WeatherAPIClient weatherAPIClient</span>)</span>
    {
        _weatherApiClient = weatherAPIClient;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">GetAvgTempBetween</span>(<span class="hljs-params">DateTime startDate, DateTime endDate</span>)</span>
    {
        <span class="hljs-comment">// ... rest of the code</span>
    }
}
</code></pre>
<p>It is just a part of the solution, <code>WeatherApp</code> is still tightly coupled with <code>WeatherAPIClient</code>. We can make them loosely coupled by following<a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_inversion_principle"><strong> Dependency Inversion Principle</strong></a></p>
<blockquote>
<p>Dependency Inversion Principle: High-level modules should not depend on low-level modules, both should depend on abstractions. Abstractions should not depend on details, details should depend upon abstractions</p>
</blockquote>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">IWeatherAPIClient</span>
{
     <span class="hljs-function">JsonNode <span class="hljs-title">GetWeatherDataBetween</span>(<span class="hljs-params">DateTime startDate, DateTime endDate</span>)</span>;
}
</code></pre>
<p>Let's make our <code>WeatherAPIClient</code> implement this interface, and modify <code>WeatherApp</code> class's constructor such that it depends on the interface rather than the concrete class</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WeatherAPIClient</span>: <span class="hljs-title">IWeatherAPIClient</span>
{
    <span class="hljs-keyword">private</span> read-only <span class="hljs-keyword">string</span> _apiKey;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherAPIClient</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> apiKey</span>)</span>
    {
        _apiKey = apiKey;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> JsonNode <span class="hljs-title">GetWeatherDataBetween</span>(<span class="hljs-params">DateTime startDate, DateTime endDate</span>)</span>
    {
       <span class="hljs-comment">// ... rest of the code</span>
    }
}
</code></pre>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WeatherApp</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IWeatherAPIClient _weatherApiClient;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherApp</span>(<span class="hljs-params">IWeatherAPIClient weatherAPIClient</span>)</span>
    {
        _weatherApiClient = weatherAPIClient;
    }


    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">GetAvgTempBetween</span>(<span class="hljs-params">DateTime startDate, DateTime endDate</span>)</span>
    {
       <span class="hljs-comment">// ... rest of the code</span>
    }
}
</code></pre>
<p>The advantage of depending on abstraction rather than concrete class is that you can swap out the implementation with some <a target="_blank" href="https://martinfowler.com/bliki/TestDouble.html">test doubles</a> during unit testing. Let me show you what I mean</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TestWeatherApp</span>
    {
        [<span class="hljs-meta">Fact</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">TestAverageTemperatureBetweenTwoDates</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">var</span> stubApiClient = <span class="hljs-keyword">new</span> Mock&lt;IWeatherAPIClient&gt;();
            <span class="hljs-keyword">var</span> startDate = DateTime.Parse(<span class="hljs-string">"2022-05-02"</span>);
            <span class="hljs-keyword">var</span> endDate = DateTime.Parse(<span class="hljs-string">"2022-05-02"</span>);
            stubApiClient.Setup(apiClient =&gt; apiClient.GetWeatherDataBetween(startDate, endDate))
                .Returns(JsonNode.Parse(<span class="hljs-string">@"{
                    ""forecast"": {
                        ""forecastday"": [
                            {
                                ""day"": {
                                    ""avgtemp_c"": 34
                                }
                            },
                             {
                                ""day"": {
                                    ""avgtemp_c"": 38
                                }
                            }
                        ]}}"</span>
                    )
                );
            <span class="hljs-keyword">var</span> weatherapp = <span class="hljs-keyword">new</span> WeatherApp(stubApiClient.Object);

            <span class="hljs-keyword">var</span> result = weatherapp.GetAvgTempBetween(startDate, endDate);

            Assert.Equal(<span class="hljs-number">36</span>, result);
        }
    }
}
</code></pre>
<p>In our unit test, instead of passing the actual instance of <code>WeatherAPIClient</code>, we passed a stub that returns some canned response. Using stub, we avoided the problem of reaching out to the network to get the data during testing, which proves that we made our code testable. </p>
<p>Whenever I find some piece of code that is tightly coupled with infrastructure concerns like database, network, filesystem..etc, I usually <strong><em>separate the code</em></strong> that is taking with infrastructure from SUT <strong><em>into a separate class</em></strong> ( <a target="_blank" href="https://deviq.com/principles/single-responsibility-principle">Single Responsibility Principle</a>), inject it via constructor following <strong><em>dependency injection</em></strong>, <strong><em>dependency inversion</em></strong> principles to make it decoupled and testable.</p>
<p>Link to the source code: <a target="_blank" href="https://github.com/SriNandan33/weatherapp">https://github.com/SriNandan33/weatherapp</a></p>
<p>If I learn more about testability, and object-oriented design, I will keep you updated here on this blog. Stay tuned. Thanks for reading, happy coding.</p>
]]></content:encoded></item><item><title><![CDATA[Guide to land your first developer job]]></title><description><![CDATA[Ever since I got my first developer job, my friends started reaching out to me asking how they can get started with programming, build projects, apply for jobs...etc. So I shared them the exact path I took to land my first tech job at a startup. Here...]]></description><link>https://keencoder.dev/guide-to-land-your-first-developer-job</link><guid isPermaLink="true">https://keencoder.dev/guide-to-land-your-first-developer-job</guid><category><![CDATA[Career]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Srinivas]]></dc:creator><pubDate>Thu, 29 Oct 2020 11:43:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679805903872/e99d747d-16e7-4b1c-a2db-ab5a6be527ac.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever since I got my first developer job, my friends started reaching out to me asking how they can get started with programming, build projects, apply for jobs...etc. So I shared them the exact path I took to land my first tech job at a startup. Here I am sharing it via my first ever blog post on the internet.</p>
<h2 id="heading-1-learn-typing">1. Learn Typing</h2>
<p>I said this to my friends many times, that is "<strong>Don't call yourself a programmer or a software developer if you don't know how to type on a keyboard</strong>".</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>Oh man! that sounded so rude :(</p>
<p>But yeah, I really feel that learning to type is a huge productivity boost even though there are many IDEs that help you with autocomplete features. I highly suggest you dedicate some of your time to learning <em>typing</em>, there are many resources out there, go check them out. <strong>Please don't skip this step.</strong></p>
<p>While you are at it, I also recommend you learn some <strong>basic shell commands</strong>, it really helps.</p>
<h2 id="heading-2-start-with-html-andamp-css">2. Start with HTML &amp; CSS</h2>
<p><strong>HTML</strong> and <strong>CSS</strong> are the <em>skeleton</em> and <em>skin</em> for any application you create. <strong>HTML</strong> stands for <strong>H</strong>yper <strong>T</strong>ext <strong>M</strong>arkup <strong>L</strong>anguage, it is used to structure the content in your applications. <strong>CSS</strong> stands for <strong>C</strong>ascading <strong>S</strong>tyle <strong>S</strong>heets, it is used to facelift your application by adding some cool colors, backgrounds, transitions, animations...etc</p>
<p>The reason why I suggested picking up <strong>HTML</strong>, <strong>CSS</strong> first is that they are very easy to pick up, there are many resources that make learning them easy. One other advantage of learning them first is, they will really help you know your <strong>learning method</strong> which is very important to know in your career. Here is how...</p>
<p>I am listing few of the best tutorials available for <strong>HTML</strong>, <strong>CSS</strong> on the internet. Try learning from them, pick one method and a resource and explore a <strong>few topics</strong> in it. If you find it difficult to learn, switch to a different method until you figure out what your learning method is.</p>
<ol>
<li><p><strong>Interactive</strong></p>
<ul>
<li><p><a target="_blank" href="https://learn.freecodecamp.org/">FreeCodeCamp</a></p>
</li>
<li><p><a target="_blank" href="https://dash.generalassemb.ly/">Dash</a> by General Assembly</p>
</li>
</ul>
</li>
<li><p><strong>Reading</strong></p>
<ul>
<li><p><a target="_blank" href="https://learn.shayhowe.com/">Learn to Code HTML &amp; CSS</a></p>
</li>
<li><p><a target="_blank" href="https://internetingishard.com/">HTML &amp; CSS is hard but id does not have to be</a></p>
</li>
</ul>
</li>
<li><p><strong>Videos</strong></p>
<ul>
<li><p><a target="_blank" href="https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/?couponCode=ACAD_W">CSS - The Complete Guide (incl. Flexbox, Grid &amp; Sass)</a></p>
</li>
<li><p><a target="_blank" href="https://scrimba.com/">Scrimba</a> (Interactive Video Tutorials)</p>
</li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>Note:</strong> To practice what you learned, I found a website that is really helpful. <a target="_blank" href="https://www.frontendmentor.io/">FrontEnd Mentor</a>.</p>
</blockquote>
<h2 id="heading-3-learn-about-version-control-git-andamp-github">3. Learn about Version Control (Git &amp; GitHub)</h2>
<p>Read what I wrote about <strong>typing?</strong> same goes for <strong>Git.</strong> Every aspiring software developer should learn how to use Git.</p>
<p>As a software developer, oftentimes you write code, save it, edit it and save it again. But, what if something goes wrong? how can you revert back your changes even after few days from the day you made changes? This is where Version Control really helps, It helps you track your changes.</p>
<p><strong>Git</strong> is a modern implementation of Version Control, <strong>Github</strong> is a code hosting platform where you can browse your code and inspect your changes. <strong>Github</strong> really helps software developers as a portfolio/showcase of your work and let your potential employers know about your coding skills. So, learn enough <strong>Git,</strong> so that you host your code on <strong>Github.</strong> Go through the following resource</p>
<p><a target="_blank" href="https://youtu.be/SWYqp7iY_Tc">Git &amp; GitHub Crash Course For Beginners</a> by <a target="_blank" href="https://www.youtube.com/channel/UC29ju8bIPH5as8OGnQzwJyA"><strong>Traversy Media</strong></a></p>
<h2 id="heading-4-pick-your-first-programming-language">4. Pick your first programming language</h2>
<p>There are many programming languages in the industry, beginners like us always have confusion when it comes to picking up our first programming language. So, pick either <strong>JavaScript</strong> or <strong>Python</strong> and learn the basics well. They are very popular among beginners and in the industry as well.</p>
<p>It does not matter what language you pick up because at some point in your career you will have to switch between languages based on the kind of applications you build. So don't get attached to your first language, focus on learning the programming fundamentals well. I found the following resources useful...</p>
<p><strong>Javascript</strong>: <a target="_blank" href="https://www.codecademy.com/learn/introduction-to-javascript">Introduction to Javascript from Codecademy</a></p>
<p><strong>Python:</strong> <a target="_blank" href="https://python.swaroopch.com/">Byte Of Python</a></p>
<h2 id="heading-5-pick-a-framework-based-on-your-language-of-choice">5. Pick a framework based on your language of choice</h2>
<p>Frameworks provide a set of tools that help developers build applications without re-inventing the wheel. I chose <strong>Python</strong> as my first programming language, so I picked up <strong>Django</strong> which is a full-stack framework. It is beginner-friendly and It has many things inbuilt such as <em>user authentication, forms, ORM (Object Relation Mapper), admin panel, unit test framework and many more</em>. So, it allows beginners to concentrate on the application and to have fun while doing that.</p>
<p>If you choose Javascript, you can pick one of the frontend frameworks (React.js, Vue.js) or backend framework (Node.js/Express.js).</p>
<h2 id="heading-6-build-an-app-to-test-your-knowledge">6. Build an app to test your knowledge</h2>
<p>Once you learn to use a framework, it is really important to build some projects to test your knowledge. It can be a simple To-Do app, a note-taking app like Evernote, a simple blog application, clones of your favorite applications like Medium, Twitter, Facebook...etc. Whatever you build, make sure you host your source code on Github and let the world know about your work by sharing it across social networks.</p>
<h2 id="heading-7-algorithms">7. Algorithms</h2>
<p>This is the step that many beginners skip including me, I did not concentrate on learning algorithms and improving my problem-solving skills. Yes, some startups do not care about algorithms, but it is very important to learn them if you want to land a job at well known companies like Google, Amazon, Apple, Uber...etc. You will see them in every interview you face, so go grab a copy of <a target="_blank" href="https://amzn.to/2GOjeVI">Cracking the Coding Interview</a> and prepare for interviews.</p>
<p>Once you have some applications hosted on GitHub, have your resume prepared, update your LinkedIn profile and apply for jobs.</p>
<p>All the best, never stop learning...</p>
]]></content:encoded></item></channel></rss>