<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>unit tests Archives - CodeJourney.net</title>
	<atom:link href="https://www.codejourney.net/tag/unit-tests/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.codejourney.net/tag/unit-tests/</link>
	<description>Become a better .NET full stack web developer</description>
	<lastBuildDate>Thu, 03 Oct 2024 13:41:05 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://i0.wp.com/www.codejourney.net/wp-content/uploads/2018/10/cropped-512px-na-512px-JPEG-BEZ-NAPISU-1.jpg?fit=32%2C32&#038;ssl=1</url>
	<title>unit tests Archives - CodeJourney.net</title>
	<link>https://www.codejourney.net/tag/unit-tests/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">123174533</site>	<item>
		<title>What is Mutation Testing and Why Should You Use It?</title>
		<link>https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/</link>
					<comments>https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/#respond</comments>
		
		<dc:creator><![CDATA[Dawid Sibiński]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 18:22:58 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mutation testing]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[typescript]]></category>
		<category><![CDATA[unit tests]]></category>
		<guid isPermaLink="false">https://www.codejourney.net/?p=4825</guid>

					<description><![CDATA[<p>Do you know what is a better testing metric than code coverage? Does 100% code coverage mean your code is well-tested? How to generate unit test cases for free, without using AI? The answer to all these questions is mutation testing. Interested? Read on 😉 Code Coverage &#8211; Our Old Friend You probably know what&#8230;</p>
<p>The post <a href="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/">What is Mutation Testing and Why Should You Use It?</a> appeared first on <a href="https://www.codejourney.net">CodeJourney.net</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Do you know what is a better testing metric than code coverage? Does 100% code coverage mean your code is well-tested? How to generate unit test cases for free, without using AI?</p>



<p>The answer to all these questions is <strong>mutation testing</strong>. Interested? Read on <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<span id="more-4825"></span>



<h2 class="wp-block-heading">Code Coverage &#8211; Our Old Friend</h2>



<p>You probably know what <a href="https://en.wikipedia.org/wiki/Code_coverage">code coverage</a> is. Traditionally, many teams tend to measure how good their tests&#8217; suite is by percentage line / statements / functions coverage. Some even require this metric to be 100%. Let&#8217;s start with this well-known approach first.</p>



<p>We are working with <code>TicketsPriceCalculator</code> class today. It contains some simple business logic:</p>



<figure class="wp-block-embed is-type-rich is-provider-embed-handler wp-block-embed-embed-handler"><div class="wp-block-embed__wrapper">
<style>.gist table { margin-bottom: 0; }</style><div style="tab-size: 8" id="gist133062269" class="gist">
    <div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-ticketspricecalculator-ts" class="file my-2">
    
    <div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-typescript  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="ticketsPriceCalculator.ts content, created by dsibinski on 04:08PM on October 01, 2024."
    >

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  <template class="js-file-alert-template">
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div></template>
<template class="js-line-alert-template">
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
</span></template>

  <table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="ticketsPriceCalculator.ts">
        <tr>
          <td id="file-ticketspricecalculator-ts-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-ticketspricecalculator-ts-LC1" class="blob-code blob-code-inner js-file-line">export class TicketsPriceCalculator {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-ticketspricecalculator-ts-LC2" class="blob-code blob-code-inner js-file-line">  calculateTotalTicketsPrice(tickets: Ticket[]): number {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-ticketspricecalculator-ts-LC3" class="blob-code blob-code-inner js-file-line">    if (tickets.length === 0) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-ticketspricecalculator-ts-LC4" class="blob-code blob-code-inner js-file-line">      return 0;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-ticketspricecalculator-ts-LC5" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-ticketspricecalculator-ts-LC6" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-ticketspricecalculator-ts-LC7" class="blob-code blob-code-inner js-file-line">    let totalPrice = tickets.reduce((sum, ticket) =&gt; sum + ticket.price, 0);</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-ticketspricecalculator-ts-LC8" class="blob-code blob-code-inner js-file-line">    const businessClassTickets = tickets.filter(</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-ticketspricecalculator-ts-LC9" class="blob-code blob-code-inner js-file-line">      (ticket) =&gt; ticket.isBusinessClass</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-ticketspricecalculator-ts-LC10" class="blob-code blob-code-inner js-file-line">    ).length;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-ticketspricecalculator-ts-LC11" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-ticketspricecalculator-ts-LC12" class="blob-code blob-code-inner js-file-line">    let totalDiscountToApply = 0;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-ticketspricecalculator-ts-LC13" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-ticketspricecalculator-ts-LC14" class="blob-code blob-code-inner js-file-line">    // Apply discounts based on total price</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-ticketspricecalculator-ts-LC15" class="blob-code blob-code-inner js-file-line">    if (totalPrice &gt; 2000) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-ticketspricecalculator-ts-LC16" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.25;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-ticketspricecalculator-ts-LC17" class="blob-code blob-code-inner js-file-line">    } else if (totalPrice &gt; 1000 &amp;&amp; totalPrice &lt;= 2000) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-ticketspricecalculator-ts-LC18" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.2;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-ticketspricecalculator-ts-LC19" class="blob-code blob-code-inner js-file-line">    } else if (totalPrice &gt; 500 &amp;&amp; totalPrice &lt;= 1000) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-ticketspricecalculator-ts-LC20" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.15;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-ticketspricecalculator-ts-LC21" class="blob-code blob-code-inner js-file-line">    } else if (totalPrice &gt;= 200 &amp;&amp; totalPrice &lt;= 500) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-ticketspricecalculator-ts-LC22" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.1;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-ticketspricecalculator-ts-LC23" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-ticketspricecalculator-ts-LC24" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-ticketspricecalculator-ts-LC25" class="blob-code blob-code-inner js-file-line">    // Apply additional discount based on number of tickets</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-ticketspricecalculator-ts-LC26" class="blob-code blob-code-inner js-file-line">    if (tickets.length &gt;= 10) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-ticketspricecalculator-ts-LC27" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.05;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-ticketspricecalculator-ts-LC28" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-ticketspricecalculator-ts-LC29" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-ticketspricecalculator-ts-LC30" class="blob-code blob-code-inner js-file-line">    // Apply business class discounts</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-ticketspricecalculator-ts-LC31" class="blob-code blob-code-inner js-file-line">    if (businessClassTickets &gt;= 10) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-ticketspricecalculator-ts-LC32" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.2;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-ticketspricecalculator-ts-LC33" class="blob-code blob-code-inner js-file-line">    } else if (businessClassTickets &gt;= 5) {</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-ticketspricecalculator-ts-LC34" class="blob-code blob-code-inner js-file-line">      totalDiscountToApply += 0.1;</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-ticketspricecalculator-ts-LC35" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-ticketspricecalculator-ts-LC36" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-ticketspricecalculator-ts-LC37" class="blob-code blob-code-inner js-file-line">    return totalPrice * (1 &#8211; totalDiscountToApply);</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-ticketspricecalculator-ts-LC38" class="blob-code blob-code-inner js-file-line">  }</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator-ts-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
          <td id="file-ticketspricecalculator-ts-LC39" class="blob-code blob-code-inner js-file-line">}</td>
        </tr>
  </table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/dsibinski/28087f239e57c7dab06d3df2e7532e6d/raw/d388fec49bd951d520a8d0af93c07907c122ce27/ticketsPriceCalculator.ts" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/dsibinski/28087f239e57c7dab06d3df2e7532e6d#file-ticketspricecalculator-ts" class="Link--inTextBlock">
          ticketsPriceCalculator.ts
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>

</div></figure>



<p>As you can see, the class has one function whith returns the total price to be paid for a set of tickets. On the way, it applies various discounts based on some business rules. Fair enough.</p>



<p>It&#8217;s a critical piece of business logic for the app we&#8217;re working on, but it has never had any tests. We were asked to write unit tests for this class. Our manager strictly requires the code coverage to be 100%. Let&#8217;s do it then. We will go line by line, analyze the business logic and add the tests. Below, you can see the results of running those tests (you can find the tests code <a href="https://gist.github.com/dsibinski/cfc8d36cf7fe45bb9114b950fa898766">here</a>):</p>



<figure class="wp-block-image size-full"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="839" height="427" data-attachment-id="4840" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/1-unit-tests-initial/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/1-unit-tests-initial.jpg?fit=839%2C427&amp;ssl=1" data-orig-size="839,427" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="1-unit-tests-initial" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/1-unit-tests-initial.jpg?fit=839%2C427&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/1-unit-tests-initial.jpg?fit=839%2C427&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/1-unit-tests-initial.jpg?resize=839%2C427&#038;ssl=1" alt="Unit tests before using mutation testing. We have 8 unit tests, all passing. Our code coverage (line, functions, statements, branches) is 100%" class="wp-image-4840" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/1-unit-tests-initial.jpg?w=839&amp;ssl=1 839w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/1-unit-tests-initial.jpg?resize=768%2C391&amp;ssl=1 768w" sizes="(max-width: 839px) 100vw, 839px" /></figure>



<p></p>



<p>Wow, that&#8217;s awesome! We did a great job. We have <strong>8 unit tests which provide 100% statements, branch, functions and lines coverage</strong>!</p>



<p>So now we are really safe, aren&#8217;t we? <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f914.png" alt="🤔" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Yeah&#8230; until you know what mutation testing is <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60e.png" alt="😎" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h2 class="wp-block-heading">What Is Mutation Testing?</h2>



<p>The idea of mutation testing is to <em>mutate</em> (change) our code. Mutation testing tools introduce changes into our production code. These changes can be really anything &#8211; from reverting a condition of an <code>if</code> statement, to changing some operators or changing a <code>string</code> value. For instance, here are some logical mutations <a href="https://stryker-mutator.io/">Stryker Mutator</a> is able to introduce (you can find the list of all mutations supported by Stryker <a href="https://stryker-mutator.io/docs/mutation-testing-elements/supported-mutators/">here</a>):</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img data-recalc-dims="1" decoding="async" width="445" height="320" data-attachment-id="4845" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/2-stryker-logical-mutations/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/2-stryker-logical-mutations.jpg?fit=445%2C320&amp;ssl=1" data-orig-size="445,320" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2-stryker-logical-mutations" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/2-stryker-logical-mutations.jpg?fit=445%2C320&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/2-stryker-logical-mutations.jpg?fit=445%2C320&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/2-stryker-logical-mutations.jpg?resize=445%2C320&#038;ssl=1" alt="Logical operator mutations supported by Stryker Mutator" class="wp-image-4845"/></figure>
</div>


<p></p>



<p>In effect, they generate modified versions of our code, which are called <em>mutants</em>. Makes sense <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Each mutant contains a single modification in our source code. What happens next is crucial. Mutation testing tool takes this mutant (it is used as the code under tests now) and executes all of our unit tests against it. The result may be twofold:</p>



<ul class="wp-block-list">
<li>all tests have passed. In other words, the <em>mutant has</em> <em>survived</em>. <strong>This is a bad situation</strong>. It implies that the modification of our source code was not detected by our tests</li>



<li>at least one test has failed. In other words, the <em>mutant has been killed</em>. <strong>This is a good scenario</strong>. It means that our tests detect changes in the production code and efficiently cover this particular scenario.</li>
</ul>



<p>The flow is more or less like this <a href="https://peterevans.dev/posts/mutation-testing/">schema from Peter Evans&#8217; blog</a> presents:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img data-recalc-dims="1" decoding="async" width="353" height="580" data-attachment-id="4847" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/3-mutation-test-schema/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/3-mutation-test-schema.png?fit=353%2C580&amp;ssl=1" data-orig-size="353,580" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="3-mutation-test-schema" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/3-mutation-test-schema.png?fit=353%2C580&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/3-mutation-test-schema.png?fit=353%2C580&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/3-mutation-test-schema.png?resize=353%2C580&#038;ssl=1" alt="Schema of mutation testing" class="wp-image-4847" style="width:353px;height:auto"/></figure>
</div>


<p></p>



<p>But why would anyone change the production code on purpose by introducing some stupid changes? It may seem counterintuitive for now, but let&#8217;s see how we can use it to our leverage.</p>



<h2 class="wp-block-heading">Mutation Testing with Stryker Mutator</h2>



<p>Let&#8217;s clearly state what we are starting with:</p>



<p><strong>8 unit tests, 100% code coverage</strong></p>



<p>Let&#8217;s now run mutation testing on our code. We are using TypeScript here, so let&#8217;s go with <a href="https://stryker-mutator.io/">Stryker Mutator</a>.</p>



<p>Here&#8217;s the result of running Stryker with <code>npx stryker run</code> on our code:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="958" height="163" data-attachment-id="4854" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/4-stryker-mutator-1/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/4-stryker-mutator-1.jpg?fit=958%2C163&amp;ssl=1" data-orig-size="958,163" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="4-stryker-mutator-1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/4-stryker-mutator-1.jpg?fit=958%2C163&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/4-stryker-mutator-1.jpg?fit=958%2C163&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/4-stryker-mutator-1.jpg?resize=958%2C163&#038;ssl=1" alt="Mutation test result - first run. Mutation score 78%, survived mutants 15" class="wp-image-4854" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/4-stryker-mutator-1.jpg?w=958&amp;ssl=1 958w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/4-stryker-mutator-1.jpg?resize=768%2C131&amp;ssl=1 768w" sizes="auto, (max-width: 958px) 100vw, 958px" /></figure>
</div>


<p></p>



<p>As you can see, 53 mutants were killed, but 15 of them survived. This gives us a mutation score of 78%. Let&#8217;s call it <em>mutation coverage</em> from now on. So to make it clear, this is our starting situation:</p>



<p><strong>8 unit tests, 100% code coverage, 78% mutation coverage</strong></p>



<p>Let&#8217;s now see how to kill those remaining mutants.</p>



<h2 class="wp-block-heading">Killing First Mutants</h2>



<p>In order to kill the mutants and improve our mutation score, we need to write more unit tests. Sounds logical, doesn&#8217;t it?</p>



<p>If still not, let&#8217;s take a deeper look at mutation tests results in VS Code. Stryker lists details of every survived mutant, for example this one:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="864" height="198" data-attachment-id="4855" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/5-stryker-mutant-1/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/5-stryker-mutant-1.jpg?fit=864%2C198&amp;ssl=1" data-orig-size="864,198" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="5-stryker-mutant-1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/5-stryker-mutant-1.jpg?fit=864%2C198&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/5-stryker-mutant-1.jpg?fit=864%2C198&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/5-stryker-mutant-1.jpg?resize=864%2C198&#038;ssl=1" alt="First mutant generated by Stryker" class="wp-image-4855" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/5-stryker-mutant-1.jpg?w=864&amp;ssl=1 864w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/5-stryker-mutant-1.jpg?resize=768%2C176&amp;ssl=1 768w" sizes="auto, (max-width: 864px) 100vw, 864px" /></figure>
</div>


<p></p>



<p>Stryker changed the greater or equal (<code>>=</code>) operator to greater operator (<code>></code>). This is a very common and very useful mutation. It usually means that our tests don&#8217;t cover the edge case associated with this particular condition.</p>



<p>In this case, the edge case value seems to be <code>5</code>. More precisely, what happens if the number of business class tickets is <em>exactly 5</em>? We don&#8217;t know, because there is no test for this particular edge case!</p>



<p>Let&#8217;s add it:</p>



<figure class="wp-block-embed is-type-rich is-provider-embed-handler wp-block-embed-embed-handler"><div class="wp-block-embed__wrapper">
<style>.gist table { margin-bottom: 0; }</style><div style="tab-size: 8" id="gist133063837" class="gist">
    <div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-ticketspricecalculator_edgecase-test-ts" class="file my-2">
    
    <div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-typescript  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="ticketsPriceCalculator_edgeCase.test.ts content, created by dsibinski on 05:23PM on October 01, 2024."
    >

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  <template class="js-file-alert-template">
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div></template>
<template class="js-line-alert-template">
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
</span></template>

  <table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="ticketsPriceCalculator_edgeCase.test.ts">
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC1" class="blob-code blob-code-inner js-file-line">  <span class=pl-en>test</span><span class=pl-kos>(</span><span class=pl-s>&quot;should apply 10% discount if there are exactly 5 business class tickets&quot;</span><span class=pl-kos>,</span> <span class=pl-kos>(</span><span class=pl-kos>)</span> <span class=pl-c1>=&gt;</span> <span class=pl-kos>{</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC2" class="blob-code blob-code-inner js-file-line">    <span class=pl-k>const</span> <span class=pl-s1>tickets</span> <span class=pl-c1>=</span> <span class=pl-v>Array</span><span class=pl-kos>.</span><span class=pl-en>from</span><span class=pl-kos>(</span><span class=pl-kos>{</span> <span class=pl-c1>length</span>: <span class=pl-c1>5</span> <span class=pl-kos>}</span><span class=pl-kos>,</span> <span class=pl-kos>(</span><span class=pl-kos>)</span> <span class=pl-c1>=&gt;</span> <span class=pl-kos>(</span><span class=pl-kos>{</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC3" class="blob-code blob-code-inner js-file-line">      <span class=pl-c1>price</span>: <span class=pl-c1>10</span><span class=pl-kos>,</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC4" class="blob-code blob-code-inner js-file-line">      <span class=pl-c1>isBusinessClass</span>: <span class=pl-c1>true</span><span class=pl-kos>,</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC5" class="blob-code blob-code-inner js-file-line">    <span class=pl-kos>}</span><span class=pl-kos>)</span><span class=pl-kos>)</span><span class=pl-kos>;</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC6" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC7" class="blob-code blob-code-inner js-file-line">    <span class=pl-k>const</span> <span class=pl-s1>totalPrice</span> <span class=pl-c1>=</span> <span class=pl-s1>calculator</span><span class=pl-kos>.</span><span class=pl-en>calculateTotalTicketsPrice</span><span class=pl-kos>(</span><span class=pl-s1>tickets</span><span class=pl-kos>)</span><span class=pl-kos>;</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC8" class="blob-code blob-code-inner js-file-line">    <span class=pl-en>expect</span><span class=pl-kos>(</span><span class=pl-s1>totalPrice</span><span class=pl-kos>)</span><span class=pl-kos>.</span><span class=pl-en>toBe</span><span class=pl-kos>(</span><span class=pl-c1>45</span><span class=pl-kos>)</span><span class=pl-kos>;</span> <span class=pl-c>// 10% discount</span></td>
        </tr>
        <tr>
          <td id="file-ticketspricecalculator_edgecase-test-ts-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-ticketspricecalculator_edgecase-test-ts-LC9" class="blob-code blob-code-inner js-file-line">  <span class=pl-kos>}</span><span class=pl-kos>)</span><span class=pl-kos>;</span></td>
        </tr>
  </table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/dsibinski/ee04a5c91df633a66935ed6a663f3ae1/raw/836811b2f5ba7f306346a9c11f4fe7de42ce2b89/ticketsPriceCalculator_edgeCase.test.ts" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/dsibinski/ee04a5c91df633a66935ed6a663f3ae1#file-ticketspricecalculator_edgecase-test-ts" class="Link--inTextBlock">
          ticketsPriceCalculator_edgeCase.test.ts
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>

</div></figure>



<p>The test passes. Let&#8217;s run mutation tests again:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="961" height="166" data-attachment-id="4856" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/6-stryker-mutator-2/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/6-stryker-mutator-2.jpg?fit=961%2C166&amp;ssl=1" data-orig-size="961,166" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="6-stryker-mutator-2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/6-stryker-mutator-2.jpg?fit=961%2C166&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/6-stryker-mutator-2.jpg?fit=961%2C166&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/6-stryker-mutator-2.jpg?resize=961%2C166&#038;ssl=1" alt="Struker Mutator second run - already 14 mutants survived and almost 80% mutation coverage" class="wp-image-4856" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/6-stryker-mutator-2.jpg?w=961&amp;ssl=1 961w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/6-stryker-mutator-2.jpg?resize=768%2C133&amp;ssl=1 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>
</div>


<p></p>



<p>That&#8217;s it! We have a new unit test and 1 more mutant killed <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f389.png" alt="🎉" class="wp-smiley" style="height: 1em; max-height: 1em;" />  Current state:</p>



<p><strong>9 (+1) unit tests, 100% code coverage, 79% mutation coverage</strong></p>



<p>I think you&#8217;re now getting what this is all about. We should be adding unit tests to cover the edge cases detected by mutations until all (or most) mutants are killed.</p>



<h2 class="wp-block-heading">Mutation Testing &#8211; Free Unit Tests Generator</h2>



<p>After adding 1 more test, the results look as follows:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="960" height="164" data-attachment-id="4859" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/7-stryker-mutator-3/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/7-stryker-mutator-3.jpg?fit=960%2C164&amp;ssl=1" data-orig-size="960,164" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="7-stryker-mutator-3" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/7-stryker-mutator-3.jpg?fit=960%2C164&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/7-stryker-mutator-3.jpg?fit=960%2C164&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/7-stryker-mutator-3.jpg?resize=960%2C164&#038;ssl=1" alt="Struker mutator with 10 tests - 86% mutation coverage" class="wp-image-4859" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/7-stryker-mutator-3.jpg?w=960&amp;ssl=1 960w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/7-stryker-mutator-3.jpg?resize=768%2C131&amp;ssl=1 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></figure>
</div>


<p></p>



<p><strong>10 (+2) unit tests, 100% code coverage, 86% mutation coverage</strong></p>



<p>Finally, this is what we managed to get after a few minutes of work:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="959" height="165" data-attachment-id="4860" data-permalink="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/8-stryker-mutator-4/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/8-stryker-mutator-4.jpg?fit=959%2C165&amp;ssl=1" data-orig-size="959,165" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="8-stryker-mutator-4" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/8-stryker-mutator-4.jpg?fit=959%2C165&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/8-stryker-mutator-4.jpg?fit=959%2C165&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/8-stryker-mutator-4.jpg?resize=959%2C165&#038;ssl=1" alt="" class="wp-image-4860" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/8-stryker-mutator-4.jpg?w=959&amp;ssl=1 959w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2024/10/8-stryker-mutator-4.jpg?resize=768%2C132&amp;ssl=1 768w" sizes="auto, (max-width: 959px) 100vw, 959px" /></figure>
</div>


<p></p>



<p>And we now have 17 unit tests in our suite! The final score looks like that:</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f38a.png" alt="🎊" class="wp-smiley" style="height: 1em; max-height: 1em;" /><strong>17 (+9) unit tests, 100% code coverage, 96% mutation coverage</strong> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f38a.png" alt="🎊" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Notice what happened here. <strong>We started with 8 unit tests and finished with 17! This is awesome! That&#8217;s how mutation testing is a free unit tests generator</strong>. And you don&#8217;t even need AI for that <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>What&#8217;s more, the generated mutations even forced me to make a little tweak to the production code. It exposed some things that didn&#8217;t make sense. I could make this change to the production code, because my tests&#8217; suite was already quite substantial.</p>



<p>Note that I didn&#8217;t push to gain 100% mutation coverage. The 3 mutants that survived don&#8217;t make much sense in our case. I encourage you to <a href="https://github.com/dsibinski/codejourney/tree/main/mutation-testing">get the code</a> and execute <code>npx stryker run</code> in the application folder to see for yourself <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>The percentage value doesn&#8217;t matter in that case. What matters is that we got 9 new unit tests and our tests&#8217; suite is more robust. Now we can go and tell our manager that the business-critical code is well tested <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h2 class="wp-block-heading">So What Now?</h2>



<p>I hope you see how valuable mutation testing is. It&#8217;s not a perfect tool that suits all cases. For example, it&#8217;s not easy to use mutation testing for complex legacy code. However, if your logic is nicely isolated, it could be a great tool. Especially if your production code heavily depends on calculations and many conditions. You may be surprised how many edge cases mutation testing can find.</p>



<p>I also love using mutation testing with TDD. These two techniques nicely complement each other.</p>



<p>I encourage you to go and try mutation testing. There are different mutation tools for various programming languages:</p>



<ul class="wp-block-list">
<li>C#, JavaScript, TypeScript, Scala: <a href="https://stryker-mutator.io/">Stryker Mutator</a></li>



<li>Ruby: <a href="https://github.com/mbj/mutant">mutant</a></li>



<li>Java: <a href="https://pitest.org/">pitest</a></li>



<li>PHP: <a href="https://infection.github.io/">Infection</a></li>



<li>C++: <a href="https://github.com/nlohmann/mutate_cpp">Mutate++</a></li>
</ul>



<p>&#8230;and probably many more. Just do some research for the language you work with and give it a try <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Because <a href="https://www.codejourney.net/improve-your-tests-with-assert-object-pattern/">testing</a> is cool, isn&#8217;t it? <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>You can find the full source code used in this article <a href="https://github.com/dsibinski/codejourney/tree/main/mutation-testing">here</a>.</p>
<p>The post <a href="https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/">What is Mutation Testing and Why Should You Use It?</a> appeared first on <a href="https://www.codejourney.net">CodeJourney.net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codejourney.net/what-is-mutation-testing-and-why-you-should-use-it/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4825</post-id>	</item>
		<item>
		<title>Write Test Progress To The Console With NUnit</title>
		<link>https://www.codejourney.net/write-test-progress-to-the-console-with-nunit/</link>
					<comments>https://www.codejourney.net/write-test-progress-to-the-console-with-nunit/#respond</comments>
		
		<dc:creator><![CDATA[Dawid Sibiński]]></dc:creator>
		<pubDate>Sun, 19 Jun 2022 13:07:28 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[nunit]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[unit tests]]></category>
		<guid isPermaLink="false">https://www.codejourney.net/?p=4070</guid>

					<description><![CDATA[<p>I recently needed to write test progress to the console with NUnit. The task we want to solve here is basically the TODO part of this snippet: The title picture of this article shows the end result. If you want to know the solution, keep reading 🙂 Context The context of this need is very&#8230;</p>
<p>The post <a href="https://www.codejourney.net/write-test-progress-to-the-console-with-nunit/">Write Test Progress To The Console With NUnit</a> appeared first on <a href="https://www.codejourney.net">CodeJourney.net</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I recently needed to write test progress to the console with NUnit. The task we want to solve here is basically the <em>TODO</em> part of this snippet:</p>



<figure class="wp-block-embed is-type-rich is-provider-embed-handler wp-block-embed-embed-handler"><div class="wp-block-embed__wrapper">
<style>.gist table { margin-bottom: 0; }</style><div style="tab-size: 8" id="gist116902181" class="gist">
    <div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-nunit_test_progress_todo-cs" class="file my-2">
    
    <div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-c  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="NUnit_test_progress_todo.cs content, created by dsibinski on 04:54AM on June 19, 2022."
    >

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  <template class="js-file-alert-template">
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div></template>
<template class="js-line-alert-template">
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
</span></template>

  <table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="NUnit_test_progress_todo.cs">
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-nunit_test_progress_todo-cs-LC1" class="blob-code blob-code-inner js-file-line">[TestFixture]</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-nunit_test_progress_todo-cs-LC2" class="blob-code blob-code-inner js-file-line">public class MyTests</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-nunit_test_progress_todo-cs-LC3" class="blob-code blob-code-inner js-file-line">{</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-nunit_test_progress_todo-cs-LC4" class="blob-code blob-code-inner js-file-line">    [Test]</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-nunit_test_progress_todo-cs-LC5" class="blob-code blob-code-inner js-file-line">    public void SampleTest()</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-nunit_test_progress_todo-cs-LC6" class="blob-code blob-code-inner js-file-line">    {</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-nunit_test_progress_todo-cs-LC7" class="blob-code blob-code-inner js-file-line">        // some operations here, like starting a server for tests in-memory&#8230;</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-nunit_test_progress_todo-cs-LC8" class="blob-code blob-code-inner js-file-line">        </td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-nunit_test_progress_todo-cs-LC9" class="blob-code blob-code-inner js-file-line">        // TODO: inform the &#39;user&#39; (the one who runs the test) that the server is already running</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-nunit_test_progress_todo-cs-LC10" class="blob-code blob-code-inner js-file-line">        while (true)</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-nunit_test_progress_todo-cs-LC11" class="blob-code blob-code-inner js-file-line">        {</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-nunit_test_progress_todo-cs-LC12" class="blob-code blob-code-inner js-file-line">            // keep it running on purpose (e.g. for E2E tests)</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-nunit_test_progress_todo-cs-LC13" class="blob-code blob-code-inner js-file-line">        }</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-nunit_test_progress_todo-cs-LC14" class="blob-code blob-code-inner js-file-line">        </td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-nunit_test_progress_todo-cs-LC15" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress_todo-cs-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-nunit_test_progress_todo-cs-LC16" class="blob-code blob-code-inner js-file-line">}</td>
        </tr>
  </table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/dsibinski/419247cf91eaa4bd67f820a9af5e0dd9/raw/1f387ac42e1bf490b1531fc7808de21fe2fe6aff/NUnit_test_progress_todo.cs" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/dsibinski/419247cf91eaa4bd67f820a9af5e0dd9#file-nunit_test_progress_todo-cs" class="Link--inTextBlock">
          NUnit_test_progress_todo.cs
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>

</div></figure>



<p>The title picture of this article shows the end result. If you want to know the solution, keep reading <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<span id="more-4070"></span>



<h2 class="wp-block-heading">Context</h2>



<p>The context of this need is very simple. I have a unit test in which I want to perform some operations and keep the test running indefinitely afterwards. The use case might be instantiation of an <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.testhost.testserver?view=aspnetcore-6.0">in-memory test server</a>. After that, I want to inform the user (programmer or the one running the test) that the server is up and running. I want to do that <strong>before the test finishes</strong>. In other words: <strong>I want to write the test&#8217;s output while it&#8217;s still running</strong>. </p>



<p>In my case, I was running two .NET Core apps in-memory. The backend server app and the ASP.NET Core web application. In the process, the web app got its IP address assigned dynamically. Meaning that the IP was different with each test run. This particular test was used to run the app in-memory and let the user manually use the application. It means the user must know the IP/URL of the in-memory web app. That&#8217;s why I needed to output the dynamic IP address into the NUnit test output <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h2 class="wp-block-heading">Solution</h2>



<p>The solution to write test progress to the console with NUnit is very simple. To do that, use <code>TestContext.Progress.WriteLine(string)</code> method from <code>NUnit.Framework</code> namespace:</p>



<figure class="wp-block-embed is-type-rich is-provider-embed-handler wp-block-embed-embed-handler"><div class="wp-block-embed__wrapper">
<style>.gist table { margin-bottom: 0; }</style><div style="tab-size: 8" id="gist116902272" class="gist">
    <div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-nunit_test_progress-cs" class="file my-2">
    
    <div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-c  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="NUnit_test_progress.cs content, created by dsibinski on 05:05AM on June 19, 2022."
    >

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  <template class="js-file-alert-template">
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div></template>
<template class="js-line-alert-template">
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
</span></template>

  <table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="NUnit_test_progress.cs">
        <tr>
          <td id="file-nunit_test_progress-cs-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-nunit_test_progress-cs-LC1" class="blob-code blob-code-inner js-file-line">[TestFixture]</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-nunit_test_progress-cs-LC2" class="blob-code blob-code-inner js-file-line">public class MyTests</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-nunit_test_progress-cs-LC3" class="blob-code blob-code-inner js-file-line">{</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-nunit_test_progress-cs-LC4" class="blob-code blob-code-inner js-file-line">    [Test]</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-nunit_test_progress-cs-LC5" class="blob-code blob-code-inner js-file-line">    public void SampleTest()</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-nunit_test_progress-cs-LC6" class="blob-code blob-code-inner js-file-line">    {</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-nunit_test_progress-cs-LC7" class="blob-code blob-code-inner js-file-line">        // some operations here, like starting a server for tests in-memory&#8230;</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-nunit_test_progress-cs-LC8" class="blob-code blob-code-inner js-file-line">        </td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-nunit_test_progress-cs-LC9" class="blob-code blob-code-inner js-file-line">        TestContext.Progress.WriteLine(&quot;The server is running now! You can reach it on https://localhost:8067/&quot;);</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-nunit_test_progress-cs-LC10" class="blob-code blob-code-inner js-file-line">        while (true)</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-nunit_test_progress-cs-LC11" class="blob-code blob-code-inner js-file-line">        {</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-nunit_test_progress-cs-LC12" class="blob-code blob-code-inner js-file-line">            // keep it running on purpose (e.g. for E2E tests)</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-nunit_test_progress-cs-LC13" class="blob-code blob-code-inner js-file-line">        }</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-nunit_test_progress-cs-LC14" class="blob-code blob-code-inner js-file-line">        </td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-nunit_test_progress-cs-LC15" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-nunit_test_progress-cs-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-nunit_test_progress-cs-LC16" class="blob-code blob-code-inner js-file-line">}</td>
        </tr>
  </table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/dsibinski/03221c21614c48cef6fdbbd5e11accb4/raw/1880d0e1f47cb145c600d96e5f1d392bf5728028/NUnit_test_progress.cs" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/dsibinski/03221c21614c48cef6fdbbd5e11accb4#file-nunit_test_progress-cs" class="Link--inTextBlock">
          NUnit_test_progress.cs
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>

</div></figure>



<p>And that&#8217;s it! I&#8217;m publishing this simple solution, because it took me some time to find <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>I previously tried with <code>TestContext.Out.WriteLine</code>, <code>System.Diagnostics.Trace.WriteLine</code> and <code>System.Console.WriteLine</code>, but all of them output the text <em>after </em>the test finishes.</p>



<p>Finally, you can also run the test from cmd using <code>dotnet test</code>:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="189" data-attachment-id="4081" data-permalink="https://www.codejourney.net/write-test-progress-to-the-console-with-nunit/nunit_cmd_console_progress/" data-orig-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?fit=1119%2C206&amp;ssl=1" data-orig-size="1119,206" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="NUnit_cmd_console_progress" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?fit=300%2C55&amp;ssl=1" data-large-file="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?fit=1024%2C189&amp;ssl=1" src="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?resize=1024%2C189&#038;ssl=1" alt="" class="wp-image-4081" srcset="https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?resize=1024%2C189&amp;ssl=1 1024w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?resize=300%2C55&amp;ssl=1 300w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?resize=768%2C141&amp;ssl=1 768w, https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/06/NUnit_cmd_console_progress.png?w=1119&amp;ssl=1 1119w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Hope it&#8217;s useful!</p>
<p>The post <a href="https://www.codejourney.net/write-test-progress-to-the-console-with-nunit/">Write Test Progress To The Console With NUnit</a> appeared first on <a href="https://www.codejourney.net">CodeJourney.net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codejourney.net/write-test-progress-to-the-console-with-nunit/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4070</post-id>	</item>
		<item>
		<title>Improve your tests with Assert Object Pattern</title>
		<link>https://www.codejourney.net/improve-your-tests-with-assert-object-pattern/</link>
					<comments>https://www.codejourney.net/improve-your-tests-with-assert-object-pattern/#comments</comments>
		
		<dc:creator><![CDATA[Dawid Sibiński]]></dc:creator>
		<pubDate>Mon, 09 Nov 2020 20:42:34 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[assert object]]></category>
		<category><![CDATA[assert object pattern]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[unit tests]]></category>
		<guid isPermaLink="false">https://www.codejourney.net/?p=3888</guid>

					<description><![CDATA[<p>The Asserts Hell Let&#8217;s consider the following unit test: What&#8217;s wrong here? Given and When sections are great single-liners. We know straightaway what&#8217;s the input and the action executed. However, Then block is too complex. It&#8217;s hard to figure out, just passing quickly through this test, what is expected. This case is even not that&#8230;</p>
<p>The post <a href="https://www.codejourney.net/improve-your-tests-with-assert-object-pattern/">Improve your tests with Assert Object Pattern</a> appeared first on <a href="https://www.codejourney.net">CodeJourney.net</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Today I&#8217;d like to share with you a very interesting concept in software testing &#8211; Assert Object pattern. It makes the <em>Assert</em> part of a test much simpler and more readable. Let&#8217;s dive right into it <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<span id="more-3888"></span>





<h2 class="wp-block-heading">The Asserts Hell</h2>



<p>Let&#8217;s consider the following unit test:</p>



<script src="https://gist.github.com/dsibinski/f8fea58079d68dd8ac0d194a33964e1b.js"></script>



<p>What&#8217;s wrong here? <em>Given</em> and <em>When</em> sections are great single-liners. We know straightaway what&#8217;s the input and the action executed. However, <em>Then</em> block is too complex. It&#8217;s hard to figure out, just passing quickly through this test, what is <em>expected</em>. This case is even not that bad thanks to the usage of <a href="https://fluentassertions.com/">FluentAssertions</a>.</p>



<p>I spend a lot of time writing tests (<a href="https://www.codejourney.net/2017/03/unit-testing-xamarin-application/">unit</a> or integration), but I spend even more time reading them. I always hope that I will find these <em>idyllic</em> tests that act as code documentation&#8230; <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9d0.png" alt="🧐" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>However, let&#8217;s go step by step. I recently took place in a <a href="https://smarttesting.pl/">software testing course</a>. That&#8217;s where I discovered the solution to <em>The Asserts Hell</em>.</p>



<h2 class="wp-block-heading">Assert Object for Better Asserts</h2>



<p>Assert Object pattern is what solves our problem. The idea is to create an <em>Assert</em> class which wraps the original object being tested. In our case the tested object is of <span style="color:#ff9f05" class="tadv-color">Product</span> class, so our assert class will be called <span style="color:#ff9f05" class="tadv-color">ProductAssert</span>.</p>



<p>Let&#8217;s see the implementation:</p>



<script src="https://gist.github.com/dsibinski/10a3c47a7e997eed29fabcb07914786b.js"></script>



<p>As you can see, we simply moved the asserts from our test&#8217;s Then section into <span style="color:#ff9f05" class="tadv-color">ProductAssert</span> class&#8217;s methods. Additionally, we always return <span style="color:#ff9f05" class="tadv-color">this</span> from each asserting method, which allows chaining functions calls.</p>



<p>We can now use such assert object<span style="color:#444" class="tadv-color"> in our</span> unit test: </p>



<script src="https://gist.github.com/dsibinski/e0a649e6134b9c6b389d3419db62f92a.js"></script>



<p>You must agree it&#8217;s much more readable now <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>We can of course improve it even more, for example by wrapping these 3 assertion methods (<span style="color:#ff9f05" class="tadv-color">BeAvailable()</span>, <span style="color:#ff9f05" class="tadv-color">HaveDiscount() </span><span style="color:#444" class="tadv-color">and</span><span style="color:#ff9f05" class="tadv-color"> Cost()</span>) into a single one. We can also easily create an <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods">extension method</a> for the <span style="color:#ff9f05" class="tadv-color">Product</span> class itself, so the assert object doesn&#8217;t have to be instantiated in our unit test. I could even add an extension to <em>FluentAssertions</em> library.</p>



<p>You can find complete source code used as examples in this article <a href="https://github.com/dsibinski/Playground/tree/main/Playground/Playground.Tests">here</a>.</p>



<h2 class="wp-block-heading">Assert Object &#8211; summary</h2>



<p>I personally find Assert Object a very useful tests code refactoring method. As a programmer, you spend most of your time not on writing, but on reading the source code. Clear and simple tests can make your (and your colleagues&#8217;) life much better <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Of course, the Assert Object pattern should not be your default way of asserting. If you can complete your test with one or two assertions, then it&#8217;s probably better to keep it without wrapping into any additional objects. Having too many <em>assert</em> statements might also mean that the objects being tested are poorly designed. However, as we often work with legacy code which we can&#8217;t easily change or refactor, it might be a good solution.</p>



<p>What patterns for writing better tests do you use? Share your tips in the comments!</p>
<p>The post <a href="https://www.codejourney.net/improve-your-tests-with-assert-object-pattern/">Improve your tests with Assert Object Pattern</a> appeared first on <a href="https://www.codejourney.net">CodeJourney.net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codejourney.net/improve-your-tests-with-assert-object-pattern/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3888</post-id>	</item>
	</channel>
</rss>
