<?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: David</title>
    <description>The latest articles on DEV Community by David (@wulymammoth).</description>
    <link>https://dev.to/wulymammoth</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%2F414039%2F869c7027-ab8e-4b34-8464-5a09ae17c277.jpeg</url>
      <title>DEV Community: David</title>
      <link>https://dev.to/wulymammoth</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wulymammoth"/>
    <language>en</language>
    <item>
      <title>Stop pressing the up (arrow) to find a previous command</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 11 Jul 2020 15:20:37 +0000</pubDate>
      <link>https://dev.to/wulymammoth/stop-pressing-up-arrow-to-find-a-previous-command-5370</link>
      <guid>https://dev.to/wulymammoth/stop-pressing-up-arrow-to-find-a-previous-command-5370</guid>
      <description>&lt;p&gt;Ever wonder if there are ways to be more efficient in our terminal and shell? Feeling a little clunky? Here are a few good-to-knows for those of us that have never dabbled in sys-admin or dev-ops work&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : Do I have to push up (arrow) multiple times to find a previous command that I need to run? What if I just want to run the last command again?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : Please, for the love of anything, stop (pressing up multiple times and eyeballing)! This is ridiculously inefficient! Three things!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-- FIRST --&lt;/strong&gt;  To simply run the previous command without moving off our keyboard's home row: &lt;code&gt;ctrl-p&lt;/code&gt; (mnemonic for "previous") followed by the &lt;code&gt;&amp;lt;Enter&amp;gt;&lt;/code&gt; key. Went past our command? &lt;code&gt;ctrl-n&lt;/code&gt; (mnemonic for "next").&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-- SECOND --&lt;/strong&gt; If we know it's not the last command, the following is probably the utility that I rely on most: &lt;code&gt;reverse-i-search&lt;/code&gt;. This utility treats our (command) &lt;code&gt;history&lt;/code&gt; like a stack and (fuzzy) finds the most recent match for any term/keyword that exists in our history. To initialize it, hit &lt;code&gt;ctrl-r&lt;/code&gt;. Once we've typed something it should arrive at our first match. If the first match isn't what we're looking for, then hit &lt;code&gt;ctrl-r&lt;/code&gt; again and it'll go to the next previous match. And if we've gone past it, use &lt;code&gt;ctrl-s&lt;/code&gt;/&lt;code&gt;&amp;lt;Shift&amp;gt;-ctrl-r&lt;/code&gt; (depending on our operating system). To exit the search, use &lt;code&gt;ctrl-g&lt;/code&gt;. This has almost completely eliminated all my use of aliases.&lt;/p&gt;

&lt;p&gt;Let's say that our history looks like this. NOTE: the numbers on the left correspond to the line number in my bash history&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;history
&lt;/span&gt;2311  &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
2312  rg &lt;span class="nt"&gt;--files&lt;/span&gt; | fzf
2313  vim reverse_singly_linked_list.py
2314  python &lt;span class="nt"&gt;-m&lt;/span&gt; unittest reverse_singly_linked_list.py
2315  ping google.com
2317  mix routes
2318  mix phx.routes
2319  git branch
2320  git log &lt;span class="nt"&gt;-3&lt;/span&gt; &lt;span class="nt"&gt;--reverse&lt;/span&gt;
2322  htop
2326  &lt;span class="nb"&gt;jobs
&lt;/span&gt;2327  git status
2328  git diff &lt;span class="nt"&gt;-w&lt;/span&gt;
2329  ./deploy.sh
2330  less README.md
2331  man &lt;span class="nb"&gt;awk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, I'm at my prompt and I'm searching for the last command that contained the following characters: &lt;code&gt;test&lt;/code&gt;. If we eyeball above, we'll notice that it's command number &lt;code&gt;2314&lt;/code&gt; that corresponds with a unit test that I ran with Python for a linked list. What most people do is press up twelve, I repeat, TWELVE, times! When hitting &lt;code&gt;ctrl-r&lt;/code&gt;, followed by entering the characters, &lt;code&gt;test&lt;/code&gt;, will find that command in its entirety. We can just hit &lt;code&gt;&amp;lt;Enter&amp;gt;&lt;/code&gt; to invoke (run) it&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;# what we type will display here&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;reverse-i-search&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="s1"&gt;': python -m unittest reverse_singly_linked_list.py
                                          👆 # match begins here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;-- LASTLY (third) --&lt;/strong&gt; we can "pipe" our &lt;code&gt;history&lt;/code&gt; into &lt;code&gt;grep&lt;/code&gt; (without the angle brackets). This will pull up ALL matches of a command that contains the given term. This is useful if we can only remember some fragments of a command AND to avoid having to hit &lt;code&gt;ctrl-r&lt;/code&gt; many times when there are multiple matches.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &amp;lt;term/keyword&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : What are the options for this thing? (some Unix utility) Do I have to go to Google every time?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : built-in Unix utilities (i.e. &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;xargs&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;) typically have many &lt;strong&gt;options&lt;/strong&gt;. One of the quickest references available is the &lt;strong&gt;manual&lt;/strong&gt;, also known as man-pages, that can simply be invoked with &lt;code&gt;$ man &amp;lt;utility&amp;gt;&lt;/code&gt;, (e.g. &lt;code&gt;$ man ls&lt;/code&gt;). I've found &lt;code&gt;ls -l&lt;/code&gt; (long format), &lt;code&gt;ls -la&lt;/code&gt; (long with directories), and &lt;code&gt;ls -lt&lt;/code&gt; (long ordered by time) to be particularly useful.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : Okay, so I'm now using man-pages, but how do I navigate this thing or find what I'm searching for? This thing is massive!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : man-pages typically adopt &lt;a href="https://en.wikipedia.org/wiki/Vi"&gt;vi&lt;/a&gt; movements (popular text editor found on almost all Unix/Linux-based machines including macOS). They can simply be searched by first hitting the &lt;code&gt;/&lt;/code&gt; (forward slash) to initiate a search, followed by some keyword or option (e.g. &lt;code&gt;/foobar&lt;/code&gt; or &lt;code&gt;/-a&lt;/code&gt;) will search for &lt;code&gt;foobar&lt;/code&gt; or &lt;code&gt;-a&lt;/code&gt; within the page.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : Okay, so that search only takes me to the first matching instance. How do I find the &lt;strong&gt;next&lt;/strong&gt; one? Or go back to the &lt;strong&gt;previous&lt;/strong&gt; one?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : We can use &lt;code&gt;n&lt;/code&gt; (lowercase and mnemonic for "next") to go to the next instance, and &lt;code&gt;&amp;lt;Shift&amp;gt;-n&lt;/code&gt; (capital) to go back (to the previous instance)&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : Is there a way to make a new directory and switch into it immediately?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : &lt;code&gt;$ mkdir foo &amp;amp;&amp;amp; cd $_&lt;/code&gt;. The last command argument is captured in the &lt;code&gt;_&lt;/code&gt; (underscore) variable. To access variables, we use the &lt;code&gt;$&lt;/code&gt; prefix&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : Is there an easier way to switch back and forth between directories?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : Use &lt;code&gt;-&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/Users/me/Desktop

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;foo
foo &lt;span class="err"&gt;$&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/Users/me/Desktop/foo

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; -
/Users/me/Desktop

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; -
/Users/me/Desktop/foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;problem&lt;/strong&gt; : How do I move around the text for a command that I've already typed or edit a previous command? How do I go to the beginning of the line or the end of the line?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solution&lt;/strong&gt; : readline shortcuts - allow us to navigate within a line and perform edits. This is a huge efficiency gain. Surprisingly, most of our tools are built with readline, so these typically work in any place that allow us to type text (i.e. Chrome or Firefox address bar, Google Doc, etc) so they are worth learning even outside of a shell&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try these out&lt;/strong&gt;. NOTE: on macOS, we must configure the meta keys for the option-key-based commands to work (how-to after the commands below). If we care about ergonomics a common key re-map is changing our caps-lock key to &lt;code&gt;ctrl&lt;/code&gt;. This can be done through our system keyboard preferences' modifier keys (on macOS):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alt-b / option-b (macOS): move cursor back one word
alt-f / option-f (macOS): move cursor forward one word
ctrl-a: move cursor to the beginning of line
ctrl-b: move cursor backward (←)
ctrl-d: delete a character
ctrl-e: move cursor to the end of line
ctrl-f: move cursor forward (→)
ctrl-k: kill the line after the cursor, add to clipboard
ctrl-n: next line, next command in history (↓)
ctrl-p: previous line, previous command in history (↑)
ctrl-u: kill the line before the cursor, add to clipboard
ctrl-w: delete a word
ctrl-y: undo / paste from the clipboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;HOW-TO&lt;/strong&gt; set up meta keys for forward and backward using option keys in iTerm2 on macOS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Profile &amp;gt; Keys&lt;/li&gt;
&lt;li&gt;Load Preset &amp;gt; Natural Text Editing&lt;/li&gt;
&lt;li&gt;Switch Left/Right Option from Normal &amp;gt; Esc+&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Using pipes in your (test) assertions</title>
      <dc:creator>David</dc:creator>
      <pubDate>Mon, 06 Jul 2020 16:04:30 +0000</pubDate>
      <link>https://dev.to/wulymammoth/using-pipes-in-your-test-assertions-43dk</link>
      <guid>https://dev.to/wulymammoth/using-pipes-in-your-test-assertions-43dk</guid>
      <description>&lt;p&gt;Love the pipe operator? Miss them in tests with &lt;code&gt;ExUnit&lt;/code&gt; when the result is derived from a pipeline of operations necessitating an intermediate variable, like &lt;code&gt;result&lt;/code&gt;? I did...&lt;/p&gt;

&lt;h2&gt;
  
  
  typical test assertion (no pipe operator)
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;AdderTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"add"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# [2, 4, 6]&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Adder&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# [3, 5, 7]&lt;/span&gt;

    &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  verbose (with pipe)
&lt;/h2&gt;

&lt;p&gt;We can employ an anonymous function (lambda). NOTE: invoked with dot-syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;AdderTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"add"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Adder&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  terse (with pipe)
&lt;/h2&gt;

&lt;p&gt;This uses Elixir's &lt;a href="https://hexdocs.pm/elixir/Kernel.SpecialForms.html#&amp;amp;/1"&gt;&amp;amp; (capture operator)&lt;/a&gt; to keep things concise&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;AdderTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"add"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Adder&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&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;assert&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  an option for those that use Elixir's formatter
&lt;/h2&gt;

&lt;p&gt;If you or your team use Elixir's formatter, then you're going to end up with something like the following where the nice whitespace that gives your arguments some room to breathe is removed. One thing that I've done is add two enhancement functions (using macros) into &lt;code&gt;test/test_helper.exs&lt;/code&gt; that become available to tests by invoking &lt;code&gt;use TestHelper&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;AdderTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"add"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Adder&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&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;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# 🤮&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here's what we can do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test/test_helper.exs&lt;/span&gt;

&lt;span class="no"&gt;ExUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;TestHelper&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defmacro&lt;/span&gt; &lt;span class="n"&gt;__using__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;ExUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Assertions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;assert:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="c1"&gt;# we can name this whatever we'd like,&lt;/span&gt;
      &lt;span class="c1"&gt;# but "is" makes sense to me in most cases&lt;/span&gt;
      &lt;span class="c1"&gt;# 👇&lt;/span&gt;
      &lt;span class="k"&gt;def&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;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expectation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expectation&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="c1"&gt;# 👈 allows us to continue chaining assertions in a pipeline&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="c1"&gt;# this one allows us to make more complex assertions&lt;/span&gt;
      &lt;span class="c1"&gt;# e.g., asserting that a nested key is of a particular value&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;has&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;assertion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="o"&gt;.&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="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# test/adder_test.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;AdderTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;TestHelper&lt;/span&gt; &lt;span class="c1"&gt;# 👈 included here&lt;/span&gt;

  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"add"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Adder&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# 👈 used here&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 👈 and here (chained)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>elixir</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
