<?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: Paweł Zaremba</title>
    <description>The latest articles on DEV Community by Paweł Zaremba (@pawzar).</description>
    <link>https://dev.to/pawzar</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%2F327094%2Fd22aa5aa-b206-434c-8c28-a6b3f6bc8ab4.png</url>
      <title>DEV Community: Paweł Zaremba</title>
      <link>https://dev.to/pawzar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pawzar"/>
    <language>en</language>
    <item>
      <title>Embedding Types in Go Reduces Noise</title>
      <dc:creator>Paweł Zaremba</dc:creator>
      <pubDate>Thu, 30 Apr 2020 11:08:05 +0000</pubDate>
      <link>https://dev.to/pawzar/embedding-types-in-go-reduces-noise-1fle</link>
      <guid>https://dev.to/pawzar/embedding-types-in-go-reduces-noise-1fle</guid>
      <description>&lt;p&gt;My &lt;a href="https://www.tegh.net/8"&gt;previous&lt;/a&gt; post was about one of the concurrency patterns that can be achieved with go.&lt;br&gt;
I immediately got some feedback on it, and this is where I will address one of them.&lt;/p&gt;

&lt;p&gt;You have seen the code reimplementing &lt;code&gt;sync.WaitGroup&lt;/code&gt; to have a semaphore in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;WaitGroup&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sem&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;  &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sem&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&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;It has been brought to my attention (Thanks, Wojtek!), that there is a "cleaner" way to do it in Go.&lt;/p&gt;

&lt;h1&gt;
  
  
  Enter: Type Embedding
&lt;/h1&gt;

&lt;p&gt;Those coming from other languages (e.g.: PHP), you might notice that there is no such thing as an &lt;code&gt;extends&lt;/code&gt; keyword. &lt;br&gt;
There is no subclassing in the popular way. What we do have is &lt;a href="https://golang.org/doc/effective_go.html#embedding"&gt;type embedding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To achieve that we change &lt;code&gt;SemaphoredWaitGroup&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;type SemaphoredWaitGroup struct {
&lt;/span&gt;    sem chan bool
&lt;span class="gd"&gt;-   wg  sync.WaitGroup
&lt;/span&gt;&lt;span class="gi"&gt;+   sync.WaitGroup
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All methods from the "inner" (embedded) struct are now a part of the "outer" (embedding) type.&lt;br&gt;
It is even possible to access them directly by calling them as if they were actually defined locally. E.g:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;newMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&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;There is a catch though. when we re-define the methods from the inner part (here we have: &lt;code&gt;Add(delta int)&lt;/code&gt; and &lt;code&gt;Done()&lt;/code&gt;), we need to change the internal calls&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;func (s *SemaphoredWaitGroup) Add(delta int) {
&lt;/span&gt;&lt;span class="gd"&gt;-   s.Add(delta)
&lt;/span&gt;&lt;span class="gi"&gt;+   s.WaitGroup.Add(delta)
&lt;/span&gt;    s.sem &amp;lt;- true
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;func (s *SemaphoredWaitGroup) Done() {
&lt;/span&gt;    &amp;lt;-s.sem
&lt;span class="gd"&gt;-   s.Done()
&lt;/span&gt;&lt;span class="gi"&gt;+   s.WaitGroup.Done()
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because the &lt;code&gt;s.Add(delta)&lt;/code&gt; and &lt;code&gt;s.Done()&lt;/code&gt; would be recursive calls, and would result in a "&lt;a href="https://en.wikipedia.org/wiki/Stack_overflow"&gt;stack overflow&lt;/a&gt;" error in this particular instance.&lt;/p&gt;

&lt;p&gt;Also, we don't need to have the &lt;code&gt;Wait()&lt;/code&gt; method pass calls through to the underlying &lt;code&gt;sync.WaitGroup&lt;/code&gt; struct.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A complete example is available on &lt;a href="https://play.golang.org/p/dXpLrguS4Ns"&gt;Go Playground&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was originally posted at: &lt;a href="https://www.tegh.net/9"&gt;https://www.tegh.net/9&lt;/a&gt; &lt;/p&gt;

</description>
      <category>php2go</category>
      <category>go</category>
      <category>polymorphism</category>
      <category>composition</category>
    </item>
    <item>
      <title>Semaphored Wait Group</title>
      <dc:creator>Paweł Zaremba</dc:creator>
      <pubDate>Wed, 29 Apr 2020 13:19:59 +0000</pubDate>
      <link>https://dev.to/pawzar/semaphored-wait-group-113</link>
      <guid>https://dev.to/pawzar/semaphored-wait-group-113</guid>
      <description>&lt;p&gt;One of the first things you might like to try when starting your journey with Go are the concurrency patterns.&lt;br&gt;
You will probably start using &lt;em&gt;&lt;a href="https://tour.golang.org/concurrency/1"&gt;goroutines&lt;/a&gt;&lt;/em&gt; to run things "in the background",&lt;br&gt;
and you will also get to know &lt;em&gt;&lt;a href="https://tour.golang.org/concurrency/2"&gt;channels&lt;/a&gt;&lt;/em&gt; that allow for safe communication between the sub-processes.&lt;/p&gt;

&lt;p&gt;When you'll want to spawn many goroutines, you will surely get to know &lt;a href="https://gobyexample.com/waitgroups"&gt;WaitGroups&lt;/a&gt; to wait for them to finish.&lt;br&gt;
There will also be the &lt;em&gt;&lt;a href="https://tour.golang.org/flowcontrol/12"&gt;defer&lt;/a&gt;&lt;/em&gt; statement which helps you to not forget to clean up after a function has finished running (and remember, deferred calls are executed in &lt;a href="https://tour.golang.org/flowcontrol/13"&gt;reverse&lt;/a&gt; order).&lt;/p&gt;

&lt;p&gt;Let's start with a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#%d done"&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#%d starting"&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;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&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="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"all done"&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;This works well, but what if we had a million items to process, and the actual work would be a memory-heavy operation? &lt;br&gt;
We don't want to start a million goroutines. &lt;br&gt;
We need something to limit the number of goroutines being run at the same time.&lt;/p&gt;

&lt;p&gt;This is where a semaphore will come in handy.&lt;br&gt;
We'll define how many concurrent workers we want, and the semaphore will not allow starting new goroutines until a slot is free.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using a Channel to Create a Simple Semaphore
&lt;/h2&gt;

&lt;p&gt;Let's say we want a maximum of 5 workers running at any time.&lt;br&gt;
We'll need a buffered channel, and we do not really care what type of values it holds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sem&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&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;Whenever we want to start a goroutine, we'll push a value to the channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&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;sem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// we need to pass the channel to the worker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we're done - we'll take one value out of the channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#%d done"&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#%d starting"&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;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;sem&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Please notice, that wen we added the &lt;code&gt;sem&lt;/code&gt; argument to the worker, we also converted the semaphore to a read-only channel using &lt;code&gt;&amp;lt;-chan&lt;/code&gt; syntax.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But wait..., we do not want to change the code too much. &lt;br&gt;
Can we just create our own implementation of a wait-group that will have the desired feature?&lt;/p&gt;

&lt;p&gt;Yes we can, and Go's interfaces will help us do it. &lt;/p&gt;
&lt;h1&gt;
  
  
  Go's Implicit Interfaces - The Ultimate Decoupling
&lt;/h1&gt;

&lt;p&gt;In most other languages the &lt;em&gt;interface&lt;/em&gt; has to be defined before it can be implemented. &lt;br&gt;
In Go - it is the other way around. &lt;br&gt;
We can create interfaces that satisfy our needs and if anything (internal or external) has the methods with matching signatures, &lt;br&gt;
Go will treat it as a type that implements the interface.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://tour.golang.org/methods/10"&gt;A Tour of Go&lt;/a&gt;: Implicit interfaces decouple the definition of an interface from its implementation, which could then appear in any package without prearrangement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, even though we cannot change the &lt;code&gt;sync.WaitGroup&lt;/code&gt; type, we can extract an interface that matches our current requirements. We'll have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;WaitGroup&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;Wait&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;and change &lt;code&gt;worker&lt;/code&gt; function's signature to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can create our own implementation of &lt;strong&gt;our&lt;/strong&gt; &lt;code&gt;WaitGroup&lt;/code&gt; interface with a built-in semaphore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sem&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;   &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sem&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&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;Finally, instead of using the default &lt;code&gt;sync.WaitGroup&lt;/code&gt; we can use our own &lt;code&gt;SemaphoredWaitGroup&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;SemaphoredWaitGroup&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sem&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&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;and we have ourselves a limited pool of workers. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The complete example is available as a &lt;a href="https://gist.github.com/pawzar/b05924b67d289247fd3259e8b961645b"&gt;GitHub Gist&lt;/a&gt;&lt;br&gt;
and on &lt;a href="https://play.golang.org/p/jW-cO39WGC5"&gt;Go Playground&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Original post at: &lt;a href="https://www.tegh.net/knowledge/semaphored-wait-group/"&gt;https://www.tegh.net/knowledge/semaphored-wait-group/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>concurrency</category>
      <category>channels</category>
      <category>semaphores</category>
    </item>
    <item>
      <title>Money Is Not Everything</title>
      <dc:creator>Paweł Zaremba</dc:creator>
      <pubDate>Mon, 27 Apr 2020 14:46:44 +0000</pubDate>
      <link>https://dev.to/pawzar/money-is-not-everything-4o6d</link>
      <guid>https://dev.to/pawzar/money-is-not-everything-4o6d</guid>
      <description>&lt;p&gt;I am currently searching for new work. &lt;br&gt;
I tend to phrase it as "looking for new opportunities" or "challenges". &lt;br&gt;
But let's call it as it is. &lt;strong&gt;I am on a job hunt.&lt;/strong&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  The money question
&lt;/h2&gt;

&lt;p&gt;Quite often I find myself in an interview baffled by a question about my financial terms.&lt;br&gt;
Some interviewers require a range, some a single number. &lt;br&gt;
It is easier if the job ad has the offered range specified from the beginning, but only a little.&lt;/p&gt;

&lt;p&gt;Having been a professional software developer for almost 15 years (i.e. since I started my &lt;a href="https://www.infoza.pl"&gt;self-employment&lt;/a&gt; in 2006) I am not shy to ask for the top offered value. &lt;br&gt;
Unfortunately there is a catch with this tactic.&lt;/p&gt;

&lt;p&gt;I have found that MANY companies LIE about the actual salary range they are capable or willing to pay. &lt;br&gt;
I have been turned down a few times because my salary expectations were said to be too high. &lt;br&gt;
The recruiters wrote: "we value your expertise, and we would like to have you on board, but you a) have too much of experience and we would not be able to challenge you enough or b) we cannot meet financial expectations". WTF, I ask you?&lt;/p&gt;

&lt;p&gt;I have since came to realise, that I do not want to work for a company that misleads its prospective employees.&lt;br&gt;
Just do not waste time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I guess I needed to get this out of my chest and in the open.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In both of my previous jobs I got to enjoy the feeling of not having to work at all, because the people there and the things we got to do, made it seem like so much fun.&lt;br&gt;
The most important thing is that we bonded and supported each other. This allowed everyone to grow. &lt;strong&gt;No money can buy that!&lt;/strong&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Tell me what you think is fair
&lt;/h1&gt;

&lt;p&gt;That is my default answer now.&lt;/p&gt;

&lt;p&gt;Money is important. It is the means with which we can support our goals and dreams, but &lt;strong&gt;it is not the deciding factor&lt;/strong&gt;.&lt;br&gt;
As it turns out - it never has been!&lt;/p&gt;

&lt;p&gt;I am sure we can come to a mutually beneficial arrangement if we just keep honest and open about our expectations and capabilities.&lt;/p&gt;

&lt;p&gt;Now, Let's talk how we can work together!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;original post: &lt;a href="https://www.tegh.net/misc/money-is-not-everything/"&gt;https://www.tegh.net/misc/money-is-not-everything/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>work</category>
      <category>personal</category>
      <category>money</category>
    </item>
    <item>
      <title>Automated testing in a build pipeline</title>
      <dc:creator>Paweł Zaremba</dc:creator>
      <pubDate>Tue, 14 Apr 2020 18:08:03 +0000</pubDate>
      <link>https://dev.to/pawzar/automated-testing-in-a-build-pipeline-eao</link>
      <guid>https://dev.to/pawzar/automated-testing-in-a-build-pipeline-eao</guid>
      <description>&lt;p&gt;A testing &lt;a href="https://www.tegh.net/knowledge/testing-is-a-mindset/"&gt;mindset&lt;/a&gt; with its' &lt;a href="https://www.tegh.net/knowledge/bashing-tests/"&gt;scripts&lt;/a&gt; would be incomplete if we did not put them to good use.&lt;/p&gt;

&lt;p&gt;Ideally, tests should be run every time we intend to share our code with anyone - be it our team or the whole world.&lt;br&gt;
It is a tech lead's wet dream to work in an environment where every dev thoroughly tests their solutions. &lt;br&gt;
As this might be impossible, we can have the next best thing. &lt;/p&gt;

&lt;p&gt;We can make tests run automatically every time new or modified code is introduced into the codebase.&lt;/p&gt;

&lt;p&gt;Let's assume we do everything in &lt;em&gt;Docker&lt;/em&gt; and any new code is built by a server that prevents merging changes until a new &lt;em&gt;image&lt;/em&gt; is successfully created.&lt;/p&gt;

&lt;p&gt;We'll use the &lt;code&gt;tests.sh&lt;/code&gt; from &lt;a href="https://www.tegh.net/knowledge/bashing-tests/"&gt;before&lt;/a&gt; and add a &lt;code&gt;test_scenario.sh&lt;/code&gt; which checks if all the use cases we need are covered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# When we run the script:&lt;/span&gt;
bash test_scenario.sh

&lt;span class="c"&gt;# We get:&lt;/span&gt;
Test &lt;span class="c"&gt;#1: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#2: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#3: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#4: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#5: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#6: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#7: PASS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, we can create a &lt;code&gt;Dockerfile&lt;/code&gt; that will use the above script to check if our app is behaving properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; bash&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; test*.sh ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;bash test_scenario.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The docker image described above will not be built if the tests fail. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Try to build the image&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# We get:&lt;/span&gt;

Sending build context to Docker daemon  4.608kB
Step 1/3 : FROM bash
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 78664daf24f4
Step 2/3 : COPY &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.sh ./
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; fe75cddc7f0f
Step 3/3 : RUN bash test_scenario.sh
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Running &lt;span class="k"&gt;in &lt;/span&gt;010702b02aea
Test &lt;span class="c"&gt;#1: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#2: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#3: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#4: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#5: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#6: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#7: FAIL&lt;/span&gt;
The &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="s1"&gt;'/bin/sh -c bash test_scenario.sh'&lt;/span&gt; returned a non-zero code: 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this approach, there will never exist a runnable version of our app that did not pass all the required tests.&lt;br&gt;
When we fix the app, the test will work again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# [...]&lt;/span&gt;
Step 3/3 : RUN bash test_scenario.sh
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Running &lt;span class="k"&gt;in &lt;/span&gt;c2d555481c28
Test &lt;span class="c"&gt;#1: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#2: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#3: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#4: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#5: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#6: PASS&lt;/span&gt;
Test &lt;span class="c"&gt;#7: PASS&lt;/span&gt;
Removing intermediate container c2d555481c28
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; d41d9ecb5ed9
Successfully built d41d9ecb5ed9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;... and we will have a new image built and ready to use.&lt;/p&gt;

&lt;p&gt;Of course, there are different types of tests. Some of them will not be able to run before the application is actually built and deployed to a testing environment.&lt;br&gt;
Real-life requires more sophisticated configurations, but the general idea is here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Both &lt;code&gt;*.sh&lt;/code&gt; files and the &lt;code&gt;Dockerfile&lt;/code&gt; are available on &lt;a href="https://github.com/teghnet/www/tree/master/src/testing"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>docker</category>
      <category>bash</category>
      <category>basics</category>
    </item>
    <item>
      <title>Multiple tests run in bulk using Bash</title>
      <dc:creator>Paweł Zaremba</dc:creator>
      <pubDate>Wed, 25 Mar 2020 15:24:24 +0000</pubDate>
      <link>https://dev.to/pawzar/multiple-tests-run-in-bulk-using-bash-1km6</link>
      <guid>https://dev.to/pawzar/multiple-tests-run-in-bulk-using-bash-1km6</guid>
      <description>&lt;p&gt;Having briefly explained what a test is we can come to an inevitable conclusion that having only a single test is never enough.&lt;br&gt;
We usually write a lot of them and it is useful to group them. &lt;/p&gt;

&lt;p&gt;Assuming that the tests we are using conform to the contract of returning proper exit statuses, the whole group can technically be treated like a single test.&lt;/p&gt;

&lt;p&gt;Let's put them inside a &lt;code&gt;tests.sh&lt;/code&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; file-a.txt
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; file-b.txt
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; file-c.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, (I assume that the script is an executable file) let's run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All is well. The required files do not exist, so the test is failing.&lt;/p&gt;

&lt;p&gt;Create the files one by one and run the test each time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;file-a.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 1&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;file-b.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 1&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;file-c.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All is well again. The test passes.&lt;/p&gt;

&lt;p&gt;Now, let's make sure the test is solid.&lt;br&gt;
Delete the first file and run the test again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;file-a.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait, what? The test returns &lt;code&gt;0&lt;/code&gt;? It should fail!&lt;/p&gt;

&lt;p&gt;The thing is that when we put some commands into a script, only the last one's return status is returned by the script itself.&lt;br&gt;
To ensure that the script will exit when a command within that script exits with a non-zero status, we use the &lt;a href="https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html"&gt;&lt;code&gt;set&lt;/code&gt;&lt;/a&gt; bash builtin with the &lt;code&gt;-e&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;Put &lt;code&gt;#!/bin/bash&lt;/code&gt; (just to make sure we will be running Bash) on the first line and &lt;code&gt;set -e&lt;/code&gt; on the second line of the test script and run it yet again.&lt;/p&gt;

&lt;p&gt;Now the test fails as it should.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run a series of tests to ensure all relevant situations are being checked.
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;file-?.txt

./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="c"&gt;# should return 1&lt;/span&gt;

&lt;span class="nb"&gt;touch &lt;/span&gt;file-a.txt
&lt;span class="nb"&gt;touch &lt;/span&gt;file-b.txt
&lt;span class="nb"&gt;touch &lt;/span&gt;file-c.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="c"&gt;# should return 0&lt;/span&gt;

&lt;span class="nb"&gt;rm &lt;/span&gt;file-a.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="c"&gt;# should return 1&lt;/span&gt;

&lt;span class="nb"&gt;touch &lt;/span&gt;file-a.txt
&lt;span class="nb"&gt;rm &lt;/span&gt;file-b.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="c"&gt;# should return 1&lt;/span&gt;

&lt;span class="nb"&gt;touch &lt;/span&gt;file-b.txt
&lt;span class="nb"&gt;rm &lt;/span&gt;file-c.txt
./tests.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="c"&gt;# should return 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This shows the general idea behind testing.&lt;/p&gt;

&lt;p&gt;I have been purposefully avoiding using the terms &lt;a href="https://en.wikipedia.org/wiki/Test_case"&gt;&lt;code&gt;test cases&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Test_suite"&gt;&lt;code&gt;test suites&lt;/code&gt;&lt;/a&gt; as they are usually more abstract concepts I do not wish to get into here.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>bash</category>
      <category>shell</category>
      <category>basics</category>
    </item>
    <item>
      <title>What is a test in software development?</title>
      <dc:creator>Paweł Zaremba</dc:creator>
      <pubDate>Wed, 25 Mar 2020 15:22:13 +0000</pubDate>
      <link>https://dev.to/pawzar/what-is-a-test-in-software-development-3deh</link>
      <guid>https://dev.to/pawzar/what-is-a-test-in-software-development-3deh</guid>
      <description>&lt;p&gt;When joining a new project (and maybe even in a previously unknown programming language) we can get overwhelmed by the complexity of the test suites. Sometimes it can even be a nightmare to run them, not to mention understand what is going on. There are lots of levels the tests can be run on.&lt;/p&gt;

&lt;p&gt;Let's start with the basics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anything that checks if a requirement is met is a test.
&lt;/h3&gt;

&lt;p&gt;How do we apply this mindset in real life?&lt;/p&gt;

&lt;p&gt;In software engineering, we want something that we can run and immediately see if what the project requires is what the solution provides.&lt;/p&gt;

&lt;p&gt;Fortunately, we have the concept of an &lt;code&gt;exit status&lt;/code&gt;. Well behaved commands return such a status (sometimes called &lt;code&gt;exit code&lt;/code&gt;). A &lt;code&gt;0&lt;/code&gt; means that the command finished successfully. A non-zero value is usually considered to be an &lt;code&gt;error code&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If a command utilizes this concept it is a perfect tool to use for testing.&lt;/p&gt;

&lt;p&gt;We can print the &lt;code&gt;exit status&lt;/code&gt; on unix-like operating systems with &lt;code&gt;echo $?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The simplest example is the &lt;code&gt;test&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; a-non-existent-file.txt
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 1&lt;/span&gt;

&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# returns: 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is already a ready-to-use test. We can put it into a CI/CD pipeline which will fail if the README file is missing.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>shell</category>
      <category>basics</category>
    </item>
  </channel>
</rss>
