ailon's DevBlog: Development related stuff in my life

Book Review: The Art of Unit Testing by Roy Osherove

2/2/2010 7:49:36 PM

The Art of Unit Testing by Roy Osherove

Personal preface

I must admit – I haven’t been doing any real-life unit testing until now. Back in 2004 I was leading a relatively big WinForms project and I thought we should do unit testing on it. Unfortunately we had already finalized our conceptual designs (which didn’t consider unit testing), the tooling at the time wasn’t as mature as it is now and, most importantly, we had no knowledge on how this unit testing thing should be done properly. So after playing around with NUnit for some time I’ve concluded that it was neither the time nor the place to start doing it for real and put it away.

After that project I was mostly involved with smaller ASP.NET projects and never thought that unit testing was really feasible for them. So, basically unit testing was always somewhere on my mind but not too close to the surface.

Five years later I’ve started working on amCharts for WPF & Silverlight and as we release new products, add new features and fix bugs I’ve started feeling a real fear of breaking something while fixing a bug or adding a new feature. Manual testing helps but the fear is always there. I understood that it’s time for “take 2” on unit testing.

This time I knew that I have to do it right. This is one of those subjects where you can’t just start doing it and learn as you go. That is a sure way to fail (see my experience above).

The Book

Fortunately this time there is this book and it’s targeted at .NET developers which is not essential but a nice bonus. I’ve been reading Roy Osherove’s blog for quite some time and following him on twitter. I’ve been using his Regulator regular expression testing tool before that. So, I sort of “knew” and respected the author, the book got raving reviews at Amazon – buying it was a no-brainer.

The book is short (less than 300 pages) but on point with almost none “water spilled” and space wasted. I’ve swallowed it in less than a week reading it in the evenings only. That wouldn’t be that fast for a fiction book, but I think that’s a record for me for a technical book. I usually fall asleep reading technical books in bed pretty quickly and I only did it once with this book ;)

It covers all the aspects of unit testing, writing good tests and testable code, tooling for .NET (also mentions tools for Java, C++, etc.). It also offers quite strong author’s opinions on the matters. Some people might not like this, but as long as you can see that it’s an opinion and not something written in stone, I really do like it.

Minor Criticism

I can’t say anything bad about the content of this book, but I have a few minor complaints about presentation. First of all I didn’t like the font used. I’m no expert of fonts and this could be the default Manning (publisher) font, but it didn’t feel right to me (too wide or something). The use of some “comic” type of font for ToC and headings is another story, but since it’s not the main font it didn’t bother me much. There were some minor issues with sample code too: incorrect indentation, a couple of auto-capitalized “return” statements and things like that, but nothing major.

The book comes with free access to ebook version in PDF, ePub and Mobipocket formats w/o DRM (as far as I understand). Unpleasant thing was that my name and email address was inserted in the footer of every page of the PDF. I don’t even know what is more unpleasant DRM or this. Should I protect the PDF now so it doesn’t spread over internet accidentally or something? If I wanted to spread illegal copies I’d find a way to remove this, but now I don’t even feel comfortable giving that PDF to my colleague which I consider a fair use (I’ll give him a paper book anyway). Anyway this is a minor issue and I should stop complaining.

Conclusion

If you are serious about starting unit testing or improving your skills, do yourself a favor and don’t just jump right in, but buy this book (especially if your main platform is .NET). It’s a really excellent starting point for anyone who doesn’t consider himself a unit testing guru (and I guess even gurus might find something new). After reading this book I feel pretty confident that my next project will include unit tests and I’ll have a good basis and this book as a reference if I have questions.

Links

Tags: , ,

MIX10K T-shirt

2/2/2010 12:44:44 PM

Got my Mix10K T-shirt Today:

Mix10K t-shirtMix10K t-shirt

Don’t forget to vote for my entry in the MIX 10k Smart Coding Challenge. You know, that’s the only chance I have of going to Las Vegas this year ;)

Tags: ,

Weekend project: Spiced Up Tic-Tac-Toe 3D

1/18/2010 2:41:56 PM

TicTacToe3D

Over the weekend I’ve spiced up my little entry in MIX 10k Challenge and posted it to games.ailon.org. Check it out. And vote for it in the contest. Thanks!

As usually source code is included, but… The objective of the initial project was to fit it into 10k and even though I’ve spiced it up visually I didn’t change the overall code architecture so it’s some pretty ugly code. Sorry :)

kick it on DotNetKicks.com Shout it submit to reddit

Tags:

Writing WPF/Silverlight compatible code. Part 6: Adding XAML files as links

1/13/2010 5:05:40 PM

Note for future readers: These series discuss WPF and Silverlight versions that are current stable versions at the time of this writing – WPF 3.5 and Silverlight 3.

These are ongoing series of posts on the subject of WPF/Silverlight compatibility. New posts will be added to the Table of Contents post as they are written so bookmark that post or just subscribe to my RSS feed.

While developing WPF/Silverlight applications and controls one of the main code sharing techniques is adding shared code files as links to one of your projects.

Visual Studio - Add As Link

This works perfectly with C# or VB files but not as good with XAML. In this article I’ll show you a workaround to make this technique work with only a small overhead.

The Problem

Suppose you’ve created a WPF project and your own custom control named MyTemplatedControl. It does nothing in our example (just sets DefaultStyleKey property).

   1: public class MyTemplatedControl : Control
   2: {
   3:     public MyTemplatedControl()
   4:     {
   5:         this.DefaultStyleKey = typeof(MyTemplatedControl);
   6:     }
   7: }

Now we create a default ControlTemplate for our control. To do this we add Themes folder to our project and Generic.xaml flie in that folder.

image

Our template will just display a blue rectangle (just so we can see if it’s applied). Here’s the XAML in Generic.xaml file.

   1: <ResourceDictionary
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:TestControl"
   5:     >
   6:  
   7:     <Style TargetType="local:MyTemplatedControl">
   8:         <Setter Property="Template">
   9:             <Setter.Value>
  10:                 <ControlTemplate TargetType="local:MyTemplatedControl">
  11:                     <Canvas>
  12:                         <Rectangle Canvas.Left="20" Canvas.Top="20" Width="100" Height="100" 
  13:                                    Fill="Blue" Stroke="Black" StrokeThickness="3" />
  14:                     </Canvas>
  15:                 </ControlTemplate>
  16:             </Setter.Value>
  17:         </Setter>
  18:     </Style>
  19: </ResourceDictionary>

We add our control to a test window and run the app we see something like this:

image

Now we want to create a Silverlight version of the control. We create a Silverlight custom control project, “Add As Link” our MyTemplatedControl.cs file, create Themes directory and “Add As Link” our Generic.xaml file. Everything compiles just fine. But when we add the control to a Silverlight application and run it we get an empty white screen. The template is not applied.

This happens because for some reason (I don’t know if it’s done for a reason or is it just a bug) XAML compiler compiles local and linked .xaml files differently. Here’s an article describing what happens. Short story is that resource key for local and linked xaml files are different and since the engine looks for a specific resource key for default styles it just can’t see the linked version because it’s key is not equal to what it looks for.

The Solution

The above mentioned LearnWPF.com article suggest a workaround of moving all resources to a separate assembly. I’m pretty sure that wouldn’t work with default styles and generally is not something you would want to do in simple scenarios.

I solved this issue using MergedDictionaries. The solution is to move you Generic.xaml content to other XAML file (or even better separate files for each control). This way you can “Add As Link” those specific files and add separate Generic.xaml files with only a list of MergedDictionaries addressing the resource key differences.

Let’s apply this technique to our example. So we move our XAML to a separate MyTemplatedControl.xaml file and reference it from MergedDictionaries in Generic.xaml.

MyTemplatedControl.xaml:

   1: <ResourceDictionary
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:TestControl"
   5:     >
   6:     <Style TargetType="local:MyTemplatedControl">
   7:         <Setter Property="Template">
   8:             <Setter.Value>
   9:                 <ControlTemplate TargetType="local:MyTemplatedControl">
  10:                     <Canvas>
  11:                         <Rectangle Canvas.Left="20" Canvas.Top="20" Width="100" Height="100" 
  12:                                    Fill="Blue" Stroke="Black" StrokeThickness="3" />
  13:                     </Canvas>
  14:                 </ControlTemplate>
  15:             </Setter.Value>
  16:         </Setter>
  17:     </Style>
  18: </ResourceDictionary>

Generic.xaml

   1: <ResourceDictionary
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     >
   5:     <ResourceDictionary.MergedDictionaries>
   6:         <ResourceDictionary Source="/WpfControl;component/Themes/MyTemplatedControl.xaml" />
   7:     </ResourceDictionary.MergedDictionaries>
   8: </ResourceDictionary>

Now we “Add As Link” MyTemplatedControl.xaml to our Silverlight project and add a copy of Generic.xaml and make required changes.

Generic.xaml (Silverlight project version)

   1: <ResourceDictionary
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     >
   5:     <ResourceDictionary.MergedDictionaries>
   6:         <ResourceDictionary Source="/SlControl;component/MyTemplatedControl.xaml" />
   7:     </ResourceDictionary.MergedDictionaries>
   8: </ResourceDictionary>

Notice the differences in Source of ResourceDictionary:

  1. It refers to out Silverlight assembly (SlControl)
  2. It addresses linked XAML file by it’s “incorrect” resource key which is a side effect of linking the XAML file described above (notice that there’s no “Themes” portion in the path)

Now our Silverlight app runs as expected:

image

This way we can share elaborate XAML between WPF and Silverlight versions (or just between several WPF and/or Silverlight projects) without having to maintain 2 versions of the file. And the only price to pay for this is that we have to add a line to both Generic.xaml files every time we add a new XAML file.

kick it on DotNetKicks.com Shout it

My Entry in MIX 10K Challenge

12/22/2009 11:00:17 AM

ttt3d500 

My entry in MIX 10K Challenge has been published. For those who don’t know the challenge is a contest where participants create small apps with combined source code size of up to 10kb. The grand prize is a trip to Las Vegas to MIX 2010 conference.

My entry is a Silverlight 3D Tic-Tac-Toe game. Check it out, vote, tweet, retweet, show your friends and co-workers. Send me to Las Vegas!

Thanks.

Tags:

Stock Chart for WPF & Silverlight 1.1 Released

12/17/2009 9:49:04 AM

amCharts Stock Chart for Silverlight and WPF

We’ve shipped final version 1.1 of amCharts Stock Chart for WPF & Silverlight. Now there’s a powerful (and FREE) advanced financial charting control for Silverlight and WPF. Key additions in this release are:

  • Silverlight version based on the same code base as WPF
  • 3 new EventBullet types: VerticalBand, HorizontalBand and GraphHighlight;
  • support for mouse wheel scrolling and zooming;
  • support for different colors for positive and negative columns in column graph;
  • performance improvements.

More details can be found in the official announcement.

Tags:

Weekend project: Open Source Silverlight Battleship Game

12/14/2009 2:58:47 PM

Ok, this took something like 2 weekends, but here it is – my Silverlight Battleship game.

Battleship - open source silverlight game

One interesting thing about this project was that I wanted it to support full screen mode and for that to work nicely I needed Viewbox control which is in WPF but not (yet) in official Silverlight distribution. But they have it in Silverlight Toolkit. But the thing is that I only needed Viewbox (which is a small and simple control) from the Toolkit and adding reference to the toolkit’s assembly added a couple of 300+ kb assemblies to my XAP. In result my simple game became a 300kb XAP and this wasn’t the size I was happy with.

Fortunately Silverlight Toolkit is open source (released under MsPL), so I took the sources, found 2 files responsible for the Viewbox, replaced a few constant references to hardcoded values and a couple of extension method calls to inline implementations (to avoid possible chain reference madness) and included that directly into my project. This way my XAP went from chubby (for a simple game) 300kb to a respectable 42k.

Another (non-technical) thing I’ve noticed while doing minor research for this project is that the Battleship we played in (soviet) school is different from the one children in the west (apparently) played. Our fleet consisted of one 4-cell ship, 2 – 3-cell ships, 3 – 2-cell ships and 4 – single-cell ships. The one described in Wikipedia had one 5-cell ship, 1 – 4-cell, 2 – 3 cell and 1 – 2 cell. So I decided to make everyone in the world (hopefully) feel at home and included an option to play with both types of fleets.

So, that’s about all I had to say about this game. Go play it and/or download the source, modify, etc. It’s released under MsPL license. Don’t forget to let me know if you make something cool out of it.

kick it on DotNetKicks.com Shout it

Tags:

Writing WPF/Silverlight compatible code. Part 5: Adding PropertyChangedCallback

11/30/2009 5:13:27 PM

Note for future readers: These series discuss WPF and Silverlight versions that are current stable versions at the time of this writing – WPF 3.5 and Silverlight 3.

These are ongoing series of posts on the subject of WPF/Silverlight compatibility. New posts will be added to the Table of Contents post as they are written so bookmark that post or just subscribe to my RSS feed.

No OverrideMetadata() Take 2

One thing I didn’t mention in the “No OverrideMetadata()” section of “Part 2: Dependency Properties” is how to add a handler to be called when value of inherited dependency property changes. In WPF you can use OverrideMetadata() method to do it like this:

   1: static MyControl()
   2: {
   3: #if !SILVERLIGHT
   4:     FrameworkPropertyMetadata newMetadata = new FrameworkPropertyMetadata();
   5:     newMetadata.PropertyChangedCallback += MyControl.VisibilityProperty_Changed;
   6:     Control.VisibilityProperty.OverrideMetadata(typeof(MyControl), newMetadata);
   7: #endif
   8: }

Then you do what you wanted to do in your handler which is called every time Visibility changes:

   1: private static void VisibilityProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
   2: {
   3:     // do something here
   4: }

As you know there’s no OverrideMetadata() in Silverlight. So what can we do? Unfortunately, to my knowledge, there’s no elegant way to do this. There are however a couple of not so pretty hacks/workarounds. One is described in an answer to a similar question on StackOverflow.

I’ve used another method which involves an extra DependencyProperty declaration and binding of the original dependency property to this one. In the above mentioned case a Silverlight portion for achieving the same result looks like this:

   1: #if SILVERLIGHT
   2:         // declare an extra DependencyProperty for the workaround
   3:         // It uses the same PropertyChangedCallback as WPF code for Visibility
   4:         private static readonly DependencyProperty VisibilityChangedWorkaroundProperty = DependencyProperty.Register(
   5:             "VisibilityChangedWorkaround", typeof(Visibility), typeof(MyControl),
   6:             new PropertyMetadata(MyControl.VisibilityProperty_Changed));
   7: #endif
   8:  
   9: public MyControl()
  10: {
  11: #if SILVERLIGHT
  12:     // visibility changed event workaround
  13:     Binding visibilityBnd = new Binding("Visibility");
  14:     visibilityBnd.Source = this;
  15:     visibilityBnd.Mode = BindingMode.TwoWay;
  16:     this.SetBinding(MyControl.VisibilityChangedWorkaroundProperty, visibilityBnd);
  17: #endif
  18: }

As you can see above, we’ve declared and extra dependency property called VisibilityChangedWorkaroundProperty and we’ve attached the same handler to it’s property changed event as the one used in the WPF code above. We don’t need a CLR property wrapper for it and we’ve declared it as private so it doesn’t show up anywhere outside of our class. Then in the constructor we bind our new workaround property to the real inherited Visibility property. So, when inherited property changes, our local property changes too, and the callback is called.

kick it on DotNetKicks.com Shout it

Writing WPF/Silverlight compatible code. Part 4: Geometries

11/23/2009 7:26:43 PM

Note for future readers: These series discuss WPF and Silverlight versions that are current stable versions at the time of this writing – WPF 3.5 and Silverlight 3.

These are ongoing series of posts on the subject of WPF/Silverlight compatibility. New posts will be added to the Table of Contents post as they are written so bookmark that post or just subscribe to my RSS feed.

Default Contstructors Only

The first thing you notice when you start working with geometries in Silverlight after you’ve dealt with them in WPF is absence of constructor overloads. So, if you’ve used to write constructs like this in WPF:

RectangleGeometry rectangle = new RectangleGeometry(new Rect(10, 10, 50, 40));


you should forget about them when you start caring about WPF/Silverlight compatibility. Use something like this instead:

   1: RectangleGeometry rectanble = new RectangleGeometry()
   2: {
   3:     Rect = new Rect(10, 10, 50, 40)
   4: };

This works in both and isn’t that much longer.

No PathSegment.IsStroked

IsStroked let’s you specify that a segment of some path shouldn’t be stroked. So, in WPF you can create a path like this

image

with XAML like this:

   1: <Path Stroke="Black" StrokeThickness="3">
   2:     <Path.Data>
   3:         <PathGeometry>
   4:             <PathFigure StartPoint="0,20">
   5:                 <LineSegment Point="20,0" />
   6:                 <LineSegment Point="40,20" />
   7:                 <LineSegment Point="60,20" IsStroked="False" />
   8:                 <LineSegment Point="80,0" />
   9:                 <LineSegment Point="100,20" />
  10:             </PathFigure>
  11:         </PathGeometry>
  12:     </Path.Data>
  13: </Path>

As you have probably guessed, it’s not going to work in Silverlight 3 (and as far as I’ve checked in Siverlight 4 beta either). For simple scenarios like the one above, you can overcome this limitation by simply dividing PathFigure into several figures (one for each continuos segment) like this

   1: <Path Stroke="Black" StrokeThickness="3">
   2:     <Path.Data>
   3:         <PathGeometry>
   4:             <PathFigure StartPoint="0,20">
   5:                 <LineSegment Point="20,0" />
   6:                 <LineSegment Point="40,20" />
   7:             </PathFigure>
   8:             <PathFigure StartPoint="60,20">
   9:                 <LineSegment Point="80,0" />
  10:                 <LineSegment Point="100,20" />
  11:             </PathFigure>
  12:         </PathGeometry>
  13:     </Path.Data>
  14: </Path>

I’ve created a simple helper extension method to do the same trick automatically in code depending on whether it’s being called in WPF or Silverlight:

   1: public static void AddLineSegment(this PathGeometry pathGeometry, Point point, bool isStroked)
   2: {
   3:     PathFigure figure = pathGeometry.Figures[pathGeometry.Figures.Count - 1];
   4:  
   5: #if SILVERLIGHT
   6:     if (isStroked)
   7:     {
   8:         figure.Segments.Add(new LineSegment() { Point = point });
   9:     }
  10:     else
  11:     {
  12:         // silverlight has no IsStroked properto on LineSegment
  13:         // so we create a new PathFigure to imitate non-stroked line segment
  14:         figure = new PathFigure();
  15:         figure.StartPoint = point;
  16:         pathGeometry.Figures.Add(figure);
  17:     }
  18: #else
  19:     figure.Segments.Add(new LineSegment(point, isStroked));
  20: #endif
  21: }

You can use it like this when constructing paths in your code:

myPathGeometry.AddLineSegment(myPoint, true);

The method can be generalized to support other types of PathSegments, but I needed it for lines so there you have lines-only version. You can generalize/adapt it yourself.

This saves us in cases like the one above. But here’s another simple case that above technique fails to solve:

image

In WPF a figure like this can be created with this XAML:

   1: <Path HorizontalAlignment="Center" VerticalAlignment="Center"
   2:     Stroke="Black" Fill="LightGreen" StrokeThickness="3">
   3:     <Path.Data>
   4:         <PathGeometry>
   5:             <PathFigure StartPoint="0,40">
   6:                 <LineSegment Point="0,20" IsStroked="False" />
   7:                 <LineSegment Point="20,0" />
   8:                 <LineSegment Point="40,20" />
   9:                 <LineSegment Point="60,20" IsStroked="False" />
  10:                 <LineSegment Point="80,0" />
  11:                 <LineSegment Point="100,20" />
  12:                 <LineSegment Point="100,40" IsStroked="False" />
  13:             </PathFigure>
  14:         </PathGeometry>
  15:     </Path.Data>
  16: </Path>

Unfortunately, I don’t know a way to achieve this in Silverlight other than overlaying 2 paths – one for the fill and one for the stroke like this:

   1: <Path Fill="LightGreen" StrokeThickness="3">
   2:     <Path.Data>
   3:         <PathGeometry>
   4:             <PathFigure StartPoint="0,40">
   5:                 <LineSegment Point="0,20"/>
   6:                 <LineSegment Point="20,0" />
   7:                 <LineSegment Point="40,20" />
   8:                 <LineSegment Point="60,20"/>
   9:                 <LineSegment Point="80,0" />
  10:                 <LineSegment Point="100,20" />
  11:                 <LineSegment Point="100,40" />
  12:             </PathFigure>
  13:         </PathGeometry>
  14:     </Path.Data>
  15: </Path>
  16:  
  17: <Path Stroke="Black" StrokeThickness="3">
  18:     <Path.Data>
  19:         <PathGeometry>
  20:             <PathFigure StartPoint="0,20">
  21:                 <LineSegment Point="20,0" />
  22:                 <LineSegment Point="40,20" />
  23:             </PathFigure>
  24:             <PathFigure StartPoint="60,20">
  25:                 <LineSegment Point="80,0" />
  26:                 <LineSegment Point="100,20" />
  27:             </PathFigure>
  28:         </PathGeometry>
  29:     </Path.Data>
  30: </Path>

And since we are talking about WPF/Silverlight reusable code here, this is the way we should do it to work in both. Let me know if you happen to know a better way of doing something like this without having to rely on 2 objects.

kick it on DotNetKicks.com Shout it

amCharts Stock Chart for Silverlight Released

11/19/2009 4:21:40 PM

amCharts has just released a beta version of amCharts Stock Chart for Silverlight!

Stock Chart for Silverlight - click for live demo

This version includes all the cool advanced features of our WPF version and enables you to have spectacular advanced stock (and basically any date/time based data) charts in your Silverlight 3 applications.

Take a look at the demos, download your copy, add an advanced control to your Silverlight application and, please, help us spread the word.

kick it on DotNetKicks.com Shout it
Copyright © 2003 - 2010 Alan Mendelevich
Powered by BlogEngine.NET 1.5.0.7