<?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: Carolyn Stransky</title>
    <description>The latest articles on DEV Community by Carolyn Stransky (@carolstran).</description>
    <link>https://dev.to/carolstran</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%2F40379%2F091261a6-fdff-486c-bd0e-2b989724a974.jpg</url>
      <title>DEV Community: Carolyn Stransky</title>
      <link>https://dev.to/carolstran</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/carolstran"/>
    <language>en</language>
    <item>
      <title>Broccoli, bots, and brains! The 3 projects where I added the Hacktoberfest topic.</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Sat, 03 Oct 2020 21:57:25 +0000</pubDate>
      <link>https://dev.to/carolstran/broccoli-bots-and-brains-the-3-projects-where-i-added-the-hacktoberfest-topic-5924</link>
      <guid>https://dev.to/carolstran/broccoli-bots-and-brains-the-3-projects-where-i-added-the-hacktoberfest-topic-5924</guid>
      <description>&lt;p&gt;For 2020, I decided to opt-in and add the &lt;code&gt;Hacktoberfest&lt;/code&gt; topic to three of my personal repositories 🎃 &lt;/p&gt;

&lt;p&gt;The goal is to provide an easy-going (and hopefully sort of fun) experience for folks looking to get involved or make their first open-source contribution!&lt;/p&gt;

&lt;p&gt;This post contains links to the projects and a short description of what they're all about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hopeful COVID-19 Bot
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/carolstran"&gt;
        carolstran
      &lt;/a&gt; / &lt;a href="https://github.com/carolstran/hopeful-covid-bot"&gt;
        hopeful-covid-bot
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🤖 Little bot that tweets uplifting COVID-19 news
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The code behind my little Twitter bot &lt;a href="https://twitter.com/hopefulcovidbot"&gt;@hopefulcovidbot&lt;/a&gt; (I promise I will relaunch it this weekend). The best way to contribute is to add an uplifting news article for the bot to tweet out.&lt;/p&gt;

&lt;p&gt;🤖 🖤 💉 🙌🏼 🧼&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeing Sprouts
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/carolstran"&gt;
        carolstran
      &lt;/a&gt; / &lt;a href="https://github.com/carolstran/seeing-sprouts"&gt;
        seeing-sprouts
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🥗 Browser extension that replaces images with brussels sprouts
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;A browser extension that replaces all images on a web page with photos of various veggies. There are step-by-step instructions in the README describing how to add support for more vegetables, nutrient-dense fruits, and other veggie-like things people enjoy!&lt;/p&gt;

&lt;p&gt;🥗 🥔 🥑 🍆 📷&lt;/p&gt;

&lt;h2&gt;
  
  
  So you want to learn GraphQL?
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/carolstran"&gt;
        carolstran
      &lt;/a&gt; / &lt;a href="https://github.com/carolstran/so-you-want-to-learn-graphql"&gt;
        so-you-want-to-learn-graphql
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ✏️ 'Choose Your Own Adventure' but with GraphQL
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Imagine 'Choose your own adventure' but for learning GraphQL. It's super messy because I always say I'm going to work on it and never do - so any support adding or sorting resources is appreciated. The &lt;code&gt;frontend&lt;/code&gt; section and anything marked &lt;code&gt;TODO&lt;/code&gt; are especially lacking. Check out the &lt;a href="https://github.com/carolstran/so-you-want-to-learn-graphql/blob/main/CONTRIBUTING.md"&gt;Contributors Guide&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;✏️ 🧠 💻 🗺 💫&lt;/p&gt;

&lt;p&gt;Feel free to comment on this post or open an issue on the repositories if you have any questions!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Do you enjoy any of these projects or find them useful? If yes, please consider &lt;a href="https://ko-fi.com/carolstran"&gt;buying me a coffee&lt;/a&gt; so I can continue to make things like this&lt;/em&gt; ☕️&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>contributorswanted</category>
    </item>
    <item>
      <title>Community Bonding with the GraphQL Foundation for Google Season of Docs</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Wed, 16 Sep 2020 11:44:03 +0000</pubDate>
      <link>https://dev.to/carolstran/community-bonding-with-the-graphql-foundation-for-google-season-of-docs-28hf</link>
      <guid>https://dev.to/carolstran/community-bonding-with-the-graphql-foundation-for-google-season-of-docs-28hf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://developers.google.com/season-of-docs"&gt;Google Season of Docs&lt;/a&gt; is a 3-month program that connects experienced technical writers with an open-source community. I was &lt;a href="https://developers.google.com/season-of-docs/docs/participants/project-graphql-carolstran"&gt;accepted into the 2020 program&lt;/a&gt; to work with the &lt;a href="https://foundation.graphql.org/"&gt;GraphQL Foundation&lt;/a&gt;. This post is part of a series intended to give insight to technical writers considering future Season of Docs cohorts.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first month of Season of Docs is known as the &lt;em&gt;&lt;strong&gt;community bonding phase&lt;/strong&gt;&lt;/em&gt;. According to Google, this period is intended to help technical writers prepare to contribute to the mentoring organization once the program is in full swing.&lt;/p&gt;

&lt;p&gt;During this phase, I was employed full-time and dedicated about 10 hours per week to the GraphQL Foundation.&lt;/p&gt;

&lt;p&gt;Some organizations will have &lt;a href="https://dev.to/prubhtej/season-of-docs-introductory-meeting-3hdn"&gt;clear expectations&lt;/a&gt; for what they’d like you to complete during this phase. Others, like the GraphQL Foundation, give you more freedom to decide how you want to get to know the community. I chose the following activities with the help of my assigned mentor, &lt;a href="https://github.com/IvanGoncharov"&gt;Ivan Goncharov&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempted to figure out the organization structure
&lt;/h2&gt;

&lt;p&gt;Part of the community bonding phase is becoming familiar with existing practices and processes. I’ve been in the GraphQL ecosystem for a while - &lt;a href="https://so-you-want-to-learn-graphql.netlify.app/"&gt;creating side projects&lt;/a&gt;, &lt;a href="https://workwithcarolyn.com/speaking/life-is-hard-and-so-is-learning-graphql"&gt;giving talks&lt;/a&gt;, and even using it at work sometimes. My previous involvement was actually a large part of why I was selected.&lt;/p&gt;

&lt;p&gt;But getting involved with the Foundation has been really different than using the specification. There’s a hierarchy and internal politics. GraphQL's history (having been incubated at Facebook) also influences the existing setup. So figuring out how decisions are made and who controls which aspect of GraphQL is confusing. &lt;/p&gt;

&lt;p&gt;I tried to decipher all of this through meetings with my mentor, watching recordings of the past &lt;a href="https://www.youtube.com/watch?v=Y4FuML4ju-s&amp;amp;list=PLP1igyLx8foH30_sDnEZnxV_8pYW3SDtb"&gt;working group meetings&lt;/a&gt;, and creating my own mind map of the Foundation structure. Once I’m more confident with it, I’ll share it in a future post. &lt;/p&gt;

&lt;h2&gt;
  
  
  Triaged issues and pull requests
&lt;/h2&gt;

&lt;p&gt;Within the first week, I was made a member of the &lt;a href="https://github.com/graphql"&gt;GraphQL organization on GitHub&lt;/a&gt; and given triage access to &lt;a href="http://github.com/graphql/graphql.github.io/"&gt;&lt;code&gt;graphql.github.io&lt;/code&gt;&lt;/a&gt; (the repository that contains the base code for the GraphQL website and documentation). &lt;/p&gt;

&lt;p&gt;For those who aren’t familiar with triaging, this can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating new labels to appropriately tag issues&lt;/li&gt;
&lt;li&gt;Reviewing code on open pull requests&lt;/li&gt;
&lt;li&gt;Reproducing and confirming any reported bugs&lt;/li&gt;
&lt;li&gt;Closing anything that’s irrelevant or duplicates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I ran into process gaps, I &lt;a href="https://github.com/graphql/graphql.github.io/issues/created_by/carolstran"&gt;opened my own issues&lt;/a&gt; or flagged it to Ivan. Many of these issues and pull requests hadn’t been touched in years, so it took time to figure out why and how to move forward. &lt;/p&gt;

&lt;p&gt;While my triage access was limited to the documentation repository, I started becoming familiar with the other repositories within the GraphQL organization. I focused on repositories that would be relevant to my project, like &lt;a href="https://github.com/graphql/graphql-spec"&gt;&lt;code&gt;graphql-spec&lt;/code&gt;&lt;/a&gt; and an existing &lt;a href="https://github.com/graphql/faq"&gt;&lt;code&gt;faq&lt;/code&gt;&lt;/a&gt;. Along the way, I’d note anything that might be useful for me in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Helped with the Gatsby migration
&lt;/h2&gt;

&lt;p&gt;Earlier this year, there were discussions about &lt;a href="https://github.com/graphql/graphql.github.io/issues/875"&gt;migrating the GraphQL website&lt;/a&gt; from custom scripts to Gatsby/Next.js. This migration was approved before I became involved with the Foundation and now it’s a priority to get this done. &lt;/p&gt;

&lt;p&gt;Due to my limited availability during this phase, the help I offered was limited to reviewing the &lt;a href="https://github.com/graphql/graphql.github.io/pull/896"&gt;existing pull request&lt;/a&gt; by &lt;a href="https://github.com/saihaj"&gt;saihaj&lt;/a&gt; and planning the steps for the migration. We settled on merging it into its own &lt;code&gt;gatsby&lt;/code&gt; branch and then open separate pull requests to fix the remaining issues. Which is part of what I’m currently working on!&lt;/p&gt;

&lt;p&gt;Want to help us out with this migration? Check out and &lt;a href="https://github.com/graphql/graphql.github.io/pull/913#issuecomment-687325610"&gt;claim one of the remaining issues&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aligned on expectations for my project
&lt;/h2&gt;

&lt;p&gt;During this phase, I also had one meeting with my mentor to discuss the new Frequently Asked Questions (FAQ) page that I’ll build. We didn’t dig deep, but we did refine the project plan, agree on initial milestones, and figured out what potential blockers I may face. &lt;/p&gt;

&lt;h3&gt;
  
  
  What happens next?
&lt;/h3&gt;

&lt;p&gt;Now that the bonding is over, it’s time to get to work on documentation development 🚀&lt;/p&gt;

&lt;p&gt;If you’re interested, check out &lt;a href="https://foundation.graphql.org/news/2020/09/21/google-season-of-docs-2020-participant-carolyn-stransky/"&gt;my blog post for the GraphQL Foundation&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;&lt;em&gt;Did you find this helpful or useful? If yes, please consider &lt;a href="https://ko-fi.com/carolstran"&gt;buying me a coffee&lt;/a&gt; so I can continue to write posts like this&lt;/em&gt; ☕️&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>documentation</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Creating a digital CV in Markdown on GitHub</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Tue, 08 Sep 2020 21:19:53 +0000</pubDate>
      <link>https://dev.to/carolstran/creating-a-digital-cv-in-markdown-on-github-1b3l</link>
      <guid>https://dev.to/carolstran/creating-a-digital-cv-in-markdown-on-github-1b3l</guid>
      <description>&lt;p&gt;In early August, I announced on Twitter that I was looking for my next role. My tweet included a link to &lt;a href="https://carolstran.github.io/cv/"&gt;my digital CV&lt;/a&gt; and ever since I’ve received a lot of questions about how I built it. So here’s a short guide!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This guide is based on a Twitter thread that I saw back in 2017. Unfortunately, I can’t remember who posted it… but if it was you, please know that I really appreciate you!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;⚠️ Prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/"&gt;GitHub account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Comfort with &lt;a href="https://www.markdownguide.org/"&gt;Markdown&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅  Steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new public repository on GitHub&lt;/li&gt;
&lt;li&gt;Enable GitHub Pages for your repository&lt;/li&gt;
&lt;li&gt;Select a theme (design template) for your CV&lt;/li&gt;
&lt;li&gt;Write your CV in Markdown&lt;/li&gt;
&lt;li&gt;
Enjoy 💅🏼&lt;/li&gt;
&lt;li&gt;Optional: Set up a custom domain&lt;/li&gt;
&lt;li&gt;
Show me your CV 💌&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a new public repository on GitHub
&lt;/h2&gt;

&lt;p&gt;Everything we need for our digital CV will live in a repository on GitHub. &lt;/p&gt;

&lt;p&gt;To start, &lt;a href="https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-new-repository"&gt;&lt;strong&gt;create a new repository&lt;/strong&gt;&lt;/a&gt; without a template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i-r6TUwL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92525736-a8070c00-f224-11ea-95bb-d5ae805bf3a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i-r6TUwL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92525736-a8070c00-f224-11ea-95bb-d5ae805bf3a8.png" alt='The GitHub top-level navigation. The cursor is clicking "New repository".'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose a name (I called my &lt;code&gt;cv&lt;/code&gt;) and include a description if you want. Make sure it's public.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This digital CV will be hosted with GitHub Pages, which &lt;a href="https://docs.github.com/en/github/working-with-github-pages/about-github-pages"&gt;requires your repository to be public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And finally, &lt;strong&gt;don't initialize it with anything&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While you won't be importing an existing repository, it helps makes the process less complicated to start with a completely blank repository. You'll see why later!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---hIdVHXO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92525986-0c29d000-f225-11ea-87e8-6de9f36145c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---hIdVHXO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92525986-0c29d000-f225-11ea-87e8-6de9f36145c5.png" alt="The new repository's settings. Most important is that it's public and not initialized with anything."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable GitHub Pages for your repository
&lt;/h2&gt;

&lt;p&gt;Your digital CV will be hosted with &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;. GitHub Pages allows you to host personal and project pages directly from a GitHub repository. It’s great because it’s free and the functionality is built-in to GitHub so there’s no need for an additional account or a complex build pipeline.&lt;/p&gt;

&lt;p&gt;To enable GitHub Pages for your CV, &lt;strong&gt;go to your repository’s Settings page&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xspTaDuO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526111-3aa7ab00-f225-11ea-991e-462f5075f222.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xspTaDuO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526111-3aa7ab00-f225-11ea-991e-462f5075f222.png" alt="Repository's menu bar with a box around Settings."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll until you find the &lt;strong&gt;GitHub Pages section&lt;/strong&gt;. There are two subsections here: Source and Theme Chooser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yUkaZV3H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526194-5c089700-f225-11ea-827f-ac3d8ea70e9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yUkaZV3H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526194-5c089700-f225-11ea-827f-ac3d8ea70e9c.png" alt="GitHub Pages section of the Settings. This will be described later in the article."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under Source, it should say, &lt;em&gt;“GitHub Pages is currently disabled. You must first add content to your repository before you can publish a GitHub Pages site.”&lt;/em&gt; Because your repository is empty, you have no branches and you’re unable to select a source. &lt;em&gt;That’s ok!&lt;/em&gt; This will be taken care of momentarily.&lt;/p&gt;

&lt;p&gt;The subsection you want is &lt;strong&gt;Theme Chooser&lt;/strong&gt;. Here, you’ll select a design template for your site. This will then create a &lt;code&gt;gh-pages&lt;/code&gt; branch and publish your site with your selected theme from that branch. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All of the options are &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; themes. &lt;strong&gt;If you don’t know Jekyll, that’s ok.&lt;/strong&gt; This guide will walk you through the necessary configuration. Honestly, I have no idea how Jekyll works beyond GitHub Pages templates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Select a theme (design template) for your CV
&lt;/h2&gt;

&lt;p&gt;CVs are supposed to give future employers an idea of who you are - so choose a theme that speaks to you! For this guide, we’ll continue with the &lt;strong&gt;“Minimal” theme&lt;/strong&gt; as an example because that’s the one I use for &lt;a href="https://carolstran.github.io/cv/"&gt;my CV&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z-ZA_5ft--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526408-bd306a80-f225-11ea-9d05-aea06ab800a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z-ZA_5ft--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526408-bd306a80-f225-11ea-9d05-aea06ab800a3.png" alt="Theme selection page, with a focus on the Minimal theme. Below the selection bar, there is a preview of this theme."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you select your theme, you’ll be prompted to edit a new &lt;code&gt;index.md&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lu6khbAn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526516-ecdf7280-f225-11ea-9e10-72a637d645fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lu6khbAn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526516-ecdf7280-f225-11ea-9e10-72a637d645fd.png" alt="Markdown editor page with a new index.md file and some boilerplate content."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you dive into that, there are a few things that happened in the background that you should know about…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new &lt;code&gt;gh-pages&lt;/code&gt; branch was created (as mentioned earlier).&lt;/li&gt;
&lt;li&gt;This &lt;code&gt;index.md&lt;/code&gt; file was created. &lt;/li&gt;
&lt;li&gt;Jekyll theme was set to “Minimal”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub Pages confirms your theme selection by creating a file called &lt;strong&gt;&lt;code&gt;_config.yml&lt;/code&gt;&lt;/strong&gt;. By default, this file will only contain a &lt;code&gt;theme&lt;/code&gt; field with your selection. &lt;/p&gt;

&lt;p&gt;Here’s what the &lt;code&gt;_config.yml&lt;/code&gt; will look like if you select the "Minimal" theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jekyll-theme-minimal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For my CV, I also added &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jekyll-theme-minimal&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;💻✒️📄🌟&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Carolyn Stransky's CV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can check out all of the configuration possibilities in the &lt;a href="https://jekyllrb.com/docs/configuration/"&gt;Jekyll documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write your CV in Markdown
&lt;/h2&gt;

&lt;p&gt;Alright, back to the generated file. This is where all of the content for your CV will be.&lt;/p&gt;

&lt;p&gt;First, you should &lt;strong&gt;rename that &lt;code&gt;index.md&lt;/code&gt; file to &lt;code&gt;README.md&lt;/code&gt;&lt;/strong&gt;. This is optional, but having it as a README allows people to see your CV’s content immediately when they visit your repository. This is especially useful if you decide to &lt;a href="https://github.blog/2016-06-16-pin-repositories-to-your-github-profile/"&gt;pin your CV repository to your GitHub profile&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If there’s no &lt;code&gt;index.md&lt;/code&gt; present, then your README will work automatically with GitHub Pages - no additional configuration required.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, you can write your CV ✍🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6AMty4lY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526956-94f53b80-f226-11ea-8b60-a009dfea40de.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6AMty4lY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/26869552/92526956-94f53b80-f226-11ea-8b60-a009dfea40de.png" alt="New file is now named README.md. The boilerplate content has been replaced with personal CV information."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll &lt;a href="https://guides.github.com/features/mastering-markdown/"&gt;write and style your content using Markdown&lt;/a&gt; and then it will be rendered according to your selected theme.&lt;/p&gt;

&lt;p&gt;For tips on how to showcase your skills effectively, I’d recommend Monica Lent’s article: &lt;a href="https://monicalent.com/blog/2020/04/21/software-developer-resume-tips/"&gt;7 software developer resume tips to help you stand out&lt;/a&gt;. If you’re looking for inspiration on how to style your content in Markdown, you can also &lt;a href="https://carolstran.github.io/cv/"&gt;check out my digital CV&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Once you’re satisfied, &lt;strong&gt;commit your changes&lt;/strong&gt; to the &lt;code&gt;gh-pages&lt;/code&gt; branch. &lt;/p&gt;

&lt;h2&gt;
  
  
  Enjoy your new digital CV
&lt;/h2&gt;

&lt;p&gt;It might take a few minutes to go live - but &lt;strong&gt;your fresh, new, digital CV should now be available on the interweb&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;p&gt;In most cases, your page will be hosted at the following url:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;github-username&amp;gt;.github.io/&amp;lt;repository-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can always confirm that your CV is published and what the url is by navigating back to the GitHub Pages section in your repository’s settings.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your digital CV isn’t updating after pushing a commit and waiting a few minutes, try doing a &lt;a href="https://www.getfilecloud.com/blog/2015/03/tech-tip-how-to-do-hard-refresh-in-browsers/#.X1aOftMzafU"&gt;hard refresh&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Optional: Set up a custom domain
&lt;/h2&gt;

&lt;p&gt;Custom domains can help your CV stand out - or alternatively, use your digital CV as a personal website.&lt;/p&gt;

&lt;p&gt;Admittedly I’ve never set up a custom domain for my CV, but there are step-by-step instructions for how to do this in the &lt;a href="https://docs.github.com/en/github/working-with-github-pages/configuring-a-custom-domain-for-your-github-pages-site"&gt;GitHub documentation&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’re not sure where to get domains, I like &lt;a href="https://www.namecheap.com/"&gt;Namecheap&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Show me your CV
&lt;/h2&gt;

&lt;p&gt;If you followed this guide and built a digital CV, I’d love to see it! Tweet me a link &lt;a href="https://twitter.com/intent/tweet?text=Hey%20@carolstran,%20check%20out%20my%20fancy%20new%20digital%20CV"&gt;@carolstran&lt;/a&gt; 💖&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Did you find this helpful or useful? If yes, please consider &lt;a href="https://ko-fi.com/carolstran"&gt;buying me a coffee&lt;/a&gt; so I can continue to write posts like this&lt;/em&gt; ☕️&lt;/p&gt;

</description>
      <category>career</category>
      <category>markdown</category>
      <category>github</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create a mock server for any REST API</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Thu, 06 Aug 2020 15:38:41 +0000</pubDate>
      <link>https://dev.to/meeshkan/create-a-mock-server-for-any-rest-api-592l</link>
      <guid>https://dev.to/meeshkan/create-a-mock-server-for-any-rest-api-592l</guid>
      <description>&lt;p&gt;If you make a REST API call from your codebase then there's a good chance that, at some point, you'll want to write a test for that integration. Instead of &lt;a href="https://dev.to/meeshkan/three-reasons-to-avoid-using-real-web-apis-in-your-integration-tests-1m3"&gt;calling the real API&lt;/a&gt;, it might make sense to use a mock. But manually stubbing data can be time-consuming and doesn't lead to a high level of confidence. &lt;/p&gt;

&lt;p&gt;That's where this tutorial comes in.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how to create a mock server for any REST API. This mock server will generate dynamic, type-based response data that you can use in your tests. You'll do this using the &lt;a href="//https:github.com/meeshkan/hmt"&gt;HTTP Mocking Toolkit (HMT)&lt;/a&gt;, a tool that mocks HTTP APIs for use in automated and exploratory testing. &lt;/p&gt;

&lt;p&gt;As an example, this tutorial uses the &lt;a href="https://ghibliapi.herokuapp.com/"&gt;Studio Ghibli API&lt;/a&gt;, which catalogs the worlds created by Japanese anime studio &lt;a href="http://www.ghibli.jp/"&gt;Studio Ghibli&lt;/a&gt;. Why Studio Ghibli? Because they RULE! &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Steps&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Collect recordings of your API's traffic&lt;/li&gt;
&lt;li&gt;Build an OpenAPI specification from your recordings&lt;/li&gt;
&lt;li&gt;Mock server traffic using your specification&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.python.org/downloads/"&gt;Python 3.6+&lt;/a&gt; installed (no previous Python knowledge is necessary, it's only for installing HMT)&lt;/li&gt;
&lt;li&gt;Familiarity with &lt;a href="https://www.programmableweb.com/api-university/what-are-apis-and-how-do-they-work"&gt;REST APIs&lt;/a&gt; and how they work&lt;/li&gt;
&lt;li&gt;Comfort using the &lt;a href="https://www.davidbaumgold.com/tutorials/command-line/"&gt;command-line&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💻 &lt;strong&gt;References&lt;/strong&gt;: &lt;br&gt;&lt;br&gt;
There's a &lt;a href="https://github.com/meeshkan/studio-ghibli-mock-server"&gt;GitHub repository&lt;/a&gt; that contains a completed Studio Ghibli mock server. You can use it as a reference for this tutorial. &lt;/p&gt;
&lt;h2&gt;
  
  
  Initial setup
&lt;/h2&gt;

&lt;p&gt;Before building the mock server, you first need to create a project directory. This will house your recordings and specifications (explained later in this tutorial).&lt;/p&gt;

&lt;p&gt;Let's do this in the terminal and name it &lt;code&gt;studio-ghibli-mock-server&lt;/code&gt;:&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="nb"&gt;mkdir &lt;/span&gt;studio-ghibli-mock-server
&lt;span class="nb"&gt;cd &lt;/span&gt;studio-ghibli-mock-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (Optional) Create a virtual environment
&lt;/h3&gt;

&lt;p&gt;Using a &lt;a href="https://towardsdatascience.com/why-you-should-use-a-virtual-environment-for-every-python-project-c17dab3b0fd0"&gt;virtual environment&lt;/a&gt; can help keep your packages organized and ensure that you have the correct Python version. For this example, you'll name yours &lt;code&gt;.aichienv&lt;/code&gt; based on &lt;a href="https://www.japantimes.co.jp/news/2020/07/28/national/studio-ghibli-theme-park-construction/"&gt;the location of the new Studio Ghibli theme park&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;First, run the following script to set up a &lt;a href="https://docs.python.org/3/library/venv.html"&gt;venv&lt;/a&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .aichienv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, launch your virtual environment:&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="nb"&gt;source&lt;/span&gt; .aichienv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, check your Python version with &lt;code&gt;python --version&lt;/code&gt;. It should be version 3.6 or higher.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Whenever you're done, you can terminate the virtual environment by running: &lt;code&gt;deactivate&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Install HMT
&lt;/h3&gt;

&lt;p&gt;You can install HMT on the command line using &lt;a href="https://pip.pypa.io/en/stable/installing/"&gt;pip&lt;/a&gt;, a package installer for Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;hmt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For HMT to install and run properly, it &lt;strong&gt;requires Python version 3.6+&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check your HMT version with &lt;code&gt;hmt --version&lt;/code&gt; to make sure the command-line interface (CLI) is installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Collect recordings of your API's traffic
&lt;/h2&gt;

&lt;p&gt;The first step towards creating a mock server is to collect recordings of your API's traffic. That way, our future mock server will know what types of data to mimic.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;record&lt;/code&gt; mode, the HMT CLI can be used to record HTTP API traffic in a format that you can later build into a specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start HMT
&lt;/h3&gt;

&lt;p&gt;To start an HMT server that will record your API traffic, use the &lt;code&gt;hmt record&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hmt record
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts HMT as a reverse proxy on the default port of &lt;code&gt;8000&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To stop HMT without losing any of your data, type &lt;code&gt;Ctrl + C&lt;/code&gt; or another &lt;code&gt;kill&lt;/code&gt; command.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Keep this running. Then, in another terminal window, you can use HMT as a proxy with &lt;a href="https://curl.haxx.se/"&gt;curl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By default, HMT uses path routing to intercept HTTP API calls. Path routing appends the URL you wish to call (&lt;code&gt;https://ghibliapi.herokuapp.com/&lt;/code&gt;) to the end of the URL of the recording server (&lt;code&gt;http://localhost:8000/&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/https://ghibliapi.herokuapp.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HMT will automatically make an API call using the URL in the path - in this case, &lt;code&gt;https://ghibliapi.herokuapp.com/&lt;/code&gt; - and return the response from the called API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run API-specific curl commands
&lt;/h3&gt;

&lt;p&gt;In order for HMT to later mock your API, it needs to understand what kinds of endpoints exist and the associated responses to expect. One way to feed it that information is by using curl.&lt;/p&gt;

&lt;p&gt;There's no minimum or maximum number of calls you should make in order for HMT to accurately record your API traffic. You have to feel it out. A general rule is that you want to record every critical endpoint at least once.&lt;/p&gt;

&lt;p&gt;With the Studio Ghibli API, there's five main endpoints: &lt;a href="https://ghibliapi.herokuapp.com/#tag/Films"&gt;Films&lt;/a&gt;, &lt;a href="https://ghibliapi.herokuapp.com/#tag/People"&gt;People&lt;/a&gt;, &lt;a href="https://ghibliapi.herokuapp.com/#tag/Locations"&gt;Locations&lt;/a&gt;, &lt;a href="https://ghibliapi.herokuapp.com/#tag/Species"&gt;Species&lt;/a&gt;, and &lt;a href="https://ghibliapi.herokuapp.com/#tag/Vehicles"&gt;Vehicles&lt;/a&gt;. You'll want to make sure to call each of those.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/meeshkan/studio-ghibli-mock-server"&gt;The example in the reference repository&lt;/a&gt; alternates between calling the root endpoint and calling a specific field within that endpoint. For thoroughness, here's exactly what was tested:&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="c"&gt;# Films&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/films

&lt;span class="c"&gt;# Film - Castle in the Sky&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/films/2baf70d1-42bb-4437-b551-e5fed5a87abe

&lt;span class="c"&gt;# People&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/people

&lt;span class="c"&gt;# Person - Granny (My Neighbor Totoro)&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/people/08ffbce4-7f94-476a-95bc-76d3c3969c19

&lt;span class="c"&gt;# Locations&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/locations

&lt;span class="c"&gt;# Location - Irontown (Princess Mononoke)&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/locations/11014596-71b0-4b3e-b8c0-1c4b15f28b9a

&lt;span class="c"&gt;# Species&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/species

&lt;span class="c"&gt;# Species - Cats&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/species/603428ba-8a86-4b0b-a9f1-65df6abef3d3

&lt;span class="c"&gt;# Vehicles&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/vehicles

&lt;span class="c"&gt;# Vehicle - Sōsuke's Boat (Ponyo on the Cliff by the Sea)&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/vehicles/923d70c9-8f15-4972-ad53-0128b261d628
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check the recordings file
&lt;/h3&gt;

&lt;p&gt;Running &lt;code&gt;hmt record&lt;/code&gt; will automatically generate two directories: &lt;code&gt;logs&lt;/code&gt; and &lt;code&gt;specs&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;By default, HMT records all traffic to the &lt;code&gt;logs&lt;/code&gt; directory in a file called &lt;code&gt;{hostname}-recordings.jsonl&lt;/code&gt;. &lt;code&gt;{hostname}&lt;/code&gt; refers to your API's host URL and in this case, that's &lt;code&gt;ghibliapi.herokuapp.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How it works is that HMT takes the recorded server traffic and serializes them as JSON objects in the &lt;a href="https://github.com/meeshkan/http-types"&gt;&lt;code&gt;http-types&lt;/code&gt;&lt;/a&gt; format. Then, this is written to a &lt;a href="http://jsonlines.org/"&gt;JSON Lines&lt;/a&gt; file. &lt;/p&gt;

&lt;p&gt;This specific formatting and file type is required for HMT to be able to build an OpenAPI specification in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Build an OpenAPI specification from your recordings
&lt;/h2&gt;

&lt;p&gt;Using the HMT CLI, you can build an &lt;a href="https://swagger.io/specification/"&gt;OpenAPI specification&lt;/a&gt; that describes how your API works. This is built from that &lt;code&gt;.jsonl&lt;/code&gt; file generated by the &lt;code&gt;record&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;On the command-line, you'll run &lt;code&gt;hmt build&lt;/code&gt; with the &lt;code&gt;--input-file&lt;/code&gt; flag followed by the path to your recordings file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hmt build &lt;span class="nt"&gt;--input-file&lt;/span&gt; logs/ghibliapi.herokuapp.com-recordings.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This uses the default build command. To see the other options, run &lt;code&gt;hmt build --help&lt;/code&gt; or check out the &lt;a href="https://github.com/meeshkan/hmt/blob/master/docs/BUILD.md"&gt;HMT build documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By default, HMT builds a new OpenAPI specification (called &lt;code&gt;openapi.json&lt;/code&gt;) in the &lt;code&gt;specs&lt;/code&gt; directory from earlier. Once you've generated the specification, you can use that to create a mock server.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Mock server traffic using your specification
&lt;/h2&gt;

&lt;p&gt;Now you can use your &lt;code&gt;openapi.json&lt;/code&gt; and a different HMT command to create a mock server. &lt;/p&gt;

&lt;p&gt;All it takes is &lt;code&gt;hmt mock&lt;/code&gt; followed by the path to the directory or file where your OpenAPI specification is (for this example, that's &lt;code&gt;specs/&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hmt mock specs/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep this running. Then, in another terminal window, make another curl request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/https://ghibliapi.herokuapp.com/people/08ffbce4-7f94-476a-95bc-76d3c3969c19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Yes, you read that right - it's almost identical to the command that you ran earlier after launching &lt;code&gt;hmt record&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the same command we ran in the second step for Granny from My Neighbor Totoro. But our server won't return Granny's exact data. Instead, it'll return the same character response fields from the Studio Ghibli API with mock data for the values based on their types. &lt;/p&gt;

&lt;p&gt;Here's an example of what this response could look like:&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;{&lt;/span&gt;
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"Bradley Joseph"&lt;/span&gt;,
  &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Jeremy Vasquez"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"gender"&lt;/span&gt;: &lt;span class="s2"&gt;"Jodi Francis"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"age"&lt;/span&gt;: &lt;span class="s2"&gt;"Karen Booth"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"eye_color"&lt;/span&gt;: &lt;span class="s2"&gt;"Andre Mcclure"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"hair_color"&lt;/span&gt;: &lt;span class="s2"&gt;"Brandon Freeman"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"films"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"Stephanie Campbell"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Paul Young"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Catherine Gonzalez DDS"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Charles Dean"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Jackson Smith"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Alexander Manning"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Anthony Reed"&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;, 
  &lt;span class="s2"&gt;"species"&lt;/span&gt;: &lt;span class="s2"&gt;"Jasmine Davis"&lt;/span&gt;,
  &lt;span class="s2"&gt;"url"&lt;/span&gt;: &lt;span class="s2"&gt;"David Olson"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Because this data is generated, there's a good chance that yours will be different if you're following along. Although the strings almost always seem to be random names 😅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There you have it, your very own mock server 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tutorial ran through the entire HMT flow: &lt;strong&gt;Collect&lt;/strong&gt;, &lt;strong&gt;build&lt;/strong&gt;, and &lt;strong&gt;mock&lt;/strong&gt;. First, you collected data by recording server traffic from the Studio Ghibli API. Then, you built an OpenAPI specification based on that data. Finally, you used that specification to spin up a Studio Ghibli mock server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to see the code for the final mock server, check out the &lt;a href="https://github.com/meeshkan/studio-ghibli-mock-server"&gt;example repository on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are many customization options for your mock server - such as custom callback scripts, format options, and response types. You can find out more in the &lt;a href="https://github.com/meeshkan/hmt/blob/master/docs/MOCK.md"&gt;HMT documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;HMT is actively maintained by our team at Meeshkan. It's also open-source 🎉 If you run into any problems with the product or have questions, please &lt;a href="https://github.com/meeshkan/hmt/issues/new/choose"&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>testing</category>
      <category>api</category>
    </item>
    <item>
      <title>Finding and fixing bugs in your tests with fast-check</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Mon, 27 Jul 2020 13:59:20 +0000</pubDate>
      <link>https://dev.to/meeshkan/finding-and-fixing-bugs-in-your-tests-with-fast-check-5036</link>
      <guid>https://dev.to/meeshkan/finding-and-fixing-bugs-in-your-tests-with-fast-check-5036</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post assumes that you have a solid understanding of JavaScript. You should also know the basics of &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2"&gt;property-based testing&lt;/a&gt; and the &lt;a href="https://dubzzz.github.io/fast-check/"&gt;fast-check framework&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently, we published &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2"&gt;Property-based testing for JavaScript developers&lt;/a&gt;. In it, we introduced &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2#what-your-existing-test-suite-probably-looks-like-and-is-missing"&gt;an issue to show the limitations of example-based testing&lt;/a&gt;. Throughout the rest of the guide, we provided examples of how to use fast-check and other property-based testing principles.&lt;/p&gt;

&lt;p&gt;But we didn't offer a fix to that initial testing bug.&lt;/p&gt;

&lt;p&gt;We've been told that this is unsatisfying, so consider this post our redemption.&lt;/p&gt;

&lt;p&gt;💻 The tests featured in this post are available in the &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs/blob/main/tests/getNumberIntl.test.js"&gt;corresponding GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of the bug in our test
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're already familiar with the referenced issue, skip to the solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine you have an input where users write in a price - but this input is &lt;code&gt;type="text"&lt;/code&gt; rather than &lt;code&gt;type="number"&lt;/code&gt;. So you need to create a function (&lt;code&gt;getNumber&lt;/code&gt;) that converts the input string into a number and an accompanying test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputString&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&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 passes 🎉&lt;/p&gt;

&lt;p&gt;Now imagine your website also operates in Germany where the meaning of commas and decimals in numbers are switched (i.e. $1,200.99 in English would be $1.200,99 in German).&lt;/p&gt;

&lt;p&gt;So you add another test case to address this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// English test case&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// German test case&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;19,95&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;19.95&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;But when you run the test, you hit an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;expect&lt;span class="o"&gt;(&lt;/span&gt;received&lt;span class="o"&gt;)&lt;/span&gt;.toBe&lt;span class="o"&gt;(&lt;/span&gt;expected&lt;span class="o"&gt;)&lt;/span&gt; // Object.is equality

Expected: 19.95
Received: NaN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Assuming that your website and input are equipped to handle various locales and localized strings, this would be a limitation of your tests - not a bug in your app.&lt;/p&gt;

&lt;p&gt;There's something that can help though: &lt;strong&gt;Property-based testing&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing this bug with fast-check
&lt;/h2&gt;

&lt;p&gt;To solve this problem, let's use &lt;a href="https://dubzzz.github.io/fast-check/"&gt;fast-check&lt;/a&gt;, a JavaScript framework for generative test cases. Our goal is to test that our function turns any valid input string into a number, regardless of locale.&lt;/p&gt;

&lt;p&gt;First, we need to pick the &lt;strong&gt;property&lt;/strong&gt; (or properties) to test for in this situation. There a couple of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It works with strings that aren't formatted.&lt;/li&gt;
&lt;li&gt;It works with strings that are formatted using one of the accepted locales (in this case, that would be German).&lt;/li&gt;
&lt;li&gt;A combination of the two.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll tackle the latter: A combination of formatted and non-formatted strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spoiler alert: Final solution
&lt;/h3&gt;

&lt;p&gt;Here's a peek at what our test will look like by the end of this post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns any valid input string into a number, regardless of locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr-FR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floatString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatString&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="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 is a lot all at once. So let's go through it step-by-step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our test
&lt;/h3&gt;

&lt;p&gt;To begin, we need to set up our test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns any valid input string into a number, regardless of locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="c1"&gt;// Everything else will go here!&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;blockquote&gt;
&lt;p&gt;Note: This test uses the &lt;code&gt;assert&lt;/code&gt; and &lt;code&gt;property&lt;/code&gt; fast-check functions. If you need a refresher, these are both covered in our &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2"&gt;JavaScript property-based testing guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Applying our properties
&lt;/h3&gt;

&lt;p&gt;To test a combination of formatted and non-formatted strings, we need to pass two different arbitraries to &lt;code&gt;property&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first will be &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/float_1"&gt;&lt;code&gt;float&lt;/code&gt;&lt;/a&gt; to generate the floating-point numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The second is also a combination of sorts. To start, we need to write a &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/constantFrom_1"&gt;&lt;code&gt;constantFrom&lt;/code&gt; function&lt;/a&gt; that takes in multiple, equally probable values. We'll use this for our German locale: &lt;code&gt;de-DE&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="cm"&gt;/* This is where you'd pass another locale */&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, we'll wrap &lt;code&gt;constantFrom&lt;/code&gt; in the &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/option_1"&gt;&lt;code&gt;option&lt;/code&gt; function&lt;/a&gt;. With &lt;code&gt;option&lt;/code&gt;, the complete arbitrary will return either &lt;code&gt;null&lt;/code&gt; (a stand-in for the English default) or our values from &lt;code&gt;constantFrom&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Prices in these locales only go to the second decimal place and we want to embody this in our test.&lt;/p&gt;

&lt;p&gt;To do this, we'll take the &lt;code&gt;testFloat&lt;/code&gt; value and use JavaScript's built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed"&gt;&lt;code&gt;toFixed&lt;/code&gt; method&lt;/a&gt; on it. The &lt;code&gt;2&lt;/code&gt; value indicates how many decimal places we want.&lt;/p&gt;

&lt;p&gt;This method returns a string, but we need a number for our final assertion. So we'll wrap it in another built-in function, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat"&gt;&lt;code&gt;parseFloat&lt;/code&gt;&lt;/a&gt;, and name this variable &lt;code&gt;fixedFloat&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we'll pass two arguments to the &lt;code&gt;property&lt;/code&gt; callback: &lt;code&gt;testFloat&lt;/code&gt; (representing each generated floating-point number) and &lt;code&gt;locale&lt;/code&gt; (representing the generated locale from our &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;constantFrom&lt;/code&gt; combination).&lt;/p&gt;

&lt;p&gt;Altogether, our &lt;code&gt;property&lt;/code&gt; function will look like this so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&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;// More to come!&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Processing the strings
&lt;/h3&gt;

&lt;p&gt;Because we're testing both formatted and non-formatted strings, we need a way to differentiate these two string types.&lt;/p&gt;

&lt;p&gt;We'll create a variable called &lt;code&gt;floatString&lt;/code&gt; that checks if there is a &lt;code&gt;locale&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;locale !== null&lt;/code&gt;, then we need to create a localized string based on the generated float.&lt;/p&gt;

&lt;p&gt;To do this, we'll use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat"&gt;&lt;code&gt;Intl.NumberFormat&lt;/code&gt; constructor&lt;/a&gt; and pass in our &lt;code&gt;locale&lt;/code&gt; value. On top, we'll chain on the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/format"&gt;&lt;code&gt;format&lt;/code&gt; method&lt;/a&gt; with our &lt;code&gt;fixedFloat&lt;/code&gt; value from earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&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;Note: This constructor should mimic existing functionality in your app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If &lt;code&gt;locale&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;, then we'll use the built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString"&gt;&lt;code&gt;toString&lt;/code&gt; method&lt;/a&gt; on &lt;code&gt;fixedFloat&lt;/code&gt;, which returns it as a string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The resulting &lt;code&gt;floatString&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floatString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding your assertion
&lt;/h3&gt;

&lt;p&gt;At last, we need the most crucial part of any test: The assertion.&lt;/p&gt;

&lt;p&gt;The following &lt;a href="https://jestjs.io/docs/en/expect"&gt;&lt;code&gt;expect&lt;/code&gt; statement&lt;/a&gt; indicates that when you pass the &lt;code&gt;floatString&lt;/code&gt; (formatted or not) to the &lt;code&gt;getNumber&lt;/code&gt; function, you expect it to equal the &lt;code&gt;fixedFloat&lt;/code&gt; number value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatString&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;After all that, you're back to that final result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns any valid input string into a number, regardless of locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr-FR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floatString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatString&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&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;Reminder: You can check out the code in our &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs/blob/main/tests/getNumberIntl.test.js"&gt;accompanying GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now your tests are more thorough and resilient 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Special thanks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/dubzzz/"&gt;Nicolas Dubien&lt;/a&gt;, the creator of fast-check, was the first to flag this issue in the original guide. He also helped develop the solution. You're the best, Nicolas!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a better solution? Comment below or &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs"&gt;open a pull request&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>debugging</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Testing apps with third-party integrations</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Fri, 24 Jul 2020 15:31:32 +0000</pubDate>
      <link>https://dev.to/meeshkan/testing-apps-with-third-party-integrations-35m9</link>
      <guid>https://dev.to/meeshkan/testing-apps-with-third-party-integrations-35m9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post assumes that you're familiar with &lt;a href="https://www.programmableweb.com/api-university/what-are-apis-and-how-do-they-work"&gt;APIs&lt;/a&gt; and have a basic understanding of testing. It's also based on a &lt;a href="https://www.youtube.com/watch?v=KFiSEQtTdpk&amp;amp;t=779s"&gt;presentation by Mike Solomon&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you’re working with the latest technologies or fighting against legacy code, you'll likely need to make a call to an API. And even more likely, this will be an API that you don't maintain.&lt;/p&gt;

&lt;p&gt;Reliance on external services is becoming more prevalent in our engineering ecosystem. As a result, we need cost-effective, secure, and reliable ways to test how our app interacts with these services.&lt;/p&gt;

&lt;p&gt;In this post, we'll examine some strategies and available tools for testing apps that use third-party integrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: If you don't have time to write tests but want to be sure your apps are covered, use an automated testing tool like Meeshkan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you test third-party integrations?
&lt;/h2&gt;

&lt;p&gt;The way we build apps has changed a lot in the past two decades. At the beginning of the 2000s, when you ran into a problem or needed a specific service, you had to build it yourself.&lt;/p&gt;

&lt;p&gt;Now, there's an API for almost everything. SendGrid for emails, Auth0 for authentication, Stripe for payments, and the list goes on. The &lt;a href="https://www.programmableweb.com/apis/directory"&gt;Programmable Web API Directory&lt;/a&gt; has over 23,000 different APIs available for use. Even &lt;a href="https://www.programmableweb.com/api/myspace-rest-api"&gt;MySpace has its own set of realtime REST APIs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But using a third-party integration that you didn't build and don't maintain is risky.&lt;/p&gt;

&lt;p&gt;You need to be sure that the calls you're making to these APIs are reliable and serving the expected data. That's why you should test them.&lt;/p&gt;

&lt;p&gt;There are a few different options for how to test these external services. Let’s start with the most common and walk-through some of the issues they can cause.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three common (but misguided) ways to test APIs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Do nothing
&lt;/h3&gt;

&lt;p&gt;Don't write tests - or comment them out when you write them and they don't work.&lt;/p&gt;

&lt;p&gt;If this is you, don't be ashamed.&lt;/p&gt;

&lt;p&gt;There's an entire economy around helping you solve issues that arise when you don't test your code. There are also products designed to test your apps when you understand the importance but don't want to manually write any (more on that later in this post).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Using the real APIs
&lt;/h3&gt;

&lt;p&gt;We have another blog post that highlights the &lt;a href="https://meeshkan.com/blog/why-not-use-real-apis-in-tests/"&gt;three primary reasons to not use the real APIs in tests&lt;/a&gt;. It covers security, integrity, and speed.&lt;/p&gt;

&lt;p&gt;But there are also lots of unfortunate scenarios that can happen when you use the real APIs in a &lt;a href="https://www.infoworld.com/article/3271126/what-is-cicd-continuous-integration-and-continuous-delivery-explained.html"&gt;CI/CD pipeline&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During the research for his initial talk, Mike Solomon collected horror stories from developers who have used real APIs in their tests. Here are two of those.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“I want you back”&lt;/strong&gt;&lt;br&gt;
One company accidentally embedded a Twilio API key in their CI environment. This caused some poor person in Kansas to receive dozens of text messages a day saying “I want you back &amp;lt;3”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;OR 1=1&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Another testing engineer created a fake username called &lt;code&gt;OR 1=1&lt;/code&gt; (a common &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/SQL_Injection"&gt;SQL injection&lt;/a&gt;). This username got sent repeatedly to a production API and the organization was banned from using the service.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Reverse engineering the API
&lt;/h3&gt;

&lt;p&gt;This option is the least dangerous, but the most time-consuming.&lt;/p&gt;

&lt;p&gt;When you create a reverse-engineered version of the API you're testing, it comes at a cost. For instance, sinking more time into writing a test script than you did the feature you're testing. Or the stubbed API data ends up being longer than the code you're testing. It's also difficult to maintain unless you endlessly monitor the changelog of that external API.&lt;/p&gt;

&lt;p&gt;None of these options are great, so let's look at more reliable strategies for testing your third-party integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better ways to test third-party integrations
&lt;/h2&gt;

&lt;p&gt;It'd be cruel to leave you without a solution, so outlined below are two cost-effective, secure options for your tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write your tests with a mocking library
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;mock&lt;/strong&gt; is a substitute for a service that mimics the original functionality. Or at least the functionality that you're aiming to test.&lt;/p&gt;

&lt;p&gt;In this case, the mock acts as a replacement for your third-party integration. That way, you don't need to make a network call from your tests. This helps make your test resilient when the network is down or slow and enables you to specify and test corner cases. Plus mocks are often less complicated to access and maintain.&lt;/p&gt;

&lt;p&gt;There are some libraries you can use to write your mocks. We recently published a post &lt;a href="https://meeshkan.com/blog/unmock-vs-nock/"&gt;comparing two JavaScript mocking libraries - nock and unmock&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ve loved and used this approach ourselves (I mean, we built &lt;a href="https://github.com/meeshkan/unmock-js"&gt;unmock&lt;/a&gt;). There are still issues with this approach though. Namely, that you have to manually write all the tests - even if the input values are generated.&lt;/p&gt;

&lt;p&gt;This can be tedious and take a lot of time. So that’s where the second option comes in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a service (like Meeshkan) to test your apps
&lt;/h3&gt;

&lt;p&gt;Yes, this is a product plug - but with good reason.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://meeshkan.com/"&gt;Meeshkan&lt;/a&gt; for those of you reading this post and wondering who has time to write tests. Our automated testing service executes and reports on a collection of generated tests. These tests are designed to imitate any third-party integrations you're working with using &lt;a href="https://meeshkan.com/docs/how-meeshkan-works/"&gt;schemas and a bit of NLP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All you need to do is authorize our GitHub app, choose a repository test, and set up your base configuration.&lt;/p&gt;

&lt;p&gt;Sound good? &lt;a href="https://meeshkan.com/"&gt;Request beta access today&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Property-based testing for JavaScript developers</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Fri, 17 Jul 2020 17:00:25 +0000</pubDate>
      <link>https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2</link>
      <guid>https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Special thanks to &lt;a href="https://github.com/dubzzz/"&gt;Nicolas Dubien&lt;/a&gt; for sharing his generative JavaScript testing wisdom with me before I began writing this guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All experienced frontend developers know one thing to be true: &lt;em&gt;Users are unpredictable.&lt;/em&gt; No matter how much user research you conduct or how thick the font-weight is on your input label, you can never be certain how users will interact with your product. That’s why, as the creators of the interface, we put in constraints. And to ensure that those constraints work properly, we write tests.&lt;/p&gt;

&lt;p&gt;But there's a problem with traditional unit and integration tests. &lt;/p&gt;

&lt;p&gt;They require us to manually think of and write every scenario that our tests will cover. Not only does this take &lt;em&gt;a lot&lt;/em&gt; of time, but it also limits the test coverage to our imaginations. Whereas users, as we know, are unpredictable. So we need a way to test our software to withstand an unlimited number of potential user flows.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;property-based testing&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;Within this guide, we’ll explain the must-knows of property-based testing in JavaScript. We'll walk through practical examples and you'll write your first test using the &lt;a href="https://dubzzz.github.io/fast-check/"&gt;fast-check&lt;/a&gt; framework. Finally, we'll touch on what other property-based testing frameworks are out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in this guide
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Property-based testing in JavaScript: What and why&lt;/li&gt;
&lt;li&gt;Differences between property-based and example-based tests&lt;/li&gt;
&lt;li&gt;What your existing test suite probably looks like (and is missing)&lt;/li&gt;
&lt;li&gt;Choosing which properties to test for&lt;/li&gt;
&lt;li&gt;Writing your first property-based test with fast-check&lt;/li&gt;
&lt;li&gt;Available property-based testing frameworks&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A solid understanding of what unit tests are.&lt;/li&gt;
&lt;li&gt;Familiarity with &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; or another JavaScript testing framework.&lt;/li&gt;
&lt;li&gt;(Optional) &lt;a href="https://www.npmjs.com/get-npm"&gt;NPM&lt;/a&gt; or &lt;a href="https://yarnpkg.com/lang/en/docs/install/#mac-stable"&gt;Yarn&lt;/a&gt; installed if you want to follow along in your IDE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🐍 Prefer Python? A similar guide is available to help you learn &lt;a href="https://meeshkan.com/blog/property-based-testing-python/"&gt;property-based testing in Python&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;References&lt;/strong&gt;: &lt;br&gt;&lt;br&gt;
We've created a &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs/"&gt;GitHub repository&lt;/a&gt; to accompany this guide. This repository includes all of the featured tests with instructions for how to execute them. It also provides more resources for learning property-based testing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Property-based testing in JavaScript: What and why
&lt;/h2&gt;

&lt;p&gt;Software testing as we know it today requires a lot of time and imagination. When you're writing traditional example-based tests, you're stuck trying to manually reproduce every action that a user &lt;em&gt;might&lt;/em&gt; make.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property-based testing&lt;/strong&gt; is a different approach to writing tests designed to accomplish more in less time. This is because instead of manually creating the exact values to be tested, it's done automatically by the framework you're using. That way, you can run hundreds or even thousands of test cases in the same amount of time it takes you to write one &lt;code&gt;expect&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;As the developer writing the tests, what you have to do is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specify what type of values the framework should generate (i.e. integers or strings).&lt;/li&gt;
&lt;li&gt;Assert those values on guarantees (or &lt;strong&gt;properties&lt;/strong&gt;) that are true regardless of the exact value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll cover how to choose which properties to test for later in this guide. But before going any further, let's talk about why you would want to integrate property-based testing into your workflow.&lt;/p&gt;

&lt;p&gt;Nicolas Dubien, the creator of the fast-check framework we're exploring in this guide, wrote a post outlining &lt;a href="https://medium.com/criteo-labs/introduction-to-property-based-testing-f5236229d237"&gt;the primary benefits of property-based testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To summarize his words, property-based testing enables developers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cover the entire scope of possible inputs&lt;/strong&gt;: Unless you specifically tell it to, property-based testing frameworks don't restrict the generated values. As a result, they test for the full spectrum of possible inputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shrink the input when tests fail&lt;/strong&gt;: Shrinking is a fundamental part of property-based testing. Each time a test fails, the framework will continue to reduce the input (i.e. removing characters in a string) to pinpoint the exact cause of the failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproduce and replay test runs&lt;/strong&gt;: Whenever a test case is executed, a seed is created. This allows you to replay the test with the same values and reproduce the failing case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this guide, we'll focus on that first benefit: Covering the entire scope of possible inputs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Differences between property-based and example-based tests
&lt;/h2&gt;

&lt;p&gt;Even with the limitations mentioned, traditional example-based tests are likely to remain the norm in software testing. And that's ok because property-based tests aren't meant to replace example-based ones. These two test types can, and very likely will, co-exist in the same codebase.&lt;/p&gt;

&lt;p&gt;While they may be based on different concepts, property-based and example-based tests have many similarities. This becomes evident when you do a side-by-side comparison of the steps necessary to write a given test:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property-based&lt;/th&gt;
&lt;th&gt;Example-based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Define data type matching a specification&lt;/td&gt;
&lt;td&gt;1. Set up some example data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Perform some operations on the data&lt;/td&gt;
&lt;td&gt;2. Perform some operations on the data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Assert properties about the result&lt;/td&gt;
&lt;td&gt;3. Assert a prediction about the result&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At its core, property-based testing is meant to provide an additional layer of confidence to your existing test suite and maybe reduce the number of boilerplate tests. So if you're looking to try out property-based testing but don't want to rewrite your entire test suite, don't worry.&lt;/p&gt;
&lt;h2&gt;
  
  
  What your existing test suite probably looks like (and is missing)
&lt;/h2&gt;

&lt;p&gt;Because property-based tests are meant to fill the coverage gaps missed by traditional testing, it's important to understand how these example-based tests work and their downfalls.&lt;/p&gt;

&lt;p&gt;Let's start with a definition: &lt;strong&gt;Example-based testing&lt;/strong&gt; is when you test for a given argument and expect to get a known return value. This return value is known because you provided the exact value to the assertion. So when you run the function or test system, it then asserts the actual result against that return value you designated.&lt;/p&gt;

&lt;p&gt;Enough theory, let's write a test.&lt;/p&gt;

&lt;p&gt;Imagine you have an input where users write in a number indicating an item's price. This input, however, is &lt;code&gt;type="text"&lt;/code&gt; rather than &lt;code&gt;type="number"&lt;/code&gt; (trust me, it happens, I've seen it). So you need to create a function (&lt;code&gt;getNumber&lt;/code&gt;) that converts the input string into a number using JavaScript's built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"&gt;&lt;code&gt;Number()&lt;/code&gt; function&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// getNumber.test.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputString&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that you have your &lt;code&gt;getNumber&lt;/code&gt; function, let's test it.&lt;/p&gt;

&lt;p&gt;To test this using example-based testing, you need to provide the test function with manually created input and return values that you know will pass. For example, the string &lt;code&gt;"35"&lt;/code&gt; should return the number &lt;code&gt;35&lt;/code&gt; after passing through your &lt;code&gt;getNumber&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// getNumber.test.js&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;35&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&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;blockquote&gt;
&lt;p&gt;Note: To run this test on your IDE, you'll need to have &lt;a href="https://jestjs.io/docs/en/getting-started"&gt;Jest&lt;/a&gt; installed and configured.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And with that, you have a passing example-based test 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Recognizing the limitations of example-based testing
&lt;/h3&gt;

&lt;p&gt;There are many situations where an example-based test like this would work well and be enough to cover what you need. &lt;/p&gt;

&lt;p&gt;But there can be downsides. &lt;/p&gt;

&lt;p&gt;When you have to create every test case yourself, you're only able to test as many cases as you're willing to write. The less you write, the more likely it is that your tests will miss catching bugs in your code.&lt;/p&gt;

&lt;p&gt;To show how this could be a problem, let's revisit your test for the &lt;code&gt;getNumber&lt;/code&gt; function. It has two of the most common ways to write a price value (whole number and with a decimal):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// getNumber.test.js&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;35&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&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;Both of these test cases pass. So if you only tested these two values, you might believe that the &lt;code&gt;getNumber&lt;/code&gt; function always returns the desired result.&lt;/p&gt;

&lt;p&gt;That's not necessarily the case though. For instance, let's say your website with this price input also operates in Germany, where the meaning of commas and decimals in numbers are switched (i.e. $400,456.50 in English would be $400.456,50 in German).&lt;/p&gt;

&lt;p&gt;So you add a third test case to address this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// getNumber.test.js&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;35&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// Add a new test case:&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;19,95&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;19.95&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;But when you run the test... you hit a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN"&gt;Not-A-Number error&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;expect&lt;span class="o"&gt;(&lt;/span&gt;received&lt;span class="o"&gt;)&lt;/span&gt;.toBe&lt;span class="o"&gt;(&lt;/span&gt;expected&lt;span class="o"&gt;)&lt;/span&gt; // Object.is equality

Expected: 19.95
Received: NaN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Turns out the &lt;code&gt;getNumber&lt;/code&gt; function doesn't work as expected when the input string contains a value or specific characters that &lt;code&gt;Number()&lt;/code&gt; doesn't recognize. The same error occurs with inputs like &lt;code&gt;twenty&lt;/code&gt; or &lt;code&gt;$50&lt;/code&gt;. Maybe you already knew that, but maybe you would've never known that without a specific test case.&lt;/p&gt;

&lt;p&gt;🐛🚨 This is one example of how property-based testing can be used to find bugs in your software. Once you realize that any string with a character that &lt;code&gt;Number()&lt;/code&gt; doesn't recognize will return &lt;code&gt;NaN&lt;/code&gt; - you might reconsider how you built that input. Adding the attribute &lt;code&gt;type="number"&lt;/code&gt; to the input restricts the possible values that users can enter and, hopefully, helps reduce bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing which properties to test for
&lt;/h2&gt;

&lt;p&gt;Issues like the one faced with the input type also help you write your property-based tests because then it's more clear what the property you're testing for actually is.&lt;/p&gt;

&lt;p&gt;Let's dig into this. In property-based testing, a &lt;strong&gt;property&lt;/strong&gt; is an aspect of the function being tested that's always true, regardless of the exact input.&lt;/p&gt;

&lt;p&gt;If you look at the &lt;code&gt;getNumber&lt;/code&gt; function from earlier, one property you'd test would be the string that is passed to &lt;code&gt;getNumber&lt;/code&gt;. Regardless of whether that input value ends up being &lt;code&gt;"59.99"&lt;/code&gt;, &lt;code&gt;"twenty"&lt;/code&gt;, or &lt;code&gt;"$50"&lt;/code&gt; - it will always be a string.&lt;/p&gt;

&lt;p&gt;Some other examples of properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;List length&lt;/em&gt; when testing the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort"&gt;&lt;code&gt;sort()&lt;/code&gt; method&lt;/a&gt; on an array. The length of the sorted list should always be the same as the original list, regardless of the specific list items.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Date&lt;/em&gt; when testing a method for the Date object like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toDateString"&gt;&lt;code&gt;toDateString()&lt;/code&gt;&lt;/a&gt;. No matter the specifics entered, it will always be a date.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Writing your first property-based test with fast-check
&lt;/h2&gt;

&lt;p&gt;To put property-based testing into practice, let's create an example test using &lt;a href="https://dubzzz.github.io/fast-check/"&gt;fast-check&lt;/a&gt;, a JavaScript framework for generative test cases.&lt;/p&gt;

&lt;p&gt;Let's use the &lt;code&gt;getNumber&lt;/code&gt; function from earlier. As a reminder, here's what that looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// getNumber.test.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputString&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let's write a property-based test using fast-check. To limit the scope, you'll only generate input strings with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"&gt;floating-point numbers&lt;/a&gt; because values with decimals are more common in prices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structuring your tests
&lt;/h3&gt;

&lt;p&gt;When getting started with fast-check, you first have to set up the base structure of your tests.&lt;/p&gt;

&lt;p&gt;Initially, it'll look identical to any other Jest test. It starts with the &lt;a href="https://jestjs.io/docs/en/api#testname-fn-timeout"&gt;&lt;code&gt;test&lt;/code&gt; global method&lt;/a&gt; and its two arguments: A string for describing the test suite and a callback function for wrapping the actual test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns an input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Your property-based test will go here!&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Introducing fast-check
&lt;/h3&gt;

&lt;p&gt;Next, you'll import the framework and introduce your first fast-check function: &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/assert_1"&gt;&lt;code&gt;assert&lt;/code&gt;&lt;/a&gt;. This function executes the test and accepts two arguments: The property that you're testing and any optional parameters. In this case, you'll use the &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/property_1"&gt;&lt;code&gt;property&lt;/code&gt;&lt;/a&gt; function to declare the property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fast-check&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns an input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* Your specific property and expect statement will go here */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing your chosen properties
&lt;/h3&gt;

&lt;p&gt;Finally, you'll add the details of the specific values you want to generate. There's an entire &lt;a href="https://dubzzz.github.io/fast-check/#/1-Guides/Arbitraries"&gt;list of built-in arbitraries&lt;/a&gt; (aka generated datatypes) provided by fast-check. As mentioned previously, this test will cover input strings with floating-point numbers. There are &lt;a href="https://dubzzz.github.io/fast-check/#/1-Guides/Arbitraries?id=numeric-number"&gt;multiple arbitraries for generating floating-point numbers&lt;/a&gt;, but this test will use &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/float_1"&gt;&lt;code&gt;float&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;float&lt;/code&gt; arbitrary will be passed as the first argument of the &lt;code&gt;property&lt;/code&gt; function, followed by a callback wrapping the &lt;a href="https://jestjs.io/docs/en/expect"&gt;&lt;code&gt;expect&lt;/code&gt; statement&lt;/a&gt; and any other logic necessary for executing the test.&lt;/p&gt;

&lt;p&gt;In this test, &lt;code&gt;testFloat&lt;/code&gt; represents each floating-point number generated by fast-check and it's then passed as an argument to the callback. The &lt;code&gt;expect&lt;/code&gt; statement indicates that when you pass the &lt;code&gt;testFloat&lt;/code&gt; as a string to your &lt;code&gt;getNumber&lt;/code&gt; function, you expect it to return the same &lt;code&gt;testFloat&lt;/code&gt; value as a number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns an input string into a number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;testFloat&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And there you have it, your first property-based test 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Examining the generated values
&lt;/h3&gt;

&lt;p&gt;By default, the property check will be run against 100 generated inputs. For many arbitraries, you can also &lt;a href="https://dubzzz.github.io/fast-check/#/1-Guides/Arbitraries"&gt;set a minimum or maximum number of generated inputs&lt;/a&gt;. At first, running hundreds of test cases might feel excessive - but these numbers are reasonable (and even considered low) in the property-based testing realm.&lt;/p&gt;

&lt;p&gt;Going back to the example test, you can peek at the generated input values using fast-check's &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/sample_1?id=sample-function"&gt;&lt;code&gt;sample&lt;/code&gt; function&lt;/a&gt;. This function takes in an arbitrary or property and the number of values to extract. It then constructs an array containing the values that would be generated in your test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you wrap the previous function in a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Console/log"&gt;&lt;code&gt;console.log()&lt;/code&gt;&lt;/a&gt; statement, you'll get something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;7.1525
1.3996
0.8122
0.0004
3.5762
0
5.9604
9.5367
0.1504
8.3446
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Your numbers will likely be different - and that's ok. You also might not want to log a bunch of random numbers in your terminal - and that's ok too. You can take our word for it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Available property-based testing frameworks
&lt;/h2&gt;

&lt;p&gt;We opted to use the &lt;a href="https://github.com/dubzzz/fast-check"&gt;fast-check&lt;/a&gt; framework for this guide, but there are many other options out there to help you write property-based tests in a variety of programming languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jsverify/jsverify"&gt;JSVerify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mcandre/node-quickcheck"&gt;node-quickcheck&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other languages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hypothesis.readthedocs.io/en/latest/"&gt;Hypothesis&lt;/a&gt;: Python (used in &lt;a href="https://dev.to/blog/property-based-testing-python/"&gt;our Python guide&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fscheck.github.io/FsCheck/"&gt;FsCheck&lt;/a&gt;: .NET&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jqwik.net/"&gt;jqwik&lt;/a&gt;: Java&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/alfert/propcheck"&gt;PropCheck&lt;/a&gt;: Elixir&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/AltSysrq/proptest"&gt;Proptest&lt;/a&gt;: Rust&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://proper-testing.github.io/"&gt;PropEr&lt;/a&gt;: Erlang&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/emil-e/rapidcheck"&gt;RapidCheck&lt;/a&gt;: C++&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hackage.haskell.org/package/QuickCheck"&gt;QuickCheck&lt;/a&gt;: Haskell&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.rs/quickcheck/0.9.2/quickcheck/"&gt;QuickCheck ported to Rust&lt;/a&gt;: Rust&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/typelevel/scalacheck"&gt;ScalaCheck&lt;/a&gt;: Scala&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While it won't replace example-based tests, property-based testing can supply additional coverage where traditional tests fall short. One of the benefits of property-based testing is that it helps cover the entire scope of possible inputs for any given function. We explored that benefit throughout this guide by creating a &lt;code&gt;getNumber&lt;/code&gt; function and writing a test that uses a generative floating-point number property.&lt;/p&gt;

&lt;p&gt;This guide wasn't intended to be a series, but the possibility of future guides about shrinking, replaying tests, property-based testing in TypeScript, or our favorite fast-check features emerged during our research. If that sounds interesting to you, comment below or &lt;a href="https://twitter.com/intent/tweet?text=Hey%20%40meeshkan%2C%20I%20just%20finished%20your%20guide%20to%20property-based%20testing%20in%20JavaScript%20and%20I%27d%20love%20to%20see%20a%20follow%20up%20on...%20https%3A%2F%2Fmeeshkan.com%2Fblog%2Fproperty-based-testing-javascript%2F"&gt;tweet at us&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://meeshkan.com/"&gt;Meeshkan&lt;/a&gt;, we're working to improve how people test their products and APIs. So if you made it to the end of this guide and have thoughts, we want to hear from you. &lt;a href="https://gitter.im/Meeshkan/community"&gt;Reach out on Gitter&lt;/a&gt; or &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs/issues/new"&gt;open an issue on GitHub&lt;/a&gt; to let us know what you think.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Functional on the frontend with fp-ts and pipe</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Wed, 27 May 2020 16:18:04 +0000</pubDate>
      <link>https://dev.to/meeshkan/functional-on-the-frontend-with-fp-ts-and-pipe-4mn9</link>
      <guid>https://dev.to/meeshkan/functional-on-the-frontend-with-fp-ts-and-pipe-4mn9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is based on an internal presentation done by &lt;a href="https://dev.to/mikesol"&gt;Mike Solomon&lt;/a&gt;, who will be further referred to as "my boss."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a team, we decided to integrate functional programming practices into the codebase for our web application. More specifically, we're using &lt;a href="https://github.com/gcanti/fp-ts"&gt;&lt;code&gt;fp-ts&lt;/code&gt;&lt;/a&gt;, a library for typed functional programming in TypeScript. &lt;/p&gt;

&lt;p&gt;This article explains why we chose &lt;code&gt;fp-ts&lt;/code&gt; and walks through a practical example using the &lt;code&gt;pipe&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  In this article:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why we're going functional&lt;/li&gt;
&lt;li&gt;Working with our existing React codebase&lt;/li&gt;
&lt;li&gt;Putting it into practice with &lt;code&gt;pipe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;More with &lt;code&gt;fp-ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why we're going functional
&lt;/h2&gt;

&lt;p&gt;Because my boss &lt;a href="https://dev.to/blog/introducing-plzwrk/"&gt;likes Haskell&lt;/a&gt; 🤷‍♀️&lt;/p&gt;

&lt;p&gt;I'm joking (mostly). My boss does have an affinity for functional programming and he's more comfortable in this type of workflow. But even if the learning curve is steep for those of us who didn't know what monads are, we've realized something. Adopting functional programming practices has improved our web application.&lt;/p&gt;

&lt;p&gt;Here are some of the reasons:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Productivity&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Descriptive errors&lt;/strong&gt; - When we see logs in the console, it's rarely &lt;code&gt;Uncaught TypeError: Cannot Read Property 'name' of undefined&lt;/code&gt; or &lt;code&gt;Object doesn't support property or method 'getPosts'&lt;/code&gt;. This helps for more efficient debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less code&lt;/strong&gt; - Functional programming takes care of many patterns that would otherwise result in boilerplate code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited options&lt;/strong&gt; - With functional programming, you can only do things a certain number of ways.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring&lt;/strong&gt; - With strong type safety, you refactor "against" the compiler. This means the red squiggles in your IDE guide the refactoring process and proposes helpful suggestions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Correctness&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type safety&lt;/strong&gt; - When you use a typed variable, you're defining a constraint on all possible values. This helps ensure that the inputs and outputs of our code work as expected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error routing&lt;/strong&gt; - With functional programming, errors become first-class citizens and are propagated to error handlers based on rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linear ordering&lt;/strong&gt; - No more jumping between &lt;code&gt;if&lt;/code&gt; this &lt;code&gt;else&lt;/code&gt; that or getting stuck in a deep-nested JavaScript &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;catch&lt;/code&gt; block.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why we chose the &lt;code&gt;fp-ts&lt;/code&gt; library
&lt;/h3&gt;

&lt;p&gt;In theory, we could've switched out &lt;code&gt;fp-ts&lt;/code&gt; for another functional programming library for TypeScript like &lt;a href="https://gigobyte.github.io/purify/"&gt;Purify&lt;/a&gt;. Both libraries have similar syntax for common functional patterns like the &lt;code&gt;Either&lt;/code&gt; class and the &lt;code&gt;chain&lt;/code&gt; function. However, &lt;code&gt;fp-ts&lt;/code&gt; has some additional classes that we use regularly like &lt;a href="https://gcanti.github.io/fp-ts/modules/Reader.ts.html"&gt;&lt;code&gt;Reader&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://gcanti.github.io/fp-ts/modules/Semigroup.ts.html"&gt;&lt;code&gt;Semigroup&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If there were terms in that last paragraph that you didn't understand, don't worry! We'll cover those in a future post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with our existing React codebase
&lt;/h2&gt;

&lt;p&gt;Fortunately for us, the codebase we're working with is still fairly new. The repository was created a little over one month ago. The initial setup was done by two developers (myself included) with no functional programming experience. But, turns out, we were already applying functional programming principles to our React application. &lt;/p&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;&lt;strong&gt;Hooks&lt;/strong&gt;&lt;/a&gt; as a functional way to manage state dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org/docs/components-and-props.html#function-and-class-components"&gt;&lt;strong&gt;Function components&lt;/strong&gt;&lt;/a&gt; instead of &lt;code&gt;class&lt;/code&gt; components.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions"&gt;&lt;strong&gt;Arrow function expressions&lt;/strong&gt;&lt;/a&gt;, which, when used without brackets, enforces a single flow of information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But taking that next step into the functional programming world required us to restructure the way we think about and read code. To make it more tangible, the rest of this article will focus on one specific function from the &lt;code&gt;fp-ts&lt;/code&gt; library: &lt;code&gt;pipe&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it into practice with &lt;code&gt;pipe&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The concept of piping goes well beyond the &lt;code&gt;fp-ts&lt;/code&gt; library. According to &lt;a href="http://www.linfo.org/pipes.html"&gt;The Linux Information Project&lt;/a&gt;, piping is defined as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A form of redirection that is used to send the output of one program to another program for further processing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds intense and a bit abstract. Let's break it down.&lt;/p&gt;

&lt;p&gt;Overall, a pipe is one big function of functions. It takes an initial value and then passes that as the argument(s) for the first internal function to use. Then it takes the result from that function and passes it to &lt;em&gt;another&lt;/em&gt; internal function. And so on, potentially forever 🤪&lt;/p&gt;

&lt;p&gt;Maybe it's better to explain with code. &lt;/p&gt;

&lt;p&gt;Here's an example of piping written in vanilla JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;examplePipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;examplePipe&lt;/code&gt; function takes in three parameters (&lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt;). For &lt;code&gt;examplePipe&lt;/code&gt; to work as expected, &lt;code&gt;a&lt;/code&gt; should be a value that can be consumed by &lt;code&gt;b&lt;/code&gt;. Then &lt;code&gt;b&lt;/code&gt; should be a function that takes &lt;code&gt;a&lt;/code&gt; as an argument. Finally, &lt;code&gt;c&lt;/code&gt; should be another function that takes the result of &lt;code&gt;b&lt;/code&gt; as an argument.&lt;/p&gt;

&lt;p&gt;Let's put in some arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;examplePipe&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&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;First, it takes an independent value: &lt;code&gt;1&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then, &lt;code&gt;1&lt;/code&gt; is passed to the next function: &lt;code&gt;(x) =&amp;gt; x+1&lt;/code&gt;. So because &lt;code&gt;x&lt;/code&gt; is equal to &lt;code&gt;1&lt;/code&gt;, the result is &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, this result (&lt;code&gt;2&lt;/code&gt;) is passed to the last function: &lt;code&gt;(x) =&amp;gt; x+5&lt;/code&gt;. Because &lt;code&gt;x&lt;/code&gt; is now equal to &lt;code&gt;2&lt;/code&gt;, the &lt;code&gt;examplePipe&lt;/code&gt; will return &lt;code&gt;7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And there you have it, our first pipe 🎉&lt;/p&gt;

&lt;p&gt;This was a generic example of piping. Next, we'll go step-by-step to see how this would work in a web application. Throughout, we'll use the &lt;a href="https://gcanti.github.io/fp-ts/modules/pipeable.ts.html"&gt;&lt;code&gt;pipe&lt;/code&gt;&lt;/a&gt; function that's available through the &lt;code&gt;fp-ts&lt;/code&gt; library.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the initial value in a &lt;code&gt;pipe&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The most minimal &lt;code&gt;pipe&lt;/code&gt; we can write is a &lt;code&gt;pipe&lt;/code&gt; with a single object, like &lt;code&gt;pipe(1)&lt;/code&gt;. Here, the first value (&lt;code&gt;1&lt;/code&gt;) isn't consumed by any functions in the &lt;code&gt;pipe&lt;/code&gt;. This means that the result of &lt;code&gt;pipe(1)&lt;/code&gt; is equal to &lt;code&gt;1&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;As soon as a &lt;code&gt;pipe&lt;/code&gt; grows to two values, it then enforces a contract - the second element of the &lt;code&gt;pipe&lt;/code&gt; must be a &lt;em&gt;function&lt;/em&gt; that can consume the first value. This first value can be anything: A number, a string, a class, a function, or even &lt;code&gt;void&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is common practice in functional programming. Instead of defining variables along the way, everything we need is defined at the start. "Priming the pipe" so to speak.&lt;/p&gt;

&lt;p&gt;Let's start creating an example. We're going to define an &lt;code&gt;exampleFunction&lt;/code&gt; that doesn't have any parameters and returns a &lt;code&gt;pipe&lt;/code&gt;. To start, &lt;code&gt;pipe&lt;/code&gt; contains an object with three values: &lt;code&gt;projects&lt;/code&gt; (independent &lt;code&gt;getProjects&lt;/code&gt; function), a &lt;code&gt;users&lt;/code&gt; array, and a &lt;code&gt;configuration&lt;/code&gt; object. &lt;/p&gt;

&lt;p&gt;It should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This example assumes we have &lt;a href="https://github.com/gcanti/fp-ts#installation"&gt;&lt;code&gt;fp-ts&lt;/code&gt; installed&lt;/a&gt; and &lt;code&gt;pipe&lt;/code&gt; imported.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another nuance of &lt;code&gt;pipe&lt;/code&gt; is the order (or lack of order) that we define our initial values. To show how this works, let's look at a real-world example.&lt;/p&gt;

&lt;p&gt;In our web application, we often define our hooks within this first part of the &lt;code&gt;pipe&lt;/code&gt; function. Alternatively, you could use &lt;code&gt;const&lt;/code&gt; to define variables like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useColorMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useColorMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useDisclosure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDisclosure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this structure, &lt;code&gt;useDisclosure&lt;/code&gt; will always be executed &lt;em&gt;after&lt;/em&gt; &lt;code&gt;useColorMode&lt;/code&gt;. This is because JavaScript code executes in order.&lt;/p&gt;

&lt;p&gt;But with an object, there are no guarantees about the order of execution. JavaScript doesn't indicate which values in an object are created in memory first. This is true for any object, but it's especially useful in our &lt;code&gt;pipe&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Defining variables within the first object of &lt;code&gt;pipe&lt;/code&gt; signals to anyone maintaining the code that the order of these variables is insignificant. This allows us to refactor with more confidence. &lt;/p&gt;

&lt;p&gt;What's also nice about putting these values first is that it distinguishes what is independent in your function. So no matter what, you know that these values don't have any dependencies or rely on anything else. This can help with debugging and code readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  First function in the &lt;code&gt;pipe&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The next part of the &lt;code&gt;pipe&lt;/code&gt; is our first function. In this function, we can pass the values defined in the first object as an argument. &lt;/p&gt;

&lt;p&gt;We do this in the following example with the &lt;code&gt;valuesFromObjectAbove&lt;/code&gt; parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valuesFromObjectAbove&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="c1"&gt;// Coming soon!&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;valuesFromObjectAbove&lt;/code&gt; represents &lt;code&gt;projects&lt;/code&gt;, &lt;code&gt;users&lt;/code&gt;, and &lt;code&gt;configuration&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can then use &lt;code&gt;valuesFromObjectAbove&lt;/code&gt; to create new values. In this example, we're creating arrays of &lt;code&gt;adminProjects&lt;/code&gt; and &lt;code&gt;notAdminProjects&lt;/code&gt; using the &lt;code&gt;projects&lt;/code&gt; value we defined in the first object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valuesFromObjectAbove&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="na"&gt;adminProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;notAdminProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, we can see this grouping of independent values first, dependent ones second. Reading the code, we can deduce that &lt;code&gt;adminProjects&lt;/code&gt; and &lt;code&gt;notAdminProjects&lt;/code&gt;, by definition, depend on a value that was created earlier. This can help with debugging. For instance, if you insert a &lt;code&gt;console.log()&lt;/code&gt; statement after the first object, you know that your log will only contain the independent values in the function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Another round of functions
&lt;/h3&gt;

&lt;p&gt;There are a few options available for what values are passed to our second function. &lt;/p&gt;

&lt;p&gt;One option is to use a &lt;a href="https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operator"&gt;spread operator&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valuesFromObjectAbove&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Look here!&lt;/span&gt;
        &lt;span class="na"&gt;adminProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;notAdminProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valuesFromFunctionAbove&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="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By using the spread operator, we're saying that we want to pass down everything. This means that &lt;code&gt;valuesFromFunctionAbove&lt;/code&gt; contains all of the values from the initial object (&lt;code&gt;projects&lt;/code&gt;, &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;configuration&lt;/code&gt;). And it also contains the values from the first function (&lt;code&gt;adminProjects&lt;/code&gt;, &lt;code&gt;notAdminProjects&lt;/code&gt;). Bonus: It's all type safe!&lt;/p&gt;

&lt;p&gt;But let's say we delete the spread operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getProjects&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valuesFromObjectAbove&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="c1"&gt;// No spread operator&lt;/span&gt;
        &lt;span class="na"&gt;adminProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;notAdminProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valuesFromObjectAbove&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valuesFromFunctionAbove&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="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, the second function only has access to &lt;code&gt;adminProjects&lt;/code&gt; and &lt;code&gt;notAdminProjects&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is the power of &lt;code&gt;pipe&lt;/code&gt;. We always know what's ready to use 💥&lt;/p&gt;

&lt;p&gt;If organized appropriately, &lt;code&gt;pipe&lt;/code&gt; can contain everything that we would need to create our React component. So those &lt;code&gt;...&lt;/code&gt; in the last two examples? That's where we could put in our JSX.&lt;/p&gt;

&lt;h2&gt;
  
  
  More with &lt;code&gt;fp-ts&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This article only scratched the surface of what the &lt;code&gt;fp-ts&lt;/code&gt; library can bring to a web application. On our team, there are many more functions and patterns that we use (&lt;code&gt;Either&lt;/code&gt;, &lt;code&gt;chain&lt;/code&gt;, &lt;code&gt;isLeft&lt;/code&gt;, &lt;code&gt;isRight&lt;/code&gt;, &lt;code&gt;Reader&lt;/code&gt;). If you'd be interested in learning about these, &lt;a href="https://twitter.com/intent/tweet?text=Check%20out%20this%20comprehensive%20article%20about%20functional%20programming%20for%20web%20applications.%20Excited%20for%20the%20next%20one!%20%40meeshkan%20https%3A%2F%2Fmeeshkan.com%2Fblog%2Ffunctional-programming-for-frontend-pipe"&gt;tweet at us&lt;/a&gt; or leave a comment and let us know! &lt;/p&gt;

&lt;p&gt;In the meantime, check out the &lt;a href="https://gcanti.github.io/fp-ts/"&gt;&lt;code&gt;fp-ts&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>functional</category>
      <category>typescript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Six questions to answer before implementing a telemetry feature</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Tue, 14 Apr 2020 13:44:04 +0000</pubDate>
      <link>https://dev.to/meeshkan/six-questions-to-answer-before-implementing-a-telemetry-feature-1c5i</link>
      <guid>https://dev.to/meeshkan/six-questions-to-answer-before-implementing-a-telemetry-feature-1c5i</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/meeshkan/understanding-telemetry-features-in-open-source-software-p5b"&gt;first post of this series&lt;/a&gt;, I covered what telemetry features are and how developers feel about them. The general consensus was that the data needs to be anonymous, it should be clearly documented and it must be able to be switched off easily (or opt-in if possible).&lt;/p&gt;

&lt;p&gt;While this sounds great, it's not always realistic for every product or organization. And it's definitely not that straightforward. There are still a few questions that you'll need to discuss together with your team.&lt;/p&gt;

&lt;p&gt;This post outlines six of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why are you collecting this data?&lt;/li&gt;
&lt;li&gt;What kind of data will you track?&lt;/li&gt;
&lt;li&gt;How will you collect the data?&lt;/li&gt;
&lt;li&gt;Who has access to this data?&lt;/li&gt;
&lt;li&gt;Opt-in or opt-out?&lt;/li&gt;
&lt;li&gt;When will you delete data?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why are you collecting this data?
&lt;/h2&gt;

&lt;p&gt;Before anything else, you'll need to ask two important questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there a valid purpose for this data to be collected?&lt;/li&gt;
&lt;li&gt;If yes, is there an alternative way to achieve the purpose without the data?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write these answers down, regardless of whether you decide to implement the feature or not. If you decide to go the telemetry route, you might want to share these answers later in user documentation (more on this in a future post). Regardless, documenting these answers internally will help align your team and fuel future discussions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of data will you track?
&lt;/h2&gt;

&lt;p&gt;Think about your purpose for collecting this data and let that inform the data you collect. If you're trying to measure usage, you could track how many people initialize your CLI and what commands they execute. Or you can prioritize bugs by tracking how many people run into particular errors and wherein the process these errors occur.&lt;/p&gt;

&lt;p&gt;You should always question whether personal data is &lt;em&gt;really&lt;/em&gt; necessary for what you need. For instance, while it might be interesting to see where in the world your users come from, tracking location is much more invasive. So unless you're trying to gauge something like where to add more customer support agents, you should reconsider.&lt;/p&gt;

&lt;p&gt;"Telemetry helps to shape the product, but not at cost of user's privacy, we need data collection but make sure none of it contains any data points which can be used to profile a user," says developer &lt;a href="https://twitter.com/trishulgoel/status/1182576734383812609?s=20"&gt;Trishul Goel&lt;/a&gt; when discussing &lt;a href="https://cliqz.com/en/whycliqz/human-web"&gt;how they do telemetry at Cliqz&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A note about anonymous data
&lt;/h3&gt;

&lt;p&gt;Some justify collecting personal data by saying, 'Well, as long as it's anonymous then it's fine.' But then you need to ask yourself another question, what does it mean for data to be anonymous?&lt;/p&gt;

&lt;p&gt;"There's no such thing as anonymous usage data, especially if a third party is doing the collecting," says open-source developer &lt;a href="https://twitter.com/NamelessCoder/status/1182663311369953280?s=20"&gt;Claus Due&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Typically, it's not enough to say that data is anonymous. Developers implementing telemetry features need to put in extra effort to make sure that people can't be identified from the data.&lt;/p&gt;

&lt;p&gt;"If you're very confident it's anonymous, depends on the data, since a lot to anonymous data has actually been found to be able to identify people," says developer and designer &lt;a href="https://twitter.com/NickColley/status/1182574947220242432?s=20"&gt;Nick Colley&lt;/a&gt;. Nick also mentioned that he prefers to focus on &lt;a href="https://ico.org.uk/for-organisations/guide-to-data-protection/guide-to-the-general-data-protection-regulation-gdpr/principles/data-minimisation/"&gt;data minimization&lt;/a&gt; because it's more "proactive and user-focused."&lt;/p&gt;

&lt;h3&gt;
  
  
  Other considerations around tracking data
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What security measures do you have in place?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This could include (but isn't limited to) penetration testing, encryption, intrusion protection and vulnerability reporting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What will you do if there is a problem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Teams should consider having an &lt;a href="https://dvikan.no/ntnu-studentserver/reports/AC49DE3D7E65E331FC78C953CB3E03C.pdf"&gt;incident response plan&lt;/a&gt; available, in case there are any issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  How will you collect the data?
&lt;/h2&gt;

&lt;p&gt;Or, alternatively, where is the data handled?&lt;/p&gt;

&lt;p&gt;The answer will depend on whether you are building your telemetry feature in-house or using a third-party integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Homegrown
&lt;/h3&gt;

&lt;p&gt;Developing your own telemetry feature will take more effort (time, money, maintenance) all around. But it also allows you to manage who has access to the data, what exactly is collected and how it is communicated to your users.&lt;/p&gt;

&lt;p&gt;If the rest of your product is already open-source, your telemetry feature should be as well. A good example of this comes from Gatsby: &lt;a href="https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-telemetry"&gt;gatsby-telemetry&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Third-party
&lt;/h3&gt;

&lt;p&gt;Using a third-party, like &lt;a href="https://opentelemetry.io/"&gt;OpenTelemetry&lt;/a&gt;, will likely require less effort upfront. It also provides a built-in support system through bug reporting and community usage. But, with any outside source, you're giving up control of the data and increasing risk as more people are potentially able to access it. Resources like Mozilla's &lt;a href="https://docs.google.com/document/d/1nMsdX8pPhpHsnC33rbc7YjHpG6tqSCtWXtREAFpJTRs/edit"&gt;Outsourced Services Worksheet&lt;/a&gt; can help you evaluate the potential risk of a third-party service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who has access to this data?
&lt;/h2&gt;

&lt;p&gt;It's recommended that data access only be granted to the people who need it to perform their jobs. The &lt;a href="https://docs.google.com/document/d/1z_1llMFf18zkM0WRPzQd1VWc7Q3Nd8RILs-4em_jvZk/edit"&gt;Security Access Controls Worksheet&lt;/a&gt; is another resource from Mozilla that can help you determine this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should this data be open?
&lt;/h3&gt;

&lt;p&gt;If this usage data is truly anonymous, you could consider having it open and available to your users.&lt;/p&gt;

&lt;p&gt;One way to do this is through public, accessible dashboards. You can use tools like &lt;a href="https://github.com/nasa/openmct"&gt;Open MCT&lt;/a&gt; to showcase telemetry data. Another way is to make it available upon request or on an as-needed basis.&lt;/p&gt;

&lt;p&gt;"I don't believe data should be open but it should be possible to get access with a reasonable process," says developer &lt;a href="https://twitter.com/Argorak/status/1182573260904583168?s=20"&gt;Florian Gilcher&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opt-in or opt-out?
&lt;/h2&gt;

&lt;p&gt;Users should always be able to decide if they're ok with having their data tracked. But &lt;em&gt;when&lt;/em&gt; to present this option is the question.&lt;/p&gt;

&lt;p&gt;This leads us to the most notorious debate in telemetry: Should users have to agree to tracking (opt-in) or should tracking be on by default (opt-out)?&lt;/p&gt;

&lt;h3&gt;
  
  
  Opt-in
&lt;/h3&gt;

&lt;p&gt;This means asking for explicit consent from users before sending any data to your system. In &lt;a href="https://dev.to/meeshkan/understanding-telemetry-features-in-open-source-software-p5b"&gt;our initial survey about telemetry in open source&lt;/a&gt;, many developers mentioned that telemetry features should be opt-in only. They also said that users should know what's being tracking and not have that information hidden in a blog post or setting somewhere.&lt;/p&gt;

&lt;p&gt;One potential trade-off with an opt-in only approach is engagement. There's a lingering question of whether people will actually opt-in.&lt;/p&gt;

&lt;p&gt;"I once build [an open-source project] with opt-in for telemetry data, bug reports and anonymous analytics," explains open-source maintainer &lt;a href="https://twitter.com/asciidisco/status/1182573376486948864?s=20"&gt;Sebastian Golasch&lt;/a&gt;. "I kindly asked the users to enable this to help improve the project, but I must admit, less than 10% (judging from the download to telemetry ratio) actually did it."&lt;/p&gt;

&lt;h3&gt;
  
  
  Opt-out
&lt;/h3&gt;

&lt;p&gt;Having telemetry settings on by default is much more common in modern products. These products give users the option to switch off tracking through an environment variable, command line argument/flag or a toggle in the product's GUI.&lt;/p&gt;

&lt;p&gt;When taking an opt-out approach, it's advised to let your users know right away that these settings are on and they are being tracked. It's more transparent and also reduces the risk of ill feelings later.&lt;/p&gt;

&lt;p&gt;"I do accept tracking if there is an explanation upfront. But I don't if I discover by accident that I am tracked," says &lt;a href="https://twitter.com/kautschpoteito/status/1183025348797177857?s=20"&gt;Stephan Schuler&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When will you delete data?
&lt;/h2&gt;

&lt;p&gt;The value of the data diminishes over time, so it's recommended to delete data when it's no longer relevant.&lt;/p&gt;

&lt;p&gt;You should agree on a specific time limit for data (i.e. 3 months, 6 months, 1 year). You can choose to communicate that to your users through documentation or when alerting them that they are being tracked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next up: Telemetry in the wild
&lt;/h2&gt;

&lt;p&gt;This is the second in an undetermined number of posts about telemetry in open-source software. Up next, I'll cover some telemetry feature examples in popular open-source products and what they are (and aren't) getting right.&lt;/p&gt;

&lt;p&gt;If you have any requests for this series, please comment below!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ethics</category>
      <category>data</category>
    </item>
    <item>
      <title>Onboarding a junior developer to your team? Here's 12 tips.</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Sat, 11 Apr 2020 17:26:23 +0000</pubDate>
      <link>https://dev.to/carolstran/onboarding-a-junior-developer-to-your-team-here-s-12-tips-4g3a</link>
      <guid>https://dev.to/carolstran/onboarding-a-junior-developer-to-your-team-here-s-12-tips-4g3a</guid>
      <description>&lt;p&gt;A few weeks ago, my friend &lt;a href="https://twitter.com/TheNicoKoenig" rel="noopener noreferrer"&gt;Nico König&lt;/a&gt; asked the Twittersphere about best practices when onboarding a new junior developer to your team:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1242770350645051394-995" src="https://platform.twitter.com/embed/Tweet.html?id=1242770350645051394"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1242770350645051394-995');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1242770350645051394&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;As someone who was recently a junior dev, I have &lt;em&gt;a lot&lt;/em&gt; of opinions on this topic. So I decided to summarize them in this post (in no particular order).&lt;/p&gt;

&lt;h2&gt;
  
  
  💭 Distinguish between opinions and best practices
&lt;/h2&gt;

&lt;p&gt;When you're talking over concepts with your junior, deliberately point out whether the things you're saying are your personal views or proven best practices. &lt;/p&gt;

&lt;p&gt;We work in such an opinion-heavy industry. So sometimes it can feel impossible to differentiate feelings from facts - especially if you're new to programming. One tangible way to help with this is to provide resources describing why something is best practice. &lt;/p&gt;

&lt;h2&gt;
  
  
  🖥 Dedicate time early on for Git commands
&lt;/h2&gt;

&lt;p&gt;On the very first day (or maybe second), walk through the Git commands that you use most frequently on the job with your junior. &lt;em&gt;Nothing&lt;/em&gt; is too basic - particularly because many bootcamps or university programs don't teach Git. For example, the bootcamp I went to used Git for version control, but all of our tasks were done solo. So more collaborative Git workflows (like branching or pull requests) were new to me when I started my first developer job.&lt;/p&gt;

&lt;p&gt;Ideally, you'd also take the time to explain what each command is actually doing. It took me &lt;em&gt;nine months&lt;/em&gt; and one colleague sitting down with a pen and paper for me to finally figure out how a &lt;code&gt;rebase&lt;/code&gt; works. Speaking of, teach them how to &lt;code&gt;rebase&lt;/code&gt; properly! &lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Have something for them to work on
&lt;/h2&gt;

&lt;p&gt;Give your junior &lt;em&gt;something&lt;/em&gt; to work on that is low pressure, but still impactful. If you're stuck on what kind of work falls into this category, think either nice-to-haves (style improvements, microinteractions, bugs that aren't critical, etc.) or general improvements (refactoring, accessibility, performance, etc). &lt;/p&gt;

&lt;p&gt;Be sure to have a dedicated backlog of tasks ready for them to choose from. For most junior developers, this will be their very first software job. So it's unrealistic to expect them to "take initiative" and decide what they should work on without a curated task list.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Give constructive code reviews
&lt;/h2&gt;

&lt;p&gt;Code reviews are a major. At best, code reviews are constructive and serve as continuous learning opportunities. At worst, they can destroy trust and safety within a team. &lt;/p&gt;

&lt;p&gt;As the reviewer, you should be pointing out things that are done well and if you have critiques, explaining &lt;em&gt;why&lt;/em&gt; something is problematic rather than only saying ‘fix this’ or offering the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  👩‍💻 Practice pair programming
&lt;/h2&gt;

&lt;p&gt;Set regular, dedicated times for pairing (like literally put it in the calendar). I'd recommend at least twice per week. You can have a set of tasks that you work on together or switch between individual tasks.  &lt;/p&gt;

&lt;p&gt;When pairing, make sure you're alternating between who's driving and who's navigating. Depending on your junior and their learning style, this could also be them observing you. Personally, I learn so much from watching and asking questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Pair on things that aren't code
&lt;/h2&gt;

&lt;p&gt;It feels weird at first, but I promise that it’s helpful. Show them your workflow, how you prioritize tasks or approach learning something new. One of the best non-coding pairing sessions I've had was a colleague walking me through how he conducts a code review.&lt;/p&gt;

&lt;p&gt;How you test your own code? Dive into a new project? Manage your time? Plan a company-wide presentation? All of this is valuable.&lt;/p&gt;

&lt;h2&gt;
  
  
  🙋‍♂️ Always be available for questions
&lt;/h2&gt;

&lt;p&gt;Make your junior a top priority. When they have questions, stop what you're doing and help them. If you don't know the answer, help them find it - whether that's searching through StackOverflow or introducing them to someone who knows that domain better.&lt;/p&gt;

&lt;p&gt;Jess Mitchell also made an especially excellent point about tone:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1242900048033259524-320" src="https://platform.twitter.com/embed/Tweet.html?id=1242900048033259524"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1242900048033259524-320');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1242900048033259524&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  💞 Get them a buddy or mentor
&lt;/h2&gt;

&lt;p&gt;This should be someone (not their direct manager) that will guide your junior through their onboarding. Your junior should also feel comfortable talking openly with this person and discussing any problems they might be having. &lt;/p&gt;

&lt;p&gt;Ideally, your junior and their buddy will meet at least once per week during the first 6 months.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn their learning style
&lt;/h2&gt;

&lt;p&gt;Get familiar with your junior’s learning style and try to cater the resources and materials you send them to that style. So if they like books, try to recommend books or written articles instead of videos courses. It's a small gesture, but it'll help them succeed and shows you care.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏰ Respect their time
&lt;/h2&gt;

&lt;p&gt;Set a good example by not sending emails at wild hours or pressing for tasks. Let them know what's expected from them in terms of working hours. An example of why this is important: In my first tech job, the lunch break didn't count as working time... but no one told me that even if I took a shorter lunch, I still couldn't leave earlier. Later, the fact that I left 30 minutes early every day was brought up as an argument not to keep me 🙄&lt;/p&gt;

&lt;p&gt;On a related note, try to encourage wellness by recommending self-care tactics and being open about mental/physical health (if you feel comfortable and safe doing so). &lt;/p&gt;

&lt;h2&gt;
  
  
  📋 Provide regular feedback
&lt;/h2&gt;

&lt;p&gt;Give regular feedback and updates about how they’re doing. If you're working in a country with a probation time, try to give weekly feedback during that time. &lt;/p&gt;

&lt;p&gt;Your junior will likely assume they are doing worse than they really are. But if there is something that needs to be fixed, be sure to tell them enough in advance that there's time to make a change.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌱 Show humility yourself
&lt;/h2&gt;

&lt;p&gt;Admit when you don’t know things and search for answers together. Offer regular opportunities for them to give you feedback and maybe even in a variety of ways (sometimes face-to-face, sometimes written, etc).&lt;/p&gt;

&lt;p&gt;Ultimately, their success is your success, so it's important to know how you're doing throughout this process as well.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Did you find this helpful or useful? If yes, please consider &lt;a href="https://ko-fi.com/carolstran" rel="noopener noreferrer"&gt;buying me a coffee&lt;/a&gt; so I can continue to write posts like this&lt;/em&gt; ☕️&lt;/p&gt;

</description>
      <category>career</category>
      <category>codenewbie</category>
      <category>productivity</category>
    </item>
    <item>
      <title>From 1 to 10,000 test cases in under an hour: A beginner's guide to property-based testing </title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Mon, 06 Apr 2020 14:48:16 +0000</pubDate>
      <link>https://dev.to/meeshkan/from-1-to-10-000-test-cases-in-under-an-hour-a-beginner-s-guide-to-property-based-testing-1jf8</link>
      <guid>https://dev.to/meeshkan/from-1-to-10-000-test-cases-in-under-an-hour-a-beginner-s-guide-to-property-based-testing-1jf8</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;This guide was co-authored by &lt;a href="//dev.to/fornwall"&gt;Fredrik Fornwall&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testing your software takes time... a lot of time. When you're writing tests, you're often stuck trying to manually reproduce every potential sequence of events. But what if you wanted to test hundreds (or thousands or even millions) of cases at once? We have an answer: &lt;strong&gt;Property-based testing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Maybe you've written unit tests before, but this is the first time you've heard about property-based testing. Or maybe you've heard the term, but still don't really get what it's about. Either way, we've got you. &lt;/p&gt;

&lt;p&gt;Throughout this guide, we'll cover the fundamentals of property-based testing. We'll walk you through practical examples and how to structure your tests. Finally, you'll learn how to use property-based testing to find bugs in your code and what existing libraries are out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in this guide
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Traditional unit tests based on examples

&lt;ul&gt;
&lt;li&gt;Limitations of example-based testing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Introduction to property-based testing

&lt;ul&gt;
&lt;li&gt;An example using Hypothesis&lt;/li&gt;
&lt;li&gt;What can be a property?&lt;/li&gt;
&lt;li&gt;How does property-based testing differ from example-based?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Example properties and how to test for them

&lt;ul&gt;
&lt;li&gt;Unexpected exceptions should never be thrown&lt;/li&gt;
&lt;li&gt;Values shouldn't change after encoding and then decoding&lt;/li&gt;
&lt;li&gt;A naive method should still give the same result&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Finding bugs with property-based testing&lt;/li&gt;
&lt;li&gt;Available libraries&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A general understanding of what unit tests are.&lt;/li&gt;
&lt;li&gt;(Optional) &lt;a href="https://www.python.org/downloads/"&gt;Python 3+&lt;/a&gt;* if you want to follow along in your own IDE. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;* This guide will use Python for code examples, but the concepts aren't limited to any specific programming language. So even if you don't know Python, we'd encourage you to read along anyway.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;References&lt;/strong&gt;:&lt;br&gt;
We've created a &lt;a href="https://github.com/meeshkan/beginners-guide-to-property-based-testing"&gt;GitHub repository&lt;/a&gt; to go with this guide. All of the featured code examples exist there as unit tests and include instructions for how to execute them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Traditional unit tests based on examples
&lt;/h2&gt;

&lt;p&gt;Most often, software testing is done using &lt;strong&gt;example-based testing&lt;/strong&gt;. This means you test that for a given argument, you get a known return value. This return value is known because, well, you provided that exact value as a sample. So when you run the function or test system, it then asserts the actual result against that sample return value.&lt;/p&gt;

&lt;p&gt;Let's look at an example. Say you want to write a function called &lt;code&gt;sort_this_list&lt;/code&gt;. This function will take a &lt;a href="https://docs.python.org/3/tutorial/introduction.html#lists"&gt;list&lt;/a&gt; as an argument and return the same list organized in ascending order. To do this, you'll use the built-in Python &lt;a href="https://docs.python.org/3/library/functions.html#sorted"&gt;&lt;code&gt;sorted&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;It might look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_sorted_list.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sorted_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sorted_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that you have your &lt;code&gt;sort_this_list&lt;/code&gt; function, let's test it. &lt;/p&gt;

&lt;p&gt;To test this using example-based testing, you need to (manually) provide the test function with return values that you know will be &lt;code&gt;True&lt;/code&gt;. For example, the list &lt;code&gt;[5, 3, 1, 4, 2]&lt;/code&gt; should return &lt;code&gt;[1, 2, 3, 4, 5]&lt;/code&gt; after it's sorted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_sorted_list.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_sort_this_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&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;3&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&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;==&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="mi"&gt;2&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;4&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="c1"&gt;# True
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&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="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And with that, you have a passing example-based test 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of example-based testing
&lt;/h3&gt;

&lt;p&gt;While example-based tests work well in many situations and provide an (arguably) low barrier of entry to testing, they do have downsides. Particularly that you have to create every test case yourself - and you can only test as many cases as you're willing to write. The less you write, the more likely it is that your tests will miss catching bugs in your code.&lt;/p&gt;

&lt;p&gt;To show why this could be a problem, let's look at the test for the &lt;code&gt;sort_this_list&lt;/code&gt; function from the last section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_sorted_list.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_sort_this_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&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;3&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&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;==&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="mi"&gt;2&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;4&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="c1"&gt;# True
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&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="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Both of these assertions return &lt;code&gt;True&lt;/code&gt;. So if you only tested these two values, you might believe that the &lt;code&gt;sort_this_list&lt;/code&gt; function always returns the desired result.&lt;/p&gt;

&lt;p&gt;But if you add a third potential return value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_sorted_list.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_sort_this_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&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;3&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&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;==&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="mi"&gt;2&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;4&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="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&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="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="c1"&gt;# Add a new test case:
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&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="s"&gt;'b'&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;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&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="mi"&gt;2&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then run the test... you'll hit an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;TypeError: &lt;span class="s1"&gt;'&amp;lt;'&lt;/span&gt; not supported between instances of &lt;span class="s1"&gt;'int'&lt;/span&gt; and &lt;span class="s1"&gt;'str'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Turns out the &lt;code&gt;sort_this_list&lt;/code&gt; function doesn't work as expected when the list contains both integers and strings. Maybe you already knew that, but maybe you would've never known that without a specific test case. &lt;/p&gt;

&lt;p&gt;Even with these limitations, example-based testing will continue to be the norm in software testing. Throughout the rest of this guide, though, we'll explore another technique. One designed to compliment your existing (likely example-based) tests and improve the test coverage of your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to property-based testing
&lt;/h2&gt;

&lt;p&gt;When thinking about the limitations of example-based testing, many questions come to mind. What if you want to test hundreds of cases? Or ones that you could never dream of coming up with yourself? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property-based testing&lt;/strong&gt; is a different approach here to help with that. With property-based testing, you don't generate the exact values manually. Instead, that is done by a computer automatically. &lt;/p&gt;

&lt;p&gt;As the developer, what you have to do is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specify what value to generate.&lt;/li&gt;
&lt;li&gt;Assert on guarantees (or &lt;strong&gt;properties&lt;/strong&gt;) that are true regardless of the exact value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  An example using Hypothesis
&lt;/h3&gt;

&lt;p&gt;To put property-based testing into practice, let's look at an example using &lt;a href="https://hypothesis.readthedocs.io/en/latest/"&gt;Hypothesis&lt;/a&gt;, a Python library for generative test cases. We chose Hypothesis mostly because we're using Python - but also because the documentation is clear and thorough. &lt;/p&gt;

&lt;p&gt;Let's use the &lt;code&gt;sort_this_list&lt;/code&gt; function from earlier. As a reminder, here's what that looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_sorted_list.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sorted_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sorted_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let's write a property-based test using Hypothesis. To limit the scope, you'll only test for lists of integers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_sorted_list.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;hypothesis.strategies&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;hypothesis&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;

&lt;span class="c1"&gt;# Use the @given decorator to guide Hypothesis to the input value needed:
&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;integers&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;span class="c1"&gt;# Use the @settings object to set the number of cases to run:
&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_examples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10000&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_sort_this_list_properties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sorted_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sort_this_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Regardless of input, sorting should never change the size:
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Regardless of input, sorting should never change the set of distinct elements:
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Regardless of input, each element in the sorted list should be
&lt;/span&gt;    &lt;span class="c1"&gt;# lower or equal to the value that comes after it:
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sorted_list&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;lt;=&lt;/span&gt; &lt;span class="n"&gt;sorted_list&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="mi"&gt;1&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;Note: If you're following along on your machine, make sure to install &lt;a href="https://hypothesis.readthedocs.io/en/latest/quickstart.html#installing"&gt;Hypothesis&lt;/a&gt; and then you can run the tests using &lt;a href="https://pypi.org/project/pytest/"&gt;pytest&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And there you have it, your first property-based test 🎉&lt;/p&gt;

&lt;p&gt;What's especially important here is the use of the &lt;a href="https://hypothesis.readthedocs.io/en/latest/details.html#hypothesis.given"&gt;&lt;code&gt;@given&lt;/code&gt;&lt;/a&gt; function decorator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;integers&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This specifies that you want a list of random integers as the input value and &lt;strong&gt;asserts on properties that are true regardless of the exact input&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another significant feature of this test is the use of the &lt;a href="https://hypothesis.readthedocs.io/en/latest/settings.html#settings"&gt;&lt;code&gt;@settings&lt;/code&gt;&lt;/a&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_examples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, it's using the &lt;a href="https://hypothesis.readthedocs.io/en/latest/settings.html#hypothesis.settings.max_examples"&gt;&lt;code&gt;max_examples&lt;/code&gt;&lt;/a&gt; setting to indicate the maximum number of satisfying test cases that will run before terminating. The default value is &lt;code&gt;100&lt;/code&gt; and in this case, it's set to &lt;code&gt;10000&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;At first, running tens of thousands of test cases might feel excessive - but these numbers are reasonable in the property-based testing realm. Even the Hypothesis documentation recommends setting this value well above the default or else it may miss uncommon bugs.&lt;/p&gt;

&lt;p&gt;Going back to the example test, if you add a &lt;code&gt;print(input_list)&lt;/code&gt; statement, you can peek at the &lt;em&gt;10,000 different generated input values&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[]
[92]
[66, 24, -25219, 94, -28953, 31131]
[-16316, -367479896]
[-7336253322929551029, -7336253322929551029, 27974, -24308, -64]
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Your values will likely be different from our example - and that's ok. You also might not want to print 10,000 example lists - and that's ok too. You can take our word for it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The number of runs and specifics of the generated data can be configured. More on that later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can be a property?
&lt;/h3&gt;

&lt;p&gt;With this style of testing, a &lt;strong&gt;property&lt;/strong&gt; is something that's true about the function being tested, regardless of the exact input. &lt;/p&gt;

&lt;p&gt;Let's see this definition applied to assertion examples from the previous &lt;code&gt;test_sort_this_list_properties&lt;/code&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;len(sorted_list) == len(input_list)&lt;/code&gt;: The property tested here is the list length. The length of the sorted list is always the same as the original list (regardless of the specific list items).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sorted_list[i] &amp;lt;= sorted_list[i + 1]&lt;/code&gt;: This property was that each element of the sorted list is in ascending order. No matter the contents of the original list, this should be true. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How does property-based testing differ from example-based?
&lt;/h3&gt;

&lt;p&gt;While they're from different concepts, property-based tests share many characteristics with example-based tests. This is illustrated in the following comparison of steps you'd take to write a given test:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Example based&lt;/th&gt;
&lt;th&gt;Property based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Set up some example data&lt;/td&gt;
&lt;td&gt;1. Define data type matching a specification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Perform some operations on the data&lt;/td&gt;
&lt;td&gt;2. Perform some operations on the data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Assert something about the result&lt;/td&gt;
&lt;td&gt;3. Assert properties about the result&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are several instances where it would be worthwhile to use property-based testing. But the same can be said for example-based testing. They can, and very likely will, co-exist in the same codebase. &lt;/p&gt;

&lt;p&gt;So if you're stressed about having to rewrite your entire test suite to try out property-based testing, don't worry. We wouldn't recommend that. &lt;/p&gt;

&lt;h2&gt;
  
  
  Example properties and how to test for them
&lt;/h2&gt;

&lt;p&gt;By now, you've written your first property-based test and many lists were sorted 🎉 But sorting lists isn't a representative example of how you'd use property-based testing in the real world. So we've gathered three example properties and in this section, we'll guide you through how they might be used to test software.&lt;/p&gt;

&lt;p&gt;All of the examples will continue to use the &lt;a href="https://hypothesis.readthedocs.io/en/latest/"&gt;Hypothesis&lt;/a&gt; testing library and its &lt;a href="https://hypothesis.readthedocs.io/en/latest/details.html#hypothesis.given"&gt;@given&lt;/a&gt; function decorator.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unexpected exceptions should never be thrown
&lt;/h3&gt;

&lt;p&gt;Something that was tested by default in the previous &lt;code&gt;test_sorted_list_properties&lt;/code&gt; function was that the code didn't throw any exceptions. The fact that the code doesn't throw any exceptions (or more generally, only expected and documented exceptions, and that it never causes a segmentation fault) is a property. And this property can be a convenient one to test, especially if the code has a lot of internal assertions.&lt;/p&gt;

&lt;p&gt;As an example, let's use the &lt;a href="https://docs.python.org/3/library/json.html#json.loads"&gt;&lt;code&gt;json.loads&lt;/code&gt;&lt;/a&gt; function from the Python standard library. Then, let's test that the &lt;code&gt;json.loads&lt;/code&gt; function never throws any exceptions other than &lt;code&gt;json.JSONDecodeError&lt;/code&gt; - regardless of input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_json_decode.py
&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&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_json_loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you run the test file, it passes 🎉 So the beliefs held up under testing!&lt;/p&gt;

&lt;h3&gt;
  
  
  Values shouldn't change after encoding and then decoding
&lt;/h3&gt;

&lt;p&gt;A commonly tested property is called symmetry. Symmetry proves in certain operations that decoding an encoded value always results in the original value.&lt;/p&gt;

&lt;p&gt;Let's apply it to &lt;a href="https://github.com/jbittel/base32-crockford"&gt;base32-crockford&lt;/a&gt;, a Python library for the &lt;a href="https://www.crockford.com/base32.html"&gt;Base32&lt;/a&gt; encoding format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_base32_crockford.py
&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;integers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&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_base32_crockford&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;base32_crockford&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base32_crockford&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;input_int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Because this decoding scheme only works for non-negative integers, you need to specify the &lt;em&gt;generation strategy&lt;/em&gt; of your input data. That's why, in this example, &lt;code&gt;some.integers(min_value=0)&lt;/code&gt; is added to the &lt;code&gt;@given&lt;/code&gt; decorator. It restricts Hypothesis to only generate integers with a minimum value of zero.&lt;/p&gt;

&lt;p&gt;Once again, the test passes 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  A naive method should still give the same result
&lt;/h3&gt;

&lt;p&gt;Sometimes, you can get the desired solution through a naive, unpractical way that isn't acceptable to use in production code. This might be due to the execution time being too slow, memory consumption being too high or it requiring specific dependencies that aren't acceptable to install in production.&lt;/p&gt;

&lt;p&gt;For example, consider counting the number of set bits in an (arbitrary sized) integer, where you have an optimized solution from the &lt;a href="https://gmpy2.readthedocs.io/en/latest/"&gt;pygmp2&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;Let's compare this with a slower solution that converts the integer to a binary string (using the &lt;a href="https://docs.python.org/3/library/functions.html#bin"&gt;bin&lt;/a&gt; function in the Python standard library) and then counts the occurrences of the string &lt;code&gt;"1"&lt;/code&gt; inside of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_gmpy_popcount.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_bits_slow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;integers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_examples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&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_gmpy2_popcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;count_bits_slow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gmpy2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;popcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For illustrative purposes, this example specifies a &lt;a href="https://hypothesis.readthedocs.io/en/latest/settings.html"&gt;&lt;code&gt;@settings(max_examples=500)&lt;/code&gt;&lt;/a&gt; decorator to tweak the default number of input values to generate.&lt;/p&gt;

&lt;p&gt;The test passes  🎉 - showing that the optimized, hard-to-follow code of &lt;code&gt;gmpy2.popcount&lt;/code&gt; gives the same results as the slower but less complex &lt;code&gt;count_bits_slow&lt;/code&gt; function. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If this was the only reason to bring in gmpy2 as a dependency, it'd be wise to benchmark if the performance improvements of it really would outweigh the cost and weight of the dependency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Finding bugs with property-based testing
&lt;/h2&gt;

&lt;p&gt;We've gone over the concepts of property-based testing and seen various properties in action - this is great. But one of the selling points of property-based tests is that they're supposed to help us find more bugs. And we haven't found any bugs yet.&lt;/p&gt;

&lt;p&gt;So let's go hunting. &lt;/p&gt;

&lt;p&gt;For this example, let's use the &lt;a href="https://pypi.org/project/json5/"&gt;json5&lt;/a&gt; library for &lt;a href="https://json5.org/"&gt;JSON5&lt;/a&gt; serialization. It's a bit niche, sure, but it's also a younger project. This means that you're more likely to uncover a bug compared to a more established library. &lt;/p&gt;

&lt;p&gt;The json5 library contains: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One &lt;strong&gt;property&lt;/strong&gt; of JSON5 is that it is a superset of JSON.&lt;/li&gt;
&lt;li&gt;Another &lt;strong&gt;property&lt;/strong&gt; proving that deserializing a serialized string should give you back the original object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's use those properties in a test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_json5_decode.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;printable&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;hypothesis.strategies&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json5&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;hypothesis&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;

&lt;span class="c1"&gt;# Construct a generator of arbitrary objects to test serialization on:
&lt;/span&gt;&lt;span class="n"&gt;some_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;booleans&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;floats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allow_nan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;printable&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_size&lt;/span&gt;&lt;span class="o"&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;|&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dictionaries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;printable&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_object&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_json5_loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dumped_json_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dumped_json5_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;parsed_object_from_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dumped_json_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parsed_object_from_json5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dumped_json5_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;parsed_object_from_json&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;input_object&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;parsed_object_from_json5&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;input_object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After creating a &lt;code&gt;some_object&lt;/code&gt; generator of &lt;a href="https://hypothesis.readthedocs.io/en/latest/data.html#recursive-data"&gt;arbitrary objects&lt;/a&gt;, you can verify aspects of the previously mentioned properties: You serialize the input using both &lt;code&gt;json&lt;/code&gt; and &lt;code&gt;json5&lt;/code&gt;. Then, you deserialize those two objects back using the &lt;code&gt;json5&lt;/code&gt; library and assert that the original object was obtained.&lt;/p&gt;

&lt;p&gt;But doing this, you'll run into a problem. At the &lt;code&gt;json5.dumps(input_object)&lt;/code&gt; statement, you get an exception inside the internals of the &lt;code&gt;json5&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;    def _is_ident&lt;span class="o"&gt;(&lt;/span&gt;k&lt;span class="o"&gt;)&lt;/span&gt;:
        k &lt;span class="o"&gt;=&lt;/span&gt; str&lt;span class="o"&gt;(&lt;/span&gt;k&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;       &lt;span class="k"&gt;if &lt;/span&gt;not _is_id_start&lt;span class="o"&gt;(&lt;/span&gt;k[0]&lt;span class="o"&gt;)&lt;/span&gt; and k[0] not &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;u&lt;span class="s1"&gt;'$'&lt;/span&gt;, u&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:
E       IndexError: string index out of range
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: If you're following along and you want to discover the bug yourself, &lt;a href="https://github.com/meeshkan/beginners-guide-to-property-based-testing/blob/master/requirements.txt#L10"&gt;uncomment &lt;code&gt;json5==0.9.3&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/meeshkan/beginners-guide-to-property-based-testing/blob/master/requirements.txt#L8"&gt;remove &lt;code&gt;json5&lt;/code&gt;&lt;/a&gt; from the &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Besides showing the stack trace, as usual, you also get an informative message showing the failed &lt;em&gt;hypothesis&lt;/em&gt; - otherwise known as the generated data that caused the test to fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ------------- Hypothesis ------------- #
Falsifying example: test_json5_loads(
    input_object={'': None},
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;{'': None}&lt;/code&gt; input data caused &lt;a href="https://github.com/dpranke/pyjson5/issues/37"&gt;the issue that was promptly reported&lt;/a&gt;. Finding the issue led to &lt;a href="https://github.com/dpranke/pyjson5/pull/38"&gt;fixing the bug&lt;/a&gt;. This fix has since been released in version 0.9.4 of the json5 library.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want to add that the fix was merged and released within 20 minutes of reporting. Very impressive work by json5 maintainer &lt;a href="https://github.com/dpranke"&gt;@dpranke&lt;/a&gt; 👏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But what about the future, how can you be sure that the problem will never resurface? &lt;/p&gt;

&lt;p&gt;Because the data currently generated contains the troublesome input (&lt;code&gt;{'': None}&lt;/code&gt;), you want to ensure that this input is always used. This should be true even if someone tweaks the &lt;code&gt;some_object&lt;/code&gt; generator or updates the version of Hypothesis used.&lt;/p&gt;

&lt;p&gt;The following fix uses the &lt;a href="https://hypothesis.readthedocs.io/en/latest/reproducing.html#hypothesis.example"&gt;@example&lt;/a&gt; decorator to add a hard-coded example to the generated input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;--- test_json5_decode_orig.py   2020-03-27 09:48:24.000000000 +0100
&lt;/span&gt;&lt;span class="gi"&gt;+++ test_json5_decode.py    2020-03-27 09:48:32.000000000 +0100
&lt;/span&gt;&lt;span class="p"&gt;@@ -14,6 +14,7 @@&lt;/span&gt;

 @given(some_object)
 @settings(max_examples=500)
&lt;span class="gi"&gt;+@example({"": None})
&lt;/span&gt; def test_json5_loads(input_object):
     dumped_json_string = json.dumps(input_object)
     dumped_json5_string = json5.dumps(input_object)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Bug found ✅ Bug fixed ✅ You're good to go 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Available libraries
&lt;/h2&gt;

&lt;p&gt;This guide uses the &lt;a href="https://hypothesis.readthedocs.io/en/latest/"&gt;Hypothesis&lt;/a&gt; library for Python. But there's a lot of functionality that wasn't covered and, as previously mentioned, the documentation is nice. We'd recommend checking it out if you're a Python user.&lt;/p&gt;

&lt;p&gt;If you're not using Python, no problem. There are several other libraries built for property-based testing, in a variety of languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/dubzzz/fast-check"&gt;fast-check&lt;/a&gt;: TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fscheck.github.io/FsCheck/"&gt;FsCheck&lt;/a&gt;: .NET&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jqwik.net/"&gt;jqwik&lt;/a&gt;: Java&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/alfert/propcheck"&gt;PropCheck&lt;/a&gt;: Elixir&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://proper-testing.github.io/"&gt;PropEr&lt;/a&gt;: Erlang&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/emil-e/rapidcheck"&gt;RapidCheck&lt;/a&gt;: C++&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hackage.haskell.org/package/QuickCheck"&gt;QuickCheck&lt;/a&gt;: Haskell&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.rs/quickcheck/0.9.2/quickcheck/"&gt;QuickCheck ported to Rust&lt;/a&gt;: Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Example-based testing isn't going anywhere any time soon. But we hope that, after reading this guide, you're motivated to incorporate some property-based tests into your codebase. &lt;/p&gt;

&lt;p&gt;Some lingering questions from us...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why weren't you using property-based testing before?&lt;/li&gt;
&lt;li&gt;After reading through this guide, would you be willing to try? &lt;/li&gt;
&lt;li&gt;Are you interested in seeing another article expanding on the topic?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At &lt;a href="https://meeshkan.com/"&gt;Meeshkan&lt;/a&gt;, we're working to improve how people test their products. So no matter if you loved or loathed this guide, we want to hear from you. Leave us a comment below, &lt;a href="https://twitter.com/meeshkanml"&gt;tweet at us&lt;/a&gt; or &lt;a href="https://gitter.im/Meeshkan/community"&gt;reach out on Gitter&lt;/a&gt; to let us know what you think.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>python</category>
    </item>
    <item>
      <title>Understanding telemetry features in open-source software</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Wed, 18 Mar 2020 15:36:50 +0000</pubDate>
      <link>https://dev.to/meeshkan/understanding-telemetry-features-in-open-source-software-p5b</link>
      <guid>https://dev.to/meeshkan/understanding-telemetry-features-in-open-source-software-p5b</guid>
      <description>&lt;p&gt;Until recently, I was unaware that many of the open-source products I use regularly - like Visual Studio Code or Netlify - have telemetry features that track usage. Admittedly, I had no idea these kinds of features existed at all. But I wasn't surprised. What bothered me more was that I didn't know my data was being tracked. &lt;/p&gt;

&lt;p&gt;So I began talking to other developers in my network. I learned that people fell somewhere on a spectrum - ranging from blissfully unaware (like me) to vigilant about data protection. Some even told me that they refuse to use products that have these features.&lt;/p&gt;

&lt;p&gt;All of this got me thinking about the general attitude and ethics around telemetry features in open source technology. Can tracking data be ethical if that data is open and available? If telemetry is bad, how can open source maintainers best track usage to improve the project? I decided to dig deeper and thus, this series was born.&lt;/p&gt;

&lt;p&gt;This first post will cover the what and why of telemetry features, insights on developer attitudes and what else you can expect from this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is telemetry?&lt;/li&gt;
&lt;li&gt;Why would I implement a telemetry feature?&lt;/li&gt;
&lt;li&gt;How do developers feel about telemetry?&lt;/li&gt;
&lt;li&gt;What's next?&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Telemetry is a feature that enables data collection. Many products (open source or otherwise) implement telemetry features to track usage. This usage data can range from performance metrics to errors encountered by users.&lt;/p&gt;

&lt;p&gt;Let's dive deeper into the term telemetry. If you look at &lt;a href="https://en.wikipedia.org/wiki/Telemetry" rel="noopener noreferrer"&gt;a very scientific resource called Wikipedia&lt;/a&gt;, it defines telemetry as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Telemetry is the collection of measurements or other data at remote or inaccessible points and their automatic transmission to receiving equipment or monitoring.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you abstract this a bit, you can see how this would apply to software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;collection of measurements or other data&lt;/code&gt;: How and when people are using the product.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;remote or inaccessible points&lt;/code&gt;: Other people's computers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;their automatic transmission&lt;/code&gt;: Actions done by the implemented telemetry features.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;receiving equipment or monitoring&lt;/code&gt;: How the product is tracking this usage data (for instance, a dashboard or log).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To put it into context, you can check out &lt;a href="https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-telemetry" rel="noopener noreferrer"&gt;Gatsby's telemetry package&lt;/a&gt;, which is entirely open source. Or if you're curious about working with a telemetry feature, take a look at this example of &lt;a href="https://github.com/codesandbox/codesandbox-client/blob/master/packages/node-services/src/module.ts#L197-L217" rel="noopener noreferrer"&gt;how CodeSandbox sends telemetry events&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why would I implement a telemetry feature?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/index.html" rel="noopener noreferrer"&gt;Firefox's source documentation&lt;/a&gt; describes this well. It says that their telemetry features are used to track "information about how Firefox performs in the wild." And this is exactly the benefit: Raw usage data.&lt;/p&gt;

&lt;p&gt;Many teams choose to implement telemetry features to help them understand how to improve their product. There are other ways to source user feedback - like case studies, surveys or even GitHub issue templates. But telemetry features are different because they can offer continuous, unfiltered insight into a user's experiences.&lt;/p&gt;

&lt;p&gt;It can be difficult to prioritize fixes or features when you aren't sure how the product is being used. And not every user will be motivated to file a bug report when they do run into issues. So for some, telemetry helps find those answers. &lt;/p&gt;

&lt;h2&gt;
  
  
  How do developers feel about telemetry?
&lt;/h2&gt;

&lt;p&gt;Back in October 2019, &lt;a href="https://twitter.com/carolstran/status/1182571331390464001" rel="noopener noreferrer"&gt;I asked Twitter&lt;/a&gt;: Are you ok with open source projects having a telemetry feature that collects anonymous usage data? Assuming you can opt-out.&lt;/p&gt;

&lt;p&gt;Over 440 developers participated in the poll, but the results varied.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1182571329456934913-331" src="https://platform.twitter.com/embed/Tweet.html?id=1182571329456934913"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1182571329456934913-331');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1182571329456934913&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;While 53% answered some form of yes, over half of them indicated that the data must be open and available. Twenty percent said no flat out. &lt;/p&gt;

&lt;p&gt;Those who answered "Depends on what's tracked" and took the time to reply brought up a variety of issues. These included opting-in rather than out, what type of data is being tracked, whether the data is anonymous and many more that we'll dive into in a later post.&lt;/p&gt;

&lt;p&gt;Developers being skeptical about telemetry is nothing new. Just look at this issue discussion from 2016 titled, &lt;a href="https://github.com/dotnet/sdk/issues/6145" rel="noopener noreferrer"&gt;.NET core should not SPY on users by default&lt;/a&gt;. But the attitude towards telemetry seems to be shifting. &lt;strong&gt;If there is some benefit that comes from sharing this usage data (less bugs, more descriptive errors, relevant features), people are more willing to do it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The majority agreed that an important factor is the recipient - who is the one collecting the data? &lt;a href="https://twitter.com/callahad" rel="noopener noreferrer"&gt;Dan Callahan&lt;/a&gt; pointed out specifically, "Happy to send telemetry to non-profits and independent developers. Otherwise, there needs to be an exchange of value." But we don't all maintain projects as independent developers or work for non-profits. So then the question becomes what value exchange would be enticing enough for people to share their personal data.&lt;/p&gt;

&lt;p&gt;In cases involving larger organizations, some mentioned that how the information is communicated and documented is what matters.&lt;/p&gt;

&lt;p&gt;No matter how you spin it, the general consensus is that the data needs to be anonymous, it should be clearly documented and it must be able to be switched off easily (or opt-in if possible). &lt;/p&gt;

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

&lt;p&gt;This is the first in an undetermined number of posts about telemetry in open-source software. Throughout this series, we'll discuss a variety of topics - from building a telemetry feature to documenting it after.&lt;/p&gt;

&lt;p&gt;If you have any requests for this series, please comment below!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ethics</category>
      <category>data</category>
    </item>
  </channel>
</rss>
