Jul 14, 2015

Stop Using Assert.Throws in Your BDD Unit Tests

I’m sure we’ve all seen the Assert.Throws assertion in test code by now, but just in case you haven’t, here's a simple example:
[Test]
public void InsertTestNameHere()
{
    var input = "a string";
    Assert.Throws<FormatException>(() => int.Parse(input));
}
If we consider this from an Arrange-Act-Assert (AAA) perspective it’s pretty easy to see that the Act and Assert logic are in a single line. It’s a very common pattern. It works, it works well, and the readability is fine, but if we start using a BDD approach to our unit testing (e.g. with SpecFlow) or we want to explicitly keep the Arrange, Act and Assert sections of our test code separated then Assert.Throws gets in the way.
To fix this we need a way of catching the exception and treating it like a normal object. In NUnit, the Assert.Catch method is for just this purpose. Here’s the adjusted code (using NUnit)
[Test]
public void InsertTestNameHere()
{
    var input = "a string";
    var exception = Assert.Catch(() => int.Parse(input));
    Assert.IsInstanceOf<FormatException>(exception);
}
In this case we’re catching any exception that int.Parse might throw. If we were more explicit and used Assert.Catch<FormatException>(), NUnit’s behaviour becomes much the same as Assert.Throws, and the test fails immediately if the expected exception isn’t detected. This isn't a behaviour we want, which is why we're using the generalised catch method. Now, since we have our exception in a variable, we can check if it’s the one we expected.
Oh, I forgot to mention it, but if no exception is thrown, Assert.Catch() fails the test immediately. It is an assertion after all. I’m sort of OK with this… but not really, as we’re still mixing assertions and actions on the same line and haven't resolved my original complaint.
For this reason I prefer XUnit’s approach.
[Fact]
public void InsertTestNameHere()
{
    var input = "a string";
    var exception = Record.Exception(() => int.Parse(input));
    Assert.NotNull(exception);
    Assert.IsType<FormatException>(exception);
}
The Record.Exception() method won't fail the test, regardless of what happens in the method. Unlike the NUnit approach, it merely records any exception arising from the call or returns null if no exception was thrown. Personally, I feel this approach is a better way to write tests around exceptions while still remaining consistent with the AAA approach. It also works well when using a BDD testing framework that separates the given/when/then step implementations as you can pass the result of the “when” method to the “then” methods with ease.

Jul 3, 2015

Tips on How to Contribute to an Open Source Project

At the Sydney Alt.Net group last month we ran an Open Source Hack Night. The idea was to move from being a consumer of open source to being a contributor, to demystify what’s involved in an open source project, talk through some of the dos and don’ts, and the practical steps of getting started. Then we jumped in and did just exactly that over pizza and drinks. It was a fun night.

This is a recap of what we talked about on the night. I’m not going to walk through the mechanics of how to make a contribution, but will list some tips on how to find and get involved in a project and how to be successful at it.

Find a project. Duh!

More and more projects these days have issues that make for good “on-ramps” into the project. The web site http://up-for-grabs.net is an aggregator site for issues that meet this criteria. Have a browse of the projects on the site and see what interests you. Or just look at a project you use in your normal day to day work and see where/how you might be able to help.

Maintainers are people, just like you.

They’re developers with the same time pressures and insecurities that you have. The project they’re working on was likely started to scratch an itch and then made public in the hope it would help others. Remember to interact and treat these people with the same respect that you yourself want to be treated.

Check the social dynamic

If you see a project you might want to contribute to, look through the issues and pull requests to see how open the maintainers communicate and how open they are to contributions and different ideas. Lurk in the chat room (if they have one) and see what the banter is like. If you don’t like what you see, move along.

Contribution guidelines

Read the contribution guidelines if they exist. And follow them! They might be in a readme.md or a contributors.md or on a wiki. If you ignore them don’t be surprised if your contribution is rejected. Pretty obvious, right Smile

Contribute small changes to start with

It reduces the time you spend before getting feedback from the maintainer(s) and they’re easier for maintainers to absorb. A large contribution that you have put a lot of time into only to have it rejected is extremely discouraging and can you off from ever making future contributions. Large contributions also carry a lot more risk for the project making maintainers leery of spending the time to look through if this is your first contribution. Remember that maintainers are just like you. What would you want to see from a new developer making changes in your work projects? Small, incremental changes or massive, cross cutting changes. It’s the same for open source maintainers. They need time to get to know you.

P.S. Check with your employer about making contributions on work time. Unsurprisingly employers expect you to be building the thing they’re paying you to build. You should also check what the rules are for contributing back code to projects you’re using for work. Some employers still have backwater policies about open source and IP protection.

You don’t need to write code to contribute

Documentation is the one thing open source projects struggle with more than anything else. Maintainers would love it if you made documentation contributions. It’s just as critical to adoption as the code is, if not more so. After all, consider how you feel about using an open source project with no documentation versus one that has great documentation. A lot of projects now use https://readthedocs.org/ to host their documentation with the sources in git repositories. It’s easy to help write documentation.

You can also contribute by responding to questions/issues on the project site, on StackOverflow, or on other forum(s). You could also create screencasts, talk about the project at user groups, blog about it or do anything else you can to raise awareness. These are all useful and valuable contributions. Don’t be constrained by thinking it’s all about code.

A counter-example

Let’s learn from a an example of what not to do, shall we? Have a look at https://github.com/aaronpowell/db.js/pull/112 and you’ll see a number of things that have gone wrong here. To make it easier, let me give you a list:

  1. Assuming the maintainer is able to respond immediately to all your requests (12 hours between the posting of the PR and re-asking for it to be merged and then 24 hours until the second request for it to be merged).
  2. Making a large contribution that deals with more than just the issue that needs fixing.
  3. Changing the development tool chain used by the project.
  4. Claiming not to have time to adjust the pull request, but expecting that the maintainer does.
  5. Getting angry with the maintainer for asking for changes to make the contribution easier to absorb.

Yeah. Don’t do this, OK? Great! We’re good to go, then.

 

Want more information?

Need to go a little deeper? Want specific “How To” information or other tips? Check out this selection of posts and articles others have written:

Most of all, dive in! Have a go! We’d love to see you involved. Good luck!

Jun 11, 2015

Lenovo Support – A Cautionary Tale

I’m in the middle of an unpleasant customer support experience with Lenovo at the moment and wanted to share my experience as a “caveat emptor” for other potential Lenovo customers (at least here in Australia)

In the Beginning.

We start our tale with an online purchase of a nice, shiny Lenovo Yoga 3 Pro for my daughter for school at the beginning of the year. Being a school laptop it gets transported back and forth to school in a backpack each day. Much like my work laptops get carried around in my backpack each day on my commute.

A few weeks back a number of keys on her keyboard started falling off. The 3. The 2. Right cursor. Left shift. M. And before you ask; no, there’s no obvious damage to the machine. It hasn’t been dropped (that I can tell). There’s no dents. No cracked screens. No warping. Nothing that I could detect that would explain why the key caps are dropping off. I should’ve taken a photo.

Now I will admit that I tried to push the keys back on, thinking they’d just click into place, but without success. They kind of half go on, but then fall off again with the lightest of touches. I guess it’s time for a support call, so I jump on the Lenovo site and start a warranty request.

Failure to Launch

I get an confirmation message (without a reference number) saying I’ll get an email from them shortly with the details for returning the machine. But there’s no email. Not even in my junk mail. I wait a few days wondering if their “eventual consistency” system will catch up (if they have one). Still no email. Great. I guess I’ll need to follow this up myself and call support. A job for tomorrow, since I’ll need to grab the serial number from the laptop again.

But then I get a call from Lenovo asking me why I haven’t arranged to send in the laptop yet. Huh? I explain I haven’t received any emails from them as yet and then they tell me “Oh, yeah. We had some issues with our email systems. Sorry”.

Well at least we’re getting somewhere, so we arrange the details for the laptop to be returned and I’m told I’ll get an email with the forms I need to include for shipping when the courier arrives.

Attempt #2

You can guess what happens next. That’s right. Nothing. No email. I wait another day and decide this is ridiculous so I trawl through Lenovo’s web site until I can find a number to call (it’s not obvious). The service rep I talk to apologises, cancels the original service request and creates a new one, organising a new collection date with me over the phone. He also calls me back the next day to follow up and check I received the email. This time I did. That’s also showing signs of better service.

So now, we finally get the laptop collected and it’s returned to base for servicing.

A Ransom Situation

3 working days later I get a status update email from Lenovo saying a quotation is ready for me to approve. A quotation for a warranty job? Hmm. That’s not a good sign, but I need the laptop back regardless. They’ve got my device hostage, so I figure I’ll accept the quotation and then call support once 9am rolls around to ask why they want me to pay since the explanation of what is wrong is unclear.

Here’s what happens. First I bring up the service request:

image

Yes, the keyboard is damaged. The keys were falling off. Duh! So I click the “Accept” button.

image

And confirm acceptance. Here’s the response:

image

Oh, yay! Great system there Lenovo.

Negotiating a Release

So now I need to call support. I follow the prompts to check on the status of a job, but the phone system asks me to enter a 10 digit job number. Lenovo only gave me a 6 digit number. Um… genius. Way to go Lenovo.

So I follow more prompts through the phone system until I manage to talk to a human. I ask him why there’s a $200 charge for a warranty fix and I’m told it’s because of “induced damage”. Was I not meant to try pushing keys back on when they fell off? Would I have even tried to do this if they hadn’t fallen off in the first place? If I’ve somehow damaged the keyboard when trying to push the keys back on I could be at fault, though it’s some pretty poor customer service if that’s the case.

Unsurprisingly at this point I’m not a happy camper. Frustrated, I explain that even if I wanted to, I can’t accept their quotation because their systems are broken so I ask him to do it over the phone for me. The reply? I’ll call you back. What? Why? No thanks. I’ll wait on the line while you do it. It can’t take that long, surely.

Turns out that it can. It’s a “different department” that handles this and it will be 1-2 working days before someone calls me back to confirm. Are you kidding? 1-2 days to get someone to make a phone call? Can we drag out this repair any longer? I just want the laptop fixed and returned.

So here I am. Still waiting for Lenovo to learn how to make an inter-departmental phone call or to write an email to someone and I’m getting stonewalled. I’m reminded of our favourite insurance manager from the Incredibles.

I’m certainly not getting anywhere penetrating Lenovo’s bureaucracy at the moment so I’m doing the only thing I can and blogging about the experience instead.

As a note, my current work laptop is now 2 years old and due to be replaced. I was seriously considering a Carbon X1 since it looks like a great piece of kit but this experience has soured me. Support is really important, especially for someone like me who completely depends on my laptop for my job.

Lenovo, you’re definitely scratched from my list of approved vendors. Just fix my device, send it back and let’s hope we never have to deal with each other again.