Here's what we do:
- Abstract phone-specific logic into facades
- Inject dependencies wherever possible
- Avoid using any code that requires to run on the UI thread upon construction, this meaning any UI control, ImageSource, basically any System.Windows type that isn't a enumeration (such as Visibility)
- Heavily rely on ValueConverters to convert business logic into UI logic.
If you do this, then you can use the the build-in Visual Studio unit testing framework, to test Windows Phone projects (not just Portable Class Libraries) with a bit of hackery.
1) First step is to disable strong name validation , this can be done with following Powershell script:
reg DELETE "HKLM\Software\Microsoft\StrongName\Verification" /f
reg ADD "HKLM\Software\Microsoft\StrongName\Verification\*,*" /f
if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64")
{
reg DELETE "HKLM\Software\Wow6432Node\Microsoft\StrongName\Verification" /f
reg ADD "HKLM\Software\Wow6432Node\Microsoft\StrongName\Verification\*,*" /f
}
Restart-Service msiserver
Notice that it creates a security vulnerability on the machine this is applied to!
2) Second step is to create a Visual Studio Unit Test Project, a regular one, not a Windows Store Unit Test Project.
3) Third step is to include the Windows Phone 8 project as a reference. This works, and you can now use Microsoft Fakes to make mscorlib and System.dll , allowing you to fake types like DateTime
in your unit tests, a very handy feature.
4) Fourth step is to get a local copy of the following Windows Phone assemblies (and any additional you need):
- System.Windows
- Microsoft.Phone
They can be found in the C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Tools\MDILXAPCompile\Framework folder.
Copy them locally to a /lib/ folder, and then unload and edit the MSBUILD xml of your Unit Test Project.
Change:
<Reference Include="System.Windows" />
<Reference Include="Microsoft.Phone" />
To
<Reference Include="System.Windows, Version=2.0.6.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
<HintPath>lib\System.Windows.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Phone, Version=8.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e, processorArchitecture=MSIL">
<HintPath>lib\Microsoft.Phone.dll</HintPath>
</Reference>
Additionally to avoid a warning when compiling, add following element to the first <PropertyGroup>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
Reload, compile, run the tests. Voilà, and you're done. You can even integrate this with the Microsoft Code Coverage functionality.
NB: Unit Testing is not officially supported by the Windows Phone Division, this is a workaround found by my team and I at the Skype Division.
Bonus answer:
Does anyone know if you can target Windows Phone 7.x using the WP8 SDK?