Testing Times

Developers, testers and testing

In the world of software, there are developers and there are testers. The developers often design and implement the software while the testers define and execute the test plans. Software engineering requires both testers and developers, and together they make quality software; one by finding problems and the other by solving problems1. At least, that's the way it should be. Unfortunately, many developers (including myself) have found themselves in situations where the QA department is nonexistent, where testing and the associated test plan updates lurk at the end of every development cycle or feature implementation.

System testJust to be clear, we're not talking unit tests like those used in test-driven development (TDD) with frameworks like NUnit or MSTest. Unit tests and TDD are somewhat unique in that they take the developer's strength of solving problems and trickpersuade developer's into seeing testing as yet another problem in need of resolution (just how do you prove a requirement was met – to the TDD Cave, Codeman!).

Sadly, manual tests found in system testing, integration testing and regression testing are not so exciting. They don't usually present cunning problems to be solved but instead provide a means for mind-numbing hours following detailed, inane instructions where the result feels obvious and the rewards are few. At least, that's my experience as a developer performing tests; the same cannot be said of testers. I've worked with some very talented, passionate quality assurance professionals whose joy found in their craft was inspiring and of whom I have been envious when I too have found myself burdened by testing.

Finding those team mates who take pride in testing and making a product better is like striking gold, but even those that find schadenfreude in identifying a colleague's mistakes can be a better option to a developer than having to run the testing themselves. However, dedicated resources for quality assurance are often seen as a luxury2, leaving developers with little option but to take that responsibility on themselves.

To be clear, I'm trying to say that developers generally hate testing and more specifically, I hate testing, but we'll do it anyway if pushed.

WHHHHAAAT??!

At this point you may be surprised to discover that I recently found myself testing some software. Whether it was a poorly defined test, a flaky feature, or just the mundanity of repeating the same operations (albeit with subtle adjustments) over and over and over again, it left me frustrated, weary and disengaged. Testing is just not my thing, but I do it because I have to – releasing untested software should never be an option for a professional software developer; our users are not our QA department. The all too familiar experience reminded me of steps that developers can take when they're the ones that have to update and execute manual testing; steps that I've seen in action and that make testing almost pleasurable (almost).

Just update the test plan

Have you ever updated a test plan without checking the test was correct, or perhaps executed a test plan that was incorrect? Updating a test plan is tedious, we have to check that existing tests are still relevant and work out where there are gaps in the test coverage. This usually means looking at requirements documents and change requests and determining various test paths, expected results, etc. It can be a lot of work and it is all too easy to fall into the trap of skipping some steps, like validating the test is correctly defined or pretending that there's no way the existing plan missed something. Not only that, but if you've diligently updated the test plan, validating each test as you go, executing it all over again is even more painful because you already know what does and does not work from updating the tests in the first place.

So, do it once and do it right. If you carefully update the test plan, validating existing tests, updating others and creating new ones, you will find yourself testing the product anyway. As tests that should work don't, change requests will get raised and the product will improve. Not only that, but you'll only need to update the document once and you won't need to run the tests more than is absolutely necessary. To cap it off, the act of defining tests is pretty close to problem solving, making it a little less tedious for a developer to perform (though it is documentation, so, you know, don't hurt yourself or anything).

Assume the tester knows nothing (and is a little slow)I met a hawk and it was red

All too often, I come across test plans that are written like a kindergarten story.

Start the application. And then open a file. And then click OK. And then check the background is white and the caption says "Bite me!".

Paragraphs of simple instructions, often with steps missing that the author assumes the tester will know and without any explanation of what it means if that test fails. Instead of this mess, introduce each test with an overview of its purpose and what failure means, followed by test instructions each on a separate line. This not only helps you and your team mates when running the tests but it also helps when they come to update the test plan. Think of the test as code; you wouldn't expect the processor to guess when you miss out lines of code (I hope) so don't expect a tester to do the same; don't forget to add comments where more detail is needed (such as why it's important to change what locale the system is using); and number each step so that it can be referred to easily in notes and change requests, e.g. "Test 2.6, step 10 failed with a value of 20 where 21 was expected"3. If you do this, you will thank yourself later.

Provide context for the results

When performing the test, you will want to be recording results for each step. When reviewing results, you will usually want to see the test step that garnered them, especially if there is a failure or an ambiguous result. Save yourself some time by specifying your tests as a table with a column for results. That way, results are recorded next to the test definition making both recording and reviewing much easier. Not only that, but you don't need to maintain a results sheet and the test definitions separately or contend with different people recording the results in different formats.

Conclusions

If you follow these three simple steps, you should end up with test definitions that look less like an account of your weeks at summer camp when you were 7 and more like the example below.

This test checks the flange sprocket exposes the doobrey flap.

Step Instructions Results
10 Open the flange sprocket. You should see the flange sprocket open. Pass – opened
20 Press the doobrey flap. Fail – unable to locate doobrey flap. Test lacking sufficient detail or doobrey flap was not exposed.
30

Of course, all this assumes you don't have a QA team or team members (or even some tools that help you define and execute manual testing). If you do, that's great; respect your QA team members (or your tools) and the work they do to keep your users from deploying their wrath upon thee. For the rest of us, stuck with ourselves and our office productivity applications in which to define and record our testing, following these tips will make our testing life (and that of those around us) just that little bit less tedious. Who knows, some of you might even start enjoying it.

  1. This is a very simplistic overview, I know. []
  2. There are valid and not so valid reasons for this, but we're not going to get into that here. []
  3. You might also consider spacing step numbers by 10 so it's easier to insert additional steps without renumbering all subsequent steps. []

Ann Arbor Day of .NET

On Saturday (29th Oct), I attended the Ann Arbor Day of .NET. I thought it would be nice to summarise what I heard. I doubt these notes on their own will be greatly useful, but I hope they act as a launch pad into deeper dives on the topics covered as well as a review of what topics were covered. There were five different tracks for the day: Cloud, Framewords & Platforms, Soft Skills, Tools and Mobile. I chose talks from the first four of these based on the talk itself, rather than the track to which it belonged (I ruled out presentations that I had seen a variation of before such as David Giard's (@DavidGiard) Introduction to Microsoft Windows Workflow and Jay R. Wren's (@jayrwren) Let's Go to C# On The iPhone, though they were excellent when I saw them).

Be A Better Developer

I started out the with Mike Wood (@mikewo) and his session, Being A Better Developer. This was a soft skills talk, meaning it was not there to show off some cool .NET feature or technology, or teach me all about C#. Instead, the focus was on what makes a great developer and what we can do to attain that status.

Mike explored the various roles that developers have to take on, the hats we have to wear. From the student learning new things everyday, to teacher imparting knowledge to those around them. From janitor—maintaining what already exists, to researcher—investigating and choosing frameworks, languages, platforms, etc. Using these roles as a foundation, we then moved on to some tips such as setting up time blocks in which to work. If the time limit is reached and the problem isn't solved, turn to someone else for help (or somewhere else, like the Internet1) to avoid thrashing and time wasting. This seems somewhat obvious and yet I'm betting that many of us don't do it as often as we should. The other tips were equally useful, obvious and often compromised in our daily development lives:

  • organize
  • prioritize
  • know your tools
  • set SMART2 goals
  • be a catalyst for change
  • be lazy…

Right, that last one is maybe a little less obvious, but the point wasn't: don't do more than you have to.

One of the best pieces of advice from this talk was to choose a good mentor. I was very fortunate when I started out my career to have several excellent mentors and I miss working with them almost every day. Even now, I imagine what they might have said in order to guide my efforts3. For an hour, Mike filled that role.

There was much more to this talk than what I've written here. This session was an excellent way to spend an hour. While much of what Mike presented could be considered commonsense, it was reassuring and also provided some new tricks for my arsenal to be deployed in any situation, not just day-to-day software development.

Things to check out after this talk


How I Learned To Love Dependency Injection

Next, on to James Bender (@jamesbender) and his presentation on how he much loves dependency injection4. This talk started out looking at the way things were and the ideas behind a loosely-coupled system; a system where each component knows as little as possible about the other components in its parent system, whether it uses the services those components provide or not. Tightly-coupled systems don't promote reuse, create brittle systems and are inherently difficult to test.

James told a compelling story, starting out with familiar concepts—a constructor that takes various interfaces through which the created object can obtain various services, the factory pattern, etc., but soon we were looking at an overview of dependency injection frameworks, what they do and how they do it.

And then, code. Code about cooking bagels. The only bad part about this was the lack of bagels to eat5. The talk moved quickly on to the various features of Ninject, an open source dependency injection framework. I would've preferred it if there was more emphasis on dependency injection, using Ninject to provide examples, rather than the "how to use Ninject" approach that was given. However, this was still very informative and laid a path towards the next part of the talk which showed how dependency injection and TDD6 go hand in hand. This in turn led to an introduction of mocking (the mock framework of choice in these examples was Rhino Mocks, but James recommended Moq for new work).

Things to check out after this talk


A Field Guide for Moving to the Cloud

We're back with Mike Wood (@mikewo) for this one. I've never done any Cloud development but I'm really interested in it and what it may do for me and the work I do, so I'm hanging a lot on this introduction (no pressure, Mike).

Mike started off with a Batman reference, tying the reason why I'm so tired (Batman: Arkham City) with the reason why I'm here. He then fired off some acronyms: IaaS, SaaS, PaaS. This is a great starting point for me as terminology is often the last refuge of miscommunication and I hate not understanding what all those acronyms and terms mean. One participant immediately asked, "What's the difference between IaaS and PaaS?" and most of us nodded, realising we didn't know either. To paraphrase, IaaS gives the most control as you're responsible for patching your OS, upgrading the frameworks, etc. PaaS manages all that for you. Mike did a great job explaining this (unlike my paraphrasing—Mike used a whiteboard and everything) and we moved on, that bit more informed and ready to learn more.

At this point, Mike gave us a run through of the Windows Azure platform, again making sure we're all talking the same language as the presentation progresses. Mike's presentation style is nice and fluid, taking questions and interruptions in his stride, and he clearly knows his topic well (Mike is an Azure MVP, after all). He walked us through the various parts of Windows Azure, Microsoft SQL Azure and Windows Azure AppFabric before we moved on to planning for our move to the Cloud.

Mike discussed identifying suitable applications for moving to the Cloud, scale of the application and the independence of scale, the services used and tight integration with loose coupling (not the first time we've heard this today but I would hope, not the first time in our careers either, otherwise, you're doing it wrong), usage patterns, latency, security and many other facets to be considered when moving to the Cloud.

The final point related to whether the move would save money or not and the importance of answering that question before making the move. This kind of information was great to see and may prove very useful when talking with project managers or business development types. Mike also pointed out using techniques like multipurpose worker roles and disposable compute instances to save as much as 50% in costs.

And then it was lunch.

Things to check out after this talk


Develop IT: Intro to PowerShell

I admit it, I have only ever used PowerShell for things that I could've done from a regular command prompt, so this talk was one I didn't want to miss. I want to know more so I can do more. I feel like PowerShell is an exclusive club for productive individuals and I'd at least like to take a look inside, so this was my opportunity. Sarah Dutkiewicz (@sadukie) was the presenter for this session, a C# MVP and co-author of Automating Microsoft Windows Server 2008 R2 with Windows PowerShell 2.0. This talk was entirely presented using PowerShell, which certainly made it stand apart from other presentations given so far today.

The initial examples given by Sarah quickly demonstrated how PowerShell provides similar behaviour to the traditional command prompt but also how it is different, providing .NET objects (dir w* | Get-Member demonstrated how dir provides an object—very cool). We then learned all about the standard PowerShell syntax that provides an easily dicoverable set of commands (known as Cmdlets in the PowerShell world) and some useful Cmdlets like Get-Help and Out-GridView (which outputs things to its own filterable grid in a window).

Sarah continued introducing us to a variety of PowerShell concepts and features including but not limited to:

  • functions
  • modules
  • manifests
  • PowerShell ISE7
  • providers
  • aliases
  • registry interaction

My biggest takeaway is how easy it can be to work with the registry from within PowerShell (just open PowerShell and enter cd hkcu: then dir to see what I mean). Overall, a great introduction that has given me a starting point for exploring PowerShell and becoming more efficient.

Things to check out after this talk


Stone Soup or Creating a Culture of Change

For the final session of the day, I rejoined James Bender (@jamesbender). I was really looking forward to this having faced many challenges in changing culture as part of my efforts for meeting the requirements of CMMI8. This was expected by event organisers to be a popular talk and I still feel that it should have been; however, the turnout was disappointingly low. This made for a more intimate session and certainly did not detract from the informative content. James expressed that this was probably the last time he would present this talk, which is a shame as I found the anecdotes and the lessons that were drawn from them to be very insightful.

The things I've learned will definitely help me in my work and elsewhere. Things like:

  • Go for low hanging fruit
  • Don't change too much at once
  • Support the change and let it simmer
  • Don't judge
  • Know your tools
  • Only introduce changes you believe in
  • Understand the business
  • Know when to say when
  • Evangelize
  • Build a network of like-minded people
  • Be a politician
  • Be a therapist
  • Realise that it might be difficult to reach everyone
  • When all else fails, buy doughnuts
  • Be patient

There's not much more I could say about this talk that would do it justice (not that my notes have really given justice to the earlier talks), but suffice to say this presentation was very relevant to me and I am very grateful to have been able to see it.

Things to check out after this talk


To conclude, I had a great day. The organisers, sponsors and speakers deserve a huge "thank you" for setting up and supporting this event. Wandering the hallways of Washtenaw Community College, attending talks in rooms and lecture halls reminded me a little of being back at university, but the speed at which the day flew by certainly did not. It was a very informative and enjoyable way to spend the day and among the best $10 I've spent this year.

  1. Use Internet search before you ask someone. []
  2. Specific, Measurable, Achievable, Realistic/Relevant, Trackable []
  3. Besides, "Shut up, Jeff!" []
  4. An appropriate amount as allowed by law. []
  5. Mmm, bagels. []
  6. Test Driven Development []
  7. Integrated Scripting Environment []
  8. Capability-Maturity Model Integration []

Jonah

I rediscovered this poem lurking in my files the other day and I don't remember the circumstances that led to it being written or the inspiration behind it. It's a little different to things that I'm used to writing. Let me know what you think.


A young man named Jonah once set out to sea, to sail the seven seas,

and at no point did he,
ever doubt whether she would be waiting,
for he knew somewhere far and away from his heart was the beautiful girl of his dreams.

So with compass in hand,
and a gold wedding band, he set sail.
Now the first night was fine as he travelled the waves, sleeping under the stars,

but the next blew a storm,
that did little to warn him of danger.
As he tried to hold course through the rain and the swells with prayers to Gods and the stars,

the storm, it grew worse,
the hull it did burst and Jonah was thrown to the depths.
For a week he was drifting through briny demise with nought but the sea to be found.

With the sun beating brutal,
and all hope left futile he drifted,
when a long came a ship full of friendship and food to save him before he had drowned.

As they fed him to health,
they shared knowledge of wealth and desires.
Now these new friends he had found were not sailors, but pirates of ill intent,

and when Jonah came round,
to see pirates abound he got frightened.
but with nothing to do, no escape to be made and all of his energy spent,

Jonah succumbed to greed,
joined the piratical breed and sailed on.
Two score years and ten, he would sail through the foam, plundering all in his wake,

until one day a tale,
met his ears over ale in a tavern.
It told of a girl with such beauty and grace that none could hope to forsake.

Jonah set down his mind,
that this beauty he'd find and they'd wed.
So a pirate named Jonah then set out to sea, to sail the seven seas,

in search of girl who,
somewhere in the world, he would marry.
Jonah knew somewhere far and away from his heart was that beautiful girl of his dreams;

with his cutlass in hand,
and a gold wedding band he set sail.
Just out of port, and outnumbered by far, Jonah's crew were caught quite unware—

revenge it would seem,
was to shatter his dream in a flash.
A merchant, quite bold, had sought Jonah's crew to reclaim what he saw as fair,

so a battle ensued,
one that Jonah would lose, he was sure.
After some time had passed, Jonah's ship lay a wreck, not a pirate alive to retell,

the tale of his plight,
and the fantastic fight they had fought.
Jonah lay with his pride, both bleeding and torn, in puddle of blood where he'd fell,

As his eyes closed up tight,
the ship sailed through the night to the shore.
When he neared the end, his ship came aground on the shore he had left as a youth,

where there stood a girl,
who had traveled the world, for her love.
A young maiden fogotten was stood on the shore, a smile of love as her proof,

and together they soared,
to the stars where he'd moored, young Jonah and his true love, Marie.
A young man named Jonah once set out to sea, to sail the seven seas,

and at no point did he,
ever doubt whether she would be waiting.
For he knew somewhere far and away from his heart was the beautiful girl of his dreams.

Hell and Hot Chocolate

This was my entry in a short story contest held among the denizens of http://bbs.chrismoore.com (affectionately known to the Mooreons that frequent it as The Boardello).  The challenge was to write a story with the title Hell and Hot Chocolate. I won a mug for this. I love that mug.

Hell and Hot Chocolate

by Jeff Yates

It was cold outside and the skies looked ominous, not that I knew what ominous meant at the time, I was only eight.  I probably would have said the skies looked scary back then or maybe, in an attempt to get the right word, called them odorous.  That would've been wrong though, they weren't odorous at all (at least not from this distance), just ominous.  Mum, fearing for the well-being of her children as mothers often do, made sure we wore extra layers before bracing the winter morning.  My sister wore hiking socks, leg warmers and boots with a pink puffer jacket, pink scarf, pink mittens, and a pink bobble hat; her cheeks glowing red against the biting wind.  I wore two pairs of socks, my wellies, jeans, a vest, a t-shirt, a white school shirt, a wool jumper with a rabbit on the front knitted by my Gran, a scarf of random colours knitted by my Gran, a wool duffle coat, and a flat cap that my parents had bought me for my birthday after my Dad got fed up of me stealing his.  We each carried a satchel containing sandwiches, crayons, paper, and a flask of milky hot chocolate.   My sister was like candy floss from the local fairground and I was like a better looking British equivalent of Macaulay Culkin in Home Alone.

It was Sunday morning and my Mum had just dropped me and my sister at the bottom of the church steps.  They were eroded from wind and rain, cracked by freeze and thaw, and harboured frost-covered plants between their old stone blocks.  Their edges were worn smooth from centuries of churchgoers traipsing their way to and from christening, matins, communion, wedding, evensong and funeral services, Easter, harvest and Christmas celebrations, and Sunday School.  That was where we were heading, Sunday School.  Every Sunday morning after the communion service we would go to Sunday school where various volunteers under the guidance of the rector would impart to us the wisdom of the Bible whilst we made Easter cards or painted one of the Disciples.  Usually, we would have been at the service too but this morning my Mum had struggled to wake me and my Dad: me because I was lazy, my Dad because he was hung-over.  So, there we were, at the bottom of the church steps waving to our Mum as the last of the congregation left the church and Mum drove away.

My sister grabbed my arm and dragged me up the icy steps, "Come on, you mong.  Stop staring at the sky, we'll be late!"  She was ten and with her maturity came her sass.  She was a proper well-spoken little madam and I looked up to her even though we were starting to grow apart; me refusing to mature beyond my years and her racing for the finish line of retirement.  I was sure that within a year, she would be married with kids and I would still be pulling the legs off spiders and putting frogs in her bed (though no Nostradamus, some of my predictions did come true, much to my sister's irritation).

*   *   *

“Today, we are going to talk about Heaven and Hell.  Who can tell me what Heaven is?”

Miss Dickle was about eighteen or nineteen.  She was a member of the youth fellowship and she was hung up on God.  I think it had something to do with the bullying she got, or the boys thinking she was a dyke (I didn’t know what that meant, but they didn’t say it like it was a good thing so I guessed it was bad which my Mum confirmed when I called her one), or a bit of both, but whatever it was, my Dad had said she was bothering God for the wrong reasons.  I could not see any signs that God was bothered by her at all, but then I could not see any signs of God full-stop—other than the ones that hopeful believers had built, installed, or written on his behalf—so what did I know?

Bobby Jenkins raised his hand, “My Mum says that sitting on the washing machine during a full-spin cycle is heaven.”

“Yes, thank you, Bobby.  That isn’t quite what I was looking for.  Anyone else?” said Miss Dickle, making a note and slipping it into her pocket while Bobby shrugged like he had given it his best shot, “No?  Well, Heaven is where God lives.”

“But I thought this was God’s house?” said Angela Joyce.  The twenty-strong group of eight year old children nodded in agreement.

“Yes, it is, but God is everywhere.”  Miss Dickle was used to thinking fast.

“So Heaven is everywhere?” said Angela.

“No.  Heaven is where we go when we die, but only if we’ve been good.  Now, who can tell me what Hell is?”

Julie Brent raised her hand, pushing it as high as she could, using her other arm to prevent the first from falling off before she got to answer.

“Yes, Julie.”

“Hell is a really hot place with fire and lava and the Devil where people go when they’re naughty.”

Julie Brent was a know-it-all and she knew it.  I hated her.

“That’s very good, Julie.  To be exact, Hell is the eternal punishment for those who do not believe in Jesus Christ like we do.  The Devil, who is sometimes called Satan or Lucifer, used to be an angel in Heaven but he tried to fight God and was sent to Hell with a third of the angels who are now demons.  Hell is filled with the souls of the damned and if you do something naughty and you don’t say sorry, that’s where you end up.  The Devil roams the Earth looking for souls to devour, separating them from the spiritual light of God and condemning them to eternal damnation.  Temptation is often used by the Devil to lure the weak away from Jesus Christ and God.  So, when you are tempted to do something that you know you shouldn’t, remember what might happen to you.”

We all sat there in silence, too scared to look anywhere but straight at Miss Dickle, whose face looked deadly serious.  I was pretty sure that none of us fully understood everything she just said, but what we did understand was more than enough to petrify us.  I was horrified, even more so when Bobby shit himself and burst into tears; he was sat right next to my flask.

*   *   *

Mum came to collect us at 11:30.  There we were, standing in the slush at the bottom of the Church steps.  My sister was holding the advent candle she had made and grinning from ear to ear as if it was the best thing ever.  I was holding my flask of hot chocolate at arm’s length, unable to believe that Miss Dickle had washed if all off like she insisted.

On the drive home, my sister happily regaled the little bits of gossip she had overheard during her advent candle manufacturing class while I tried not to think about the implications of my “how to scare the shit out of at least one kid” class.   It wasn’t until we got home that Mum took me aside to ask why I appeared so upset (seems I had been sniffling a little on the way home).  So, I told her what happened, word for word, or at least as well as I could remember and when I was finished, she gave me a hug.

“So, you’re worried that you might go to Hell?”

“No,” I said.

“No?”

“Well, I was, but then Bobby pooed on my hot choc’lit.”

“And that stopped you worrying?”

“Well, you always say it might be tempting to drink it before Miss Dickle finished talking but I shouldn’t.  But today I was going to, then Bobby pooed on it.  And now he’s going to Hell.”

“I don’t think that’s very nice, honey.  You can’t send someone to Hell just for pooing their pants.”

“But he didn’t say sorry and Miss Dickle said that if you don’t say sorry after you’ve done something naughty, you go to Hell.”

“Well, I don’t think Miss Dickle explained that very well.  How about I make you a fresh mug of hot chocolate and we’ll talk about this after dinner?”

“Ok,” I smiled and ran off to watch Bugs Bunny with my Dad.

*   *   *

It wasn’t until the following weekend when I returned to Sunday School, that I discovered Bobby had bigger things to worry about than Hell.  After all, why worry about where you’ll end up when you’re dead when you have to spend the rest of your life being called Bobby Poopants, Poobum Bobby, and Bobby Bobby Bumboy (although that last one didn’t really become popular until he came out during high school).  He never lived down the embarrassment of defecating to the point that it oozed from his shorts and I never ever used that flask again.  Angela Joyce became a hard-hitting journalist, probing politicians and celebrities with her unique style of questioning. Julie Brent got ordained and continued to have an answer for everything.  Miss Dickle got a theology degree and after many years as a missionary, she embraced her sexuality and moved in with Julie Brent.

As for me, well, that’s another story altogether.

Crash handling in Silverlight (Part Two)

This post is the second part of a two part series.

Adding a little polish

In part one of this series we learned about the basic out-of-the-box crash handling that a new Silverlight project provides for both in- and out-of-browser applications, we learned how we can catch unhandled exceptions inside our application or let them escape into the browser to be handled by JavaScript (or a bit of both) and we learned that we are at the mercy of the HTML bridge.

What we had was far from fancy; the user would end up with a potentially broken Silverlight application or a blank screen and only some cryptic text in the JavaScript console to explain. This is not how we make friends, but now that we have a foundation, we can look at how to enhance the experience for our quality departments, ourselves and the poor souls that must suffer for our mistakes, our users. However, some simple modifications to our error handler can move the cryptic text out of the console into the page. We can even add some pizzazz and remove most of the cryptic text too. So let's take what we were left with at the end of part one and add a little polish.

In the following example, I've constructed a simple page that gives the user some information and provides a mailto link for sending the details to our QA department. When a crash occurs, the Silverlight application is hidden and the error page is displayed, customized to the specific error code1 and information.

function onSilverlightError(sender, args) {
    var errorType = args.ErrorType;
    var iErrorCode = args.ErrorCode;

    var emailMessage = "Dear Support,%0A%0A" +
        "Your application crashed.%0A%0A" +
        "Honestly, I only:%0A" +
        " ADD SOME DETAIL OF WHAT HAPPENED HERE%0A%0A" +
        "If you could fix this, that would be super awesome.%0A%0A" +
        "Thanks,%0A" +
        "A Very Important User%0A%0A~~~~~~~~%0A%0A";

    if (sender != null && sender != 0) {
        emailMessage += "Source: " + sender.getHost().Source + "%0A";
    }
    emailMessage += "Code: " + iErrorCode + "%0A";
    emailMessage += "Category: " + errorType + "%0A";
    emailMessage += "Message: " + args.ErrorMessage + "%0A";

    if (errorType == "ParserError") {
        emailMessage += "File: " + args.xamlFile + "%0A";
        emailMessage += "Line: " + args.lineNumber + "%0A";
        emailMessage += "Position: " + args.charPosition + "%0A";
    }
    else if (errorType == "RuntimeError") {
        if (args.lineNumber != 0) {
            emailMessage += "Line: " + args.lineNumber + "%0A";
            emailMessage += "Position: " + args.charPosition + "%0A";
        }
        emailMessage += "Method Name: " + args.methodName + "%0A";
    }

    var errorScreen = "<h1>Hello World!</h1>"
        + "<p>Sorry, but our application appears to have left the building.</p>"
        + "<p>Please <a href=\"mailto:quality@example.com\?subject=Incident Report&body="
        + emailMessage
        + "\">click here</a> and send us an e-mail.</p>";
    document.getElementById("silverlightControlHost").style.display = "none";
    var errorDiv = document.getElementById("errorLocation");
    errorDiv.innerHTML = errorScreen;
    errorDiv.style.display = "block";
}

Now, I understand, this is not the most elegant JavaScript in the world, but it works. Here is what your user sees…

Example of what a user will see when the application crashes
Example of what a user will see when the application crashes

…and if the user clicks our mailto link, they'll get something like this…

Example of the auto-generated e-mail incident report
Example of the auto-generated e-mail incident report

The example could be expanded to add additional information such as the URL of the application, the version of Silverlight and the user agent string by just modifying the JavaScript to include that information2. You could even show the same information on the HTML page that you include in the e-mail (in fact, you can go even further than that, just use your imagination…or read on for some suggestions). And yes, a little CSS would help, but I never promised it would be pretty—pretty can come later; I'm aiming for functional and as functional goes for showing that something is non-functional, this is good enough.

A bridge too far

Of course, as we have access to all the wonders of HTML and JavaScript, we could do so much more. For example, we could play a video to entertain the user while we call a web service that sends our error report automatically to our servers and tweets an apology (it's the personal touches that count). However, it doesn't matter how fancy and special we make the crash experience, it is all for nought once the user installs and uses our application out-of-browser or the HTML bridge is disabled. So, what do we do?

Out of the browser and into the app

The simplest way I have found to handle crash reporting in an out-of-browser application (or an application that lacks the HTML bridge) is to throw up a ChildWindow containing the details of the crash and provide no discernible means to dismiss it, thus disabling your application from further use without closing the application. This relies on the Silverlight runtime remaining intact even though your application suffered a problem; however, from my experience, crashes that take out the runtime are rare, especially in applications that have been tested and have well-formed, correct XAML.

Of course, if the runtime is still working, why stop at a ChildWindow? If you have access to the Silverlight runtime, you could do more like call a web service call or use some trusted API3 or COM4 interface. Whatever you try, exercise caution as you don't want your crash handling to crash as well. Keep it simple and it will serve you well.

Conclusions

Whichever route you choose, you should work hard to cater for all the scenarios that might be encountered, that way you will provide the support your user deserves. When deciding on your crash reporting strategy, always consider:

  • What level of network connectivity might be available?
  • Will the application be in- or out-of-browser? Do you support both?
  • Will the application be trusted and therefore have access to COM or Windows APIs?5
  • What Silverlight runtime(s) will you want to support?
  1. If you were paying attention there, you may have noticed that I mentioned the error code. There are many error codes that can be reported by Silverlight. You can use the error code to tailor your report or even consider not reporting a crash at all, but that depends on just how badly your application will react to the error. []
  2. Getting the User Agent string or the site URL are relatively simple, especially when compared with retrieving the Silverlight runtime version from within JavaScript. Thankfully, this was solved already, just visit this blog for details. []
  3. Silveright 5 []
  4. Silverlight 4 and up []
  5. Starting in Silverlight 5, both in- and out-of-browser trusted applications are supported. Earlier versions only support trusted applications when out-of-browser. []