0 Comments

image

In this post we will look at how we can write UI tests for a Xamarin.Android app. The app which we are testing is a basic app based on the MVVM pattern. You can find a detailed blog post on the in and outs of the app under test here.

Assuming you already have a Xamarin Test Cloud (XTC) project added to your solution. As described in this former post. Lets get started by preparing the app for UI testing.

Enabling your Android app for the XTC tests

You do not have to do anything to enable your app to be compatible with XTC. That being said when writing a test with Xamarin Test Cloud. The test should not recognize a control by the content it is displaying. Rather it identifies a control via an ID which is not visible to the end user but rather a invisible ID. Setting this ID is best done via the accessibility label attribute. You can set this in the AXML code of your view i.e. control:

This ID will not have to change if the locale changes. Even if the location of the UI element changes it will still be found by the test. Thus IDs should be generally used to identify controls as they allow for higher resilient test code.

Writing Test(s)

After tuning our the UI code we can start writing the test. One way is to use the XTC recorder. While this tool brings a great benefit when starting off with or smaller apps (as it would be the case in this post). I usually prefer to use the REPL which is easy to use and can be invoked at any point in the test code.

When the UI is prepared accordingly we can start writing the test. One way is to use the XTC recorder. While this tool brings a great benefit when starting of with or smaller apps (as it would be the case in this post), I usually prefer to use the REPL which is easy to use and can be inserted to be started at any point in your code.

The REPL is especially useful once you have a large testing framework. Having a framework i.e. helpers in place you can run those before firing up the REPL. So you can start exploring and interacting with the UI right were you need to.

XtcTreeWithIds_thumb

Starting the REPL is as easy as adding the following line to your test method:

You can see the entire apps visual tree outlined.

Now we can define the steps we want to perform in our test:

Note how the test takes screenshots at every stage. This allows to easily identify the steps on the Xamarin test cloud and give them a label. While this might seem to be a bit of an overkill for such a small sample. When writing larger tests naming your steps i.e. screen shots will help you narrowing down where an error is happening.
One good thing about the tests is that they also run well on your local machine. So using e.g. the al Studio we can execute the tests over the NUnit Runner:

shows resharper testrunner in visual studio after executing a test

You can choose to run the tests on an emulator or device as you like. Just select the desired target as you would when starting the application. Or submit it to the test cloud i.e. integrate it in our build process.

Conclusion

This post described how to get started writing automated UI tests with Xamarin Test Cloud for a Xamarin.Android. Showing you how to adopt your UI for writing resilient test. Based on NUnit the tests are running on a stable and battle proven foundation.

Keep in mind that UI tests should not be the only testing you rely on for testing your app. But in combination with Unit and Integration tests they can provide great value to your project. Running them on Xamarin Test Cloud allows you to run them on a sea of devices. Along with different versions of Android i.e. vendor flavours.

You can find the entire sample on GitHub.

0 Comments

nuget

See how you can easily create NuGet packages to publish cross platform C# libraries that allow to integrate platform specific code in your Portable Class Library (PCL) based Projects. In a former post you can read about how to create a cross platform library and see how the library has to be consumed by the e.g. app consuming the library. This post builds up on where that last post left off and shows how we can use the library providing the OS version number in a NuGet package. So the package we want to create has the following structure:

 

  • OSVersion.Core
  • OSVersion.UWP
  • OSVersion.Droid
  • OSVersion.iOS

 

Our goal is to generate a single NuGet package which can be added to any of the above named platforms.

Note: Though this post focuses on the platforms Universal Windows Platform (UWP), Android and iOS the approach can be easily extended to support additional platforms such as .Net, Silverlight et al.

Creating the package definition

First of all we will need to install the NuGet command line tool. Make sure that you add it to your PATH. After it is added to your path you can execute the NuGet commands with PowerShell. To create a NuGet package you need a nuspec file which you can generate by executing the command):

nuget spec

The location of the nuspec file does not really matter – I tend to have it in my root directory i.e. where the Solution file is. If you open the file in your lightweight editor of choice, you can edit the package specification to your gusto or for our sample somewhat like this:

<?xml version="1.0"?>
<package >
  <metadata>
    <id>OSVersion</id>
    <version>1.0.0.3</version>
    <title>OS Version</title>
    <authors>Mark Allibone</authors>
    <owners>Mark Allibone</owners>
    <!--<licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>-->
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Get the OS version for your UWP, Android or iOS app.</description>
    <releaseNotes>This is the initial release.</releaseNotes>
    <copyright>Copyright 2015</copyright>
    <tags>OSVersion</tags>
  </metadata>
  
  <files>
    <file src="OSVersionAPI\bin\Release\OsVersionAPI.Core.dll" target="lib\portable-net45+wp8+wpa81+netcore45+monoandroid1+xamarin.ios10+UAP10\OsVersionAPI.Core.dll" />
    <file src="OSVersionAPI\bin\Release\OsVersionAPI.Core.pdb" target="lib\portable-net45+wp8+wpa81+netcore45+monoandroid1+xamarin.ios10+UAP10\OsVersionAPI.Core.pdb" />
    <file src="OSVersionAPI\bin\Release\OsVersionAPI.Core.xml" target="lib\portable-net45+wp8+wpa81+netcore45+monoandroid1+xamarin.ios10+UAP10\OsVersionAPI.Core.xml" />
    
    <file src="OSVersionAPI.UWP\bin\Release\OsVersionAPI.Core.dll" target="lib\UAP10\OsVersionAPI.Core.dll" />
    <file src="OSVersionAPI.UWP\bin\Release\OsVersionAPI.Core.pdb" target="lib\UAP10\OsVersionAPI.Core.pdb" />
    <file src="OSVersionAPI.UWP\bin\Release\OsVersionAPI.Core.xml" target="lib\UAP10\OsVersionAPI.Core.xml" />
    
    <file src="OSVersionAPI.Droid\bin\Release\OsVersionAPI.Core.dll" target="lib\monoandroid1\OsVersionAPI.Core.dll" />
    <file src="OSVersionAPI.Droid\bin\Release\OsVersionAPI.Core.pdb" target="lib\monoandroid1\OsVersionAPI.Core.pdb" />
    <file src="OSVersionAPI.Droid\bin\Release\OsVersionAPI.Core.xml" target="lib\monoandroid1\OsVersionAPI.Core.xml" />
    
    <file src="OSVersionAPI.iOS\bin\iPhone\Release\OsVersionAPI.Core.dll" target="lib\xamarin.ios10\OsVersionAPI.Core.dll" />
    <file src="OSVersionAPI.iOS\bin\iPhone\Release\OsVersionAPI.Core.pdb" target="lib\xamarin.ios10\OsVersionAPI.Core.pdb" />
    <file src="OSVersionAPI.iOS\bin\iPhone\Release\OsVersionAPI.Core.xml" target="lib\xamarin.ios10\OsVersionAPI.Core.xml" />
  </files>
</package>

Beware of the target folder structure, these names may seem a bit strange (I’m looking at you Xamarin.Android…) but these actually have to align with a pattern or else you will run into problems when installing the NuGet package. You can find the target folder names on the NuGet website.

Integrating some Metadata in the NuGet package

You are not required to add the pdb (used for Debugging) or the XML file (Code Documentation for Intellisense) but it is considered best practice and makes the life of the developer using the library easier so I would suggest you follow along with this.

To enable the XML metadata file, right click on a project under Properties, Build you can set the checkmark for XML documentation file. Now you should have an XML file in your build output.

Per default the pdb file should be generated during the build, except for iOS (it’s always you iOS isn’t it…) - anyhow, right click on your project then under Properties, Build, Advanced… set Debug Info to pdb-only.

Beware that these settings are per build Configuration so make sure you set it for Release builds as you usually ship the Release build of a library.

Packing it up

Now all that is left to do is creating the package which we can do with the following command:

nuget pack

After the package is created the next thing to do is make it available for consumption. This means either pushing the package to NuGet or creating your own NuGet repository. Due to the fact, that this here is only a demo I will go with the second option.

Integrating the package in an app

Now we can simply add the OS Version library over the package manager. Notice that we get the same result as in the former blog post but this time the developer using the library will not be required to add the library multiple times to the project i.e. this potential error source no longer exists.

So when we now run the app under UWP we get the following output.

Win10VersionNumber

Note if we would only add the NuGet package to the NativePcl.Core project the output would simply show the stub implementation.

StubVersionNumber

So all the principals that were described in the last post still apply. But adding the library has been greatly simplified.

Conclusion

In this blog post you saw how a cross platform NuGet package can be created which lends itself very well to create cross platform libraries that implement native features which have to implemented differently for each targeted platform. There are many great libraries already out in the wild that use this approach e.g. MVVM Light, SQLite, PCL Storage and many many more.

You can find the sample project on GitHub.

0 Comments

See how you can offer cross platform APIs based on C# that you can consume in Universal Windows Platform Apps (UWP), Xamarin.iOS, Xamarin.Android, Xamarin.Forms, ASP.Net and even your classic .Net WPF app. In my last post I showed how one can use platform specific libraries and code in a Portable Class Library with dependency injection. This approach is great when you are developing your own app but it gets somewhat quirky, when you want to offer a library to fellow co-workers/developers, as you force them to setup your own library through dependency injection. But there is of course another way that allows you to encapsulate your implementation details neatly while still providing platform specific features to your PCL code.

The library in this blog post will provide the OS version for a UWP, Xamarin.iOS and Xamarin.Android app.

Setting up the library

The library consists of four projects:

  • OSVersion.Core
  • OSVersion.UWP
  • OSVersion.Droid
  • OSVersion.iOS

One thing which is a bit special about all the projects is that all of their Default Namespace and the Assembly name all have the same name.

NamespaceBinaryName

In each project we implement the SystemInformationHandler.cs class, on the PCL we simply implement a stub:

public class SystemInformationHandler
{
    #region Implementation of ISystemInformationHandler

    public static string OSVersion => "Gnabber";

    #endregion
}

For the other platforms such as UWP we implement the calls to the UWP specific APIs:

public class SystemInformationHandler
{
    public static string OSVersion
    {
        get { return OsVersionString(); }
    }

    private static string OsVersionString()
    {
        string sv = AnalyticsInfo.VersionInfo.DeviceFamilyVersion;
        ulong v = ulong.Parse(sv);
        ulong v1 = (v & 0xFFFF000000000000L) >> 48;
        ulong v2 = (v & 0x0000FFFF00000000L) >> 32;
        ulong v3 = (v & 0x00000000FFFF0000L) >> 16;
        ulong v4 = (v & 0x000000000000FFFFL);

        return $"Windows {v1}.{v2}.{v3}.{v4}";
    }
}

So in the end we have implemented the generic class in the PCL and specific classes for each platform we target to support. Now lets see how we can consume this library in an app.

Consuming the library

The app will exist of the usual cross platform mobile app setup which means we will have usual suspects covering Windows, Android and iOS with a Portable Class Library aka Core to share the reusable code.

NativePclProjectOverview

In the core we have our business logic code and view models (I’m a huge fan of the MVVM Light library, to find out more just view my mvvm light posts). In the NativePcl.Core project we have a service OsVersionService.cs for returning the version number:

public class OsVersionService : IOsVersionService
{
    public string GetVersion()
    {
        return SystemInformationHandler.OSVersion;
    }
}

Reference the OSVersion.Core library as binary – DO NOT reference it as project or you will be facing compile errors in one of the next steps. Don’t ask me how I know Winking smile

Because all our assemblies of the OSVersion library will be compiled to assemblies with the same name we can’t just simply reference the project file but have to add the binary i.e. the compiled version of the library. If you are looking at the sample from GitHub, make sure to compile the solution under release build as the OSVersion is referenced via binary in the release output folder of the projects.

The method invokes the OSVersion property in the OSVersion library - leaving out the specific project e.g. UWP intent fully here. On the clients for example the Android app we have a single screen showing the version number defined in the MainView.xaml:

<Page
    x:Class="NativePcl.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:NativePcl.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="{Binding OSVersion}" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TitleTextBlockStyle}"></TextBlock>
    </Grid>
</Page>

And the corresponding code behind or as we are using view models MainViewModel.cs:

public class MainViewModel : ViewModelBase
{
    private readonly IOsVersionService _osVersionService;

    public MainViewModel(IOsVersionService osVersionService)
    {
        if (osVersionService == null) throw new ArgumentNullException(nameof(osVersionService));
        _osVersionService = osVersionService;
    }

    public string OSVersion => _osVersionService.GetVersion();
}

If we now run the app we will get the follow output:

coreVersion

Now this is the output we defined in the OSVersion.Core, if we now reference the binary of the OSVersion.UWP in the NativePcl.UWP project things get really interesting. Instead of receiving an error because we are adding two assemblies with the same name the compiler will prefer the platform specific library over the PCL implementation. And even though we never invoke the library directly from our NativePcl.UWP app the OS version returned now is returned from the platform specific i.e. OSVersion.UWP implementation of the GetVersion() method resulting in the following output:

uwpVersion

Now while this approach allows for writing platform independent logic in the PCL and calling platform specific implementations during runtime it is somewhat tedious as it requires that the developer will reference the correct version of the library. And all of them have the same name which is just calling for some frustrated minutes to happen due to referencing the wrong version of the library. Luckily there is a technique that allows to use the approach described above without burdening the developer consuming the library of referencing the binaries correctly. By wrapping the library in a NuGet package consuming the library is as simple as adding the package to all of your projects and the NuGet package manager will just like the build engine prefer to link the platform specific binary over the PCL library to the project. So instead of having to choose which binary to add the developer can now simply add the identical NuGet package to all of the projects and it will just work.

Conclusion

In this post you saw how to create APIs that can be consumed in the PCL and still provide platform specific functionality. For all of this to work we had to set the namespace and assembly of the projects to identical names. On the consumer one can either simply add a NuGet package containing all of the implementations i.e. PCL, UWP, Android and iOS or add the binaries of the corresponding API compilation to the app implementation e.g. OSVersion.Coreto NativePcl.Core.

This approach allows you to create APIs which can be reused across multiple platforms providing the same method definitions across the platforms.

You can find the sample on GitHub. (make sure to compile it first as a release build)

2 Comments

3856456237_f05ebd2602_o

The Portable Class Library (PCL) allows developers to share C#, F# and VB code across multiple devices, platforms and runtime environments such as .Net, Xamarin or Windows Store Apps. In this previous post you can see how you can write portable business logic and integrate it with all the various platforms. But what if you actually want to use something the other way round say the GPS position, file system etc.. What then? This is exactly his post we will look at the following topics:

  • Using Interface Segregation and Dependency Inversion to our favor
    • Interface in the PCL
    • Implementation on the Platform
  • Injecting the implementation at runtime into the PCL
  • Making the resolution of dependencies a breeze with MVVM Light

So lets get to it!

Using Dependency Injection to our favor

Remember SOLID? Well it turns out the last letter stand exactly for the pattern we will be using to solve our “How will I be able to use a platform specific feature cross platform “. The PCL code is platform independent and therefore can be used across multiple platforms, so we want to put near to all of our business logic into a PCL. Further by accessing concrete class implementations via interfaces we can define an Interface in the PCL and create it’s concrete implementation in a platform specific project.

PCLDIOverview

Dependency Injection in action

For example lets say we want to display the current OS version for each platform, this is a very platform specific feature. To access such a information in the PLC we first define an Interface in the PCL that describes the contract the implementation has to implement:

public interface ISystemInformationHandler
{
    string OSVersion { get; }
}

In the concrete platforms we can then inherit the interface and implement the handler which calls the platform specific API (bellow you see the Android implementation):

internal class SystemInformationHandler:ISystemInformationHandler
{
    #region Implementation of ISystemInformationHandler

    //public string OSVersion => System.Environment.OSVersion.ToString();
    public string OSVersion => $"Android {Android.OS.Build.VERSION.SdkInt} {Android.OS.Build.VERSION.Release}";

    #endregion
}

Now in the PCL we can have a class for example a view model that requires the handler to display the information.

public class MainViewModel : ViewModelBase
{
    private readonly ISystemInformationHandler _systemInformationHandler;

    public MainViewModel(ISystemInformationHandler systemInformationHandler)
    {
        if (systemInformationHandler == null) throw new ArgumentNullException(nameof(systemInformationHandler));
        _systemInformationHandler = systemInformationHandler;
    }

    public string OSVersion => _systemInformationHandler.OSVersion;
}

The view model requires as a parameter argument an instance of the IOSVersionHandler interface. So when we create an instance of the MainViewModel in the platform project, we can simply create an instance of interface and pass it into the view model when we create it.

var mainViewModel = new MainViewModel(new SystemInformationHandler());

And receive the following output for e.g. Android:

 

Cross platform Dependency resolution with MVVM Lights

Now resolving all of these dependencies by hand can get very tedious over time. You might have noticed that I’m using MVVM Light which comes with a lightweight Dependency Injection Container called Simple IoC. Lets see how we can use this component to further streamline our cross platform development efforts.

Note:for an introduction to MVVM Light please refer to this blog post for AndroidoriOSto get you started with the basics.

In the PCL we have the ViewModelLocator.cs which defines all of the instances used, but without the platform specific resolution.

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            // Create design time view services and models
            SimpleIoc.Default.Register<ISystemInformationHandler, SystemInformationHandlerStub>();
        }

        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }
}

On each platform we now extend the Locator and register the platform specific classes i.e. resolution for interfaces.

internal class Locator : ViewModelLocator
{
    private static readonly Lazy<Locator> _locator = new Lazy<Locator>(() => new Locator(), LazyThreadSafetyMode.PublicationOnly);
    public static Locator Instance => _locator.Value;

    private Locator()
    {
        SimpleIoc.Default.Register<ISystemInformationHandler, SystemInformationHandler>();
    }
}

Now we can simply request an instance of the view model (MVVM Light per default only creates one instance for each registered class) and use it. In Android this would look something like this in the MainActivity.cs:

[Activity(Label = "PclDISample.Droid", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    #region UI Controls

    private TextView OSVersion => FindViewById<TextView>(Resource.Id.OSVersion);

    #endregion

    private MainViewModel VM => Locator.Instance.Main;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);

        // Get our button from the layout resource,
        // and attach an event to it
        OSVersion.Text = VM.OSVersion;

        var mainViewModel = new MainViewModel(new SystemInformationHandler());
    }
}

In Windows 10 we can simply set the Datacontext accordingly in XAML:

<Page
    x:Class="PclDISample.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclDISample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="{Binding OSVersion}" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TitleTextBlockStyle}"></TextBlock>
    </Grid>
</Page>

As you can see once all is registered with the simple Inversion of Control Container (IoC) of MVVM Light all of the dependency resolution will be performed automatically. If a dependency is missing, an exception will be thrown at runtime (not during compilation), so make sure to test all your views, user controls et al that they load correctly.

Conclusion

In this post you saw how you can use Dependency Injection to provide platform specific features to cross platform code located in the PCL without creating any circular dependency errors. By using interfaces in the PCL and injecting the concrete implementations during runtime we can create thin wrappers that provide platform specific features through a generic defined interface. Finally we saw how we can use MVVM Light to create a more manageable and more manageable dependency resolution with the Simple IoC Locator.

You can find the complete sample on GitHub.

Big thanks to Laurent Bugnion the creator the MVVM Light.

0 Comments

This has been driving me bonkers the last couple of days so I just wanted to jot down the steps to get the Emulator up and running under Windows 10. In my case after upgrading from Win 8.1. So if you ever received one of the following errors:

  • [Critical] An internal virtual network switch is required for emulated devices to run.
  • [Critical] XDE Exit Code: CouldntCreateInternalSwitch (16)
  • [Critical] XDE Exit Code: CouldntStartVm (10)
  • [Critical] XDE Exit Code: InvalidArguments (3)
  • For UDP connection errors see update of July 2016 at the end.

These steps should help you bring the Emulator back up and running:

Disclaimer: Please note that you perform these steps at your own risk. Generally speaking all should run just fine but some steps will remove some Hyper-V settings and this might affect your network connectivity or virtual machine setup. So take these steps as worked on my machine advice.

  1. Ensure no XDE.exe task is running (Task Manager)
  2. Repair Android SDK – Open Programs and Features > Microsoft Visual Studio Emulator for Android > select Change in the menu bar and choose Repair in the Visual Studio dialog
  3. Remove All Hyper-V virtual switches – open the  Hyper-V Manager > select the Virtual Switch Manager… (located in the menu on the right) > select each virtual switch and select remove > click onto Apply
    1. If there is an error while removing a virtual switch, try restarting your computer
  4. Run XdeCleanup.exe – Depends on your install but on the Surface Pro 3 you should find it under: "C:\Program Files (x86)\Microsoft XDE\10.0.10240.0"

Now try to get your Emulator up and running. If you still receive error messages try the following steps:

  • (Surface Pro 3) Reinstall the network drivers > Open the Device Manager> under View select Show hidden devices > Uninstall Marvell AVASTAR Wireless-AC Network Controller and Surface Ethernet Adapter > Restart which will automatically reinstall the drivers from the recovery partition
  • Clean up network bridges > Open Network Connections > Add Bridge (this option only showed up the first time) > Remove the added bridge again

Now your Emulator should fire up.

Remark

I had to repeat step 3 a couple of times – even after the emulator would start up the first time but maybe that is just a configuration issue on my machine…

Hope this helps and happy coding! Smile

Resources

http://stackoverflow.com/questions/31613607/visual-studio-2015-emulator-for-android-not-working-xde-exe-exit-code-3


Update - 20. July 2016

Managed to wreck my Android Emulator again yesterday. This time none of the above attempts fixed it for me. Since this is one of the more frequented blog posts I thought I would update to share another possible solution.

The Error message was that no UDP connection could be established with the Emulator. Following these steps solved the issue:

  • Open Device Manager (On Win10 simply search for Device Manager in the Start Menu)
  • Under Viewselect Show hidden devices
  • Delete all virtual network devices except your Network card (you do not have remove the Bluetooth devices)
  • Open Hyper-V and remove all Hyper-V virtual network endpoints as described under Point 3
  • Reboot
These steps solved the mentioned issue above and is based on the following Troubleshooting articleby Microsoft.