This project is read-only.

Support for unit testing

Jan 28, 2009 at 3:20 PM
Would you guys consider adding interfaces for certain classes to support unit testing of classes dependent on, say, the Map?
Jan 28, 2009 at 5:48 PM
I am certainly open to supporting structured unit testing such as NUnit.  However, I don't recall that your are required to invasively modify the tested code to be able to write test classes.  Not even sure that would be a good idea due to the Heisenberg principle.  BTW, here is a good article on best practices for unit testing: 10 Ways to Make Your Code More Testable.  I'd like to hear more about why we need to add interfaces.  Surely, you are not suggesting this because you're too lazy to code up a test class.

Jan 28, 2009 at 7:42 PM
It is so that dependencies that are NOT under test (i.e. the Map) can be stubbed or mocked. DeepEarth already has some interfaces, such as ILayer, but that doesn't help with stubbing the derived GeometryLayer class, for example, unless you only need to stub the limited properties defined in the ILayer interface.

Mind you, stubbing in Silverlight is far from trivial, as evidenced by the Prism team's unit tests. It's all well and good to do unit testing by building a pile of stubbed implementations, but then who tests the stubs?

There's some hope on the horizon that Moq or Rhino.Mocks will be able to support Silverlight now that Castle's DynamicProxy is able to support Silverlight.
Jan 28, 2009 at 8:06 PM
First, yes we are interested in supporting more structured Unit Testing.  I think it would be great for us to add some NUnit test cases.  However, I say no thanks to modifying the code base as you suggest.  It begs the question, if you write your test cases to test a class without any of its dependencies, have you really tested it?  I say no.
Jan 28, 2009 at 9:12 PM
RoadWarrior, I wish you would reconsider your position. Interfaces are one of the main principles of testability. It's even listed as the first recommendation in the article you linked to.

Imagine that I have a class that gets data from a service and calls the map in response to user actions on that data (e.g. a ViewModel in the MVVM pattern). If I want to test this class, then I will mock (not stub) all of its dependencies. This way, I'm only executing tests against the class I am testing, I can run those tests without any specific dependencies present, and those tests are reusable if I decide to change the implementation of one of those dependencies (e.g. a different service, a different map client, etc.).

Using interfaces would not only allow users of DeepEarth to test their code, it would allow the DeepEarth developers to write tests against the DeepEarth source code as well. As rmatsu wrote, mocking frameworks need to support Silverlight for that to work well, but that should happen in the next few months.
Jan 28, 2009 at 10:29 PM
Edited Jan 28, 2009 at 11:33 PM
Actually, the first recommendation in the article is not about stubbing, but about using interfaces for testing reuse.  For example, the IAgent interface can be applied to multiple classes such as SecretAgent, and AirlineAgent.  Essentially, you can write a single test case to generically test all classes that implement IAgent.  I get that.  We do use interfaces where polymorphic behavior is found (e.g. ITileSource), and writing a test case that test all  classes that implement a common interface makes a lot of sense.  However, most of our classes in the DeepEarth core are not polymorphic, (e.g. Map, MouseControl, etc...) and do not have this reuse potential.

Lets talk about stubbing/mocking.  First, you mentioned services.  By definition services already have an interface to define the contract, so you already have the ability to stub any service.  So this discussion should really be about implementing interfaces on ordinary classes that don't already have an interface.  I am still not convinced this is worth the effort.  Let's take a class like CoordTransform.  I can't imagine doing the all the work to stub out its dependencies (SpatialReference, Screen, ViewPort, the MSI).  If you disagree, I'd like to see your implementation of a stub for the MSI.  All that being said, I like to keep an open mind and am interested to take a look at these mocking frameworks when they are ready for Silverlight.  Regardless of what we decide, you do have the source code.  That means you always have the ability to stub as you please.