<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.jessesquire.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.jessesquire.com/" rel="alternate" type="text/html" /><updated>2026-04-07T01:50:30+00:00</updated><id>https://www.jessesquire.com/feed.xml</id><title type="html">Jesse Squire</title><subtitle>The technical blog and personal site of Jesse Squire.</subtitle><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><entry><title type="html">Configure GitHub Activity Signing with Windows Subsystem for Linux (WSL)</title><link href="https://www.jessesquire.com/articles/2019/03/31/configure-github-activity-signing-with-wsl/" rel="alternate" type="text/html" title="Configure GitHub Activity Signing with Windows Subsystem for Linux (WSL)" /><published>2019-03-31T19:02:18+00:00</published><updated>2019-03-31T19:02:18+00:00</updated><id>https://www.jessesquire.com/articles/2019/03/31/configure-github-activity-signing-with-wsl</id><content type="html" xml:base="https://www.jessesquire.com/articles/2019/03/31/configure-github-activity-signing-with-wsl/"><![CDATA[<p>Now that I’m in a role where my job entails writing code for Microsoft products in the open on GitHub, I thought that it may be a good idea to make sure that my commits and related activities on GitHub were signed and could be verified as my contributions.  That isn’t meant to imply that I have major concerns about spoofing, but I remembered that it happened to <a href="https://twitter.com/shanselman">Scott Hanselman</a> last year and that he set up signing in response to it.</p>

<p>Scott ended up <a href="https://www.hanselman.com/blog/HowToSetupSignedGitCommitsWithAYubiKeyNEOAndGPGAndKeybaseOnWindows.aspx">configuring GPG signing with a YubiKey</a>, which looked like an intimidating process.  I wanted to do something more basic and see if using the stock on-box storage was as straightforward as configuring SSH authentication for GitHub.</p>

<h1 id="setting-the-stage">Setting the Stage</h1>

<p>In my normal development flow, I use the git command line, either under WSL on Windows or natively on Linux.  While I may use a GUI tool occasionally to help visualize the commit graph for a repository, I tend to do all of the activities that I’m interested in signing outside of them.  I prefer a dedicated stand-alone command line window to embedded instances, such as the terminal in Visual Studio Code.</p>

<p>As a result, the process that I’m describing here is focused on integrating GPG signing into a git workflow from a stand-alone terminal window.  Some things may or may not work elsewhere but, I’ve honestly not spent any time exploring or verifying other tools.  The other goal that I had was to try and minimize the number of times in a day that I’d have to unlock my GPG key with a password.</p>

<p>GitHub has some great documentation on the process, walking through the steps needed locally as well as within the GitHub site in order to enable signing.  For the most part, I’ll be referring back to them where possible, up through configuring the basic signing mechanism.  There are a few things needed to enable local caching of your GPG credentials to avoid a password prompt for each commit that those guides didn’t cover.</p>

<h1 id="prerequisites">Prerequisites</h1>

<p>Before starting, I find it helpful to have the necessary packages installed and ready to go, rather than pulling them down as needed.  To that end, I’d recommend installing the following on a Debian-based distribution, such as Ubuntu:</p>

<ul class="with-paragraph single end-section">
  <li><code class="language-plaintext highlighter-rouge">build-essential</code></li>
  <li><code class="language-plaintext highlighter-rouge">apt-transport-https</code></li>
  <li><code class="language-plaintext highlighter-rouge">software-properties-common</code></li>
  <li><code class="language-plaintext highlighter-rouge">ca-certificates</code></li>
  <li><code class="language-plaintext highlighter-rouge">curl</code></li>
  <li><code class="language-plaintext highlighter-rouge">git</code></li>
  <li><code class="language-plaintext highlighter-rouge">gpg</code></li>
  <li><code class="language-plaintext highlighter-rouge">gnupg</code></li>
  <li><code class="language-plaintext highlighter-rouge">gpg-agent</code></li>
  <li><code class="language-plaintext highlighter-rouge">pinentry-curses</code></li>
</ul>

<h1 id="generating-the-key">Generating the Key</h1>

<p>I’d recommend following the GitHub Help guide - <a href="https://help.github.com/en/articles/generating-a-new-gpg-key">Generating a new GPG key</a>.  It has a nice step-by-step flow for each operating system.  In my case, the Linux steps went smoothly and I’d echo the GitHub advice of using a 4096 bit key.  As the guide mentions, you can verify the key that you created using:<br />
<code class="language-plaintext no-wrap with-paragraph highlighter-rouge">gpg --list-secret-keys --keyid-format LONG</code></p>

<h1 id="configuring-github">Configuring GitHub</h1>

<p>Here, again, GitHub Help provides an excellent guide - <a href="https://help.github.com/en/articles/adding-a-new-gpg-key-to-your-github-account">Adding a new GPG key to your GitHub account</a>, which builds upon the previous guide for key generation.  Before starting the configuration guide, you’ll want to make sure that you have your key available.</p>

<p class="with-paragraph">To do so, start by listing your available GPG keys, using:<br />
<code class="language-plaintext no-wrap highlighter-rouge">gpg --list-secret-keys --keyid-format LONG</code></p>

<p class="with-paragraph">From the list, copy the id of the key that you’ll be using to sign, which will be in a line that looks like:<br />
<code class="language-plaintext no-wrap with-paragraph highlighter-rouge">sec    [Key Length]/[Key ID] [Date Created and Expiry Date]</code></p>

<p class="with-paragraph">If the <code class="language-plaintext highlighter-rouge">sec</code> line of your output is the following, then your key Id is <code class="language-plaintext highlighter-rouge">3AA5C34371567BD2</code>.<br />
<code class="language-plaintext no-wrap with-paragraph highlighter-rouge">sec    4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]</code></p>

<p class="with-paragraph">Once you have the key, you’ll need to export the full key in armor format.  You can do so using:<br />
<code class="language-plaintext no-wrap highlighter-rouge">gpg --armor --export &lt;&lt; YOUR KEY ID &gt;&gt;</code></p>

<p class="with-paragraph">GitHub will expect the public portion of your key, starting with <code class="language-plaintext no-wrap highlighter-rouge">-----BEGIN PGP PUBLIC KEY BLOCK-----</code> up through <code class="language-plaintext no-wrap highlighter-rouge">-----END PGP PUBLIC KEY BLOCK-----</code>, including those markers copied as part of your key.</p>

<p class="with-paragraph">Once you follow the steps in the guide, GitHub will have your key registered and is ready to verify your signed activities.</p>

<h1 id="register-your-key-with-git">Register Your Key with Git</h1>

<p>The most important step in configuring the terminal is to tell git to make use of your key.  Again, GitHub Help has a useful guide - <a href="https://help.github.com/en/articles/telling-git-about-your-signing-key#telling-git-about-your-gpg-key-1">Telling Git about your signing key</a>, from which the steps that we’re interested in fall under the <code class="language-plaintext highlighter-rouge">Telling Git about your GPG key</code> title.  In a nutshell, the steps are:</p>

<ol class="with-paragraph">
  <li>List your available GPG keys and copy the Id of the key that you’ll be using to sign, the same way that you had done when configuring GitHub.</li>
  <li>Configure your <code class="language-plaintext no-color highlighter-rouge">.gitconfig</code> to associate the key by using the command:<br /><code class="language-plaintext no-wrap highlighter-rouge">git config --global user.signingkey &lt;&lt; YOUR KEY ID &gt;&gt;</code></li>
</ol>

<p>Optionally, if you’d like to instruct git to always sign commits and tags, you can run the following to update your git configuration:</p>

<ul class="with-paragraph single end-section">
  <li><code class="language-plaintext highlighter-rouge">git config --global commit.gpgsign true</code></li>
  <li><code class="language-plaintext highlighter-rouge">git config --global tag.gpgsign true</code></li>
</ul>

<h1 id="configuring-entry-and-caching-for-your-gpg-credentials">Configuring Entry and Caching for your GPG Credentials</h1>

<p>At this point, you’re able to perform end-to-end signing for commits, tags, and related GitHub activities.  The unfortunate part is that your git client will prompt for a password before each of those operations, which tends to have a negative impact on productivity.  To get around this, it is possible to cache your GPG key password, allowing you to use the git client normally, without additional entry, but producing signed commits.</p>

<p>Unfortunately, this is an area where there wasn’t a helpful GitHub guide and most of the resources that I found were focused on macOS and/or out of date.  The basic gist of what we’d like to do is use the <code class="language-plaintext highlighter-rouge">gpg-agent</code> as a cache for the credentials and integrate that with the WSL terminal, having the <code class="language-plaintext no-color highlighter-rouge">curses</code> user experience prompt for entry of the GPG password, so that it’s very clear when it’s needed.</p>

<p>To start, we’ll need to configure GPG to make use of the agent for caching and set the key used by default.  In <code class="language-plaintext no-color highlighter-rouge">~/.gnupg/gpg.conf</code>, add or update the following:</p>

<div class="language-text with-paragraph highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Uncomment within config (or add this line)
# This tells gpg to use the gpg-agent
use-agent

# Set the default key
default-key &lt;&lt; YOUR KEY ID &gt;&gt;
</code></pre></div></div>

<p>The next step is to configure the GPG Agent to cache your password and instruct it how we would like to be prompted for password entry.  The GPG Agent allows for the time of the cache to be specified, so that you’re able to make the choice that is right for you.  In the example, caching is set to 400 days (34560000 seconds) so that it can be entered once and then is not needed again until the computer or WSL session are restarted.  In <code class="language-plaintext no-color highlighter-rouge">~/.gnupg/gpg-agent.conf</code>, the cache times and an executable for password prompting are registered.  The GPU configuration should contain the following, though you may need to change the location of your pin entry program to the output of the command <code class="language-plaintext highlighter-rouge">which pinentry-curses</code>, depending on your operating system:</p>

<div class="language-text with-paragraph highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default-cache-ttl 34560000
max-cache-ttl 34560000
pinentry-program /usr/bin/pinentry-curses
</code></pre></div></div>

<p>The final step is to ensure that the GPG agent launches when your WSL session starts and that the environment is prepared.  Note that this is an area where things have changed fairly recently, and most of the resources that I found on the web were outdated.  The approach that I’m using here was tested with GPG v2.2.4 and GPG Agent v2.2.4.  In either <code class="language-plaintext no-color highlighter-rouge">~/.profile</code> or <code class="language-plaintext no-color highlighter-rouge">~/.bashrc</code>, add the following:</p>

<div class="language-text with-paragraph highlighter-rouge"><div class="highlight"><pre class="highlight"><code># enable GPG signing
export GPG_TTY=$(tty)

if [ ! -f ~/.gnupg/S.gpg-agent ]; then
    eval $( gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf )
fi

export GPG_AGENT_INFO=${HOME}/.gnupg/S.gpg-agent:0:1
</code></pre></div></div>

<h1 id="thats-all-folks">That’s All, Folks</h1>

<p>If you’ve gotten this far, then git in your Windows Subsystem for Linux terminal should be all set to sign commits.  While there may be a few steps involved, they felt reasonably straightforward to me, once I had figured out the environment configuration.  Hopefully, this guide helped to lay out the end-to-end steps and will save others from having to piece them together from multiple resources.</p>

<h1 id="helpful-resources">Helpful Resources</h1>

<ul class="single">
  <li><a href="https://help.github.com/en/articles/signing-commits">GitHub Help - Signing commits</a></li>
  <li><a href="https://help.github.com/en/articles/generating-a-new-gpg-key">GitHub Help - Generating a new GPG key</a></li>
  <li><a href="https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work">Git GPG Documentation</a></li>
  <li><a href="https://www.gnupg.org/documentation/manuals/gnupg/Agent-Options.html">GPG Agent Configuration Options</a></li>
  <li><a href="https://gpgtools.org/">GPG Suite</a> <em class="tiny-text">(allows GPG integration with the macOS keychain)</em></li>
  <li><a href="https://www.gpg4win.org/">Gpg4win</a> <em class="tiny-text">(allows GPG integration with Windows and may enable GUI clients)</em></li>
  <li><a href="https://jasonrogena.github.io/2016/09/14/osx-signing-off-git-using-gpg.html">Signing Git Commits and Tags Using Your GPG Key</a> <em class="tiny-text">(a guide focused on macOS, used as inspiration for this one)</em></li>
</ul>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="git" /><category term="github" /><category term="wsl" /><category term="configuration" /><summary type="html"><![CDATA[Now that I’m in a role where my job entails writing code for Microsoft products in the open on GitHub, I thought that it may be a good idea to make sure that my commits and related activities on GitHub were signed and could be verified as my contributions. That isn’t meant to imply that I have major concerns about spoofing, but I remembered that it happened to Scott Hanselman last year and that he set up signing in response to it.]]></summary></entry><entry><title type="html">Reflections on my First Development Job</title><link href="https://www.jessesquire.com/articles/2019/03/09/relections-on-my-first-development-job/" rel="alternate" type="text/html" title="Reflections on my First Development Job" /><published>2019-03-09T18:34:26+00:00</published><updated>2019-03-09T18:34:26+00:00</updated><id>https://www.jessesquire.com/articles/2019/03/09/relections-on-my-first-development-job</id><content type="html" xml:base="https://www.jessesquire.com/articles/2019/03/09/relections-on-my-first-development-job/"><![CDATA[<style>em { padding-left: 0.6em; padding-right: 0.4em; }</style>

<p>December of 2018 marked the 20th anniversary for my being given money to tell computers what to do.  As I’m currently in the process of adjusting to a new role, I thought that it may be amusing to reminisce back on the first paying job as a developer that I had.</p>

<h1 id="setting-the-stage">Setting the Stage</h1>

<p>One of my big goals going through college was to graduate without having any loans or other debts hanging over my head.  As someone paying my own way, that meant that I didn’t have the luxury of exploring unpaid internships nor taking a low paying position to gain experience.  Luckily, the fast food job that I started in high school had a tuition reimbursement program for college students.  Unfortunately, that means that I had been working in the food service industry for roughly 8 years by the time I entered my last semester.  As you can imagine, I was ready for a change and chomping at the bit to move into my chosen field and start building my career.  By the mid-point of my last year, my tuition was fully paid and I excitedly began looking.</p>

<p>Given that I live in an area well outside of any urban center, my choices for a programming position were somewhat limited since I had to be close enough to make the drive to school for classes.  Remarkably, though I had tough luck searching, I somehow caught the attention of a local(ish) company who reached out about a role.</p>

<h1 id="the-fun-begins">The Fun Begins</h1>

<p>The interview process was a bit odd and awkward.  I wasn’t asked any technical questions nor, really, anything beyond whether I’d be willing to learn FoxPro and what I expected as a salary.  They weren’t forthcoming with much about the company or product and came across as overly secretive.  I negotiated up from the $8 an hour that I was offered to a whopping $10 an hour. It was a slight pay cut from what I was making, but I was finally going to stop smelling like grease and spend my day writing code!</p>

<p>The company was small and split its efforts between doing custom installation of networks and developing a software package aimed at a niche market of managing a small business in a very specific industry <em>(details intentionally vague to avoid calling out the company)</em>.</p>

<h1 id="the-product">The Product</h1>

<p>The management software, like most packages in the late 90s, was distributed on physical disks and accompanied by a very large manual.  A new version was created each year which customers could opt to upgrade to or not.  Support contracts and live call center access was sold as a separate add-on.  It was written in Visual FoxPro and shipped as a core unit with some optional add-ons.  The FoxPro runtime was packaged and each of the core and add-on modules were included as loose FoxPro files in the directory.  All-told, there was one directory level that contained a hundred or so FoxPro files of different types and then the files and structure for the FoxPro engine.</p>

<p>The software didn’t change very much from year-to-year, typically.  A few bug fixes, some minor enhancements, and maybe a retired feature were typical for a yearly ship cycle.  The big change was an update to the bitmap that served as the background for the application and loading splash screen.  It always had the year featured prominently as part of the product name.  <em>(To be fair, this was back in the days of Windows 95, Windows 98, Office 95, and similar naming schemes.)</em>  Apparently, customers were willing to pay a solid 8-10 thousand dollars each year for an upgrade so long as the splash screen had a new year displayed and a new, thick manual came with the box.</p>

<h1 id="heres-where-it-gets-weird">Here’s Where it Gets Weird</h1>

<p>The owner of the company, Mike, was the person that “interviewed” me.  He and a partner had started the company and wrote the original few years of the management software before Mike stepped away from hands-on development and hired others to do the work.  By the time I joined, Mike had been away from programming for a solid 10+ years, but his shadow loomed large.  I learned very quickly during my first few weeks that Mike still dictated many of the practices for development and that my initial impression of him being a bit odd was on point.  He had some interesting rules that we had to follow:</p>

<ul class="with-paragraph">
  <li>Development will always be done in a version of FoxPro that is at least 1 major version behind the current release. <strong><em>Why?</em></strong>  Mike had his environment crash once after installing the most recent version and didn’t want to deal with “unstable software” that could cost him money.</li>
  <li>The names of all files will begin with a “w”.<strong><em>Why?</em></strong>  Because Mike likes “w”s.</li>
  <li>Files were to be named in lowercase without underscores, dashes, or spaces in them and were not to exceed 8 characters, including the leading “w”. <strong><em>Why?</em></strong>   Because Mike felt that Windows was a fad and required that DOS limitations were adhered to.</li>
  <li>All variable names were to begin with “M”.<strong><em>Why?</em></strong>   To denote that it was a “memory variable.”  Nobody was able to explain to me what other type of variable we were trying to distinguish from.  There was no such thing as a “file variable,” for instance.  Everything was just a standard memory pointer.</li>
  <li>Variable names were to be in UPPERCASE only, must contain only letters and digits, and may not exceed 8 characters, including the leading “M.” <strong><em>Why?</em></strong>   Because FoxPro 2.0 wasn’t able to deal with longer names or special characters and Mike required that we be compatible with it in case we ever had to rollback.  For the record, FoxPro 2.0 was 7 years older than our version and ran on a different operating system than our product was sold on.</li>
  <li>We were not allowed to use arrays.<strong><em>Why?</em></strong>   Mike “didn’t understand” arrays and, thus, didn’t like them.</li>
  <li>We were not allowed to use SQL.<strong><em>Why?</em></strong>  Mike “didn’t understand” SQL.  Instead, we were to open each table file that we needed, programmatically set a join between them in memory, and then linearly scan them and copy over the information that we were trying to retrieve.</li>
</ul>

<p>I suspect that there were more quirks, but those are the ones that I can still recall.  My final memory is that, after arguing that using an array was necessary to implement whatever first task I was assigned, I was banished to being a networking cable pull assistant for the next two weeks as “a time to reflect on the importance of following standards.”</p>

<h1 id="well-that-was-fast">Well, That was Fast</h1>

<p>Shortly into my tenure, one of my college professors approached me with an opportunity that he had been kind enough to recommend me for.  I was offered double what I was making to take a role working on technology that wasn’t in danger of being obsolete, Visual Basic - quite a hot technology at the time.</p>

<p>Thus ended my time with Mike’s company.  It may have only been 3 months, but it left quite an impression.</p>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="work" /><category term="retrospective" /><category term="humor" /><summary type="html"><![CDATA[December of 2018 marked the 20th anniversary for my being given money to tell computers what to do. As I’m currently in the process of adjusting to a new role, I thought that it may be amusing to reminisce back on the first paying job as a developer that I had.]]></summary></entry><entry><title type="html">Truffle Tests Fail to Compile with Solidity 0.4.21</title><link href="https://www.jessesquire.com/articles/2018/04/19/truffle-assertions-compile-errors/" rel="alternate" type="text/html" title="Truffle Tests Fail to Compile with Solidity 0.4.21" /><published>2018-04-19T10:19:34+00:00</published><updated>2018-04-19T10:19:34+00:00</updated><id>https://www.jessesquire.com/articles/2018/04/19/truffle-assertions-compile-errors</id><content type="html" xml:base="https://www.jessesquire.com/articles/2018/04/19/truffle-assertions-compile-errors/"><![CDATA[<p>I was exploring the <a href="http://truffleframework.com">Truffle Framework</a> for developing against Ethereum and working my way through its <a href="http://truffleframework.com/tutorials/pet-shop">Pet Shop Tutorial</a> with things going well until I hit the first section on testing.  When I attempted to run the tests that it had me write, I ran into compiler errors against the Truffle assertion library.  It seems that the package was written against v0.4.17 of the Solidity compiler while I’m using the current release, v0.4.21, and there have been breaking changes.</p>

<p>The fix appears to have already made in the <code class="language-plaintext highlighter-rouge">next</code> branch in the Truffle repository, but I was able to hack my way around them for the time being.  If you’re running into the same issue, you may be able to work around it until the next Truffle package release by replacing <code class="language-plaintext highlighter-rouge">$NPM_ROOT/node_modules/truffle/build/Assert.sol</code> with the version in this <a href="https://gist.github.com/jsquire/6f2649f6f50133fc8d7a7f8cb66f7b69">Gist</a>.</p>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="blockchain" /><category term="ethereum" /><category term="solidity" /><category term="development" /><summary type="html"><![CDATA[I was exploring the Truffle Framework for developing against Ethereum and working my way through its Pet Shop Tutorial with things going well until I hit the first section on testing. When I attempted to run the tests that it had me write, I ran into compiler errors against the Truffle assertion library. It seems that the package was written against v0.4.17 of the Solidity compiler while I’m using the current release, v0.4.21, and there have been breaking changes.]]></summary></entry><entry><title type="html">Miner is Not Available for My Private Ethereum Network</title><link href="https://www.jessesquire.com/articles/2018/04/19/miner-not-available-for-private-etherum-network/" rel="alternate" type="text/html" title="Miner is Not Available for My Private Ethereum Network" /><published>2018-04-19T09:35:23+00:00</published><updated>2018-04-19T09:35:23+00:00</updated><id>https://www.jessesquire.com/articles/2018/04/19/miner-not-available-for-private-etherum-network</id><content type="html" xml:base="https://www.jessesquire.com/articles/2018/04/19/miner-not-available-for-private-etherum-network/"><![CDATA[<p>I’ve been working to build some knowledge and skills around Blockchain technologies lately and was trying to use <code class="language-plaintext highlighter-rouge">geth</code> as both the server and a miner node for a private network.  I created the network using <code class="language-plaintext highlighter-rouge">geth --datadir=./chaindata/ init ./genesis.json</code>. After launching the console in another window using <code class="language-plaintext highlighter-rouge">geth attach</code>, each time that I tried to invoke <code class="language-plaintext highlighter-rouge">miner.start()</code>, I was met with an error because <code class="language-plaintext highlighter-rouge">miner</code> was unknown.  Unfortunately, I didn’t find much help in searching the web - there seemed to be few, if any, mentions of it.</p>

<p>It turns out that the default set of APIs that <code class="language-plaintext highlighter-rouge">geth</code> published did not include <code class="language-plaintext highlighter-rouge">miner</code>, nor did it include <code class="language-plaintext highlighter-rouge">admin</code> which is often referenced by tutiorials for managing the network.  The good news is that these are easily configured using the <code class="language-plaintext highlighter-rouge">--rpcapi</code> parameter; launching the network using <code class="language-plaintext highlighter-rouge">geth --datadir=./chaindata/ --rpc --rpcapi "eth,net,web3,admin,personal,miner"</code> fixed my issue.</p>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="blockchain" /><category term="ethereum" /><category term="development" /><summary type="html"><![CDATA[I’ve been working to build some knowledge and skills around Blockchain technologies lately and was trying to use geth as both the server and a miner node for a private network. I created the network using geth --datadir=./chaindata/ init ./genesis.json. After launching the console in another window using geth attach, each time that I tried to invoke miner.start(), I was met with an error because miner was unknown. Unfortunately, I didn’t find much help in searching the web - there seemed to be few, if any, mentions of it.]]></summary></entry><entry><title type="html">Using xUnit Theory Member Data with F#</title><link href="https://www.jessesquire.com/articles/2018/02/17/xunit-memberdata-with-fsharp/" rel="alternate" type="text/html" title="Using xUnit Theory Member Data with F#" /><published>2018-02-17T06:03:16+00:00</published><updated>2018-02-17T06:03:16+00:00</updated><id>https://www.jessesquire.com/articles/2018/02/17/xunit-memberdata-with-fsharp</id><content type="html" xml:base="https://www.jessesquire.com/articles/2018/02/17/xunit-memberdata-with-fsharp/"><![CDATA[<p>I’ve been using an introductory book on machine learning as an excuse to start cuddling up to F# again, after letting my skills deteriorate.  I’m adding unit tests into the mix with the book materials, using FsUnit with xUnit.  In doing so, I struggled a bit to get a <code class="language-plaintext highlighter-rouge">Theory</code> based on member data working correctly.</p>

<p>I wasn’t able to turn much up in a few searches, so I wanted to capture it here, lest I forget again in the future.   The basic structure that worked for me was:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">MachineLearningBook</span><span class="p">.</span><span class="nn">SpamDetector</span><span class="p">.</span><span class="nc">UnitTests</span>
    <span class="k">module</span> <span class="nc">DocumentTests</span> <span class="p">=</span>

        <span class="k">open</span> <span class="nn">FSharp</span><span class="p">.</span><span class="nc">Reflection</span>
        <span class="k">open</span> <span class="nn">MachineLearningBook</span><span class="p">.</span><span class="nc">SpamDetector</span>
        <span class="k">open</span> <span class="nc">Xunit</span>
        <span class="k">open</span> <span class="nn">FsUnit</span><span class="p">.</span><span class="nc">Xunit</span>

        <span class="k">type</span> <span class="n">``Parsing a DocType should produce the expected results``</span> <span class="bp">()</span> <span class="p">=</span>
            
            <span class="k">static</span> <span class="k">member</span> <span class="nc">DocTypeNameData</span> 
                <span class="k">with</span> <span class="n">get</span><span class="bp">()</span> <span class="p">=</span> 
                    <span class="nn">FSharpType</span><span class="p">.</span><span class="nc">GetUnionCases</span> <span class="n">typeof</span><span class="p">&lt;</span><span class="nn">Document</span><span class="p">.</span><span class="nc">DocType</span><span class="p">&gt;</span> 
                    <span class="p">|&gt;</span> <span class="nn">Seq</span><span class="p">.</span><span class="n">map</span> <span class="p">(</span><span class="k">fun</span> <span class="n">case</span> <span class="p">-&gt;</span> <span class="p">[|</span> <span class="n">case</span><span class="p">.</span><span class="nc">Name</span> <span class="o">|])</span>

            
            <span class="p">[&lt;</span><span class="nc">Theory</span><span class="p">&gt;]</span>
            <span class="p">[&lt;</span><span class="nc">MemberData</span><span class="p">(</span><span class="s2">"DocTypeNameData"</span><span class="o">)&gt;]</span>            
            <span class="k">member</span> <span class="n">verify</span><span class="p">.</span><span class="n">``Exact DocTypes can be parsed``</span> <span class="p">(</span><span class="n">docTypeName</span><span class="p">:</span><span class="kt">string</span><span class="p">)</span> <span class="p">=</span>
                <span class="k">let</span> <span class="n">result</span> <span class="p">=</span> <span class="nn">Document</span><span class="p">.</span><span class="nn">DocType</span><span class="p">.</span><span class="n">parse</span> <span class="n">docTypeName</span>
                
                <span class="n">result</span><span class="p">.</span><span class="nc">IsSome</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">be</span> <span class="nc">True</span>
                <span class="n">result</span><span class="p">.</span><span class="nn">Value</span><span class="p">.</span><span class="nc">ToString</span><span class="bp">()</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="n">docTypeName</span>
</code></pre></div></div>

<p>Hopefully, that helps someone (or future me) to avoid some pain.</p>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="xunit" /><category term="f#" /><category term="development" /><summary type="html"><![CDATA[I’ve been using an introductory book on machine learning as an excuse to start cuddling up to F# again, after letting my skills deteriorate. I’m adding unit tests into the mix with the book materials, using FsUnit with xUnit. In doing so, I struggled a bit to get a Theory based on member data working correctly.]]></summary></entry><entry><title type="html">Visual Studio Fails to Discover Tests</title><link href="https://www.jessesquire.com/articles/2018/02/04/visual-studio-fails-to-discover-tests/" rel="alternate" type="text/html" title="Visual Studio Fails to Discover Tests" /><published>2018-02-04T07:40:10+00:00</published><updated>2018-02-04T07:40:10+00:00</updated><id>https://www.jessesquire.com/articles/2018/02/04/visual-studio-fails-to-discover-tests</id><content type="html" xml:base="https://www.jessesquire.com/articles/2018/02/04/visual-studio-fails-to-discover-tests/"><![CDATA[<p>Every once in a while, Visual Studio fails to discover my tests at all.  There’s no build error, nor other indication in the output window or IDE… just zero tests discovered.  This seemed to happen often when I was working with Service Fabric and the SDK/tools were updated.   That may, or may not, be coincidence but, anecdotally, I haven’t seemed to encounter it outside of that context.</p>

<p>To fix discovery, here’s the steps that have helped get me working again:</p>

<ul>
  <li>Shut down all instances of Visual Studio</li>
  <li>Remove the <code class="language-plaintext highlighter-rouge">CompnentModelCache</code> directory from the application data for the current version of Visual Studio.  For example, for Visual Studio 2017 v15.5.6, I need to delete: <code class="language-plaintext highlighter-rouge">%LocalAppData%\Microsoft\VisualStudio\15.0_7464e363\CompnentModelCache</code></li>
  <li>Clear out the any unit test runners from the Visual Studio Test Explorer extensions.  To do so, delete <code class="language-plaintext highlighter-rouge">%temp%\VisualStudioTestExplorerExtensions</code></li>
  <li>Restart Visual Studio.</li>
</ul>

<p>Though it was written in reference to Visual Studio 2013, this <a href="https://stackoverflow.com/questions/25304425/visual-studio-2013-doesnt-discover-unit-tests">StackOverflow Thread</a> was incredibly helpful and still relevant to Visual Studio 2017.  It’s where I found the right combination to fix my issue after some trial-and-error.  If the above isn’t working for you, there’s some other advice in the thread that may.</p>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="xunit" /><category term="visual-studio" /><category term="development" /><summary type="html"><![CDATA[Every once in a while, Visual Studio fails to discover my tests at all. There’s no build error, nor other indication in the output window or IDE… just zero tests discovered. This seemed to happen often when I was working with Service Fabric and the SDK/tools were updated. That may, or may not, be coincidence but, anecdotally, I haven’t seemed to encounter it outside of that context.]]></summary></entry><entry><title type="html">Visual Studio Test Discovery Error Due to Illegal Characters in the Path</title><link href="https://www.jessesquire.com/articles/2018/02/03/xunit-test-discovery-illegal-characters-in-path/" rel="alternate" type="text/html" title="Visual Studio Test Discovery Error Due to Illegal Characters in the Path" /><published>2018-02-03T17:28:12+00:00</published><updated>2018-02-03T17:28:12+00:00</updated><id>https://www.jessesquire.com/articles/2018/02/03/xunit-test-discovery-illegal-characters-in-path</id><content type="html" xml:base="https://www.jessesquire.com/articles/2018/02/03/xunit-test-discovery-illegal-characters-in-path/"><![CDATA[<p>I recently ran into an issue when working on a .NET Core application in which the Visual Studio failed to discover tests with an error about illegal characters in the path, despite the build being successful.  I spent a good amount of time looking over every path that was related to the solution - the project paths, build output paths, NuGet package paths, and any paths in the project configuration.  All to no avail.</p>

<p>After doing a bunch of searches, and trying a variety of things that didn’t work, turns out that the root cause had nothing to do with the solution or its projects.  Rather, it was related to my PATH environment variables.  In my case, the system PATH contained a path segment that was wrapped in double quotes and wasn’t playing nice.  Removing the quotes fixed things up and hasn’t seemed to have a negative impact in other areas that the PATH is used - at least, not that I’ve noticed so far.</p>

<p>I’m not sure if the underlying incompatibility was related to Visual Studio or the xUnit test runner, but thanks to this <a href="https://github.com/xunit/xunit/issues/1413">xUnit issue</a> for shedding light on the problem.</p>]]></content><author><name>{&quot;bluesky&quot; =&gt; &quot;omg.squire.wtf&quot;}</name></author><category term="articles" /><category term="xunit" /><category term="visual-studio" /><category term="development" /><summary type="html"><![CDATA[I recently ran into an issue when working on a .NET Core application in which the Visual Studio failed to discover tests with an error about illegal characters in the path, despite the build being successful. I spent a good amount of time looking over every path that was related to the solution - the project paths, build output paths, NuGet package paths, and any paths in the project configuration. All to no avail.]]></summary></entry></feed>