Jekyll2021-04-08T14:07:36-04:00https://blog.prokrams.com/feed.xmlMichael Letterle’s BlogPhenomenal Cosmic Powers in an itty bitty cubicleMichael Letterleblog@prokrams.comUsing NUnit’s Test Selection Language in .NET Core2019-12-16T08:37:00-05:002019-12-16T08:37:00-05:00https://blog.prokrams.com/2019/12/16/nunit3-filter-dotnet<p><a href="/2019/12/16/nunit3-filter-dotnet/#tldr">TLDR</a>; In the next release of the <a href="https://github.com/nunit/nunit3-vs-adapter">NUnit3 VS Test Adapter</a>, it will be possible to utilize filters written
in NUnit’s native <a href="https://github.com/nunit/docs/wiki/Test-Selection-Language">Test Selection Language</a>.</p>
<h2 id="background">Background</h2>
<p>With the release of <a href="https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-1">.NET Core 3.1</a>, I’ve been finding myself
working on porting a number of code bases from Windows-only .NET Framework to this new exciting cross-platform world. My .NET Unit Testing
Framework of choice has long been <a href="https://nunit.org/">NUnit</a> and a number of these code bases have utilized nunit to run continuous integration
testing.</p>
<!--more-->
<p>There is a lot of infrastructure in those CI processes that has been built around the <a href="https://github.com/nunit/nunit-console">nunit console runner</a>.
We specify output locations for the report xml via <code class="language-plaintext highlighter-rouge">--work</code> and <code class="language-plaintext highlighter-rouge">--result</code>, allowing the CI system to report on it. Since the system reports
on the aggregate of test runs across environments and systems, we also utilize the <a href="https://github.com/nunit/docs/wiki/Template-Based-Test-Naming">Template Based Test Naming</a>
with <code class="language-plaintext highlighter-rouge">--test-name-format</code> to distinguish the same test across environments. Since a single test assembly might have tests that are only valid on a
specific platform, over time a robust system of filters has developed using NUnit’s Test Selection Language and specified with <code class="language-plaintext highlighter-rouge">--where</code>.</p>
<p>Unfortunately, when it came time to start running some of these tests on <em>non-Windows</em> platforms, it was quickly discovered that the nunit console runner
is a <em>Windows-only</em> application (since it is compiled for the legacy Windows Framework). Luckily, we had already added the NUnit3 VS Test Adapter
to our test project in order to run tests from Visual Studio. This also allows us to use <code class="language-plaintext highlighter-rouge">dotnet test</code> to run the test project utilizing the NUnit test engine
anywhere .NET Core can run. So, the next step was to figure out how to configure the test engine via <code class="language-plaintext highlighter-rouge">dotnet test</code> to act in the same way as it does
with the <code class="language-plaintext highlighter-rouge">where</code>, <code class="language-plaintext highlighter-rouge">test-name-format</code>, <code class="language-plaintext highlighter-rouge">work</code>, and <code class="language-plaintext highlighter-rouge">result</code> command line options.</p>
<h2 id="configuring-the-nunit-engine">Configuring the NUnit Engine</h2>
<p>As it turns out, the <a href="https://github.com/microsoft/vstest">vstest framework</a> has an extensible framework for configuring test runners using <a href="https://github.com/microsoft/vstest-docs/blob/master/docs/configure.md">runsettings</a>. The documentation for NUnit’s <a href="https://github.com/nunit/docs/wiki/Tips-And-Tricks">Adapter Settings</a> shows a number of options that can be tweaked,
and <code class="language-plaintext highlighter-rouge">dotnet test</code> allows us to set these on the <a href="https://github.com/Microsoft/vstest-docs/blob/master/docs/RunSettingsArguments.md">command line</a>. For instance
given an existing command line of:</p>
<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">nunit3</span><span class="na">-console </span><span class="kd">TestAssembly</span>.dll <span class="na">--work</span><span class="o">=</span><span class="kd">workDir</span> <span class="na">--result</span><span class="o">=</span><span class="kd">test</span><span class="na">-results</span>\TestAssembly.xml <span class="na">--test-name-format</span><span class="o">=</span><span class="kd">testEnvironment</span>.<span class="o">{</span><span class="kd">m</span><span class="o">}</span>.<span class="o">{</span><span class="kd">a</span><span class="o">}</span>
</code></pre></div></div>
<p>You can get the same results with:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dotnet vstest TestAssembly.dll <span class="nt">--</span> NUnit.WorkDirectory<span class="o">=</span>workDir NUnit.TestOutputXml<span class="o">=</span>test-results NUnit.DefaultTestNamePattern<span class="o">=</span>testEnvironment.<span class="o">{</span>m<span class="o">}</span>.<span class="o">{</span>a<span class="o">}</span>
</code></pre></div></div>
<p>We use <code class="language-plaintext highlighter-rouge">dotnet vstest</code> in this example in order to operate on the pre-built test assembly. Passing runsettings to <code class="language-plaintext highlighter-rouge">dotnet test</code> to operate on a test project
works exactly the same way.</p>
<p>Note that the <code class="language-plaintext highlighter-rouge">result</code> option differs, this is because the console runner allows specification of the filename for the output, while the runsettings only allow
specification of the output directory (the filename is [TestAssembly].xml), so the two examples <em>are</em> equivalent.</p>
<h2 id="the-filtering-problem">The Filtering Problem</h2>
<p>But… what about <code class="language-plaintext highlighter-rouge">where</code>? This is where things got a bit tricker. As it turns out, vstest itself already has a cross-framework <a href="https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests#nunit">filtering language</a>
that supports NUnit. Unfortunately, the syntax is completely different from NUnit’s native Test Selection Language. Perhaps one could try to
translate between NUnit’s TSL and native VSTest filters, but that seems like adding a needless level of complexity. It’s also not clear that the
VSTest filter language even supports all of the same features as NUnit’s Test Selection Language. Plus, we can already pass other computed arguments
mostly unchanged between <code class="language-plaintext highlighter-rouge">nunit3-console</code> and <code class="language-plaintext highlighter-rouge">dotnet test</code>, why should <code class="language-plaintext highlighter-rouge">where</code> be any different? The NUnit engine used by both the console
runner and the vstest adapter supports the Test Selection Language, why not just expose the functionality the same way?</p>
<h2 id="tldr">The Solution</h2>
<p>Clearly something had to be done, so I rolled up my sleeves and dug into the NUnit engine and vstest adapter code to see what I could do. A couple days
of hacking later, and I submitted a <a href="https://github.com/nunit/nunit3-vs-adapter/pull/669">pull request</a> adding just this functionality to the
NUnit VS Adapter Settings. Any existing <code class="language-plaintext highlighter-rouge">where</code> argument can be specified in the runsettings and it should work exactly the same as if it
were passed to the console runner’s command line. This allows us to take an existing invocation of the console runner like:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nunit3-console TestAssembly.dll <span class="nt">--where</span><span class="o">=</span><span class="s2">"cat == SomeCategory or method == SomeMethodName or namespace == My.Name.Space or name == 'TestMethod(5)'"</span>
</code></pre></div></div>
<p>and pass the same filter unmodified to the test runner on .NET Core like:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dotnet <span class="nb">test</span> <span class="nt">--</span> NUnit.Where<span class="o">=</span><span class="s2">"cat == SomeCategory or method == SomeMethodName or namespace == My.Name.Space or name == 'TestMethod(5)'"</span>
</code></pre></div></div>
<p>And the exact same subset of tests should run.</p>
<p>Filtering can also be configured in a <code class="language-plaintext highlighter-rouge">.runsettings</code> file like so:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><RunSettings></span>
<span class="nt"><NUnit></span>
<span class="nt"><Where></span>cat == SomeCategory or method == SomeMethodName or namespace == My.Name.Space or name == 'TestMethod(5)'<span class="nt"></Where></span>
<span class="nt"></NUnit></span>
<span class="nt"></RunSettings></span>
</code></pre></div></div>
<p>And passed to <code class="language-plaintext highlighter-rouge">dotnet test -s [filename].runsettings</code>, <code class="language-plaintext highlighter-rouge">dotnet vstest --settings:[filename].runsettings</code>, or <code class="language-plaintext highlighter-rouge">vstest.console.exe /settings:[filename].runsettings</code></p>
<h2 id="summary">Summary</h2>
<p>There are a number of ways to configure the NUnit Test engine when running tests, using either the console runner or runsettings with vstest.
In the next release of the vstest adapter, it will be possible to pass a NUnit Test Selection Language filter to the test engine using a <code class="language-plaintext highlighter-rouge">NUnit.Where</code>
runsetting. This will allow filters that work with the existing console runner to be passed, unmodified, to the <code class="language-plaintext highlighter-rouge">dotnet test</code> command line.</p>
<p>Overtime, I would suspect more options and features to be added to the VS Test Adapter as it’s the most natural way to run NUnit tests under
.NET Core.</p>Michael Letterleblog@prokrams.comTLDR; In the next release of the NUnit3 VS Test Adapter, it will be possible to utilize filters written in NUnit’s native Test Selection Language. Background With the release of .NET Core 3.1, I’ve been finding myself working on porting a number of code bases from Windows-only .NET Framework to this new exciting cross-platform world. My .NET Unit Testing Framework of choice has long been NUnit and a number of these code bases have utilized nunit to run continuous integration testing.Kalamazoo X 2012: Hidden Gem Of The Midwest Conference Scene2012-05-03T21:53:49-04:002012-05-03T21:53:49-04:00https://blog.prokrams.com/2012/05/03/kalamazoo-x-2012-hidden-gem-of-the-midwest-conference-scene<p>I woke up on Saturday April 21st 2012 not knowing what to expect. Well, not exactly. <a href="https://twitter.com/mjeaton">Michael Eaton</a> had been telling me for the last few years about the conference he helps organize called <a href="http://kalamazoox.org">Kalamazoo X</a>. How he hand selects the best speakers he’s heard throughout the previous year and asks them to come out to Kalamazoo and give a 30 minute talk for the single track conference. Unlike your typical technical conference, KalX is strictly about soft skills. The touchy-feely type of information that another human saying to you will have a far greater impact than simply reading printed words on a page.</p>
<p>So, I had the <em>idea</em> of Kalamazoo X in my head, but still had not actually <em>experienced</em> it; and since no one’s baby is ugly, I couldn’t exactly count on Mr. Eaton as a <strong>completely</strong> unbiased observer. So I was unsure exactly what lay a head as I walked towards the venue on that crisp, cold and deceiptively sunny Michigan morning.</p>
<p>Leaving the lying Sun’s ineffectual rays behind, I entered the classroom of the community college where the event was being held. As I began to pour a rejuvenating cup of coffee, I glanced around the room. As noted above, KalX is single track, so all attendees are in the same room for the duration of the event. Now, KalX is described as a conference, but at this point it’s small enough that it may be more accurately described as a <em>gathering</em>. Attendence numbers under hundred, leading to a very intimate feeling. Like being surrounded by a group of friends to hear other friends talk with you.</p>
<p>As <a href="http://twitter.com/jeffblankenburg">Jeff Blankenburg</a> took the stage, I should have known that there should have been no room in my mind for any lingering doubts. For the next thirty minutes he did a fantastic job of speaking on the topic of “How to Learn”. A big point of Jeff’s talk was how “time” and “priority” are fungible. That is, you can exchange priority for time. One of the notes I made was that “Stupid sometimes equals Great”, meaning that mistakes are wonderful things to be embraced as that is how knowledge is gained.</p>
<p>Following up was <a href="http://twitter.com/objo">Joe O’Brien</a> on “People: The Missing Ingredient”. After hearing him talk about <a href="http://pragprog.com/book/ahptl/pragmatic-thinking-and-learning">“Pragmatic Thinking And Learning”</a> for about the billionth time, I finally broke down and bought myself a copy. Next was <a href="http://twitter.com/maniactive">Laura Bergells</a> with an excellent talk on the personality makeup of teams and how opposing personalities make a team complete, the idea of “Creative Tension” as opposed to stagnant “Groupthink”. <a href="http://twitter.com/suzanbond">Suzan Bond</a> took center stage with an amazing talk on intuition, with a riveting lead-in story of how intuition saved her life. The ever entertaining <a href="http://twitter.com/rubybuddha">Leon Gersing</a> gave a interesting presentation titled “Going Gonzo” about pushing boundaries of the dominant culture. One of the notes I made from that talk still resonates with me today: “The pressure to be right leads to lack of wisdom.”</p>
<p>By this time, it was the middle of the day and it was time for a break. Lunch was a nice selection of box lunches. A decent enough meal and enough fuel to recharge for the second half of the day. Unbelievably this was only 50% of the talks so far!</p>
<p>After lunch was <a href="http://twitter.com/timwingfield">Tim Wingfield</a> with a talk on “Your Career Is Yours”, a talk that surely resonated with a number of the students in the room. However there was a great deal of valuable reminders about what it means to have a <em>career</em> in Software Development for anyone of any level. <a href="http://twitter.com/searls">Justin Searls</a> took hit the proverbial stage with a talk that is marked in my notes as being <strong>SO AWESOME</strong>. The talk was titled “The Mythical Team-Month” and was a great sermon on the values of early failure with quick turn around. <a href="http://twitter.com/antiheroine">Jen Myers</a> followed up with the talk “Developers Can’t Design and Other Myths”, a talk I had seen her give at <a href="http://www.codemash.org">CodeMash</a> earlier in the year and which was still enlightening to see a second time. <a href="http://twitter.com/elizabethn">Elizabeth Naramore</a> instructed us on “Dealing With Difficult People” by noting that it’s often a case if you having to deal with yourself. The always fascinating <a href="http://twitter.com/alanstevens">Alan Stevens</a> finished off the day with “Making A Difference”, a creed on transforming the world by starting with ourselves. One of the quotes that stuck with my from that inspiring talk was “Armoring yourself is not brave. Bravery is taking your armor off”. That is, it is far braver to expose yourself than it is to hide yourself away.</p>
<p>Overall the number one theme at Kalamazoo X seemed to be that one must strive to subvert their natural defensive mechanisms. Hack your mind.</p>
<p>It’s really hard to describe with written word how inspiring and polished all these speakers were. All had amazing stage presence with excellent material delivered in clear and concise, yet entertaining ways. Any one of these talks would be a worthy keynote at any conference of any size. I hear <a href="https://twitter.com/#!/mjeaton/statuses/194129067379920896">rumors</a> that videos of the talk may make their ways online, and I certainly hope this is the case. Not only because I hope others can be similarly enlightened, but also I’d really like to experience those talks over again!</p>
<p>Kalamazoo X is really a hidden gem of the midwest region conference scene, one I can’t believe I’ve skipped the past three years. Miss it at your own peril. I know I’ll be returning.</p>michaelI woke up on Saturday April 21st 2012 not knowing what to expect. Well, not exactly. Michael Eaton had been telling me for the last few years about the conference he helps organize called Kalamazoo X. How he hand selects the best speakers he’s heard throughout the previous year and asks them to come out to Kalamazoo and give a 30 minute talk for the single track conference. Unlike your typical technical conference, KalX is strictly about soft skills. The touchy-feely type of information that another human saying to you will have a far greater impact than simply reading printed words on a page.Hudson and TFS2008 For Continuous Integration2010-07-24T15:16:03-04:002010-07-24T15:16:03-04:00https://blog.prokrams.com/2010/07/24/hudson-and-tfs2008-for-continuous-integration<p>At <a href="http://www.preemptive.com/">work</a> we’re taking some time to get a proper <a href="http://en.wikipedia.org/wiki/Continuous_Integration">CI</a> environment up and running. Since we also have <a href="http://www.preemptive.com/products/dasho/overview">a Java product</a>, <a href="http://hudson-ci.org/">Hudson</a> was already set up and being used. I had used Hudson in the past for doing continuous integration of <a href="http://www.ironruby.net/">IronRuby</a> under <a href="http://www.mono-project.com/Main_Page">Mono</a> on <a href="http://www.ubuntu.com/">Linux</a>. Getting our build up and running was pretty much a breeze thanks to the <a href="http://wiki.hudson-ci.org/display/HUDSON/Team+Foundation+Server+Plugin">TFS</a>, <a href="http://wiki.hudson-ci.org/display/HUDSON/Gallio+Plugin">Gallio</a>, <a href="http://wiki.hudson-ci.org/display/HUDSON/MSBuild+Plugin">MSBuild</a>, and <a href="http://wiki.hudson-ci.org/display/HUDSON/NCover+Plugin">NCover</a> plugins. Once that was set up and running, it was easy enough to<a href="http://msdn.microsoft.com/en-us/magazine/cc507647.aspx"> subscribe to the CheckinEvent on TFS</a> and have it<a href="http://wiki.hudson-ci.org/display/HUDSON/Remote+access+API"> ping a defined URL</a> on Hudson to kick off the build. Yay! Proper Continuous Integration!</p>
<p>But then something unexpected started to happen. At two hour intervals, the build would kick off, even if not check in had occurred! Some digging into the Windows Event Log, lead to what seemed to be the culprit. Every two hours TFS syncs users and groups with Active Directory. For some reason this raises a CheckinEvent. So the cause was discovered, now how to stop it? A quick searching on [SearchEngine] revealed<a href="http://blogs.msdn.com/b/adamsinger/archive/2007/07/31/great-news.aspx"> this tidbit</a>:</p>
<blockquote>
<p>you can now take advantage of the ability to modify the periodic AD/GSS sync period. To do so, you need to manually modify a Web.config file on the Application Tier that by deafult will appear under the folder “%PROGRAMFILES%\Microsoft Visual Studio 2008 Team Foundation Server\Web Services\services”. DISCLAIMER: I do not guarrantee that this will not cause your computer to eat all of the data it has ever come into contact with, possible with fire. This confers no warranties and no rights, your mileage may vary, use at your own risk, void where prohibited, etc. [Note: still my blog]. You’ll need to add the following two lines to the key/value pair section at the top of this file, followed by resetting IIS to make sure our application pool picks up the changes:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><add key="IdentityUpdatePeriod" value="01:00:00" />
<add key="IdentityUpdateInitial" value="01:00:00" />
</code></pre></div> </div>
<p>Note that I’ve set both the initial update (i.e. the delay after startup that the first periodic sync happens) and the delay between periodic syncs to 1 hour. You can increase this to multiple hours, or decrease it to a matter of minutes.</p>
</blockquote>
<p>So after making those changes, I noticed that the Events were no longer being logged every two hours, but the CheckinEvent was still getting raised at that interval! What could be going on? Well after some (read: A LOT) of [SearchEngine]ing, <a href="http://blogs.msdn.com/b/granth/archive/2008/09/15/does-tfs-guarantee-event-subscription-delivery.aspx">it turns out</a>, TFS will automatically try resending “failed” alerts every two hours for ~12 hours. Since the CheckinEvent subscription is expecting a SOAP webservice, and not just a random url, it thinks that the notification “failed” when it doesn’t get the response it expects. Causing it to try resending to the same url over, and over, and over again at two hour intervals.</p>
<p>So what we need is a very very simple web service to take the SOAP message then turn around and ping a url. This way TFS gets the response it expects and acknowledges that the notification was successfully sent.</p>
<p>All you have to do is implement the ‘Notify’ method that TFS expects to be able to call:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nf">SoapDocumentMethod</span><span class="p">(</span><span class="s">"http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify"</span><span class="p">,</span> <span class="n">RequestNamespace</span> <span class="p">=</span> <span class="s">"http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03"</span><span class="p">)]</span>
<span class="p">[</span><span class="n">WebMethod</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Notify</span><span class="p">(</span><span class="kt">string</span> <span class="n">eventXml</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">try</span>
<span class="p">{</span>
<span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">WebRequest</span> <span class="n">req</span> <span class="p">=</span> <span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">HttpWebRequest</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="s">"http://www.example.org/hudson/job/AutomatedBuild/build?token=TOKEN"</span><span class="p">);</span>
<span class="n">req</span><span class="p">.</span><span class="nf">GetResponse</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">catch</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I have put together a simple service that will do this for multiple URLs defined in the Web.config. Feel free to get it <a href="http://github.com/mletterle/TFSUrlPinger">here</a> at <a href="https://github.com/">GitHub</a> and save yourself the frustration I encountered.</p>michaelAt work we’re taking some time to get a proper CI environment up and running. Since we also have a Java product, Hudson was already set up and being used. I had used Hudson in the past for doing continuous integration of IronRuby under Mono on Linux. Getting our build up and running was pretty much a breeze thanks to the TFS, Gallio, MSBuild, and NCover plugins. Once that was set up and running, it was easy enough to subscribe to the CheckinEvent on TFS and have it ping a defined URL on Hudson to kick off the build. Yay! Proper Continuous Integration!25 Random Facts About The Prokrammer2009-02-05T22:40:13-05:002009-02-05T22:40:13-05:00https://blog.prokrams.com/2009/02/05/25-random-facts-about-the-prokrammer<p>This meme has been floating around Facebook lately, I’m not going to tag anyone here since I did it there, but thought I’d share this list with those of you who might not be on Facebook:</p>
<p>(progn (setq num 1)(princ “\n\n25 Random Things About Me\n\n”)(while (< num 26) (princ (format “%d. \n” num))(setq num (1+ num))))</p>
<p>25 Random Things About Me</p>
<ol>
<li>I have been programming since I was 8.</li>
<li>I’m writing this list in emacs.</li>
<li>I was on the Varsity Team for the 1997 Ohio State Academic Decathlon Team.</li>
<li>I’ve only been west of the Mississippi once, for the National Academic Decathlon Championships in St. George, Utah.</li>
<li>I spent the ages of 5 to 9 in Marietta, GA.</li>
<li>I’m fantastically good at making my daughter vomit.</li>
<li>I spent a year at DeVry in Columbus working on a BA in Electronic Engineering, before moving back home. I flunked every class.</li>
<li>I worked in Technical support for 8 years, all the way up to Middle Management until I had the chance to take an “Employee Requested Demotion” to get started programming.</li>
<li>I was introduced to my wife in high school, but we really didn’t meet until we ran across each other on AOL. We had lived less then a mile apart for almost a decade.</li>
<li>I was a BBS junkie growing up during my teens. I even sysop’d my own for a while.</li>
<li>My buddy (Jim Balcomb) and I use to sneak out of my house in the middle of the night to go dumpster diving. “I’m pretending to be a garbage bag, shut up!”</li>
<li>I was one of those linux zealots who hated Microsoft and vowed never to work in an MS shop… until I started getting paid to support a small number of Terminal Servers (the rest were running an OS called Real/32). Now I’m a Microsoft MVP.</li>
<li>I’m currently keeping track of everything I eat and drink, in order to force myself to be healthier in my choices. You can see what I’m eating and drinking here: <a href="http://twitpic.com/photos/mletterle_diet">http://twitpic.com/photos/mletterle_diet</a></li>
<li>My wife and I tried to have a baby for four years before we finally had our daughter via IVF.</li>
<li>Three days after our daughter was born, we had to rush her to the hospital at 4am. I rode in the ambulance that took her from the ER to the Children’s hospital. Three weeks later she came out healthy and we haven’t looked back since.</li>
<li>I was absolutely terrified of getting my blood taken and hated shots, before we had to go through IVF. I still don’t like them, but I no longer am in mortal terror for a blood draw or shot.</li>
<li>I smoked cigarettes regularly from about age 14 until 20, including pipes in college. I still enjoy a good cigar now and then.</li>
<li>I own two guitars, an acoustic and an electric. I play both poorly, but am determined to be good (at least passable) on them someday.</li>
<li>I once read Dante’s Inferno over summer vacation while a teen. Just because I wanted to.</li>
<li>I am very dexterous with my feet. I can pick up and throw things with them. My mother always said we had Hobbit feet, owning to the patch of hair on top.</li>
<li>I took the cookie from the cookie jar. See number 13.</li>
<li>I am an Eagle Scout. But only because my parents hounded me about it for a good two years.</li>
<li>I can crack the bones in my right toes on demand.</li>
<li>I once [REDACTED] in [REDACTED] to [REDACTED] until [REDACTED].</li>
<li>Yes, I wrote the lisp program above so I wouldn’t have to type all these numbers. <br />
nil</li>
</ol>michaelThis meme has been floating around Facebook lately, I’m not going to tag anyone here since I did it there, but thought I’d share this list with those of you who might not be on Facebook:The 30 Day Intake Experiment2009-01-31T21:49:13-05:002009-01-31T21:49:13-05:00https://blog.prokrams.com/2009/01/31/the-30-day-intake-experiment<p>My entire life I’ve been what is commonly known as “fat”, or, as the clothing industry calls it, “Big and Tall”. I have been blessed with both an impressive girth and height. For as long as I can remember these have been my defining physical qualities. I generally cast an imposing figure over my contemporaries, that didn’t stop the teasing during my childhood of course, but those times passed generally without much incident. And for years these attributes caused me no real harm, medically I was “healthy” besides my obesity. My cholesterol was low, my blood pressure normal, no problems with sugar levels.</p>
<p>Now, as I stare down thirty, this is no longer quite true. For the most part I’m still healthy (again, except for the pounds of extra flesh), but cracks in my infrastructure have begun to creep up. The blood pressure is starting to tick up slightly, the cholesterol and sugar are still good, for now. But more worrisome is my knees. Starting about a year and a half ago they began “grinding” and generally starting to, well, not be their old weight-supporting selves any more. Even more troubling is I have a family history of knee problems. My father (who is NOT obese) is having both his knees replaced this year.</p>
<p>So, what does this have to do with the title of this blog post? What is the “30 Day Intake Experiment”? The 30 day experiment I am about to take is my first step towards, hopefully, leading a more healthy life style. This is my attempt to be honest with myself about my eating habits. For the next thirty days, I will be recording EVERY piece of food and drink that I consume. I have created a <a href="http://twitter.com/mletterle_diet">twitter account</a> and will be posting pictures of every meal I have every day. In this manner I will not be able to “cheat” or lie to myself about what my diet <em>is</em>.</p>
<p>I fully intend to follow this up with increased physical activity as well, it’s a little difficult during the height of a Cleveland winter, but I will find some way. This is simply the first step. Believe it or not, I once had a membership at a gym, and those two years were probably when I’ve felt the most energetic and healthy. It’s definitely something I want to get back to. Ironically, I originally joined the gym in anticipation of our daughter, and haven’t been able to go back since we’ve had her. Children take up a ton of time :)</p>
<p>In another twist, completely unknown to me, this month is the “<a href="http://calebjenkins.wordpress.com/2009/01/29/official-rules/">Fit in February Developer Challenge</a>”. Strangely apropos don’t you think?</p>michaelMy entire life I’ve been what is commonly known as “fat”, or, as the clothing industry calls it, “Big and Tall”. I have been blessed with both an impressive girth and height. For as long as I can remember these have been my defining physical qualities. I generally cast an imposing figure over my contemporaries, that didn’t stop the teasing during my childhood of course, but those times passed generally without much incident. And for years these attributes caused me no real harm, medically I was “healthy” besides my obesity. My cholesterol was low, my blood pressure normal, no problems with sugar levels.Agile Summer Camp Recap2008-09-08T21:32:53-04:002008-09-08T21:32:53-04:00https://blog.prokrams.com/2008/09/08/agile-summer-camp-recap<p>I had the pleasure of spending this past weekend with a group of about two dozen of the most talented and<a href="http://blog.prokrams.com/wp-content/uploads/2008/09/agilesummercamp.png"><img src="http://blog.prokrams.com/wp-content/uploads/2008/09/agilesummercamp-thumb.png" alt="AgileSummerCamp" /></a> passionate developers in this region, and some from outside. This was no ordinary conference though, this was camping! We had no electricity, no flushing toilets, and a hand pump for running water. The great thing about the lack of power though is that distraction was at an absolute minimum, all we could really do was talk and listen. I kept a camp journal, below is the transcription (with some embellishment):</p>
<hr />
<p>9/5/08</p>
<p>We have arrived at Agile Summer Camp. After claiming a bottom bunk in the rear of the cabin, I am sitting in my camp chair enjoying a beer while <a href="http://blog.sonerdy.com/">Brandon Joyce</a>, funky town dancer extraordinaire, cranks the camp radio so we can listen to <a href="http://www.isaachayes.com/">Chef</a> (RIP) croon on a 70s station. <a href="http://www.codinggeekette.com/">Sadukie</a> is dead-tree blogging and <a href="http://blog.cloudsocket.com/">Woody</a> and <a href="http://matthew.werstler.name/page.asp?page=bio">Matt Werstler</a> have gone for firewood. We are anxiously awaiting the arrival of <a href="http://michaeleatonconsulting.com/blog/">Mike Eaton</a> who has recently called and is nearby.</p>
<p>Suddenly, a car arrives. Could this be Mr. Eaton? Or a guy with a chainsaw (I hope he has <a href="http://www.youtube.com/watch?v=7aO3TO5L0bM">bud light</a>!). It turns out to be <a href="http://www.joshholmes.com/">Josh Holmes</a> (who looks like he could have a chainsaw…). He is followed shortly by Eaton, and then others.</p>
<p>There was a guest log in the back of the cabin packet that contained a riddle, as people arrived we asked for them to take it on, but no one could come up with an answer, see if you can:</p>
<blockquote>
>
> We buried the loot where the fish used to swim
>
>
>
> 40 paces westerly of monitor, third stopper (not for bathtub) from the left. one foot down right side.
>
>
>
> 1st Clue: Are you good enough?
>
>
>
> -John from Beaverton May 26, 2008
>
> </blockquote>
<p>The evening ends with awesome discussions on community and a few already on the topic of agile. Also me and Mike Eaton finish a fifth and a pint of <a href="http://www.jackdaniels.com/Default.aspx">Jack</a> ourselves (okay <a href="http://www.platinumbay.com/blogs/">Steve Andrews</a> helped a <em>little)</em>.</p>
<hr />
<p>9/6/08</p>
<p>CLANK! CLING! CLANG! I am roused from my fitful sleep by the sharp cry of metal to metal. I change in my sleeping bag and make my way out of the cabin to find turkey sausage and eggs being cooked on the, now assembled, camp stove….</p>
<hr />
<p><a href="http://www.flickr.com/photos/sadukie/2838455464/sizes/m/"><img src="http://farm4.static.flickr.com/3091/2838455464_e73bf697dd.jpg" alt="" /></a></p>
<p>The rest of the journal devolves into generic notes, most of which can be found <a href="http://www.agilesummercamp.com/wiki/proposedTopics.ashx">here</a> (along with a lot more detail on the actual sessions).</p>
<p>Needless to say it was very educational and loads of fun.</p>michaelI had the pleasure of spending this past weekend with a group of about two dozen of the most talented and passionate developers in this region, and some from outside. This was no ordinary conference though, this was camping! We had no electricity, no flushing toilets, and a hand pump for running water. The great thing about the lack of power though is that distraction was at an absolute minimum, all we could really do was talk and listen. I kept a camp journal, below is the transcription (with some embellishment):Interviewed on Alt.NET Podcast2008-08-29T22:19:31-04:002008-08-29T22:19:31-04:00https://blog.prokrams.com/2008/08/29/interviewed-on-altnet-podcast<p>I had the pleasure of being <a href="http://altnetpodcast.com/episodes/9-state-of-ironruby">interviewed</a> along side <a href="http://rubydoes.net/">Aaron Junod</a> on the <a href="http://altnetpodcast.com/">Alt.NET Podcast</a> to discuss <a href="http://www.ironruby.net">IronRuby</a>. <img src="http://blog.prokrams.com/wp-content/uploads/2008/08/altdotnetmike.png" alt="altdotnetmike" /></p>
<p><a href="http://blowmage.com/">Michael Moore</a> was a wonderful host and did an amazing job editing the conversation down to something tight. It was an exciting opportunity to talk about IronRuby specifically and Ruby in general. Hopefully it will help spark even more interest in it.</p>
<p>On a personal note, I’m interested in any feedback you might have, from the technical to the stylistic. It was my first time doing a podcast, so it’s definitely a learning experience for me.</p>michaelI had the pleasure of being interviewed along side Aaron Junod on the Alt.NET Podcast to discuss IronRuby. devLink 2008: Open Spaces and Waffle Houses2008-08-27T23:06:54-04:002008-08-27T23:06:54-04:00https://blog.prokrams.com/2008/08/27/devlink-2008-open-spaces-and-waffle-houses<p>I had the pleasure of attending <a href="http://www.devlink.net/">devLink</a> this past weekend in <a href="http://www.mtsu.edu/">Murfreesboro, Tennessee.</a> Honestly, I almost blew this conference off. The sessions really didn’t appeal to me, and it was a bit of a hike to get to. But then <a href="http://www.pandamonial.com/">Amanda Laucher</a> <a href="http://www.pandamonial.com/2008/06/devlink-bus-route.html">announced</a> the <a href="http://www.devlink.net/TravelInfo/RidethedevLinkBus/tabid/116/Default.aspx">DevLink Bus</a>. And I started to waver… Then I heard that <a href="http://netcave.org/">Alan Stevens</a> would be organizing <a href="http://www.openspaceworld.org/">Open Spaces</a> during the conference. I was sold.</p>
<p>Wednesday evening around 7:30, my wife dropped me off at <a href="http://www.codinggeekette.com/">Sadukie’s</a> house. <a href="http://blog.sonerdy.com/">Brandon Joyce</a> was already there, watching <a href="http://www.familyguy.com/">Family Guy</a>. After Sadukie finished gathering up her wares, we piled into her Durango and headed off to pick up <a href="http://www.coreyhaines.com/coreysramblings/">Corey Haines</a>. A quick trip across town and we were <a href="http://maps.google.com/maps?f=d&saddr=Cleveland,+OH&daddr=Toledo,+OH&hl=en&geocode=&mra=ls&sll=41.540243,-81.444292&sspn=0.007757,0.019312&ie=UTF8&t=h&z=9">on our way</a> to Toledo to catch the bus.</p>
<p>Well, more accurately we were on our way to Toledo to <em>wait</em> for the bus. The bus apparently went to the wrong side of town and it had to turn around to pick us up. This wasn’t entirely bad. It gave us enough time to pick up beer and for Corey to have an impromptu parking lot concert. And what’s better then beer and music?</p>
<p><img src="http://farm4.static.flickr.com/3071/2793807246_80ea256399_m.jpg" alt="" /></p>
<p>Eventually the bus arrived and we REALLY began our journey. A journey of <a href="http://www.imdb.com/title/tt0090305/">corny movies</a> and <a href="http://en.wikipedia.org/wiki/Insomnia">lack of sleep</a>. After much tossing and turning and cursing of lack of leg room, we arrived in Tennessee about 9am. At which point I collapsed in my <a href="http://doubletree1.hilton.com/en_US/dt/hotel/MBTDTDT/index.do">hotel</a> room and passed out. Waking up in the evening, I followed my instinct to the local hotel bar/restaurant. Later on, I ended up making my way to Alan’s room where a party was going down. Guitars, Cigars, and Beers were being passed around with abandon until hotel security came to the door and asked us nicely to stop.</p>
<p>The rest of the time in Tennessee is really a blur. I wish I could give a detailed synopsis of each day, replete with details and names. But honestly, the days meld into one another, linked only by great conversations, new experiences, and wonderful people. I can’t stress enough the amount of knowledge I gained, and the success of the Open Space format that was put into place.</p>
<p>Alas, it was over much too soon. By Saturday night it was time to board the bus once again, and make the long, <a href="http://www.imdb.com/title/tt0118715/">movie</a> filled trip back to Ohio… Who knows, maybe this time I could get some sleep? I cuddled up to the window and slowly drifted…</p>
<p>“THUMP, THUMP, THUMP, THUMP!” Okay, so sleep wasn’t going to happen.</p>
<p>[</p>
<p><img src="http://farm4.static.flickr.com/3266/2797454393_a608e72fa4_m.jpg" alt="" /></p>
<p>](http://www.flickr.com/photos/29942169@N08/2797454393/sizes/s/in/set-72157606951193028/)</p>
<p>A blown tire. Great, <a href="http://infozerk.com/averyblog/">James Avery’s</a> ribbing about <a href="http://en.wikipedia.org/wiki/Cliff_Burton">“Everyone was screaming… except Cliff”</a> went through my head. It didn’t help that we passed <a href="http://en.wikipedia.org/wiki/Carrollton_bus_disaster">a sign commemorating a 1988 bus tragedy</a> (<a href="http://twitter.com/AlanBarber/statuses/897100189">no joke</a>). The bus slowly inched along, until we pulled into a gas station in <a href="http://maps.google.com/maps?hl=en&q=english+kentucky&ie=UTF8&ll=38.641009,-85.128593&spn=0.129521,0.30899&t=h&z=12">English, Kentucky</a>. Our faces aglow in the soft light of nearby Waffle House. We waited. And Waited. <a href="http://www.cootersplace.com">Cooter</a> showed up, and proceeded to sheer three bolts off the wheel. So we continued to wait. But while we waited, a remarkable thing happened. Incredible conversations took place. On <a href="http://www.flickr.com/photos/29942169@N08/2797907590/in/set-72157606951193028/">Comments</a>, on <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">SRP</a>, and any number of things. The Open Spaces continued into the most open space possible, the world beyond the conference. Then the acetylene torch came out.</p>
<p>[</p>
<p><img src="http://farm4.static.flickr.com/3036/2797488593_dbbb788cab_m.jpg" alt="" /></p>
<p>](http://www.flickr.com/photos/29942169@N08/2797488593/sizes/s/in/set-72157606951193028/)</p>
<p>So we waited a bit more. Marriages came and went we waited so long. Eventually a new tire was on and we were off. By 1pm I was home holding my daughter and reflecting on a fantastic conference. I was thankful I ended up going, though some images will be seared into my brain, forever.</p>
<p><a href="http://www.flickr.com/photos/29942169@N08/2797451193/sizes/s/in/set-72157606951193028/"><img src="http://farm4.static.flickr.com/3014/2797451193_e8576bf235_m.jpg" alt="" /></a></p>
<p>I’ll at least be able to say I shared a tour bus with a member of <a href="http://en.wikipedia.org/wiki/Ratt">Ratt</a>.</p>
<p><img src="http://farm4.static.flickr.com/3277/2797212777_60a629222e_m.jpg" alt="" /></p>
<p>The best part is that the conversation continues at the <a href="http://heartlandopenspaces.com">Heartland Open Spaces Wiki</a>. Be sure to stop by and join in!</p>
<p>Next, I’ll be at <a href="http://www.agilesummercamp.com/">Agile Summer Camp</a>, and then I’m home until <a href="http://www.codemash.org/">CodeMash</a> in January 2009. To all my new friends, old friends, and friends to be, I hope to see you there!</p>michaelI had the pleasure of attending devLink this past weekend in Murfreesboro, Tennessee. Honestly, I almost blew this conference off. The sessions really didn’t appeal to me, and it was a bit of a hike to get to. But then Amanda Laucher announced the DevLink Bus. And I started to waver… Then I heard that Alan Stevens would be organizing Open Spaces during the conference. I was sold.IronRuby vs JRuby vs MRI. Performance Mini-Shootout.2008-08-27T21:15:52-04:002008-08-27T21:15:52-04:00https://blog.prokrams.com/2008/08/27/ironruby-vs-jruby-vs-mri-performance-mini-shootout<p>One of the things I went over in my <a href="http://blog.prokrams.com/2008/08/25/erubycon-recap/">eRubyCon talk</a> was the relative performance of <a href="http://www.ironruby.net/">IronRuby</a> compared to both <a href="http://jruby.codehaus.org/">JRuby</a> <a href="http://flickr.com/photos/46576087@N00/2141649813/sizes/s/"><img src="http://farm3.static.flickr.com/2254/2141649813_03e886d464_m.jpg" alt="" /></a>(which I consider to be a cousin of sorts to IronRuby) and <a href="http://www.ruby-lang.org/en/">MRI</a>. I did this by running the <a href="http://antoniocangiano.com/2007/12/03/the-great-ruby-shootout/">same tests</a> that <a href="http://antoniocangiano.com/">Antonio Cangiano</a> ran in December.</p>
<p>There were a few test results that really stood out. The lists test was by far the worst for IR, where it was 56 times as slow as MRI and 3 times as slow as JRuby. But this wasn’t the only sore spot, there were other places that show room for improvement. Namely, vm1_blocks in which IronRuby was almost 9 times as slow as MRI. Also so_exception where IronRuby brought up the tail by being 10 times as slow as MRI.</p>
<p>The nitty gritty is that IronRuby is about twice as slow as MRI with JRuby being slightly faster, overall. As the below graph illustrates:</p>
<p><a href="http://blog.prokrams.com/wp-content/uploads/2008/08/image.png"><img src="http://blog.prokrams.com/wp-content/uploads/2008/08/image-thumb.png" alt="image" /></a></p>
<p>There are a few high points in this test though. Number one, is that IronRuby ran the majority of the tests. There were only four failures out of forty, for a 90% success rate. For comparison JRuby had 95% success rate. Number two, there were actually a few tests in which IronRuby beat JRuby and MRI. No small feat for such a young implementation.</p>
<p>I think this mini-shootout illustrates that there is a lot of room for improvement for IronRuby. However, a little perspective goes a long way. JRuby was <a href="http://groups.google.com/group/comp.lang.ruby/msg/7d05f2ad7d84e6f3?hl=en">announced in 2001</a>, IronRuby was <a href="http://www.iunknown.com/2007/04/introducing_iro.html">announced last April</a>. The JRuby team has had 7 years to get to where they are today, whereas IronRuby has only had almost a year and a half! As the DLR improves IronRuby will receive those performance gains for free, and as compatibility becomes more stable the core team can focus on performance as well. The raw data can be downloaded <a href="http://prokrams.com/files/ShootOut.csv">here</a>.</p>michaelOne of the things I went over in my eRubyCon talk was the relative performance of IronRuby compared to both JRuby (which I consider to be a cousin of sorts to IronRuby) and MRI. I did this by running the same tests that Antonio Cangiano ran in December.eRubyCon Recap2008-08-25T21:30:28-04:002008-08-25T21:30:28-04:00https://blog.prokrams.com/2008/08/25/erubycon-recap<p>What a fantastic conference this was two weeks ago. A great lineup of speakers, and fantastic after event gatherings. And I missed the first day! <a href="http://www.joshholmes.com">Josh Holmes</a> has a great <a href="http://www.joshholmes.com/CategoryView,category,eRubyCon.aspx">series of posts</a> detailing the event, so I won’t repeat the play by play here. But I can say that I will definitely be making the trip to Columbus for <a href="http://www.erubycon.com/">eRubyCon</a> 2009.</p>
<p>This was the first conference I have gone to where I actually presented. My talk was originally geared more towards .NET developers interested in Ruby, thinking that there would be more Java and .NET enterprise folks there then it turned out. After I arrived, as I listened to the attendees, I realized the audience was primarily people already doing Ruby. I also noticed a certain level of distrust around Microsoft in general, even though the event was hosted in their office! As I was going to be speaking on <a href="http://www.ironruby.net">IronRuby</a>, a Microsoft project, this concerned me a bit. So I ended up putting in an opening section about some of, what I believe to be, the positive changes at Microsoft over the last half-decade or so. I highlighted efforts like <a href="http://www.codeplex.com">CodePlex</a> and <a href="http://port25.technet.com">Port25</a>. A number of people seemed to copy down the Port25 address, so I hope I helped open some eyes in this case. I also went over the current state of IronRuby, and compared it’s performance to <a href="http://jruby.codehaus.org/">JRuby</a>. I then asked who did .NET work in their day to day jobs and must have had about 5 people raise their hands. Then I went through a short demo of opening up and changing a standard WinForms app using IronRuby. It seemed to go well, I’ve gotten positive feedback on it and a number of suggestions for improvement.</p>
<p>I can’t thank <a href="http://www.objo.com/">Joe O’Brien</a> enough for the opportunity or confidence in me he showed by allowing me to speak. The slides and demo used for my presentation are <a href="http://prokrams.com/decks/eRubyCon/2008/IronRubyRealWorld.zip">here</a>.</p>michaelWhat a fantastic conference this was two weeks ago. A great lineup of speakers, and fantastic after event gatherings. And I missed the first day! Josh Holmes has a great series of posts detailing the event, so I won’t repeat the play by play here. But I can say that I will definitely be making the trip to Columbus for eRubyCon 2009.