If you read the previous blog post, you might wonder if you can wrap a string in nested tags, you know, something like this:
And the answer is no. No, you can’t. Well you can, but it’s not going to give you the result you want. For instance, if you apply the transform to the string “Hello”, you’ll get this:
Which is useless.
The reason is obviously that the Tag method calls following the first one will all be channeled in to the same Tag. Even though there’s an implicit cast to string, there’s nothing in the code triggering that cast. Of course, you could explicitly call ToString on the Tag, like so:
But that’s admitting defeat, since it breaks the illusion we’re trying to create. Plus it’s ugly.
A better way of working around the problem is to compose simple one-tag transforms, like so:
Which is kind of neat and yields the desired result:
But we can attack the problem more directly. There’s not a whole lot we can do to prevent our Tag object from capturing the subsequent method calls to Tag. But we are free to respond to those method calls in any ol’ way we like. A trivial change to TryInvokeMember will do just nicely:
So we just single out calls for a method named Tag with a single string parameter. For those method calls, we’re not going to do the regular fluent collection of method names and parameters thing. Instead, we’ll convert the existing Tag to a string, and return a brand new Tag to wrap that string. And now we can go a-nesting tags as much as we’d like, and still get the result we wanted. Win!
In a project I’m working on, we needed a simple way of wrapping strings in tags in a custom grid in our ASP.NET MVC application. The strings should only be wrapped given certain conditions. We really wanted to avoid double if checks, you know, once for the opening tag and one for the closing tag?
We ended up using a Func from string to string to perform wrapping as appropriate. By default, the Func would just be the identify function; that is, it would return the string unchanged. When the right conditions were fulfilled, though, we’d replace it with a Func that would create a new string, where the original one was wrapped in the appropriate tag.
The code I came up with lets you write transforms such as this:
Which is pretty elegant and compact, don’t you think? Though perhaps a bit unusual. In particular, you might be wondering about the following:
- How come there’s a Tag method on the string?
- Where do the other methods come from?
- How come the return value is a string?
So #1 is easy, right? It has to be an extension method. As you well know, an extension method is just an illusion created by the C# compiler. But it’s a neat illusion that allows for succinct syntax. The extension method looks like this:
So it simply creates an instance of the Tag class, passing in the string to be wrapped and the name of the tag. That’s all. So that explains #2 as well, right? Href and Style must be methods defined on the Tag class? Well no. That would be tedious work, since we’d need methods for all possible HTML tag attributes. I’m not doing that.
If you look closely at the signature of the Tag method, you’ll see that it returns an instance of type dynamic. Now what does that mean, exactly? When dynamic was introduced in C# 4, prominent bloggers were all “oooh it’s statically typed as dynamic, my mind is blown, yada yada yada”, you know, posing as if they didn’t have giant brains grokking this stuff pretty easily? It’s not that hard. As usual, the compiler is sugaring the truth for us. Our trusty ol’ friend ILSpy is kind enough to let us figure out what dynamic really means, by revealing all the gunk the compiler spews out in response to it. You’ll find that it introduces a CallSite at the point in code when you’re interacting with the dynamic type, as well as a CallSiteBinder to handle the run-time binding of operations on the CallSite.
We don’t have to deal with all of that, though. Long story short, Tag inherits from DynamicObject, a built-in building block for creating types with potensially interesting dynamic behaviour. DynamicObject exposes several virtual methods that are called during run-time method dispatch. So basically when the run-time is trying to figure out which method to invoke and to invoke it, you’ve got these nice hooks where you can insert your own stuff. Tag, for instance, implements its own version of TryInvokeMember, which is invoked by the run-time to, uh, you know, try to invoke a member? It takes the following arguments:
- An instance of InvokeMemberBinder (a subtype of CallSiteBinder) which provides run-time binding information.
- An array of objects containing any arguments passed to the method.
- An out parameter which should be assigned the return value for the method.
Here is Tag‘s implementation of TryInvokeMember:
What does it do? Well, not a whole lot, really. Essentially it just hamsters values from the method call (the method name and its first argument) in a dictionary. So for instance, when trying to call the Href method in the example above, it’s going to store the value “http://einarwh.posterous.com” for the key “href”. Simple enough. And what about the return value from the Href method call? We’ll just return the Tag instance itself. That way, we get a nice fluent composition of method calls, all of which end up in the Tag‘s internal dictionary. Finally we return true from TryInvokeMember to indicate that the method call succeeded.
Of course, you’re not going to get any IntelliSense to help you get the attributes for your HTML tags right. If you misspell Href, that’s your problem. There’s no checking of anything, this is all just a trick for getting a compact syntax.
Finally, Tag defines an implicit cast to string, which explains #3. The implicit cast just invokes the ToString method on the Tag instance.
The ToString method is responsible for actually wrapping the original string in opening and closing tags, as well as injecting any hamstered dictionary entries into the opening tag as attributes.
And that’s it, really. That’s all there is. Here’s the complete code:
Last week, I teamed up with Bjørn Einar (control-engineer gone js-hipster) and Jonas (bona fide smalltalk hacker) to talk about .NET gadgeteer at the NDC 2012 conference in Oslo. .NET gadgeteer is a rapid prototyping platform for embedded devices running the .NET micro framework – a scaled down version of the .NET framework itself. You can read the abstract of our talk here if you like. The talk itself is available online as well. You can view it here.
The purpose of the talk was to push the envelope a bit, and try out things that embedded .NET micro devices aren’t really suited for. We think it’s important for developers to fool around a bit, without considering mundane things like business value. That allows for immersion and engagement in projects that are pure fun.
I started gently though, with a faux-test driven implementation of Conway’s Game of Life. That is, I wrote the implementation of Life first, and then retro-fitted a couple of unit tests to make it seem like I’d followed the rules of the TDD police. That way I could conjure up the illusion of a true software craftsman, when in fact I’d just written a few tests after the implementation was done, regression tests if you will.
I feel like I had a reasonable excuse for cheating though: at the time, there were no unit testing frameworks available for the .NET micro framework. So you know how TDD opponents find it tedious to write the test before the implementation? Well, in this case I would have to write the unit testing framework before writing the test as well. So the barrier to entry was a wee bit higher.
Now in order to create the illusion of proper craftsmanship in retrospect, I did end up writing tests, and in order to do that, I did have to write my own testing framework. So procrastination didn’t really help all that much. But there you go. Goes to show that the TDD police is on to something, I suppose.
Anyways, the testing framework I wrote is called μnit, pronounced [mju:nit]. Which is a terribly clever name, I’m sure you’ll agree. First off, the μ looks very much like a u. So in terms of glyphs, it basically reads like unit. At the same time, the μ is used as a prefix signifying “micro” in the metric system of measurement – which is perfect since it’s written for the .NET *micro* framework. So yeah, it just reeks of clever, that name.
Implementation-wise it’s pretty run-of-the-mill, though. You’ll find that μnit works just about like any other xUnit framework out there. While the .NET micro framework is obviously scaled down compared to the full .NET framework, it is not a toy framework. Among the capabilities it shares with its bigger sibling is reflection, which is the key ingredient in all the xUnit frameworks I know of. Or at least I suppose it is, I haven’t really looked at the source code of any of them. Guess I should. Bound to learn something.
Anyways, the way I think these frameworks work is that you have some mechanics for identifying test methods hanging off of test classes. For each test method, you create an instance of the test class, run the method, and evaluate the result. Since you don’t want to state explicitly which test methods to run, you typically use reflection to identify and run all the test methods instead. At least that’s how μnit works.
One feature that got axed in the .NET micro framework is custom attributes, and hence there can be no [Test] annotation for labelling test methods. So μnit uses naming conventions for identifying test methods instead, just like in jUnit 3 and earlier. But that’s just cosmetics, it doesn’t really change anything. In μnit we use the arbitrary yet common convention that test methods should start with the prefix “Test”. In addition, they must be public, return void and have no parameters. Test classes must inherit from the Fixture base class, and must have a parameterless constructor. All catering for the tiny bit of reflection voodoo necessary to run the tests.
Here’s the Fixture class that all test classes must inherit from:
As you can see, Fixture defines empty virtual methods for set-up and tear-down, named SetUp and TearDown, respectively. Test classes can override these to make something actually happen before and after a test method is run. Conventional stuff.
The task of identifying test methods to run is handler by the TestFinder class.
You might wonder why I’m using the feeble, untyped ArrayList, giving the code that unmistakeable old-school C# 1.1 tinge? The reason is simple: the .NET micro framework doesn’t have generics. But we managed to get by in 2003, we’ll manage now.
What the code does is pretty much what we outlined above: fetch all the types in the assembly, identify the ones that inherit from Fixture, and proceed to create a TestGroup for each test class we find. A TestGroup is just a thin veneer on top of the test class:
The TestFinder is used by the TestRunner, which does the bulk of the work in μnit, really. Here it is:
That’s a fair amount of code, and quite a few new concepts that haven’t been introduced yet. At a high level, it’s not that complex though. It works as follows. The user of a test runner will typically be interested in notification during the test run. Hence TestRunner exposes three events that fire when the test run starts, when it completes, and when each test has been run respectively. To receive notifications, the user can either hook up to those events directly or register one or more so-called test clients. We’ll look at some examples of test clients later on. To avoid blocking test clients and support cancellation of the test run, the tests run in their own thread.
As you can see from the RunTest method, each test results in a SingleTestResult, containing a TestOutcome of Pass or Fail. I don’t know how terribly useful it is, but μnit currently distinguishes between failures due to failed assertions and failures due to other exceptions. It made sense at the time.
The SingleTestResult instances are aggregated into TestClassResult instances, which in turn are aggregated into a single TestGroupResult instance representing the entire test run. All of these classes implement ITestResult, which looks like this:
Now for a SingleTestResult, the NumberOfTests will obviously be 1, whereas for a TestClassResult it will match the number of SingleTestResult instances contained by the TestClassResult, and similarly for the TestGroupResult.
So that pretty much wraps it up for the core of μnit. Let’s take a look at how it looks at the client side, for someone who might want to use μnit to write some tests. The most convenient thing to do is probably to register a test client; that is, some object that implements ITestClient. ITestClient looks like this:
The registered test client will then receive callbacks as appropriate when the tests are running.
In order to be useful, test clients typically need to translate notifications into something that a human can see and act upon if necessary. In the .NET gadgeteer world, it means you need to interact with some hardware.
For the Game of Life implementation (which can be browsed here if you’re interested) I implemented two test clients interacting with elements of the FEZ Spider kit: a DisplayTestClient that shows test results on a small display, and a LedTestClient that simply uses a multicolored LED light to give feedback to the user. Here’s the code for the latter:
As you can see, it starts the test run by turning the LED light off. Then, as individual test results come in, the LED light starts blinking. On the first passing test, it will start blinking green. It will continue to do so until a failing test result comes in, at which point it will switch to blinking red instead. Once it has started blinking red, it will stay red, regardless of subsequent results. So the LedTestClient doesn’t actually tell you which test failed, it just tells you if some test failed. Useful for a sanity check, but not much else. That’s where the DisplayTestClient comes in, since it actually shows the names of the tests as they pass or fail.
How does it look in practice? Here’s a video of μnit tests for Game of Life running on the FEZ Spider. When the tests all succeed, we proceed to run Game of Life. Whee!