28 June 2013

x86/ARM configuration gotcha in Windows Phone 8 projects when adding unit test projects

BUILD 2013 may be all the rage at this moment, but between watching sessions online this here die-hard still is doing some Windows Phone development. Doing so, I ran into a particular side effect that occurs when including a unit test project – something I had not noticed before. But if you read my articles about unit testing, got inspired by it and want to try something - you might get confused, run into weird looking errors, or even submit an incorrect XAP, so I thought it best to make a short writeup.

Create a single Windows Phone app, select your solution in the Solution Explorer and then right-click “Properties”, you will see the following dialog:

image
Nothing spectacular. But now add a unit test project, add a reference in the unit test project to the app, and get the solution properties again.

image

The unit test runner apparently is a program that does not so much run on the emulator as on your PC, and therefore is an x86 program. No sweat. Since the phone emulators run on your PC as well, they will run this flawlessly. But there are some potential issues you now have to take into account. Because if you compile your app now, in stead of ConfigGotcha.xap Visual Studio now makes ConfigGotcha_Debug_x86.xap. Which will not run on your phone because that hasn't got an x86 processor. You will see the following error:
”Deployment failed because an app with target platform x86 cannot be deployed to Device. If the target platform is win32/ x86, select an emulator. If the target platform is ARM, select Device.”

I don’t even want to contemplate what happens when you try to submit this XAP ;-)

But anyway, if you try to be smart like me and change the ConfigGotcha app to Any CPU again – it will run now on both your Windows Phone and the emulator, but when you try to run the tests you will get this error:

“Target platform x86 is incompatible with the selected device type. Make sure that they are compatible with each other and try again. Example: - X86 or Win32 platform is compatible with emulator and not compatible with arm device.  Similarly arm platform is compatible with arm device and not compatible with emulator.
Unit tests in source C:\projects\ConfigGotcha\ConfigGotcha.Test\Bin\x86\Debug\ConfigGotcha.Test.dll cannot be run. Please create a Windows Store or Windows Phone Unit Test project.”

So, the story is this:

  • When you want to unit test your app, both the tested and the test project apparently must have platform “x86”. The resulting XAP will be unit testable, and run on the emulator – but not on your phone.
  • When you want to deploy or submit an app, set the configuration to “Any CPU”. The resulting XAP will run on your emulator and your phone, and can be submitted.

The gotcha of course is that you fix an error, run the tests, forget to set “x86” back to “Any CPU”, select release configuration, build the app – which will not create a XAP in “release” but in x86, and you submit the release XAP, which is not recompiled and still contains the error.

This will of course happen – at 3am after a long debugging session - and to prevent that, I recommend the following: select the solution properties again, select “Release” from the configuration dropdown, set the platform of all your projects but the unit test projects to Any CPU, and disable Build and Deploy for the unit test projects, like this:

image

Net result: when you select release, Visual Studio will automatically build a XAP for Any CPU and app that runs both on the phone and your emulator, and can be submitted.

If you want have all debug functionality of the debug mode but still want to be able to run on the phone you can add a configuration, like this:

  • Hit the “Configuration Manager” button top-right of the dialog,
  • Select “New” under “Active solution configuration”,
  • Select “Debug” under “Copy settings from”
  • Enter some suitable name (I chose DebugAnyCpu)
  • Hit OK

image

imageNow make sure the other settings of the new DebugAnyCPU configuration are the same as the release settings (so, everything Any CPU and make the unit tests not compile or deploy). If you now look in Visual Studio and click the configuration manager, you will see you have an extra configuration as displayed to the right.

  • Selecting Debug will make now a unit testable application that will run on your emulator, but not on your phone
  • Selecting DebugAnyCpu will make a debug application that can run on your phone and your emulator – but you cannot unit test
  • Selecting “Release” will make a proper release app that can run on emulator, device – and the resulting XAP can be submitted.

By creating this configuration you can have all the options you need, and protect yourself from accidentally uploading the wrong XAP after pushing through into the wee hours of the night finding a bug in your app.

Happy unit testing!

3 comments:

PeterF said...

Risky not to test the release build. Sometimes timing issues etc. are not happening in debug mode... Haven't seen it in .NET lately but it is fairly common in C++ (different initializations etc)

Anonymous said...

Fantastic post and well described; thanks!

Joost van Schaik said...

@PeterF in that case you can always make a copy of the release configuration for x86 as well and run tests on that, right ;-)