Tuesday, June 29, 2010

Unit Testing Dynamic XAP Files

By now, you probably are aware that you can dynamically load XAP files using the Managed Extensibility Framework (MEF) within your Silverlight applications. Have you been scratching your head, however, and wondering how on earth you would actually test something like that?

It is possible, and here's a quick post to show one way you can.

First, we need a decent deployment service. You're not really going to hard-code the download and management, are you? I didn't think so. If you need an example, look no further than the sample code I posted to Advanced Silverlight Applications using MEF. Here's what the interface looks like:

public interface IDeploymentService
{
    void RequestXap(string xapName, Action<Exception> xapLoaded);       
       
    AggregateCatalog Catalog { get; }
}

This keeps it simple. Request the xap file, then specify a delegate for a callback. You'll either get a null exception object (it was successful) or a non-null (uh... oh.)

Now, let's focus on testing it using the Silverlight Unit Testing Framework. The first caveat is that you cannot use it on the file system. This means that your project will not work if you run it with a test page rather than hooking it to a web server (local or not).

Doing this is simple. In your ASP.NET project, go to the Silverlight tab and add your test project. When you are adding it, there is an option to generate a test page. I typically have one "test" web project with all of my test Silverlight applications, so I will have multiple test pages. To run a particular test, you simply set your ASP.NET web project as the start up project, then the corresponding test page (we're talking the aspx, not the html) as the start page. I usually delete the automatically generated HTML pages.

Now we need to give MEF a test container. The caveat here is that, without a lot of work, it's not straightforward to reconfigure the host container so you'll want to make sure you test a given dynamic XAP file only once, because once it's loaded, it's loaded.

This is what my application object ends up looking like:

public partial class App
{
    public AggregateCatalog TestCatalog { get; private set; }

    public App()
    {
        Startup += Application_Startup;            
        InitializeComponent();
    }

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        // set up a catalog for tests
        TestCatalog = new AggregateCatalog();
        TestCatalog.Catalogs.Add(new DeploymentCatalog());

        var container = new CompositionContainer(TestCatalog);

        CompositionHost.Initialize(container);

        // now set up the unit testing framework
        var settings = UnitTestSystem.CreateDefaultSettings();
        RootVisual = UnitTestSystem.CreateTestPage(settings);
    }              
}

Here, I haven't composed anything, just set up the container.

Now I'm going to add a simple dynamic XAP for testing. I add a new Silverlight application and wire it to the test web site but do NOT generate a test page. I blow away the App.xaml and MainPage.xaml resources, and add a simple class called Exports. Here is my class:

public class Exports
{
    private const string TESTTEXT = "TestText";

    [Export(TESTTEXT, typeof(string))]
    public string TestText { get { return TESTTEXT; } }
}

Yes, you got it - just a simple export of a string value. Now let's write our test. I create a new test class and decorate it with the TestClass attribute. I am also running asynchronous tests, so it's best to inherit the test from SilverlightTest which has some base methods for asynchronous testing.

Let's take a look at the set up for my test:

[TestClass]
    public class DeploymentServiceTest : SilverlightTest
    {
        private const string DYNAMIC_XAP = "DynamicXap.xap";
        private const string TESTTEXT = "TestText";

        private DeploymentService _target;
    
        [Import(TESTTEXT, AllowDefault = true, AllowRecomposition = true)]
        public string TestString { get; set; }
     
        public DeploymentServiceTest()
        {
            CompositionInitializer.SatisfyImports(this);
        }

        [TestInitialize]
        public void TestInit()
        {
            if (Application.Current.Host.Source.Scheme.Contains("file"))
            {
                _target = null;
            }
            else
            {
                _target = new DeploymentService();
                ((App) Application.Current).TestCatalog.Catalogs.Add(_target.Catalog);
            }
        }
}

So right now I'm simply setting up my targets. The property is key - by composing imports on construction, I register my test class with the MEF system. Right now, however, I haven't loaded anything, so it won't be able to satisfy the import. By using AllowDefault true, however, I tell it I'm expecting something later and setting it to null is fine. The recomposition is what will trigger an update once the catalogs change. I also reach out to the test catalog I set up in the main application and add the catalog from my deployment service to it. Note that if I am running on the file system, I don't bother setting up my service.

Next, I can add a stub to determine if I can even test this. If I am running from the file system, the deployment service is never set up. I created a helpful method that asserts an "inconclusive" when this is the case:

private bool _CheckWeb()
{
    if (_target == null)
    {
        Assert.Inconclusive("Cannot test deployment service from a test page. Must be hosted in web.");
        return false;
    }

    return true;
}        

Now we can write our main test. First, we check to make sure we are in a web context. Then, we load the xap, and once it is loaded, confirm there were no errors and that our property was successfully set:

[Asynchronous]
[TestMethod]
public void TestValidXap()
{
    if (!_CheckWeb())
    {
        return;
    }

    Assert.IsTrue(string.IsNullOrEmpty(TestString), "Test string should be null or empty at start of test.");
    _target.RequestXap(DYNAMIC_XAP, exception =>
                                        {
                                            Assert.IsNull(exception, "Test failed: exception returned.");
                                            Assert.IsFalse(string.IsNullOrEmpty(TestString),
                                                            "Test failed: string was not populated.");
                                            Assert.AreEqual(TESTTEXT, TestString,
                                                            "Test failed: property does not match.");
            }
}

And that's pretty much all there is to it - of course, I am also adding checks for things like contract validation (are you passing me a valid xap name?) and managing duplicates, but you get the picture.

Jeremy Likness

Saturday, June 26, 2010

Advanced Silverlight Applications using the Managed Extensibility Framework

This week I had the pleasure of attending my first CodeStock event in Knoxville, TN. Let me start by saying it was an amazing event. I give many thanks to the attendees, for keeping it a strong and thriving community, the sponsors (including my company, Wintellect), the speakers, and of course the organizers. You can learn more about the event at the page I linked to above. I highly recommend it - great venue and setup, and fantastic people. I connected and made friends with many people in both the .NET and programming community in general.

X-Fit Sample Application

For my talk on advanced applications in Silverlight using the Managed Extensibility Framework, I built a sample application called "the X-Fit Sample Application." I often hear complaints that demos and blog posts focus on one screen and a button. I wanted to build something with more depth than that, and used that application for my presentation.

What does it demonstrate?

  • Region management
  • De-coupling of views and view models
  • Dynamic loading of XAP files on-demand
  • OOB (Out-of-Browser)
  • Recognizing out of browser and behaving differently
  • Loading a plugin from the file system
  • Messaging using MEF
  • "Tracing" using Debug
  • Debugging MEF parts (imports and exports)
  • ...and plenty more

You can click here to view: X-Fit Sample Application

The source code and slide shows from my deck are both available at this link:

Deck and source

To use the application, jump into it and fill out the information. You'll find the first example of dynamic loading because once you save the information, the additional tabs will load with some charts and graphs. If you close the application, then re-launch it, it will automatically detect your user (using isolated storage) and not show the set up screen again.

You can right click and install locally. If you access the BMR tab (graphs showing basal metabolic rate) you'll notice a help link for more information. In the web version, this will simply pop open a new window to a Wikipedia page. In the out-of-browser version, it will introduce a new tab and show the information inline using the web browser control.

The little "plus" and "x" demonstrate different features. The "x" simply throws an error. If you are viewing the application, you'll get a generic message. If you are debugging, it will show the debug dump information.

There is a "SampleApplicationData" project included with the main source. It will build but is not referenced in the project. If you click the "plus" sign, you'll get an open file dialog. You can then browse to the XAP for the sample data, and click it. When you then refresh the application, it will be loaded with "John Doe" and some sample data.

A second code stock example will create a XAP that you can right-click and download here: CodeStock Example (right-click and download). Click the plus, browse to the XAP, and then select it to see the CodeStock logo.

Obviously there is a lot more in the slide deck and in the source code. Understand I'm not trying to establish best practices - for example, the simple messenger may not be the right implementation if you have views that are short-lived (due to event references) and PRISM provides very robust region management "out of the box" you can use. The idea here was to demonstrate what is possible in a sample application that goes a little deeper than a view and a button.

Oh, and thanks to the Silverlight team for the Cosmopolitan theme.

Thanks again, everyone, it was a great experience and I hope to come back in the future.

Jeremy Likness

Wednesday, June 16, 2010

Silverlight UI Automation and Full VS 2010 Integration

OK, so it's not exactly "out of the box" but the most recent PRISM 4.0 Drop (drop 2) seems to contain something Silverlight developers have been begging for ... for quite some time.

It's buried within the "QuickStart" folder under the "BasicMVVM" project. This project provides guidance for the Model-View-ViewModel pattern and is worth a deep look. It may provide a basic framework for your future applications.

In that same folder, you'll find BasicMVVM.Tests.AcceptanceTest. Fire this project up and take a look at it. It contains some helper classes and launchers to host the Silverlight automation piece. If you're impatient like me, build and fire it off. That is where you start to have fun!

Silverlight Test Integration

Yes, that is the test panel within Visual Studio 2010, not the Silverlight Unit Testing Framework in a browser window. Even more interesting is watching the form appear on the screen, then automatically get filled out by the engine as the acceptance tests are run.

So what we have here is full UI automation for tests as well as VSTS integration.

This is obviously a huge jump for Silverlight ... I'm looking forward to digging in deeper to explore what's possible with this!

Jeremy Likness

Thursday, June 10, 2010

Tips and Tricks for INotifyPropertyChanged

As a WPF or Silverlight developer, you know that your models must implement INotifyPropertyChanged and it can be a pain. To do it safely, you really need to check to see if there are any registered handlers, then raise the event. To add insult to injury, the event arguments take a string, so if you mistype the property name you're out of luck. Some clever individuals have created nice code snippets to generate the needed plumbing, but it doesn't help with refactoring.

One common solution is to create a base class that provides the plumbing for a raise property notification.

The first Prism 4.0 drop has a typical example of this, and one that mirrors what I've done in quite a few places. Take a look at some snippets from the base view model designed in the Model-View-ViewModel (MVVM) quick start:

        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected void RaisePropertyChanged(params string[] propertyNames)
        {
            foreach (var name in propertyNames)
            {
                this.RaisePropertyChanged(name);
            }
        }

        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
        {
            var propertyName = ExtractPropertyName(propertyExpresssion);
            this.RaisePropertyChanged(propertyName);
        }

        private string ExtractPropertyName<T>(Expression<Func<T>> propertyExpresssion)
        {
            if (propertyExpresssion == null)
            {
                throw new ArgumentNullException("propertyExpression");
            }

            var memberExpression = propertyExpresssion.Body as MemberExpression;
            if (memberExpression == null)
            {
                throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
            }

            var property = memberExpression.Member as PropertyInfo;
            if (property == null)
            {
                throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
            }

            if (!property.DeclaringType.IsAssignableFrom(this.GetType()))
            {
                throw new ArgumentException("The referenced property belongs to a different type.", "propertyExpression");
            }

            var getMethod = property.GetGetMethod(true);
            if (getMethod == null)
            {
                // this shouldn't happen - the expression would reject the property before reaching this far
                throw new ArgumentException("The referenced property does not have a get method.", "propertyExpression");
            }

            if (getMethod.IsStatic)
            {
                throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
            }

            return memberExpression.Member.Name;
        }
    }

The piece that extracts the expression is key, because it allows you to get away from RaisePropertyChanged("property") and move to the more strongly-typed and refactoring-friendly RaisePropertyChanged(()=>property).

The base class might work well for some, but putting too much functionality in the base class can sometimes become a problem. The main reason is due to the fact that there is not multiple inheritance, therefore if you have multiple functions that are aspects of some classes and not others, you either need to create a grab bag of different derived classes, or drag along the functionality you don't need.

Fortunately, extension methods allow us to have the best of both worlds. We can simply extend the behavior as it is defined, via the INotifyPropertyChanged interface, and then implement it with an extension.

Take a look at the property helper class:

public static class PropertyHelper
{        
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        if (propertyExpression == null)
        {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpression.Body as MemberExpression;

        if (memberExpression == null)
        {
            throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;

        if (property == null)
        {
            throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
        }
            
        return memberExpression.Member.Name;
    }

    public static void RaisePropertyChanged<T>(this INotifyPropertyChanged src, Expression<Func<T>> propertyExpression, PropertyChangedEventHandler handler)
    {
        if (handler != null)
        {
            handler(src, new PropertyChangedEventArgs(ExtractPropertyName(propertyExpression)));
        }
    }
}

Notice how we extend the interface and simply take in the property expression and the handler. Now, I can raise the property like this:

private string _myProperty;

public string MyProperty 
{
   get 
   {
      return _myProperty;
   }

   set 
   {
      _myProperty = value;
      this.RaisePropertyChanged(()=>MyProperty, PropertyChangedHandler); 
   }
}

Of course, you don't even have to make it an extension method at all - it could simply be a helper you call directly.

There is only one problem with this implementation, that I would be remiss if I didn't call out. In a typical system you're probably fine, but you are taking something internal to the class (the change handler) and sending it out in the wild. Something outside of your class could then manipulate or hook into the handler (as we are doing, on purpose, for the property event) and cause unexpected behaviors and results. If you can live with that caveat and it helps, then here is one more way to handle the pattern.

Bonus Round: Observable Enumerables

Oh, one more thing. Have you found you often bind things like charts, lists, and grids to lists where the entire list changes? In other words, you are never adding or removing individual items, but instead clearing your ObservableCollection and re-adding them? Depending on how you do that, it can be a costly operation as the CollectionChanged will fire for each item. But ... assigning a new list will suddenly kill your data-binding, because the controls lose their reference to the list (the original binding).

Solution?

Expose an IEnumerable<T> that contains whatever logic you need to build the list - whether it is the return from a service call, spinning up a new list, etc. Then, whenever you have a condition that changes the list (i.e. a new search term, filter property, refresh command, etc) simply raise the property changed event for that list.

It will end up looking something like this:

public class MyViewModel : INotifyPropertyChanged 
{
   public IParameters Parameters { get; set; }

   public IService Service { get; set; }

   private List<Widget> _widgets; 

   public MyViewModel()
   {
      // this code may go somewhere else depending on how you wire up dependencies
      Parameters.PropertyChanged += (o,e) => _NewQuery;
      Service.QueryAsyncCompleted += (o,e) => 
      {
         _widgets = e.Result; 
         RaisePropertyChanged(()=>TopFiveQuery, PropertyChanged);
         RaisePropertyChanged(()=>Query, PropertyChanged);
      }
   }

   private void _NewQuery()
   {
      Service.QueryAsync(Parameters);
   }
   
   public IEnumerable<Widget> TopFiveQuery
   {
       return (from w in _widgets orderby w.DateModified descending 
               select w).Take(5).AsEnumerable();
   }

   public IEnumerable<Widget> Query
   {
       return _widgets;   
   }

   public event PropertyChangedEventHandler PropertyChanged;
}

Now a control can be bound to the Query directly. Whenever the user changes parameters, it fires a property changed event that calls out to the service. When the service returns, it loads up the results and then fires the property changed for the list, which rebinds the list to the control. The reason I show it this way is you might reuse the data in different lists and have different filters. By exposing the enumerable interface, you can provide multiple queries and have them all update and re-bind on the single service call.

Enjoy!

Jeremy Likness

Wednesday, June 9, 2010

Managed Extensibility Framework for Line of Business Applications in .NET 4.0

I recently gave a talk for the Atlanta Microsoft Professionals users group about using the Managed Extensibility Framework for Line of Business applications in .NET 4.0. We had a great turnout and I appreciate everyone who attended. The talk was based on my blog post "10 Reasons to use the Managed Extensibility Framework."

While the talk itself wasn't recorded, I'm happy to share the slide deck with you. You can download it here and watch the presentation for yourself. I covered not only the benefits of using MEF, but touched on some of the costs associated with it as well.

This is the abstract for the talk:

With the release of Visual Studio 2010, the Managed Extensibility Framework (MEF) became a first-class citizen of the .NET 4.0 Framework. It is the same system used for extensibility and plug-ins within Visual Studio 2010 itself. Learn the ten reasons why you would want to use the Managed Extensibility Framework in your own applications and how MEF can assist you with building dynamic, modular, extensible, testable applications faster than ever before. This deep dive will cover advanced MEF topics included strongly typed meta-data and custom export providers as well as how MEF differs between Web, WPF, Console, and Silverlight applications.

Enjoy the presentation!

Jeremy Likness