ESRI.ArcGISRuntime.Xamarin.Forms 100.12 no more useable with .NET Core unittests

1053
3
09-07-2021 11:50 PM
GregorSchweizer
New Contributor

Hi

After upgrading our Xamarin application to ArcGIS Runtime 100.12, we noticed that the ESRI.ArcGISRuntime.Xamarin.Forms assembly is now a "reference assembly". So it can no longer be used to instantiate objects. We have a lot of .NET Core unit tests that use objects from it (like MapView as an example). .NET Core was used because of performance improvement over UWP.
If a MapView is only created and used in a test, then the ESRI.ArcGISRuntime.WPF assembly can be used. But for our shared libraries where MapView is used as a member/parameter it will not work anymore (type mismatch).

Does someone has a solution for this situation?

What was the reason to define the ESRI.ArcGISRuntime.Xamarin.Forms assembly as reference-assembly?

Why does ESRI not provide interfaces for the ESRI.ArcGISRuntime.Xamarin.Forms objects (GeoView, MapView, SceneView) in the .NET Standard ESRI.ArcGISRuntime? That would be really helpful to be able to use that objects in tests independent of the platform. Sure, we can define our own interface and proxy-classes to achieve that, but should that not be a part of the SDK?

Tags (1)
0 Kudos
3 Replies
dotMorten_esri
Esri Notable Contributor

Xamarin.Forms only supports the iOS, Android and UWP at runtime - it cannot be used with .NET Standard and has never been supported. The .NET Core target relies on WPF, and we have no Forms binding for WPF.
If you need to run on .NET Core, you'll need to not reference the Forms package.

Why does ESRI not provide interfaces for the ESRI.ArcGISRuntime.Xamarin.Forms objects

We don't provide interfaces for types that frequently evolve, as changing that interface would be a breaking change.

jsiemensLatitudegeo
New Contributor

Hi Morten,

Thanks for taking the time to reply and provide that information. Unfortunately though this puts us in a really difficult position. That effectively leaves us with only one possible solution which is to use a UWP unit test app to run our tests. This is a problem because the UWP unit test app is really bad in the following ways (not your fault):

  • It's extremely slow. I compared the times that it takes to run a single test using the UWP unit test app, to a .Net core unit test project, from the time that I hit 'run' to the time that it finishes the test: 18s for .net core, 43 seconds for UWP test project. That's every time we want to run a single test, which as you know when doing TDD, you're going to run many many times, so this time lost really adds up.
  • No code coverage. The UWP test app just doesn't support it. .Net core does.
  • Requires UI interactivity - every time we run a test, the unit test window pops up (twice at that). This also has implications on our build pipeline because then our build agent has to run in interactive mode.

So for those reasons, we'd really prefer not to run our tests in UWP, and would rather do .Net Core. You see that the Xamarin Forms team uses .Net framework, which has similar performance and coverage capabilities to .net core tests, to run a good chunk of their tests:

https://github.com/xamarin/Xamarin.Forms/blob/5.0.0/Xamarin.Forms.Core.UnitTests/Xamarin.Forms.Core....

Additionally the fact that the Runtime is available as a .Net standard library would seem to imply that it should run in anything that supports .Net standard. That's kind of the main point of .Net standard. As well, this worked before, so why should it not work now? Even if it wasn't officially supported, it was very beneficial to us.

As for interfaces, yeah sure, it's technically a breaking change if someone implements IMapView and you change it, but I feel like it could be remedied by just putting a comment on the interface indicating that it will change over time, and you should expect your code to not compile if you upgrade and you have implemented said interface. I think people could easily live with that if it buys them the ability to more easily unit test their app. I understand not wanting to create breaking changes, but it's coming at the cost of testability.

At the end of the day, I really don't see how it will be possible for us to efficientiently write and run unit tests with the restrictions that have been imposed. Do you have any suggestions? What do you do internally?

At this point, we're going to have to make some hard decisions.

Jeff

0 Kudos
dotMorten_esri
Esri Notable Contributor

What I'd suggest you do is split your unit tests into two: The ones you run on .NET Core only references  the 'Esri.ArcGISRuntime' nuget package, as this one is supported on .NET Core. These should be all your non-UI tests. The Forms package contains Forms specific types that are meant to be used in UI so you can use this in UI Tests which must be run on a device that we support forms on. Using the Forms libraries in a .NET Core application in U11 wasn't supported, isn't tested, and you could easily get you into runtime exceptions.

As for interfaces, yeah sure, it's technically a breaking change if someone implements IMapView and you change it, but I feel like it could be remedied by just putting a comment on the interface indicating that it will change over time

Unfortunately it still breaks binary compatibility. If say you use a 3rd party library or plug-in that hasn't been compiled for v.next yet, you'd be stuck on the old version until all your dependencies have been updated.

For .NET Maui, since we're only compiling that for .NET 6, we're going to solve that problem with default interface members, so it will be non-breaking there, and yes you'll get an IMapView interface with Maui (and we'll probably also tell you not to extend it). 

> Additionally the fact that the Runtime is available as a .Net standard library would seem to imply that it should run in anything that supports .Net standard. That's kind of the main point of .Net standard

That's not quite the case. .NET Standard ensures you have a common set of APIs to code against across many platforms. But it isn't a runtime, and there is no such thing as a ".NET Standard Application" (hence why you can only make .NET Standard class libraries). At the end of the day you still have to compile your application for a specific runtime. It's true that many .NET class libraries only relies on the runtime APIs provided by .NET, so they are usable on all the platforms .NET Core runs, but ArcGIS Runtime relies not only this, but also its own native runtime that is specifically compiled for each platform. Those runtime platforms today are win32, uwp, ios and android.

In the next release we'll actually have our assemblies much more clearly attributed with platform support attributes, so you'd get proper warnings if you try and run this on a platform that isn't indicated as supported. .NET Core 3,1 itself actually supports running on many platforms, but again requires the correct runtime for that to work, and we've been quite clear that it was only Windows that was supported there. With .NET 5, it's a little more clear as the target is "net5.0-windows" and not just the base "net5.0" target, but that wasn't something we could do in 3.1, although it got implied by the WPF dependency it had (for U13 we hope to provide net6.0-windows, net6.0-ios and net6.0-android targets - we'll still provide a net6.0 reference assembly for compiling your cross platform business logic, but in the end, you'll still need to target a specific platform to run them).

So bottom line: The netstandard target is really only supported for class libraries. For running applications, you much pick a supported platform, and .NET Core isn't supported with Forms.