<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohamed Halawa</title>
    <description>The latest articles on DEV Community by Mohamed Halawa (@imhalawa).</description>
    <link>https://dev.to/imhalawa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F148611%2F967f6942-45f2-4b3c-924d-82fbe1762a58.jpg</url>
      <title>DEV Community: Mohamed Halawa</title>
      <link>https://dev.to/imhalawa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imhalawa"/>
    <language>en</language>
    <item>
      <title>The Essential Unit Testing Techniques, Part 1</title>
      <dc:creator>Mohamed Halawa</dc:creator>
      <pubDate>Thu, 29 Jul 2021 19:20:44 +0000</pubDate>
      <link>https://dev.to/imhalawa/the-essential-unit-testing-techniques-1kk5</link>
      <guid>https://dev.to/imhalawa/the-essential-unit-testing-techniques-1kk5</guid>
      <description>&lt;p&gt;Unit testing plays a vital role in the software development process, but how do we actually test our code? &lt;/p&gt;

&lt;p&gt;In the following article I'll try to summarize and mention various techniques followed by .NET Developer using the &lt;a href="https://nunit.org/"&gt;NUnit&lt;/a&gt; library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing strings
&lt;/h2&gt;

&lt;p&gt;Testing against specific strings is not a robust way of testing strings, For example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;strong&amp;gt;abc&amp;lt;/strong&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👍 As a rule of thumb, testing strings is recommended to be more general than if it was too specific it would fail with every tiny change!&lt;/p&gt;

&lt;p&gt;👍 Strings are all about format! so any method that can test the format for you is a viable testing method!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using string interpolation &lt;code&gt;$"{}"&lt;/code&gt; or &lt;code&gt;string.Format()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;Does.StartWith&lt;/code&gt;, &lt;code&gt;Does.EndWith&lt;/code&gt;, &lt;code&gt;Does.Contain&lt;/code&gt; methods provided by &lt;code&gt;NUnit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using Regex (more advanced)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Using &lt;code&gt;$"{}"&lt;/code&gt; format or &lt;code&gt;string.Format&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can easily check the targeted format using &lt;code&gt;string.format&lt;/code&gt; or &lt;code&gt;$"{}"&lt;/code&gt; along with &lt;code&gt;Assert.That(result,Is.EqualTo())&lt;/code&gt;, for example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&amp;lt;strong&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/strong&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Using &lt;code&gt;Does.StartWith&lt;/code&gt;, &lt;code&gt;Does.EndWith&lt;/code&gt;, &lt;code&gt;Does.Contain&lt;/code&gt; Methods
&lt;/h3&gt;

&lt;p&gt;You can also use the fellow methods to check if a string is enclosed between specific words or tags!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;strong&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EndWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;/strong&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Using Regex
&lt;/h3&gt;

&lt;p&gt;Regex is the god-level matching mechanism for strings! and fortunately, you can use it with &lt;code&gt;NUnit&lt;/code&gt; to test your strings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;pattern&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing arrays and collections
&lt;/h2&gt;

&lt;p&gt;Testing arrays or collections is a little bit tricky since there are many factors you can test&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Testing if an Array has any elements
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔘 Yet, it's a general test case!&lt;/p&gt;

&lt;p&gt;❓How can you make sure if it has a certain count of elements?&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Testing the count of a collection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualtTo&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔘 It's also a general test case!&lt;/p&gt;

&lt;p&gt;❓How can you make sure if it has a certain element?!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Testing if a collection contains X
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤕 It brings more headache due to the repetitive work!&lt;/p&gt;

&lt;p&gt;⚡ Fortunately, there is another way to do just the same!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EquivalentTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⁉️ What about the order of it's elements!&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Testing the order of a collection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ordered&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⁉️ And What about the uniqueness of its elements!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Testing the uniqueness of a collection's elements!
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unique&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing Methods
&lt;/h2&gt;

&lt;p&gt;Like arrays, there are also many factors that you consider when testing a method or a function!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;return type&lt;/li&gt;
&lt;li&gt;return value&lt;/li&gt;
&lt;li&gt;void methods&lt;/li&gt;
&lt;li&gt;exceptions are thrown by methods&lt;/li&gt;
&lt;li&gt;events being raised by a method&lt;/li&gt;
&lt;li&gt;private methods&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing return type
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;NUnit&lt;/code&gt; provides two different ways to test the return type of a method or a function.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Is.TypeOf&amp;lt;&amp;gt;()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Is.InstanceOf&amp;lt;&amp;gt;()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Is.TypeOf&amp;lt;&amp;gt;()&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Checks if an instance (object or value) is of a specific type and just that type. for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;Is.InstanceOf&amp;lt;&amp;gt;()&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Checks if an instance (object or value) is of a specific type or one of its derivatives. for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InstanceOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🗒️ It also provides the non-generic version of both methods, that can be used along with &lt;code&gt;typeof&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing void methods (commands)
&lt;/h3&gt;

&lt;p&gt;Void methods or commands are trickier to test than anything else because they &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;change a state of an object either in memory, database&lt;/li&gt;
&lt;li&gt;persist a state, they may store an object in a database or call a web service or a message queue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unfortunately, the only way to accomplish such a task is to preserve the state of the object being affected by that method. For example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorLogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ErrorLogged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;LastError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

        &lt;span class="c1"&gt;// Write the log to a storage&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;

        &lt;span class="n"&gt;ErrorLogged&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log_WhenStringIsNotNullOrWhiteSpace_ThrowAnException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing methods that throw an exception
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;NUnit&lt;/code&gt; provides a way to test if a method throws a specific exception and no matter it's a built-in exception or custom exception you can always test it!&lt;/p&gt;

&lt;p&gt;But... you cannot just call your method in a normal way and expecting the Assert to detect that exception rather you've to call it as a delegate within the &lt;code&gt;Assert.That&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So, Instead of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log_InvalidErrorMessage_ThrowArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Execution will be stopped as a result for the exception and the test will fail!&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Throws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log_InvalidErrorMessage_ThrowArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="n"&gt;Throws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you notice, I've used the &lt;code&gt;Throws.ArgumentNullException&lt;/code&gt; property to assert the result and that is a built-in exception. &lt;/p&gt;

&lt;p&gt;❓What about the Custom Exceptions?&lt;/p&gt;

&lt;p&gt;💬 Well, you can use the &lt;code&gt;Throws.Exception.TypeOf&amp;lt;&amp;gt;()&lt;/code&gt; method just for that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing methods that raise an event
&lt;/h2&gt;

&lt;p&gt;Testing events is nothing more than testing if it was raised for a specific scenario or not, so what we gonna really need is a simple indicator to answer our question. For Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorLogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ErrorLogged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;LastError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

        &lt;span class="c1"&gt;// Write the log to a storage&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;

        &lt;span class="n"&gt;ErrorLogged&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, our event will send an argument which is &lt;code&gt;Guid.NewGuid()&lt;/code&gt; which we can assume to be the indicator that will tell us if it was raised or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log_ValidError_RaiseErrorLoggedEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;messge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Subscribe to the event&lt;/span&gt;
    &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorLogged&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;So, to test the event, we are going to subscribe to it first&lt;/li&gt;
&lt;li&gt;Assign the passed &lt;code&gt;Guid&lt;/code&gt; to a local variable, that was previously initialized with a default value.&lt;/li&gt;
&lt;li&gt;Finally, we can assert that the &lt;code&gt;Id&lt;/code&gt; is not the same as its default value! which means that event has already been raised and mutated the local variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing private methods
&lt;/h3&gt;

&lt;p&gt;⁉️ How to test the private or protected methods? &lt;/p&gt;

&lt;p&gt;💭 You shouldn't test private methods! we are only testing the API of a class (aka public members)&lt;/p&gt;

&lt;p&gt;❔ Does it mean that we should test against Interfaces?&lt;/p&gt;

&lt;h4&gt;
  
  
  Reasons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Private methods are participating to be an actual part of the implementation details of a class, which can be changed at anytime from one version to another. but public members would stay the same!&lt;/li&gt;
&lt;li&gt;Hence, if you tested against private members your tests will be coupled with implementation detail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---zS3ODL1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jg3sh9oeq4kwzeqlordq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---zS3ODL1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jg3sh9oeq4kwzeqlordq.png" alt="Testing Private Methods" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Code Coverage
&lt;/h2&gt;

&lt;p&gt;⁉️ How do we know if we have enough tests?&lt;/p&gt;

&lt;p&gt;Well, you can make use of a code coverage tool that is mainly were designed to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale your code&lt;/li&gt;
&lt;li&gt;Answer that question by telling what parts of our code that's not fully covered by tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Available Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Visual Studio Enterprise Edition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resharper Ultimate, Dot Cover&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Dot Cover is a unit test runner&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;NCover&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/unit-testing-csharp/"&gt;Unit testing for C# developers, by Mosh Hamedani&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>csharp</category>
      <category>nunit</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>The Branch &amp; Merge Game</title>
      <dc:creator>Mohamed Halawa</dc:creator>
      <pubDate>Thu, 29 Jul 2021 17:05:49 +0000</pubDate>
      <link>https://dev.to/imhalawa/the-branch-merge-game-279f</link>
      <guid>https://dev.to/imhalawa/the-branch-merge-game-279f</guid>
      <description>&lt;h2&gt;
  
  
  What is Version Control?
&lt;/h2&gt;

&lt;p&gt;Version control is a system that allows you to keep track of your work and helps you to easily explore the changes you have made no matter what are you changing &lt;strong&gt;data&lt;/strong&gt;, &lt;strong&gt;coding scripts&lt;/strong&gt;, &lt;strong&gt;notes&lt;/strong&gt;, etc. any file in general.&lt;/p&gt;

&lt;p&gt;It also allows the collaboration between developers on a single project easily through branching &amp;amp; merging.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits Of Version Control
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Makes it easy for you to keep track of collaborative and personal projects - all files necessary for certain analyses can be held together and people can add in their code, graphs, etc.&lt;/li&gt;
&lt;li&gt;As the projects develop. each file being tracked by git has a history, making it easy to explore the changes that occurred to it at different time points.&lt;/li&gt;
&lt;li&gt;Easily navigate among the many versions of the files you create&lt;/li&gt;
&lt;li&gt;Enables reviewing other people’s code and also the collaborative code review for collaborative projects.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Version Control Systems
&lt;/h2&gt;

&lt;p&gt;Our main focus in this article is Git as version control. But, we have to mention other available solutions for version control that are being used widely in Enterprise projects and Individual One.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git — Most Popular &amp;amp; Used among the Enterprise and Individuals&lt;/li&gt;
&lt;li&gt;AWS Code Commit&lt;/li&gt;
&lt;li&gt;Azure DevOps Server (TFS)&lt;/li&gt;
&lt;li&gt;Subversion (SVN)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many solutions for version control, but I've mentioned the popular ones according to the &lt;a href="https://www.g2.com/categories/version-control-systems?tab=highest_rated"&gt;G2 Survey&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Way Back Machine — Before Version Control
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rg63d2BJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytg9vjv67v8v7szlbx86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rg63d2BJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytg9vjv67v8v7szlbx86.png" alt="The Way Back Machine" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An obvious question a 21st-century developer might ask, &lt;strong&gt;How did people develop software before git or version control?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a 21st-century developer, I made very tiny research trying to answer that question and most of them seem to have a common way of doing "&lt;strong&gt;Version Control&lt;/strong&gt;" which was a &lt;strong&gt;Shared Drive. It's&lt;/strong&gt; either mapped to your pc through a network or being accumulated on a single portable hard disk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4GW_BBao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuq4ic7soms3723kls5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4GW_BBao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuq4ic7soms3723kls5h.png" alt="screen shot" width="696" height="501"&gt;&lt;/a&gt;&lt;br&gt;
source: &lt;a href="https://dev.to/pandaquests/how-did-people-develop-software-before-git-or-version-control-1564"&gt;http://www.dev.to&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I tried to find a way to contact Mr. Douglas to ask his permission to mention his words in this SS but I failed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Was it the only way of doing that, copy &amp;amp; paste on a shared hard drive?&lt;/strong&gt; No, they used what is so-called &lt;a href="https://www.gnu.org/software/gnuastro/manual/html_node/Release-tarball.html"&gt;tarball&lt;/a&gt; to version their software which was mainly used by GNU to deliver their open-source software. &lt;/p&gt;

&lt;p&gt;A tarball is a snapshot of one particular moment in the application development history along with all the necessary files to configure, build, and install the application easily.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Git?
&lt;/h2&gt;

&lt;p&gt;Aside from the fact that it's the most commonly used version control system, It has several advantages. So let's highlight the most epics or features that make it a good-to-go choice especially according to SVN.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--73H40MI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d13drf0vsf392im7rug8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--73H40MI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d13drf0vsf392im7rug8.png" alt="Git" width="420" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Git utilizes multiple repositories&lt;/strong&gt;: a central repository and a series of local repositories which are exact copies of the central repository complete &lt;strong&gt;with the entire history of changes.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git has a staging area.&lt;/strong&gt; This just means that if you made 100 new changes to your code, you can break these 100 changes into 10 or 20 or more commits each with their own comments and their own detailed explanation of what just happened!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It’s faster to commit.&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;Because you commit to the central repository more often in SVN, network traffic slows everyone down.&lt;/li&gt;
&lt;li&gt;Whereas with Git, you’re working mostly on your local repository and only committing to the central repository every so often.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No more single point of failure.&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;With SVN, if the central repository goes down or some code breaks the build, no other developers can commit their code until the repository is fixed.&lt;/li&gt;
&lt;li&gt;With Git, each developer has their own repository, so it doesn’t matter if the central repository is broken. Developers can continue to commit code locally until the central repository has been fixed, and then they can push their changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It’s available offline.&lt;/strong&gt; Unlike SVN, Git can work offline, allowing your team to continue working without losing features if they lose connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It’s open-source and cross-platform.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Hey! I guess you forgot to mention that SVN repos are far bigger in size than Git!
= mmm, Nope I didn't forget But: &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt; This claim is actually &lt;a href="https://svnvsgit.com/"&gt;a Myth&lt;/a&gt;! they are close in size since they both are using a delta compression algorithm. &lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;I'm not trying to compare Git vs SVN here, it's not the purpose of that article!&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  A Break!
&lt;/h2&gt;

&lt;p&gt;By reaching this point, you might consider taking a 5-minutes break!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5h_F4x5w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r1n63lv8wmvvltzlrux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5h_F4x5w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r1n63lv8wmvvltzlrux.png" alt="break" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a repository?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gU7QOYtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icishu5ba9u0qeggr4n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gU7QOYtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icishu5ba9u0qeggr4n4.png" alt="repository" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A repository is a special type of directory that contains all of your project's files and each file's revision history. &lt;/p&gt;

&lt;p&gt;With Git, that repository must contain a &lt;code&gt;.git&lt;/code&gt; hidden directory that holds all information that Git needs to: &lt;strong&gt;keep track of changes&lt;/strong&gt;, &lt;strong&gt;maintain history&lt;/strong&gt;, &lt;strong&gt;commits&lt;/strong&gt;, &lt;strong&gt;remote repository information to push to&lt;/strong&gt;, .. and so on. &lt;strong&gt;Meaning&lt;/strong&gt;, if you delete the &lt;code&gt;.git&lt;/code&gt; directory, then you delete your project’s history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So why a repository is a special type of directory again?&lt;/strong&gt; simply because it contains the &lt;code&gt;.git&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;A repository can hold any type of files and multiple directories. By default, it will keep track of all changes that affect all the files and maintain their history, but you can choose to ignore some files or directories that you believe are not important to exist in the remote repository -being hold by a Git service provider like GitHub- by listing these files or directories in the &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is branching?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gU7QOYtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icishu5ba9u0qeggr4n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gU7QOYtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icishu5ba9u0qeggr4n4.png" alt="branching" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Branching means you diverge from the main line of development and continue to do work without messing with that mainline. In many VCS tools, this is a somewhat expensive process, often requiring you to create a new copy of your source code directory, which can take a long time for large projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a git branch?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2FI5nQWg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68au3tt7nkbmuqh3iuvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2FI5nQWg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68au3tt7nkbmuqh3iuvi.png" alt="git branch" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A branch in Git is simply a lightweight movable pointer to one of these commits.&lt;/strong&gt; The default branch name in Git is master. As you start making commits, you’re given a master branch that points to the last commit you made. Every time you commit, the master branch pointer moves forward automatically.&lt;/p&gt;

&lt;p&gt;The way &lt;strong&gt;Git branches is incredibly lightweight&lt;/strong&gt;, making branching operations nearly instantaneous, and switching back and forth between branches generally just as fast. and Unlike many other VCSs, Git encourages workflows that branch and merge often, even multiple times in a day. Understanding and mastering this feature gives you a powerful and unique tool and can entirely change your development.&lt;/p&gt;

&lt;p&gt;The “master” branch in Git &lt;strong&gt;is not a special branch.&lt;/strong&gt; It is exactly like any other branch. The only reason nearly every repository has one is that the &lt;code&gt;git init&lt;/code&gt; command creates it by default and most people don’t bother to change it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Branching Strategy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tm0XeTsc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1532622785990-d2c36a76f5a6%3Fixlib%3Drb-1.2.1%26q%3D85%26fm%3Djpg%26crop%3Dentropy%26cs%3Dsrgb" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tm0XeTsc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1532622785990-d2c36a76f5a6%3Fixlib%3Drb-1.2.1%26q%3D85%26fm%3Djpg%26crop%3Dentropy%26cs%3Dsrgb" alt="https://images.unsplash.com/photo-1532622785990-d2c36a76f5a6?ixlib=rb-1.2.1&amp;amp;q=85&amp;amp;fm=jpg&amp;amp;crop=entropy&amp;amp;cs=srgb" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is meant by a branching strategy?
&lt;/h3&gt;

&lt;p&gt;A “branching strategy” refers to the strategy a software development team employs when writing, merging, and shipping code in the context of a version control system like Git. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why do we need a branching strategy?
&lt;/h3&gt;

&lt;p&gt;Have you ever wondered how to manage and maintain your remote repository in the case of a team, not individuals, even multiple teams? how would you &lt;strong&gt;handle the changes&lt;/strong&gt;? make sure that the remote repository is &lt;strong&gt;always updated&lt;/strong&gt;?  how would you &lt;strong&gt;deliver certain features&lt;/strong&gt; and ignore others? &lt;/p&gt;

&lt;p&gt;These issues are solved by making what is so a &lt;strong&gt;branching strategy but&lt;/strong&gt; don't panic there are existing strategies for general purpose usage, check &lt;a href=""&gt;branching flows&lt;/a&gt; for fast-forward.&lt;/p&gt;

&lt;p&gt;A branching strategy also ensures everyone on the team is following the same process for making changes to source control. The right strategy &lt;strong&gt;enhances collaboration&lt;/strong&gt;, &lt;strong&gt;efficiency&lt;/strong&gt;, and &lt;strong&gt;accuracy&lt;/strong&gt; in the software delivery process, while the wrong strategy (or no strategy) leads to hours of lost effort.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our Goal
&lt;/h3&gt;

&lt;p&gt;The goal of any branching strategy is to solve the previous problem and to enable teams to work together on the same source code without trampling on each other. if you achieved that you've simply made a working strategy!&lt;/p&gt;

&lt;h3&gt;
  
  
  Considerations
&lt;/h3&gt;

&lt;p&gt;There are several things to consider handling while designing a branching strategy, here are the common issues&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XhZ-Al7E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1w73w99qobj5nbb0qnx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XhZ-Al7E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1w73w99qobj5nbb0qnx.png" alt="Considerations" width="512" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Typical development workflow
&lt;/h4&gt;

&lt;p&gt;The typical day-to-day flow includes normal changes that developers make to the code. These changes are ordinary in terms of size and complexity for your codebase and, generally, will make up the bulk of all the changes your developers make. Since this flow will be used the most frequently, your strategy here must ensure proper coordination among the developers and support all relevant policies such as automated testing, pull requests, and deployments.&lt;/p&gt;

&lt;h4&gt;
  
  
  Emergency hotfixes
&lt;/h4&gt;

&lt;p&gt;An emergency hotfix is when a particular incident or issue has been expedited to deal with some emergent situation, normally bug fixes. Your flow must account for a developer who needs to make an urgent change and get it all the way through your process and into production while still aligning with your typical development workflow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Small vs. large changes
&lt;/h4&gt;

&lt;p&gt;As the industry has evolved, the emphasis on developers working on smaller changes and limited batch sizes has increased due to the broader use of flow-based delivery practices. However, there are still times when you must make large, complex changes, and your branching strategy must accommodate those situations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Standard vs. experimental changes
&lt;/h4&gt;

&lt;p&gt;Developers feel greater certainty about how standard code changes will perform than with experimental code changes. For example, if you’re evaluating a new library or framework, you may feel uncertain about how well it integrates with your codebase. In that case, your change may or may not actually go to production but still needs to be shared with other developers. Your branching strategy must account for these types of experimental changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common types of branches
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NpnTEjI---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kso8wvbkrcns3dgyr354.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NpnTEjI---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kso8wvbkrcns3dgyr354.png" alt="types of branches" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Main branch
&lt;/h4&gt;

&lt;p&gt;Every Git repository has a main (also referred to as mainline or the master branch). When a Git repository is created, the main exists automatically as the implicit first branch. The use of a main and the timing of changes landing on it vary depending on the exact branching strategy being used. In main-based development, the main is the central branch to which all developers send their code changes.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Development branch
&lt;/h4&gt;

&lt;p&gt;The development branch is a long-lived feature branch that holds changes made by developers before they’re ready to go to production. It parallels the main and is never removed. Some teams have the development branch correspond with a non-production environment. As such, commits to the development branch trigger test environment deployments. Development and main are frequently bidirectionally integrated, and it’s typical for a team member to bear the responsibility of integrating them.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Release branch
&lt;/h4&gt;

&lt;p&gt;A release branch can be either short-lived or long-lived depending on the strategy. In either case, the release branch reflects a set of changes that are intended to go through the production release process.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Feature branch
&lt;/h4&gt;

&lt;p&gt;A feature branch can be short- or long-lived depending on the specific branching flow. The branch often is used by a single developer for only their changes, but it is possible to share it with other developers as well. Again, the branching strategy will determine how exactly you define a “feature branch”.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Hotfix branch
&lt;/h4&gt;

&lt;p&gt;A hotfix branch is a branch that’s used generally to hold changes related to emergency bug fixes. They can be short-lived or long-lived, though generally, they exist as long-lived branches split off from a release branch. They tend to be more common in teams with explicitly versioned products, such as installed applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Popular Branching flows
&lt;/h3&gt;

&lt;h4&gt;
  
  
  GitFlow
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;GitFlow&lt;/a&gt; was introduced by Vincent Driessen in 2010 to share insight into the use of Git for source control as its use became more widespread. GitFlow relies essentially on every type of branch that was discussed previously with the bulk of the development workflow centering on the long-lived development branch as a shared integration branch for all the developers. The main branch, in this case, essentially reflects a history of all the changes that have gone to production.&lt;/p&gt;

&lt;h4&gt;
  
  
  GitHub Flow
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://guides.github.com/introduction/flow/"&gt;GitHub Flow&lt;/a&gt; was popularized by GitHub as a simpler alternative to GitFlow. It calls for the following workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main branch is always releasable, and in fact, releases are generally done directly from it.&lt;/li&gt;
&lt;li&gt;Each developer creates a new branch, the feature branch, for their changes from the main branch.&lt;/li&gt;
&lt;li&gt;Feature branches can be deployed to a testing environment for verification or pushed directly to the main branch and deployed to a non-production environment from there.&lt;/li&gt;
&lt;li&gt;A short-lived release branch may be used off the main branch to prepare for and execute a release.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Challenges&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Both of these branching strategies can work for the right environment, but they have similar downsides. The biggest downside is neither flow adequately supports Continuous Integration. And Continuous Integration is becoming an essential modern development practice. By relying on feature branches, it’s too easy to focus on the benefits of change isolation and ignore the costs. Instead, a better strategy would support Continuous Integration, wherein developers integrate code regularly (i.e., at least every day). Fortunately, there is a branching strategy able to meet all these needs: &lt;strong&gt;trunk-based development.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XUQ6Q9ci--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9m8j3l4ehl5queavgcpe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XUQ6Q9ci--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9m8j3l4ehl5queavgcpe.jpg" alt="What's Next?" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not an in-detail article, it's a high-level one that allows people to discover the missing parts in their strategy. and since I've started that just to enable reaching the point where we can set up our version control system in a way that would support Continuous Integration. my next writing will be dedicated to Trunk-based Development along with any other alternative technique that I might find out while researching.&lt;/p&gt;

&lt;p&gt;For now, thanks for giving me your precious time. I'll gladly accept comments that aim to enhance the content quality or correct mistaken info that I wrote here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/gnuastro/manual/html_node/Release-tarball.html"&gt;https://www.gnu.org/software/gnuastro/manual/html_node/Release-tarball.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.g2.com/categories/version-control-systems?tab=highest_rated"&gt;https://www.g2.com/categories/version-control-systems?tab=highest_rated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://backlog.com/blog/git-vs-svn-version-control-system/"&gt;https://backlog.com/blog/git-vs-svn-version-control-system/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.hackbrightacademy.com/blog/svn-vs-git/"&gt;https://blog.hackbrightacademy.com/blog/svn-vs-git/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://svnvsgit.com/"&gt;https://svnvsgit.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href="https://launchdarkly.com/blog/git-branching-strategies-vs-trunk-based-development/%5D("&gt;https://launchdarkly.com/blog/git-branching-strategies-vs-trunk-based-development/](&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>versioncontrol</category>
      <category>git</category>
      <category>devops</category>
    </item>
    <item>
      <title>A Short Guide to Console Messages</title>
      <dc:creator>Mohamed Halawa</dc:creator>
      <pubDate>Fri, 19 Feb 2021 13:18:50 +0000</pubDate>
      <link>https://dev.to/imhalawa/a-short-guide-to-console-messages-420m</link>
      <guid>https://dev.to/imhalawa/a-short-guide-to-console-messages-420m</guid>
      <description>&lt;p&gt;Curious to know how to log different types of messages in console? Okay Just follow up with me..&lt;/p&gt;

&lt;p&gt;There are 6 types of messages that &lt;strong&gt;Chrome DevTools Console&lt;/strong&gt; supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Information&lt;/li&gt;
&lt;li&gt;Warning&lt;/li&gt;
&lt;li&gt;Error&lt;/li&gt;
&lt;li&gt;Table&lt;/li&gt;
&lt;li&gt;Group&lt;/li&gt;
&lt;li&gt;Custom Message&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Information
&lt;/h2&gt;

&lt;p&gt;It can be done via &lt;code&gt;console.log(&amp;lt;value&amp;gt;)&lt;/code&gt; function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[INFO]: You've Inserted 1 row in the database!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RnX5edmI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/eNxIMYK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RnX5edmI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/eNxIMYK.png" alt="info" width="676" height="23"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Warning
&lt;/h2&gt;

&lt;p&gt;It can be done via &lt;code&gt;console.warn(&amp;lt;value&amp;gt;)&lt;/code&gt; function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[WARNING]: You're about to leave this page !&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_SYQiW1w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/1rpz6H4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_SYQiW1w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/1rpz6H4.png" alt="warning" width="671" height="23"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check it's Stack Trace by pressing the left-most little cursor ▶️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cDXmhDr_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/aNJ61cT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cDXmhDr_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/aNJ61cT.png" alt="warning-expanded" width="665" height="49"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Error
&lt;/h2&gt;

&lt;p&gt;It can be done via &lt;code&gt;console.error(&amp;lt;value&amp;gt;)&lt;/code&gt; function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[Error]: This kind of operations requires a Quantum Machine !&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aIVNn4_g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/MBTWyKg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aIVNn4_g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/MBTWyKg.png" alt="error" width="681" height="49"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Table
&lt;/h2&gt;

&lt;p&gt;It can be done via &lt;code&gt;console.table([&amp;lt;Array of Objects&amp;gt;])&lt;/code&gt; function&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_humankind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;homosapien&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Uncle Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neanderthal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;denisovan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Donald Trump&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_humankind&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YrR64Jrt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/JGe1t5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YrR64Jrt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/JGe1t5g.png" alt="table" width="645" height="124"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Group
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;console.group(&amp;lt;label&amp;gt;)&lt;/code&gt; &lt;code&gt;console.groupEnd(&amp;lt;label&amp;gt;)&lt;/code&gt; both are used to achieve it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;humanGroup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;List of Human:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Begin the group&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;humanGroup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;homosapien&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neanderthal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;denisovan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Necessary to end the group&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;humanGroup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yRf-vfX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/aAqL3nq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yRf-vfX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/aAqL3nq.png" alt="group" width="663" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  [Optional Section] Further Explanation
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Store a the string that represents the group title (label) into a variable to make it easy recalling it &lt;br&gt;
E.G.&lt;code&gt;let label = 'List of Human:'&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start the group by Invoking &lt;code&gt;console.group(label)&lt;/code&gt; or &lt;code&gt;console.group('List of Human:'&lt;/code&gt;)`&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;​    We don't need the second invocation because we already stored the title in the &lt;code&gt;label&lt;/code&gt; variable !&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Add elements to that group by passing it to the &lt;code&gt;console.info(&amp;lt;content&amp;gt;)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, Claim the end of the group using &lt;code&gt;console.groupEnd(label)&lt;/code&gt; or &lt;code&gt;console.groupEnd('List of Human:'&lt;/code&gt;)`&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;That's exactly why we defined the &lt;code&gt;label&lt;/code&gt; variable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's easier to recall&lt;/li&gt;
&lt;li&gt;Avoid probable spelling mistakes ! &lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Custom Message
&lt;/h2&gt;

&lt;p&gt;Ever wondered &lt;strong&gt;How facebook style the stop console message&lt;/strong&gt; whenever you try to inspect it?&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ivUk4KCf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jKcxj6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ivUk4KCf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jKcxj6w.png" alt="facebook" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, it's possible via &lt;code&gt;console.log()&lt;/code&gt; but you have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a preceding &lt;code&gt;%c&lt;/code&gt; to mark it as a &lt;strong&gt;custom Log&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pass your css rules to style the content as a second argument.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the final Invocation form is: &lt;code&gt;console.log('%c&amp;lt;content&amp;gt;',styleRules)&lt;/code&gt;;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spacing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        padding: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
        background-color: yellow;
        color: blue;
        font-weight: Bold;
        border: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; solid red;
        border-radius: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
        font-size: 2em;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%cThis is a Custom Log !&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9IuSvA3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/L7DGpWk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9IuSvA3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/L7DGpWk.png" alt="custom" width="650" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>todayilearned</category>
      <category>console</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
