<?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>Forem: Leah Einhorn</title>
    <description>The latest articles on Forem by Leah Einhorn (@leahein).</description>
    <link>https://forem.com/leahein</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%2F2287%2F15165051.png</url>
      <title>Forem: Leah Einhorn</title>
      <link>https://forem.com/leahein</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/leahein"/>
    <language>en</language>
    <item>
      <title>Secure your app in a few easy steps 🔒</title>
      <dc:creator>Leah Einhorn</dc:creator>
      <pubDate>Sat, 13 Nov 2021 00:26:33 +0000</pubDate>
      <link>https://forem.com/leahein/secure-your-app-in-a-few-easy-steps-2amo</link>
      <guid>https://forem.com/leahein/secure-your-app-in-a-few-easy-steps-2amo</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P-9joOja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.amuniversal.com/c8be7f806cc901301d50001dd8b71c47" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P-9joOja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.amuniversal.com/c8be7f806cc901301d50001dd8b71c47" alt="Dilbert Security" width="880" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Security is a broad topic, and one that’s hard to master. However, there are some really simple things you can do to increase the security of your web application.&lt;/p&gt;

&lt;p&gt;For starters, there are some HTTP Response Headers you can include in your web responses, that can prevent easily preventable vulnerabilities.&lt;/p&gt;

&lt;p&gt;This will aim to outline all of the headers recommended by the &lt;a href="https://owasp.org/www-project-secure-headers/"&gt;OWASP Secure Headers Project&lt;/a&gt;, as part of a series. Let's begin with a couple.&lt;/p&gt;

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

&lt;p&gt;As a caveat, these are by no means foolproof. However, they do provide a first layer of &lt;a href="https://www.forcepoint.com/cyber-edu/defense-depth"&gt;defense in depth&lt;/a&gt; for attackers.&lt;/p&gt;

&lt;h4&gt;
  
  
  How To
&lt;/h4&gt;

&lt;p&gt;The recommended mechanism for configuring your web application to return these headers in every response, is by configuring your web server. Since &lt;a href="https://www.nginx.com/"&gt;&lt;code&gt;nginx&lt;/code&gt;&lt;/a&gt; is a widely used option, I will provide examples that demonstrate how to implement these headers via &lt;code&gt;nginx&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  X-Frame-Options
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prevents&lt;/strong&gt;: Clickjacking &lt;br&gt;
&lt;strong&gt;What it is&lt;/strong&gt;: A Clickjacking attack is when a malicious website overlays their website with another website. The content isn't visible to the user, and so they can be tricked into clicking on things on the trusted website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Malicious website overlays a bank website with their own website, with a button to win a free iPad. The user clicks the button, but instead is tricked into actually clicking on a (non-visible) button that will wire money to the attacker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actual Attack Headline&lt;/strong&gt;: &lt;a href="https://www.itpro.co.uk/624283/facebook-hit-by-more-clickjacking-attacks"&gt;Facebook hit by more clickjacking attacks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options"&gt;&lt;code&gt;X-Frame-Options: DENY&lt;/code&gt;&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This header can be used to indicate whether or not a browser should be allowed to render a page in an iframe. Sites can use this to avoid clickjacking attacks by specifying that their content should not be embedded into other sites.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since &lt;code&gt;X-Frame-Options&lt;/code&gt; was never a formally defined standard, a new header and value, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors"&gt;&lt;code&gt;Content-Security-Policy: frame-ancestors 'none';&lt;/code&gt;&lt;/a&gt;, has come to take its place. The browser gives precedence to &lt;code&gt;X-Frame-Options&lt;/code&gt;, which is still the most prevalent way to mitigate clickjacking. It is recommended to include both headers in the response, so as to support both older and newer browsers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# nginx.conf&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Frame-Options&lt;/span&gt; &lt;span class="s"&gt;"DENY"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Security-Policy&lt;/span&gt; &lt;span class="s"&gt;"frame-ancestors&lt;/span&gt; &lt;span class="s"&gt;'none'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  X-Content-Type-Options
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prevents&lt;/strong&gt;: MIME-sniffing&lt;br&gt;
&lt;strong&gt;What it is&lt;/strong&gt;: MIME sniffing is a technique used by web browsers to examine the contents of a file, when the file format is ambiguous. This is done for the purpose of determining the file format, so it can render the contents appropriately. The vulnerability comes into play when an attacker disguises a malicious script as a different file type (let's say a JPG). Doing so allows the attacker to successfully upload the malicious content. Consequently, when the content is loaded, the browser will render it as a script, rather than an image, thereby executing the malicious content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt; &lt;a href="https://dev.toX-Content-Type-Options"&gt;&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt;&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This header is a marker used by the server to indicate that the MIME types advertised in the &lt;code&gt;Content-Type&lt;/code&gt; headers should be followed and not be changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are deliberately configured.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# nginx.conf&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt; &lt;span class="s"&gt;"nosniff"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;By adding a few lines of code to your web server configuration, you can easily prevent some common vulnerabilities. &lt;/p&gt;

</description>
      <category>security</category>
      <category>nginx</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Snapshot Testing in Python</title>
      <dc:creator>Leah Einhorn</dc:creator>
      <pubDate>Mon, 26 Nov 2018 00:51:54 +0000</pubDate>
      <link>https://forem.com/leahein/snapshot-testing-in-python-11i6</link>
      <guid>https://forem.com/leahein/snapshot-testing-in-python-11i6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foatj0peqdec33lheuyjt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foatj0peqdec33lheuyjt.jpg" alt="snapshot" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever found yourself writing long, tedious tests that take in a large data structure, and test the output of a similar, validated data structure? Whether it's converting a dictionary to a named tuple or serializing an object, if you've ever tried testing a data model or a GraphQL model for an API, you've probably experienced this.  &lt;/p&gt;

&lt;p&gt;Writing tests and replicating the same response we expect can be a tedious and monotonous task.  Snapshot testing can be a great way to ease the pain of testing these data structures.  As our APIs evolve, we need to know when our changes introduce any breaking changes, and a snapshot test will tell us exactly that.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Snapshot testing?
&lt;/h3&gt;

&lt;p&gt;Put simply, &lt;code&gt;A snapshot is a single state of your output, saved in a file.&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A typical snapshot test case for a mobile app renders a UI component, takes a screenshot, then compares it to a reference image stored alongside the test. The test will fail if the two images do not match: either the change is unexpected, or the screenshot needs to be updated to the new version of the UI component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A similar approach can be taken when it comes to testing your APIs or data structures. Instead of rendering the graphical UI, you can use a test renderer, such as the &lt;a href="https://github.com/syrusakbary/snapshottest" rel="noopener noreferrer"&gt;&lt;code&gt;SnapshotTest&lt;/code&gt;&lt;/a&gt; library, to quickly generate a serializable value for your API response.&lt;/p&gt;

&lt;p&gt;Snapshots lets us write all these tests in a breeze, as it automatically creates the snapshots for us the first time the test is executed.  Then, every subsequent time the tests are run, it will compare the output with the file snapshot.  If they are different, our tests will fail, immediately alerting us of the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use the &lt;code&gt;SnapshotTest&lt;/code&gt; library
&lt;/h3&gt;

&lt;p&gt;First, we install the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;snapshottest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll provide code snippets below for both the python built-in &lt;code&gt;unittest&lt;/code&gt; library and &lt;code&gt;pytest&lt;/code&gt;, but you can probably use this with any testing framework you choose.&lt;/p&gt;

&lt;p&gt;We'll begin with a simple namedtuple that we'd like to test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;Our Clown Code&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;namedtuple&lt;/span&gt;

&lt;span class="n"&gt;Clown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;namedtuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Clown&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nose_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With unittest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snapshottest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestClown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_clown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="n"&gt;clown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Clown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bozo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;red and round&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                  
      &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertMatchSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# &amp;gt;&amp;gt; python -m unittest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With pytest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_clown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="n"&gt;clown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Clown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bozo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;red and round&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                  
      &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="c1"&gt;# &amp;gt;&amp;gt; pytest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a snapshot directory and a snapshot file the first time the test is executed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; pytest
&lt;span class="o"&gt;===================&lt;/span&gt; SnapshotTest summary &lt;span class="o"&gt;===================&lt;/span&gt;
1 snapshot passed.
1 snapshot written &lt;span class="k"&gt;in &lt;/span&gt;1 &lt;span class="nb"&gt;test &lt;/span&gt;suites.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next time we run our tests, it will compare the results of our test with the snapshot.  Since nothing changed, we get the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; pytest
&lt;span class="o"&gt;===================&lt;/span&gt; SnapshotTest summary &lt;span class="o"&gt;===================&lt;/span&gt;

1 snapshot passed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If our data structure or output changes, the snapshot tests will fail. We can then compare the changes and determine whether they are valid.  To update the snapshot we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pytest &lt;span class="nt"&gt;--snapshot-update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifke55an8pfp3sxcuysr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifke55an8pfp3sxcuysr.jpg" alt="snapshot" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obviously the above is a super simple test case, and we're not really testing any logic.  But this same pattern can be applied for testing API requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_my_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_api.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or for testing a GraphQL API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;graphene.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_hey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;{ hey }&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Snapshot testing may not be a replacement for unit or integration tests, but it's a great way to quickly and effectively determine whether the state of your API or data serialization has changed.&lt;/p&gt;

</description>
      <category>python</category>
      <category>snapshottest</category>
      <category>testing</category>
      <category>pytest</category>
    </item>
    <item>
      <title>Continuous Integration with `make` for AWS Lambda using Python</title>
      <dc:creator>Leah Einhorn</dc:creator>
      <pubDate>Sun, 05 Aug 2018 19:45:35 +0000</pubDate>
      <link>https://forem.com/leahein/continuous-integration-with-make-for-aws-lambda-using-python-3dll</link>
      <guid>https://forem.com/leahein/continuous-integration-with-make-for-aws-lambda-using-python-3dll</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.skilljar.com%2Fhs-fs%2Fhubfs%2Fsalesforce_integration.png%3Ft%3D1533167571059%26width%3D440%26height%3D212%26name%3Dsalesforce_integration.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.skilljar.com%2Fhs-fs%2Fhubfs%2Fsalesforce_integration.png%3Ft%3D1533167571059%26width%3D440%26height%3D212%26name%3Dsalesforce_integration.png" alt="pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;When deploying python code to AWS Lambda, you are required to zip all your code into a single zip file, and add all your package dependencies (python libraries that you usually pip install into your virtualenv) into the root level of your directory.&lt;/p&gt;

&lt;p&gt;I wanted a way to do this easily, without having to log into the AWS console&lt;br&gt;
and using the GUI to zip all my contents every time I modify the source code. I also wanted a way to test the code and stop the process from deploying if the tests didn't pass.  Kind of what you would expect if you had a continuous integration server, such as Jenkins.  The goal was to be able to modify code or pip install packages, and with a single command be able to test my code, zip my code, and deploy it to lambda. &lt;/p&gt;
&lt;h2&gt;
  
  
  Make Intro
&lt;/h2&gt;

&lt;p&gt;If you aren't familiar with &lt;code&gt;make&lt;/code&gt;, here is a description:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A GNU build automation tool that automatically builds programs from source code by reading files called Makefiles, which specifies how to build the program. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is commonly used in c programs to compile all source code and bundle it into a single executable file, and comes pre-installed on most UNIX systems, such as MacOS and Linux. Another great benefit to &lt;code&gt;make&lt;/code&gt; is that it is smart enough to re-build &lt;em&gt;just&lt;/em&gt; the files that have changed, and doesn't regenerate &lt;em&gt;every&lt;/em&gt; file every time.  Rules will execute in the order you specify, and stop executing if any of the commands fail.&lt;/p&gt;

&lt;p&gt;Ultimately, it seems like a great use case for our needs, since we essentially&lt;br&gt;
want to transform our source files to a single target result (the zip file)! We also want the deployment process to halt and stop executing commands if our tests fail.  &lt;/p&gt;

&lt;p&gt;First, just a quick intro to some &lt;code&gt;make&lt;/code&gt; commands and syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To do stuff with make, you type &lt;strong&gt;&lt;code&gt;make&lt;/code&gt;&lt;/strong&gt; in your terminal in a directory that has a file called "Makefile"&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Makefile&lt;/strong&gt; is a collection of rules.  Each rule is a &lt;strong&gt;recipe&lt;/strong&gt; to do a
specific thing. &lt;/li&gt;
&lt;li&gt;Recipe syntax:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;  &lt;span class="nl"&gt;&amp;lt;target&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;prerequisites...&amp;gt;&lt;/span&gt;
    &amp;lt;commands&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;strong&gt;target&lt;/strong&gt; would be what you call from the terminal to execute commands, such as &lt;code&gt;make &amp;lt;target&amp;gt;&lt;/code&gt;, similar to a function name. &lt;br&gt;
&lt;strong&gt;prerequisites&lt;/strong&gt; are anything this target relies upon, which could be a file or another target. &lt;br&gt;
&lt;strong&gt;commands&lt;/strong&gt; are where you can specify a series of commands you’d like to execute, like a function body. &lt;/p&gt;

&lt;p&gt;The target is required, the prerequisites and commands are optional, but you must have one or the other.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Magic variables: This is special make syntax that allows us to easily refer 
to the target / prerequisites.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example:
&lt;/span&gt;&lt;span class="nl"&gt;libs/&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;requirements.txt requirements-test.txt&lt;/span&gt;
  &lt;span class="nl"&gt;$@   # refers to target&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;"libs/" &lt;/span&gt;
  &lt;span class="nl"&gt;$&amp;lt;   # refers to the first prerequisite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;"requirements.txt" &lt;/span&gt;
  &lt;span class="nl"&gt;$^   # refers to all prerequisites&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;"requirements.txt requirements-test.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The syntax is unique and could take time to get used to! But in my opinion it is part of what makes &lt;code&gt;make&lt;/code&gt; (uh) a powerful tool when compiling source code, rather than using a bash script. &lt;a href="https://devhints.io/makefile" rel="noopener noreferrer"&gt;Here's a cheat sheet for reference.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How To
&lt;/h2&gt;

&lt;p&gt;We will want to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test our code&lt;/li&gt;
&lt;li&gt;Zip our code&lt;/li&gt;
&lt;li&gt;Deploy our code&lt;/li&gt;
&lt;li&gt;Clean up any files / dirs we created&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This tutorial assumes you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pip&lt;/li&gt;
&lt;li&gt;aws cli &lt;/li&gt;
&lt;li&gt;make&lt;/li&gt;
&lt;li&gt;zip&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Test our code
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;mypy pylint nose tox &lt;/span&gt;&lt;span class="c"&gt;##&lt;/span&gt;&lt;span class="nf"&gt; Run all tests&lt;/span&gt;
    pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="c"&gt;# install your test dependencies&lt;/span&gt;
    &lt;span class="c"&gt;## run your tests here.  some examples:&lt;/span&gt;
    python &lt;span class="nt"&gt;-m&lt;/span&gt; unittest discover tests/
    nose
    pylint main.py
    mypy main.py
    tox
    &lt;span class="c"&gt;# etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Zip our code
&lt;/h3&gt;

&lt;p&gt;We begin by installing the library dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Our target is the libs dir, which has a requirements file as a prerequisite
&lt;/span&gt;
&lt;span class="nl"&gt;libs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;requirements.txt &lt;/span&gt;&lt;span class="c"&gt;##&lt;/span&gt;&lt;span class="nf"&gt; Install all libraries&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="c"&gt;# Create the libs dir if it doesn't exist&lt;/span&gt;
        pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="c"&gt;# We use -t to specify the destination of the&lt;/span&gt;
        &lt;span class="c"&gt;# packages, so that it doesn't install in your virtual env by default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zip the source code and the libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Our target is the zip file, which has libs as a prerequisite 
&lt;/span&gt;
&lt;span class="nl"&gt;output.zip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;libs &lt;/span&gt;&lt;span class="c"&gt;##&lt;/span&gt;&lt;span class="nf"&gt; Output all code to zip file&lt;/span&gt;
        zip &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.py &lt;span class="c"&gt;# zip all python source code into output.zip&lt;/span&gt;
        &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;  zip &lt;span class="nt"&gt;-rm&lt;/span&gt; ../&lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="c"&gt;# zip libraries installed in the libs dir into output.zip&lt;/span&gt;

        &lt;span class="c"&gt;# We `cd` into the directory since zip will always keep the relative 
&lt;/span&gt;     &lt;span class="c"&gt;# paths, and lambda requires the library dependencies at the root.
&lt;/span&gt;
        &lt;span class="c"&gt;# Each line of a make command is run as a separate invocation of 
&lt;/span&gt;     &lt;span class="c"&gt;# the shell, which is why we need to combine the cd and zip command here.
&lt;/span&gt;
        &lt;span class="c"&gt;# We use the -rm flag so it removes the libraries after zipping, 
&lt;/span&gt;     &lt;span class="c"&gt;# since we don't need these.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy our code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Our target is deploy, which has the zip file as a prerequisite 
# Note: since deploy doesn't refer to an actual file or directory, it's good 
# practice to declare this as .PHONY, so make knows not to look for that file.
&lt;/span&gt;
&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;deploy&lt;/span&gt;
&lt;span class="nl"&gt;deploy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;output.zip &lt;/span&gt;&lt;span class="c"&gt;##&lt;/span&gt;&lt;span class="nf"&gt; Deploy all code to aws&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;aws lambda update-function-code &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--function-name&lt;/span&gt; my-lambda-function &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://&lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt;
 &lt;span class="c"&gt;# This assumes you have the aws cli, but if not, run `pip install awscli`
&lt;/span&gt;
 &lt;span class="c"&gt;# The "-" says to ignore the exit status, and continue executing even if it
&lt;/span&gt; &lt;span class="c"&gt;# fails.  This is so we can clean up the files when we're done, even if
&lt;/span&gt; &lt;span class="c"&gt;# deployment failed.  
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  And finally, clean up files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean&lt;/span&gt;
&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;##&lt;/span&gt;&lt;span class="nf"&gt; Remove zipped files and directories generated during build&lt;/span&gt;
    &lt;span class="nb"&gt;rm &lt;/span&gt;output.zip
    &lt;span class="nb"&gt;rmdir &lt;/span&gt;libs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we'll want to run all these targets and execute it with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# `make all` will execute all prerequisite targets!
&lt;/span&gt;
&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;
&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;test deploy clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Make is a powerful tool that can be used to run a series of commands, and can be a useful build automation tool when deploying to lambda.  &lt;/p&gt;

&lt;p&gt;We use it to zip our python source code, as well as our dependencies, and push the code to aws.&lt;/p&gt;

&lt;p&gt;Now, with a single command in your terminal, &lt;code&gt;make all&lt;/code&gt;, we have our continuous integration pipeline set up for lambda!&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;Make can do a lot more with its special syntax, so if you'd like to learn more, &lt;a href="https://gist.github.com/isaacs/62a2d1825d04437c6f08" rel="noopener noreferrer"&gt;check out this tutorial&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ci</category>
      <category>lambda</category>
      <category>python</category>
      <category>make</category>
    </item>
  </channel>
</rss>
