Apr 01 Keith | Dev

Silverlight Unit Tests and Continuous Integration - StatLight

There are few options for running Silverlight unit tests on the build server. The November release of the Silverlight Toolkit doest support test automation from the command line, however it’s only experimental. In my testing I feel its just not yet there, I’ve seen issues with builds hanging, it doesn't work with IE6 on XP (which is still widely deployed within large organizations), and its messy to get the test results to merge into a single file to integrate with Cruise Control (if that's what your using). Finally, all the test targets are within the csproj files which makes automating from a single build script problematic (given the .sln isn’t itself an msbuild file, you end up with hardcoded paths in your build script). The preview bits may address these issues but there not official just yet. Its worth keeping an eye on these as the test runner is massively improved.

The most reliable option I’ve found is StatLight. It works great with Team City and support multiple test frameworks.

Where it really pays off is running tests via the command line.  For example the following will run all the test for Test.xap (which in this case we’ll pretend its a test project from the Silverlight Toolkit testing framework). The --Continuous flag will keep StatLight running continuously and automatically re-run the tests when the .xap change, great for TDD.

StatLight.exe -x=PathToTestProject\bin\Debug\Tests.xap --Continuous SomeOptionalTagAsUsedByYourTestFramework

Jump over to your MS build script and add a target similar to the below for running tests via the build server. The --teamcity flag converts the output of the test (via the consoles standard output stream) to a format that team city can understand. The awesomeness of Team City means this just works :).

<Target Name="RunSilverlightTests">
  <Exec Command="&quot;.\Tools\StatLight\StatLight.exe&quot; -x=&quot;SomePathToTestProject\(SomeTests.xap&quot; --teamcity" />
</Target>

When using MSTest for Silverlight (aka the Silverlight Toolkit Test Framework), StatLight will analyses your test xap, fire up a Winform in the background, host Silverlight, run the test and collect the output. To date this is the most reliable approach I’ve found.

Mar 31 Keith | Dev

New Silverlight Testing Framework Drop

There is a new ‘preview’ drop of the Silverlight testing framework available from Jeff Wilcox, he posted it on his mix 2010 site. It also works on Windows Mobile 7. It has a new GUI runner which is much improved and much faster than that last runner.

I’ve dropped it into our code base and our 600 or so test (.Net 3.5, Silverlight 3) are running at twice the speed. It also comes with a Tag selector similar to that found in the Silverlight Toolkit test suite.

If you’re on .Net 3.5 and Silverlight 3 I’d say drop it in, alternatively you can wait until sometime April when the new drop of the toolkit and Silverlight 4 is due.

The tag selector:

 image

Some simple tests to demo the tool:

image

The Tag selector via the Windows Mobile 7 Emulator:

image

And the test results:

image

Jan 14 Keith | Dev

Strongly Typed INotifyPropertyChanged Event Raisers

INotifyPropertyChanged has been around forever, and so has the nasty string based property names that are passed to raise the events. Its all familiar stuff:

class Program 
{
    static void Main(string[] args)
    {
        
        var streamingPricesService = new StreamingPricesService();

        Expression<Action<Object, PropertyChangedEventArgs>> test = (o, e) => Console.WriteLine("Property '{0}' changed ", e.PropertyName);

        streamingPricesService.PropertyChanged 
            += (o, e) => Console.WriteLine("Property '{0}' changed ", e.PropertyName);
        streamingPricesService.PropertyChanged
            += (o, e) => Console.WriteLine("Property '{0}' changed ", e.PropertyName);
        streamingPricesService.IsOnline = true;

        Console.ReadKey();
    }

    private class StreamingPricesService : INotifyPropertyChanged
    {
        private bool _isOnline;
        public bool IsOnline
        {
            get { return _isOnline; }
            set
            {
                if (_isOnline != value)
                {
                    _isOnline = value;
                    InvokePropertyChanged("IsOnline");
                }
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void InvokePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler changed = PropertyChanged;
            if (changed != null) changed(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
 

..and its nasty!!

Enter Lambda LambdaExpression, its been around the block by now,  you’ve all seen them, the PropertyChanged wireup below uses the meta data it exposes above, its type-safe and IMO cleaner. You can wrap the functionality up anyway you like, typically I’d put the INotifyPropertyChanged functionality in a class called NotifyingBase and keep the PropertyHelper in a separate class as its usually used in other situations too (however below its just all in 2 classes).

using System;
using System.ComponentModel;
using System.Linq.Expressions;

namespace ConsoleApplication3
{
    class Program 
    {
        static void Main(string[] args)
        {
            var streamingPricesService = new StreamingPricesService();

            streamingPricesService.PropertyChanged += (o, e) => Console.WriteLine("Property '{0}' changed ", e.PropertyName);
            streamingPricesService.PropertyChanged += (o, e) => Console.WriteLine("Property '{0}' changed ", e.PropertyName);
            streamingPricesService.IsOnline = true;

            Console.ReadKey();
        }

        private class StreamingPricesService : INotifyPropertyChanged
        {
            private bool _isOnline;
            public bool IsOnline
            {
                get { return _isOnline; }
                set
                {
                    if (_isOnline != value)
                    {
                        _isOnline = value;
                        InvokePropertyChanged(() => IsOnline);
                    }
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;

            private void InvokePropertyChanged<T>(Expression<Func<T>> expression)
            {
                PropertyChangedEventHandler changed = PropertyChanged;
                if (changed != null)
                {
                    var propertyName = PropertyHelper.GetPropertyName(expression);
                    changed(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }

    public class PropertyHelper
    {
        public static string GetPropertyName<T>(Expression<Func<T>> expression)
        {
            return GetPropertyNameFromLambda(expression);
        }

        public static string GetPropertyName<T>(Expression<Func<T, Object>> expression)
        {
            return GetPropertyNameFromLambda(expression);
        }

        private static string GetPropertyNameFromLambda(LambdaExpression lambda)
        {
            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = lambda.Body as UnaryExpression;
                memberExpression = unaryExpression.Operand as MemberExpression;
            }
            else
                memberExpression = lambda.Body as MemberExpression;

            if (memberExpression == null)
                throw new ArgumentException(String.Format("Property expression '{0}' did not provide a property name.", lambda));

            return memberExpression.Member.Name;
        }
    }
}

Jan 12 Keith |

Setting up a Blog

Done but not dusted the new blog is up and running. BlogEngine.Net to run the blog. Windows Live Writer to enable decent posting.  SyntaxHighlighter to allow for readable and ‘copyable’ source code. PreCode to allow SyntaxHighlighter to play nicely with Windows Live Writer, And finally, Greenshot to allow for decent screen capture (that won’t kill your bandwidth!). Not to mention domain names, hosting, coming up with that all important blog title and a theme that's sure to change like the London weather (but hopefully with the opposite trend: better not worse)!.

In summary:

BlogEngine.Net

Windows Live Writer

SyntaxHighlighter

private static string GetPropertyNameFromLambda(LambdaExpression lambda)
{
    MemberExpression memberExpression;
    if (lambda.Body is UnaryExpression)
    {
        var unaryExpression = lambda.Body as UnaryExpression;
        memberExpression = unaryExpression.Operand as MemberExpression;
    }
    else
        memberExpression = lambda.Body as MemberExpression;

    if (memberExpression == null)
        throw new ArgumentException(String.Format("Property expression '{0}' did not provide a property name.", lambda));

    if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
        throw new ArgumentException("Property expression refers to a member on another type");

    return memberExpression.Member.Name;
}

PreCode (used to insert the above snippet into Live Writer)

image

image

Greenshot (only configuration shown, it hijacks printscreen to allow you to select what screen area to capture, and via JEPG quality, the file size. Its awesome).

image


About the author

Keith Woods

Keith Woods works for Lab49, a consulting firm that builds advanced solutions for the financial services industry.