DaedTech

Stories about Software

By

How To Put Your Favorite Source Code Goodies on Nuget

A while back, I made a post encouraging people to get fed up every now and then and figure out a better way of doing something. Well, tonight I take my own advice. I am sick and tired of rifling through old projects to find code that I copy and paste into literally every non-trivial .NET solution that I create. There’s a thing for this, and it’s called Nuget. I use it all the time to consume other people’s code, libraries and utilities, but not my own. Nope, for my own, I copy and paste stuff from other projects. Not anymore. This ends now.

My mission tonight is to take a simple bit of code that I add to all my unit test projects and to make it publicly available view Nuget. Below is the code. Pretty straightforward and unremarkable. For about 5 versions of MSTest, I’ve hated the “ExpectedException” attribute for testing that something throws an exception. It’s imprecise. All it tests is that somewhere, anywhere, in the course of execution, an exception of the type in question is thrown. Could be on the first line of the method, could be on the last, could happen in the middle from something nested 8 calls deep in the call stack. Who knows? Well, I want to know and be precise, so here’s what I do instead:

public static class ExtendedAssert
{
    /// Check that a statement throws a specific type of exception
    /// Exception type inheriting from Exception
    /// Action that should throw the exception
    public static void Throws(Action executable) where TException : Exception
    {
        try
        {
            executable();
        }
        catch (Exception ex)
        {
            Assert.IsTrue(ex.GetType() == typeof(TException), String.Format("Expected exception of type {0} but got {1}", typeof(TException), ex.GetType()));
            return;
        }
        Assert.Fail(String.Format("Expected exception of type {0}, but no exception was thrown.", typeof(TException)));
    }

    /// Check that a statement throws some kind of exception
    /// Action that should throw the exception
    /// Optionally specify a message
    public static void Throws(Action executable, string message = null)
    {
        try
        {
            executable();
        }
        catch
        {
            Assert.IsTrue(true);
            return;
        }
        Assert.Fail(message ?? "Expected an exception but none was thrown.");
    }

    /// Check that a statement does not throw an exception
    /// Action to execute
    public static void DoesNotThrow(Action executable)
    {
        try
        {
            executable();
        }
        catch (Exception ex)
        {
            Assert.Fail(String.Format("Expected no exception, but exception of type {0} was thrown.", ex.GetType()));
        }
    }

Now, let’s put this on Nuget somehow. I found my way to this link, with instructions. Having no idea what I’m doing (though I did play with this once, maybe a year and a half ago), I’m going with the GUI option even though there’s also a command line option. So, I downloaded the installer and installed the Nuget package explorer.

From there, I followed the link’s instructions, more or less. I edited the package meta data to include version info, ID, author info, and a description. Then, I started to play around with the “Framework Assemblies” section, but abandoned that after a moment. Instead, I went up to Content->Add->Existing file and added ExtendedAssert. Once I saw the source code pop up, I was pretty content (sorry about the little Grindstone timer in the screenshot — didn’t notice ’til it was too late):

PackageExplorer

Next up, I ran Tools->Analyze Package. No issues found. Not too shabby for someone with no idea what he’s doing! Now, to go for the gusto — let’s publish this sucker. File->Publish and, drumroll please…. ruh roh. I need something called a “Publish Key” to publish it to nuget.org.

PublishKey

But, as it turns out, getting an API key is simple. Just sign up at nuget.org and you get one. I used my Microsoft account to sign up. I uploaded my DaedTech logo for the profile picture and tweaked a few settings and got my very own API key (found by clicking on my account name under the “search packages” text box at the top). There was even a little clipboard logo next to it for handy copying, and I copied it into the window shown above, and, viola! After about 20 seconds, the publish was successful. I’d show you a screenshot, but I’m not sure if I’m supposed to keep the API key a secret. Better safe than sorry. Actually, belay that last thought — you are supposed to keep it a secret. If you click on “More Info” under your API key, it says, and I quote:

Your API key provides you with a token that identifies you to the gallery. Keep this a secret. You can always regenerate your key at any time (invalidating previous keys) if your token is accidentally revealed.

Emphasis mine — turns out my instinct was right. And, sorry for the freewheeling nature of this post, but I’m literally figuring this stuff out as I type, and I thought it might make for an interesting read to see how someone else pokes around at this kind of experimenting.

Okay, now to see if I can actually get that thing. I’m going to create a brand new test project in Visual Studio and see if I can install my beloved ExtendedAssert through Nuget, now.

NugetSuccess

Holy crap, awesome! I’m famous! (Actually, that was so easy that I kind of feel guilty — I thought it’d be some kind of battle, like publishing a phone app or something). But, the moment of truth was a little less exciting. I installed the package, and it really didn’t do anything. My source code file didn’t appear. Hmmm…

After a bit of googling, I found this stack overflow question. Let’s give that a try, optimistically upvoting the question and accepted answer before I forget. I right clicked in the “package contents” window, added a content folder, and then dragged ExtendedAssert into that folder. In order to re-publish, I had to rev the version number, so I revved the patch decimal, since this is a hot patch to cover an embarrassing release if I’ve ever seen one. No time for testing on my machine or a staging environment — let’s slam this baby right into production!

Woohoo! It worked and compiled! Check it out:

NugetInstallSuccess

But, there’s still one sort of embarrassing problem — V1.0.1 has the namespace from whichever project I picked rather than the default namespace for the assembly. That’s kind of awkward. Let’s go back to google and see about tidying that up. First hit was promising. I’m going to try replacing the namespace with a “source code transformation” as shown here:

s

Then, according to the link, I also need to change the filename to ExtendedAssert.cs.pp (this took me another publish to figure out that I won’t bore you with). Let’s rev again and go into production. Jackpot! Don’t believe me? Go grab it yourself.

The Lessons Here

A few things I’ll note at this point. First off, I recall that it’s possible to save these packages locally and for me to try them before I push to Nuget. I should definitely have done that, so there’s a meta-lesson here in that I fell into the classic newbie trap of thinking “oh, this is simple and it’ll just work, so I’ll push it to the server.” I’m three patches in and it’s finally working. Glad I don’t have tens of thousands of users for this thing.

But the biggest thing to take away from this is that Nuget is really easy. I had no idea what I was doing and within an hour I had a package up. For the last 5 years or so, every time I start a new project, I’d shuffle around on the machine to find another ExtendedAssert.cs that I could copy into the new project. If it’s a new machine, I’d email it to myself. A new job? Have a coworker at the old one email it to me. Sheesh, barbaric. And I put up with it for years, but not anymore. Given how simple this is, I’m going to start making little Nuget packages for all my miscellaneous source code goodies that I transport with me from project to project. I encourage you to do the same.

14 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Markus
Markus
9 years ago

Might be a bit off-topic but: Regarding the Assert Extensions: I’ve been there. 🙂

I can wholeheartedly recommend using FluentAssertions. It provides the functionality you want plus so much more, for example object graph comparison, collection asserts, event monitoring and so on.

Here’s an overview of the functionality: https://github.com/dennisdoomen/fluentassertions/wiki

Very fitting, it’s also available as a nuget package: https://www.nuget.org/packages/FluentAssertions

Thanks to NCrunch (thank you for that tip by the way) and FluentAssertions, TDD has become my go-to programming method and I wouldn’t want to use TDD without it. The amount of time and code I save is just unbelievable.

Robert Bonham
Robert Bonham
9 years ago
Reply to  Markus

NCrunch + FluentAssertions = Testing Goodness

Erik Dietrich
9 years ago
Reply to  Markus

In the Java world, the mocking library that I used to use was fluent, and I really liked the semantics around that — stuff like when(thingHappens).then(doThisOtherThing); I haven’t seen this before, and I’m so used to unit tests having the iconic assert in them that it would take some getting used to. But, it looks like the learning curve would be worth it as the readability is clearly superior to Assert.AreEqual(), etc. I’m definitely going to find a project on which to test drive this — thanks for the tip! One question I have — when you write tests this… Read more »

Markus
Markus
9 years ago
Reply to  Erik Dietrich

I’ve only recently started using it at work so I can’t tell you much about the learning curve for my colleagues. The colleagues in my team are mostly “old-school” programmers who object to TDD and “over-use” of interfaces and squirm when seeing lambda statements. I wouldn’t even want to try to convice them to use TDD let alone FluentAssertions because it would be a waste of time for both sides sadly. But on my current project I’m working with one of the more open-minded programmers who became really interested in using FluentAssertions and started using it himself immediately. The framework… Read more »

Erik Dietrich
9 years ago
Reply to  Markus

Well, I’m glad if NCrunch and TDD are working out for you — always nice to trade tips and improvements with people.

Robert Bonham
Robert Bonham
9 years ago
Reply to  Erik Dietrich

I take a simple approach and make a comment
// Assertions

The examples on the GitHub page were all I needed to get going (as far as a learning curve)
https://github.com/dennisdoomen/FluentAssertions

Robert Bonham
Robert Bonham
9 years ago

Erik;
Great article, I’ve been fighting through this very thing this week of constantly looking for my go to code, scattered across my last dozen projects.

A suggestion is in nuget, make the ‘Project Information’ link aim to this article or one dedicated to the packages functionality. I love nuget, but there is so much stuff out there, I’m constantly looking at the project pages to make sure I’m getting what I need.

Keep up the great articles/videos

Robert

Erik Dietrich
9 years ago
Reply to  Robert Bonham

Thanks, and glad you liked. One of the things that I found when doing this was that looking for info on how to publish seemed often to lead me to searches for existing packages. It’s not that there wasn’t info that I could find, but it maybe wasn’t as discoverable as it could be. Seems like it’d be awesome if there were a how-to gallery somewhere (and maybe there is) of example nuget package files and what they result in when installed. So, “here’s what to do if you want the package to drop a DLL and assembly reference into… Read more »

Mark IJbema
Mark IJbema
9 years ago

Liked the article 🙂 actually writing as you go shows how easy it actually is.

One tip I learned publishing rubygems, publish as 0.0.1 first, and take a few days to ensure there are no embarassing mistakes, and then bump to 1.0

Erik Dietrich
9 years ago
Reply to  Mark IJbema

Good idea — I’ll definitely be doing that going forward. Thanks!

trackback

[…] How To Put Your Favorite Source Code Goodies on Nuget – Erik Dietrich discusses and walks through the process of using NuGet Packages to share soruce code between your own projects increasing the maintainability of your code, and reducing the need to copy and paste between projects. […]

bsimser
bsimser
9 years ago

Use a local folder for testing before you upload to NuGet. Just add a new package source as the location on your hard drive where the .nupkg is and voila, easy package testing. Test to your hearts content then when you’re ready push it up to NuGet.

Erik Dietrich
9 years ago
Reply to  bsimser

If memory serves, that’s what I did the first time that I played with NuGet packages a few years back. I was experimenting with storing the packages internally on a shared drive as a source of packages. Definitely for future source code bits I box up for NuGet.org I’ll go with your suggestion.

Robert Bonham
Robert Bonham
9 years ago
Reply to  bsimser

My personal NuGet packages are living in my OneDrive. This article was a wake up call, don’t know why I never thought of it for keeping my own code/patterns ready to for quicker startups.