xUnit for Xamarin is dead, long live xUnit for Devices!

March 16, 2015 Uncategorized , ,

xUnit for Xamarin is dead, long live xUnit for Devices!

In conjunction with today’s release of xUnit 2.0 RTM, I’m happy to announce the initial release of xUnit for Devices (GitHub | NuGet). This has been a long time coming and I’d like to thank Brad Wilson and James Newkirk for their tremendous efforts over the years.

Project rename

xUnit for Devices started out as xUnit for Xamarin. Over the course of development however, it became apparent that what we really have is an MVVM-based test runner where the view was only an implementation detail. Current support is limited to platforms Xamarin Forms supports, but in the future it’s pretty easy to add a desktop/WPF view and support any additional GUI platform as needed.

Upgrading your projects to RTM

If you’ve been using xUnit for Xamarin, the easiest way to update is by using NuGet. There’s a final xunit.runner.xamarin package that pulls in the new xunit.runner.devices package. After upgrading, you can simply remove the old package and keep the dependencies. Windows Phone 8 users will need to make one additional change in the MainPage.xaml to update the assemly name from xunit.runner.xamarin to xunit.runner.devices.

Getting Started

The RTM 1.0 release is available on NuGet and on GitHub.

For iOS and Android, create a new blank Xamarin app project to host the unit test runner. Make sure to give any capabilities/permissions you need in the appropriate manifest.

For WP8, create a new Unit Test Project and then remove the MSTestFramework reference.

Then for all platforms, install/update the xunit.runner.devices package via the GUI or Package Manager Console:
Install-Package xunit.runner.devices

Then look for the .cs.txt, xaml.txt files that are the templates for your platform and copy/paste the contents into the app. Specifically,
– iOS: replace the contents of AppDelegate.cs with AppDelegate.cs.txt
– Android: replace the contents of MainActivity.cs with MainActivity.cs.txt
– WP8: replace the contents of MainPage.xaml.cs with MainPage.xaml.cs.txt and MainPage.xaml with MainPage.xaml.txt

xUnit Device Runners 1.0 RC3

February 23, 2015 Uncategorized , ,

Following the release of xUnit 2.0 RC3, the Xamarin Device Runners have been updated to work with RC3.

One note for Android users: due to a dependence on Xamarin Forms, your runner app project needs to use API level 21 as its target and SDK. You can target down to API level 15 if you wish. You can also reference other MonoAndroid or Portable Class Libraries if you want to keep your unit tests at a different API level. You also might need to specify a default theme on some devices to workaround a different Xamarin Forms bug. Please see the updated MainActivity.cs.txt for the specifics.

Wait, what happened to RC2?

If you blinked, you missed it. RC2 of the Device Runners came out Saturday. With xUnit RC3 being a quick update from RC2, it’s best to skip to the latest.

As always, if you run into any issues, feel free to reach out to @onovotny on Twitter or post an issue on GitHub.

Getting Started

RC3 is available on NuGet and on GitHub.

For iOS and Android, create a new blank Xamarin app project to host the unit test runner. Make sure to give any capabilities/permissions you need in the appropriate manifest.

For WP8, create a new Unit Test Project and then remove the MSTestFramework reference.

Then for all platforms, install/update the xUnit.Runner.Xamarin package via the GUI or Package Manager Console:
Install-Package xunit.runner.xamarin -Pre

Then look for the .cs.txt, xaml.txt files that are the templates for your platform and copy/paste the contents into the app. Specifically,
– iOS: replace the contents of AppDelegate.cs with AppDelegate.cs.txt
– Android: replace the contents of MainActivity.cs with MainActivity.cs.txt
– WP8: replace the contents of MainPage.xaml.cs with MainPage.xaml.cs.txt and MainPage.xaml with MainPage.xaml.txt

Announcing: xUnit Device Runner RC1

January 31, 2015 Uncategorized , , , ,

xUnit Device Runner 1.0 RC1

I’m pleased to announce the release of the xUnit Device Runners Release Candidate 1. This release adds support for the Xamarin.iOS Unified profile, required for all new iOS applications now and updates starting in July.

Other notable enhancements include a filter for searching test cases by name and status (pass/fail/not run).

To get started, please see the following posts:

If you run into any issues, please file a report in the issue tracker.

Xamarin 3.9 is Stable: Update Now

January 12, 2015 Uncategorized

Xamarin just pushed 3.9 to the stable channel. I’d recommend everyone doing Xamarin work update to this. The most important updates are:

  1. Support for creating 64-bit iOS apps. This uses the new “Xamarin.iOS Unified” profile. The existing profile has been deprecated but will remain for legacy enterprise-only apps. As of Feb 1, Apple will require new apps to be 64-bit and as of June 1, updates to existing apps must be 64-bit.
  2. Support for Visual Studio 2015 Preview. For those of you using the VS 2015 preview, Xamarin 3.9 supports it.
  3. Visual Studio Android Emulator support. The VS Android emulator uses Hyper-V, so it’s fast and also works if you had to enable HyperV for any other reason and thus can’t use Genymotion or other ring 0-based virtualization.

DataTemplateSelector for Xamarin.Forms

December 31, 2014 Uncategorized , ,

Next up in the saga of Xamarin Forms: DataTemplateSelector‘s.

For people coming into Xamarin Forms from Microsoft XAML, it’s easy to see many gaps. Xamarin Forms is still young, but there are some workarounds. I’ve already blogged about how to implement a ContentPresenter, next up is the DataTemplateSelector.

Supposed you want to put a list of items into a ListView but use a different DataTemplate for some of the items? In Microsoft XAML, you could set the ItemTemplateSelector property to a custom DataTemplateSelector and you’d be all set. Sadly, this is not yet available within Xamarin Forms, but we can create our own.

To see the specific usage/examples of how to implement a custom DataTemplateSelector instance, please refer to MSDN or your favorite search engine. Usage will be exactly the same*

There are a few classes we’ll need:

  1. DataTemplateSelector.cs
    public class DataTemplateSelector
    {
        public virtual DataTemplate SelectTemplate(object item, BindableObject container)
        {
            return null;
        }
    }
    
  2. ExtendedlistView.cs
    public class ExtendedListView : ListView
    {
        public static readonly BindableProperty ItemTemplateSelectorProperty = BindableProperty.Create("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(ExtendedListView), null, propertyChanged: OnDataTemplateSelectorChanged);
        private DataTemplateSelector currentItemSelector;
        private static void OnDataTemplateSelectorChanged(BindableObject bindable, object oldvalue, object newvalue)
        {
            ((ExtendedListView)bindable).OnDataTemplateSelectorChanged((DataTemplateSelector)oldvalue, (DataTemplateSelector)newvalue);
        }            
        protected virtual void OnDataTemplateSelectorChanged(DataTemplateSelector oldValue, DataTemplateSelector newValue)
        {
            // check to see we don't have an ItemTemplate set
            if (ItemTemplate != null && newValue != null)
                throw new ArgumentException("Cannot set both ItemTemplate and ItemTemplateSelector", "ItemTemplateSelector");
            currentItemSelector = newValue;
        }
        protected override Cell CreateDefault(object item)
        {
            if (currentItemSelector != null)
            {
                var template = currentItemSelector.SelectTemplate(item, this);
                if (template != null)
                {
                    var templateInstance = template.CreateContent();
                    // see if it's a view or a cell
                    var templateView = templateInstance as View;
                    var templateCell = templateInstance as Cell;
                    if (templateView == null && templateCell == null)
                        throw new InvalidOperationException("DataTemplate must be either a Cell or a View");
                    if (templateView != null) // we got a view, wrap in a cell
                        templateCell = new ViewCell { View = templateView };
                    return templateCell;
                }
            }
            return base.CreateDefault(item);
        }
        public DataTemplateSelector ItemTemplateSelector
        {
            get
            {
                return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty);
            }
            set
            {
                SetValue(ItemTemplateSelectorProperty, value);
            }
        }
    }
    

With these two pieces, you can now create your own selector. Suppose you have an RSS Feed that you want to display an alternate template every 4 items. For this example, we’ll assume that each item in the list has an index attached.

We’ll start with our custom selector:

public class NewsItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate NewsItem { get; set; }
    public DataTemplate NewsItemLarge { get; set; }

    public override DataTemplate SelectTemplate(object item, BindableObject container)
    {
        // must have IListItems
        var li = (IListItem)item;

        if (li.Index == 0 || li.Index%4 == 0)
        {
            return NewsItemLarge;
        }
        return NewsItem;
    }
}

Now in the App.xaml, lets add our templates. (Aside: See this example for how to use XAML for your App class allowing you to easily use XAML shared resources.)

  <DataTemplate x:Key="NewsItem">
    <Grid MinimumHeightRequest="320">
      <Grid.RowDefinitions>
        <RowDefinition Height="120"/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="140"/>
        <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <Image Grid.Row="0" Grid.Column="0" Source="{Binding ImageUrl}" HeightRequest="110" Aspect="AspectFill" VerticalOptions="Start" />
      <StackLayout Grid.Row="0" Grid.Column="1" Padding="16, 0, 10, 8">
        <Label Grid.Row="0" Grid.ColumnSpan="2" VerticalOptions="Center" Text="{Binding Title}" />
        <ContentView HeightRequest="4" /><!-- Hack for margin -->
        <Label Grid.Row="1" Grid.Column="1" VerticalOptions="Start" Text="{Binding Summary}" />
      </StackLayout>
    </Grid>
  </DataTemplate>

  <DataTemplate x:Key="NewsItemLarge">
    <Grid MinimumHeightRequest="520">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="120" />
      </Grid.RowDefinitions>
      <Image Grid.Row="0" Source="{Binding ImageUrl}" HeightRequest="400" Aspect="AspectFill" VerticalOptions="Start" />
      <StackLayout Grid.Row="1" Padding="16, 0, 10, 8">
        <Label Grid.Row="0" Grid.ColumnSpan="2" VerticalOptions="Center" Text="{Binding Title}" />
        <ContentView HeightRequest="4" />
        <!-- Hack for margin -->
        <Label Grid.Row="1" Grid.Column="1" Style="{StaticResource ItemSubheaderText}" VerticalOptions="Start" Text="{Binding Summary}" />
      </StackLayout>
    </Grid>
  </DataTemplate> 

Here’s the custom DataTemplateSelector:

public class NewsItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate NewsItem { get; set; }
    public DataTemplate NewsItemLarge { get; set; }

    public override DataTemplate SelectTemplate(object item, BindableObject container)
    {
        // must have IListItems
        var li = (IListItem)item;

        if (li.Index == 0 || li.Index%4 == 0)
        {
            return NewsItemLarge;
        }
        return NewsItem;
    }
}

Finally, we’ll add an instance of the DataTemplateSelector to the App.xaml:

  <controls:NewsItemTemplateSelector x:Key="NewsItemTemplateSelector"                                         NewsItem="{StaticResource NewsItem}"                                         NewsItemLarge="{StaticResource NewsItemLarge}" />

Later on, when we want to use it, we can use it with our ExtendedListView:

<controls:ExtendedListView ItemsSource="{Binding Items}"              ItemTemplateSelector="{StaticResource NewsItemTemplateSelector}">
</controls:ExtendedListView>

When rendered, the first item will have the large image template and then every fourth item will too.

BONUS: You can use either View or Cell-derived types in your DataTemplates as the control will automatically wrap Views into a ViewCell.

Enjoy!

*probably.

ContentPresenter for Xamarin.Forms

December 31, 2014 Uncategorized , ,

While working on a new Xamarin Forms project, I came across the need for a ContentPresenter ala Microsoft XAML. The basic idea is to use a placeholder for a piece of content (usually a ViewModel) and then supply a DataTemplate to control how it should be displayed.

A simple example might look like this:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <controls:ContentPresenter Grid.Row="1"
               BindingContext="{Binding MyModel, Source={StaticResource Locator}}" 
               ItemTemplate="{StaticResource MyModelTemplate}"
               />

</Grid>

This goes back to some of the more “classic” MVVM patterns where we want to make our display more componentized.

In Xamarin Forms Today (v1.3.0), if you want to create a custom component, you can derive from ContentView and go to town. Add your widgets either with XAML or in code. Many times though, we don’t really need to create a new class/view directly. A DataTemplate is sufficient as we can bind to the ViewModel and use Commands to take action. These are the so-called “zero code-behind” views.

In this case, a ContentPresenter is all we need – set the BindingContext to your ViewModel and create/bind a DataTemplate. New to Forms 1.3, you can now put resources in the Application-level, so you can more easily share those instances.

Here’s the complete code, sans-usings, to implement your own. This can go either in a Shared code or PCL:

public class ContentPresenter : ContentView
{
    public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(ContentPresenter), null, propertyChanged: OnItemTemplateChanged);

    private static void OnItemTemplateChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var cp = (ContentPresenter)bindable; 

        var template = cp.ItemTemplate;
        if (template != null)
        {
            var content = (View)template.CreateContent();
            cp.Content = content;
        }
        else
        {
            cp.Content = null;
        }
    }

    public DataTemplate ItemTemplate
    {
        get
        {
            return (DataTemplate)GetValue(ItemTemplateProperty);
        }
        set
        {
            SetValue(ItemTemplateProperty, value);
        }
    }
}

If you want, you can get fancy with Triggers and change the ItemTemplate to vary based on whatever conditions you want.

Now available: xUnit for Windows Phone 8 Silverlight

November 21, 2014 Uncategorized ,

With the release of xUnit 2 beta 5, Windows Phone 8 Siverlight is now supported; here’s how to get started.

Side note: If you’ve previously had the xUnit Extension VSIX installed, you need to remove it for beta 5. You no longer need it. See the release notes for details.

Unfortunatey, due to limitations in the Visual Studio Test Explorer’s architecture, we can’t yet integrate into the Test Explorer window like we can for Universal or Dekstop apps. Instead, we have to run the unit tests as an app on the device, exactly like we do for Xamarin. In fact, with Xamarin Forms providing the UI, we’re able to bring the same runner support to WP8.

Steps to create a Windows Phone 8 Silverlight test project

  1. Read the post on getting started with Xamarin. It’s almost identical.
  2. Use the latest version of the runner, 0.99.5-beta5 at the time of this writing.
  3. When creating the WP8 App, use the Windows Phone 8 Silverlight (Blank) template.
  4. Replace the contents of MainPage.xaml.cs with the contents of MainPage.xaml.cs.txt added to your project

To run tests, simply run the app either in the debugger or deploy and run.

Known issues

The Xamarin Forms-based runner is bare bones. It needs a lot of work to add features. But it does work to execute xUnit tests and run them in a debugger to figure out why stuff’s not working :)

How you can help

Pull requests are very much welcome over at the project site. If you need help getting up-and-running, just ping me on Twitter.

Beware: Xamarin beta channel is borked!

September 12, 2014 Uncategorized

Here’s the core issue: Xamarin’s QA screwed up with the beta channel on Windows. If you use any portable class libraries in your projects (even if not at all Xamarin related!), VS will fail to load them due to a Xamarin bug. This is pretty poor and should never have made it to beta.

That said, if you want to use Xcode 6, you need to use Xamarin.iOS 8 on your Mac. Problem is that the stable version of Xamarin for VS won’t work with that…needs the matching beta. If you try to use Xcode 6 with the stable Xamarin.iOS, it can’t debug…so bam.

I’m sure this will be cleared up very shortly, but you might want to refrain from either installing Xcode 6 on your Mac or using the Xamarin beta channels for the next several days. Version 3.6.197 on Windows is the bad one….they say it’s fixed already, so the question is how quickly can the push an update out.

Now Shipping: xUnit support for Windows 8 and Windows Phone App 8.1

August 11, 2014 Uncategorized , ,

After years of unofficial hacks to get xUnit working for Windows Store apps, I’m happy to announce that xUnit v2 beta 4 ships with official support. As an added bonus, Windows Phone App 8.1 support is included as well.

To use xUnit for Store, you need the latest xUnit.net runner for Visual Studio installed.

Steps to create a Windows 8 Store Unit Test for xUnit:

  1. Install the runner
  2. Create a new Windows Store Unit Test project
  3. In the project references, remove the MSTestFramework reference and delete the UnitTest1.cs sample test
  4. Use NuGet to Install-Package xunit -Pre and install at least version 2.0.0-beta4-build2738
  5. Create your tests
  6. When you compile, you’ll see the tests in the Test Explorer window (make sure to show that window if it’s not visible)

Steps to create a Windows Phone App Unit Test for xUnit:

  1. Install the runner
  2. Create a new Windows Phone App Unit Test project (not Windows Phone 8.1 Silverlight)
  3. In the project references, remove the MSTestFramework reference and delete the UnitTest1.cs sample test
  4. Use NuGet to Install-Package xunit -Pre and install at least version 2.0.0-beta4-build2738
  5. Create your tests
  6. When you compile, you’ll see the tests in the Test Explorer window (make sure to show that window if it’s not visible)

To Do

  • Windows Phone 8 support – technical issues to overcome
  • Project Templates

Limitations

Right now, only Any CPU/x86 is supported by the VS Runner due to limitations in the VS Runner’s extensibility model. We plan on shipping a device runner, similar to the Xamarin Runner that will enable on-device ARM testing.

I’d like to thank @bradwilson and @jamesnewkirk for their patience and persistence with merging these large pull requests and keeping the release bar so high.

Announce: Ninject for Xamarin (and everything else)

August 4, 2014 Uncategorized , , ,

I’m happy to announce Ninject support for Xamarin.iOS and Xamarin.Android. Together with the previous release, which included support for Universal Apps, Ninject now supports every major platform in a single Portable.Ninject NuGet package.

Not being enough to simply support each platform, the Portable.Ninject package includes a Portable Class Library (PCL) reference assembly so you can reference Ninject in your PCL’s. Just make sure to also add the NuGet reference to your main application so the “real” bits get used instead of the reference assemblies. This means it’s easy to have NinjectModule‘s in your portable code.

For more documentation, please visit the Dojo or the Wiki.

To get started

  1. Add the Portable.Ninject package to your project.
  2. If your project is a PCL, also add the package to your main app.
  3. Somewhere in your main app, usually your App class (Windows), AppDelegate (iOS), or Application class (Android), create the Kernel and load your types/modules.

Limitations

This package just has the core Ninject functionality. Much of Ninject’s power comes from its extensions, including Convention Based Binding and Factory. These extensions have not yet been forked and updated to work with Portable.Ninject, but they shouldn’t be hard to do. Please drop a note to let me know which extensions you’d like to see brought over.

Contributing

Contributions are very much welcome! Please clone/fork my repo and use the bait-switch branch as your starting point. The solution contains unit test projects for all platforms; to run the xUnit ones for Wpa81 or Win8, you’ll need the latest xUnit runner for Visual Studio extension installed too.