Xamarin: UITest backdoor

When running your UI tests, locally or in Xamarin Test Cloud, you sometimes want to execute code in your app from your tests. You might for instance want to setup some mock implementations instead of making actual API calls, or you might want to trigger some OS specific code from your tests. In these scenario’s backdoors come in handy!

Backdoors itself are not very complex, but it opens up a lot of possibilities with UI tests. In the past I used backdoors to:

  • Setup authentication for tests
  • Create a specific state in your app to run your tests in.
  • Set mock implementations from my UI tests.
  • Trigger deeplink

And I can think of a lot more useful scenario’s. You can create a backdoor with the following code:

iOS
In your AppDelegate class you need to create an method that returns NSString, is public,  is annotated with Export attribute and takes an NSString as parameter. For example:

public class AppDelegate : UIApplicationDelegate
{
 [Export("myBackdoorMethod:")] // notice the colon at the end of the method name
 public NSString MyBackdoorMethod(NSString value)
 {
 // In through the backdoor - do some work.
 }
}

Android
On Android you need to create a method in your MainActivity that is public, returns string/void, is annotated with Export attribute and takes an string/int/bool as parameter:

public class MainActivity : Activity
{
    [Export("MyBackdoorMethod")]
    public void MyBackdoorMethod(string value)
    {
        // In through the backdoor - do some work.
    }
}

Invoking the backdoor from your UI tests:

if (app is Xamarin.UITest.iOS.iOSApp)
{
    app.Invoke("myBackdoorMethod:", "exampleString");
}
else
{
    app.Invoke("MyBackdoorMethod", "exampleString");
}

Note: The signature of the backdoor methods is very important as the Backdoors – Xamarin docs mention.

If you want to switch out your actual implementations for mocks, the use of compiler flags (combined with build configurations) might be more suited. You can read more on this over here.

Related links:

Build configurations and compiler flags

If you have developed some Xamarin applications in the past, you might have stumbled on the excessive range of configuration options you can choose from. The settings you’re using in development may be very different from your Release settings. For example; you don’t want to include debug information in the app that will be published to the App Stores. It will increase the app size enormously and expose technical info about your app that might be useful to malicious people.

Besides the difference of Release and Debug configurations, you sometimes need a extra set of configurations. Visual Studio allows you to create additional build configurations:

Configuration Manager

Configuration Manager

Build configurations

Build configurations

Compiler flags / Conditional compilation symbols

Per build configuration you can also specify a set of compiler flags. Compiler flags on itself don’t have any impact on your app, but you can use these flags in your code. By default the build configuration called Debug, has a compiler flag called “Debug”. In your code you can check if this flag is set (and therefor Debug configuration is active) and execute some Debug code. A common scenario is to Log additional information when the Debug flag is set.

Compiler flags

Setting compiler flags

Using compiler flag in code:

#if Debug
	InitializeUiTests();
#endif

Related links:

Xamarin: The magic of Fody weaving

When creating Xamarin apps a lot of people choose to go with the MVVM pattern. There are a lot of beautiful frameworks out there to make the life of an MVVM developer easier, but sometimes you just want to do it the hard way and write it yourself.

If you ever created an Xamarin app using the MVVM pattern (without any framework) and data binding, you may have noticed there is a lot of boilerplate code to notify property changes. As your ViewModels grow, this becomes a nightmare!

Fody.PropertyChanged to the rescue!
Fody is an extensible library that adds an post build task to the MSBuild pipeline. With this task it manipulates the generated IL code, depending on what add-ins you are using. Add-ins can be build on the Fody core. One of the add-ins is Fody.PropertyChanged. As you might guess, this add-in generates the code for notifying changes in a ViewModel. The add-in will look for properties in classes that implement INotifyPropertyChanged or properties/classes annotated with the [ImplementPropertyChanged] attribute.

Example class PersonViewModel:

[ImplementPropertyChanged]
public class PersonViewModel
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }

public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}

After applying Fody magic it will become:

public class PersonViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

string givenNames;
public string GivenNames
{
get { return givenNames; }
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged("GivenNames");
OnPropertyChanged("FullName");
}
}
}

string familyName;
public string FamilyName
{
get { return familyName; }
set
{
if (value != familyName)
{
familyName = value;
OnPropertyChanged("FamilyName");
OnPropertyChanged("FullName");
}
}
}

public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}

public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Fody.PropertyChanged has another killer feature called Fody NotificationInterception which makes it possible to execute some code before propertyChanged gets triggered. This feature can be for example used for logging purpose or to make sure you are calling propertyChanged on the main thread. See related links for more info.

If you want to give Fody.PropertyChanged (or any other Fody add-in) a try, just install the NuGet package and you’re good to go!

Note:
Fody requires your release builds to contain debug symbols. You can enable this in your project settings by setting Build->compiler->debug information to “Symbols only”.

Fody-release

Related links: