Tuesday, June 17, 2008
Posted on Tuesday, June 17, 2008 10:18:00 AM (Mountain Daylight Time, UTC-06:00)  Comments [3] | 
Categories: .NET | Unit Testing

Based on the outcome of the Developer Survey, I thought I' put together some posts on the common patterns referenced in some of the questions, starting with the Model View Controller (MVC) family.

There has been plenty written about MVC on the formal side of things - here are two good sources of information - Wikipedia MVC entry,  and some thoughts from Martin Fowler.

The Basics

The MVC family of patterns are about separating the presentation of data from the business logic surrounding the management of the data. There are many other patterns based on the key MVC ideas - Passive View, Supervising Controller, Presentation Model and Separated Presentation are 4 such patterns. The differences are subtle, and all share they key idea of separating the presentation logic from the business logic, from the data itself. It's worth noting that the opposite of MVC family is called "Autonomous View" in which all the logic is in the form itself - so if this is how you are developing, now you can use a fancy name for it!

Since MVC was one of the first patterns that dealt with this separation, we'll start with it, and look at the three components...

Model:

The model is the data and it's usually a class. So in GIS-land, it could be a "Parcel" class, which may have a Geometry property. The important part is that this class has no dependencies on the presentation layer, or the controller. It's just a dumb data container. Typically this class will implement one or more interfaces, which the View and Controller will utilize. Interfaces are used a lot in these patterns, so here's a link to an article that compares Abstract Classes and Interfaces that can serve as a refresher if needed.

View:

As the name suggests the View is responsible for organizing and presenting the Model. Usually this means showing it visually on a form. In order to remove dependencies between the View and the Model, the View will interact with an interface, instead of a specific view class - i.e. IParcelFeature instead of "Parcel". The view typically raises events when the user makes changes in the interface, and exposes properties allowing the Controller to "see" the model or other state of the view. The View does not make any changes to the Model itself (in some  MV* patterns does not actually have visibility of the model - the controller sets all the control values directly, and responds to all control events). Again, the events and properties of the View are defined via an interface.

Controller:

The name conveys things pretty well - this is the business logic component that controls what actually happens to the model when an event occurs in the view. There may be multiple controllers that can work with a given class, or multiple model classes that can work with a given controller. This is where the Interfaces on the Models come in. If the Controller's "contract" is based on an Interface (IParcelFeature), then we can use the Controller with any class that implements the interface. Similarly, the Controller also implements an Interface, which is it's contract with the View.

Pulling it to all together:

In MVC, the Controller gets a model and a View. It then passed the required data to the View which renders the UI. When the user interacts with the UI (i.e. clicks a button), the View raises events, which the Controller responds to by making required changes to the Model, which is then used to update the View.

Why Bother?

So - this is nice, but why separate things out like this? There are a number of reasons. First is known as Single Responsibility. This concept basically says that a class should have one purpose, and anything not connected with that purpose should be in a separate class. In regards to the subject at hand, it would tell you to avoid mixing presentation code, with business logic because they are not actually related.

Another reason for MVC is re-use. If you model your application like this, you can plug and play the components - particularly the View. So, suppose you need to create a business application that has a windows forms client for some functionality, a web client for some other functions, and a web service API. You can build out a model, a controller, and three views - one for the windows forms application, one for a web form, and a third (more limited one) for the web service.

A final (and biggest) reason is testability. If you keep the Model (data) separate from the View (User Interface) which is separate from the Controller (business logic), writing unit tests becomes much easier. If you've implemented interfaces as the contract between the components, you can test the components individually.

The Pain of Testing

Without getting too deep into unit testing, the basic idea is to have a test harness which spins up various classes in your code, and executes methods. This gets complicated because our classes have dependencies on data - stored in databases, shape files, whatever. If we want to re-run our tests frequently, we want to be sure our test data is static - otherwise the tests break, and that defeats the purpose. So - the next best option is to create "fake" static data in our tests. The brute force method would be to create specific test classes which implement the required interfaces (ISomeView, ISomeModel etc), but just contain enough logic to complete the test. Depending on the test you would have an invalid geometry, invalid PIN number or a myriad of other conditions. This would allow you to create test "Parcels" in your unit test harness, that you could then pass to the Controller to test it's methods, without actually connecting to a shape file. You could also create a class that implemented the View interface, and use that to raise events and ensure that the Controller reacted correctly. Essentially you can write unit tests for everything but the "click" event handler in the UI layer. Since that code was likely written for you by the IDE, and it's super basic, it's not a really high priority for testing.

Easing the Pain of Testing: Dynamic Mocking

Of course that's a lot of work, and developers hate extra work, so tools were created to help out. While this is beyond the scope of this post, I'm talking about "mocking" frameworks, such as NMock, RhinoMocks or TypeMock. These frameworks can create a "test dummy" class that implements a specific  interface right in the test definition. You basically "record" some values into the Mock, then pass it into a method, and it can validate behavior.

Of course you still need to fill up the dynamically mocked Interface with valid data - and the geometries are likely the scariest thing to start with. So that's where I started a few years ago.

I can haz code?

I don't have anything lying around that's easily sharable, but I did post a sample about Supervising Controller code about a year ago. The code is in VB.NET, with a Visual Studio 2005 solution, and is oriented towards showing how to create a plug-in framework, while leveraging Supervising Controller, so that's the gist of the article. It also does not have any tests, but I'll be posting more leveraging MVC patterns and unit testing in the future.

Plug-in Framework & Supervising Controller Example (Article - read this before digging into the code)

Download Sample Code

Summary

The idea here was to introduce the main idea of the MVC pattern - separation of behavior logic from presentation logic, usually to facilitate testing. The actual implementation of this idea can take many flavors, and can vary in complexity, but the underlying concept is the same.

Wednesday, June 04, 2008
Posted on Wednesday, June 04, 2008 7:28:43 AM (Mountain Daylight Time, UTC-06:00)  Comments [4] | 
Categories: .NET | Devt Tools | Fundamentals | Unit Testing

This is the third and final part of a three part series summarizing the results of the 2008 Geospatial Developer Survey. For further information, be sure to check out read part one and part two

 

Use of Source Control Systems

This is where we start to see some divergence from the larger developer community.

 scc

Source control is as much a part of most developers lives as the language they use. It should be automatic and used by default. Subversion is good, and free. It's not trivial to setup, but with free subversion hosting services like Assembla.com, there is virtually no reason not use it. (btw - although I have an "Assembla" badge in my sidebar, I am not paid to endorse them - their service is solid and so I promote it).

Automated Build Tools

With more than half of the respondents not doing automated builds, we are seeing more of the separation from main-stream development.

autobuild-tools

All the choices on this question were .NET, but I also compiled the "Other - Please specify" results into a chart.

 autobuild-other

Unit Testing

There were 3 questions on unit testing, mainly because I see this as a key element raising the quality of GIS software projects. Unit testing is as much a philosophy about how you develop software as it is the actual writing of tests. Committing to doing unit testing really says you care about quality, and that you realize that manual testing, while valuable, is never as consistent as automated tests. So, with that we start with a look at what percent of projects are using unit testing.

Using_Unit-Testing

I don't know how this stacks up to other industries, but I'd say there is room for some growth here. Everyone talks about GIS getting on the "service bus", but we need to make sure that when we get on the bus, our code does not fail!

The next question basically asked why you were not doing more unit testing.

why-not-unit-testing

This is actually pretty good. I'd have to question the 14% who don't think it's valuable, but I'll chock that up to them not knowing what's really involved.

I've heard the "not-enough time" thing before, but the problem is that you will have bugs. And someone will find them. Better the developer finding them sooner than a client finding them later. Also, in terms of time, on big projects, I think you actually save time.Having automated tests, helps you prevent regression. Think about all the stuff that breaks between a big ArcGIS releases - that's regression, and that's what good automated tests can catch.  

Difficulty. This is true. Writing good unit tests is hard. Using good design patterns help, and good tools can ease the pain, but even still it's not easy. Writing unit tests for ArcObjects code is very difficult, but not impossible. In these cases, I focus the tests on the most critical parts of a system - basically putting the effort where it will payoff the most. For these areas, I shoot for 100% code coverage - if they are the most complex, I want to make sure that my tests cover all possibilities. Again, difficult, but if you are writing a complex spatial rule engine, that works with relationships between multiple layers, business workflows, and user permissions, there is no realistic way to manually test it on any sort of a regular basis.

The next question was "If tests were easier to write, would you write more of them?"

unit-tesing-easier

So, a resounding YES on that. This is great, because as a community we can actually make this happen. 

A couple years back I threw some code out there under the umbrella of "ArcUnit" - the files referenced in those posts are now gone, but it was some demo code that showed how to unit test geometry operations, by serializing geometries and storing them in the unit test assembly. The code is now on Assembla in the ArcDeveloper project, under TestingUtilities. Seeing as there is interest in this, I'll likely write some more articles on this.

Unit Testing Frameworks

Ok - the Java people really ripped on this question. After adding an "Other", I did tabulate the results for all that as well.

unit-testing-frameworks

This gets somewhat interesting - 60% of people said they are not using any tools, but back in the "What percent of your projects use unit testing" only 38% said "None". I guess some "homegrown" unit testing could explain a few percent, but... anyhow. Interesting that MBUnit and MSTest are so low. MSTest is baked into Visual Studio 2008 (Professional and above), and MBUnit is both free and awesome.

As for the "other", here's how that stacked up.other-ut-frwk

Apparently I could have saved myself a heap of greif if I'd just added jUnit to the list!

The final Unit Testing question went out to the edge - "What do you think of Test Driven Development"

tdd

So at least one zealot in the crowd aims pretty high! For the "No opinion" crowd, TDD is the practice of writing your unit test before the implementation. The intent of this is to essentially define the desired behavior in the test, then make the software behave in that way. No doubt this is difficult, and requires you to be a total unit testing & pattern guru. I *think* this is possible, even on complex projects like GIS, but you'd need to be working with a test friendly GIS framework (as in don't come asking me to build you an ArcGIS Server .NET ADF site using TDD!)

 

Code Refactoring

As you write code, there are times when you need to change it's structure - usually to conform to a pattern, to facilitate extensibility, or just because your function got long and messy (i.e. you're making maintenance easier!). This is called refactoring. The first question was related to how often you refactor your code.

refactoring

The second question related to the use of .NET Refactoring tools. I appologize again to the non-.NET people, but I don't know of any Java Refactoring tools.

net-refactoring

What's interesting here is that the "Not Refactoring" people are not even using the tools in Visual Studio. When we were doing a lot of desktop development, we used RefactorPro - mainly because they had good Visual Basic.NET support. Now that we're using C# and doing 99% web development, we are finding that the IDE tools / manual refactoring is sufficient.

Code Documentation Generation

This was a quick question on the use of automatic code documentation generators. They are pretty common in the larger developer community, and relatively easy to bring into the mix, and spit out some good API documentation. Worth the effort in my opinion.

doc-tools

 

Comments

Fifty-Two respondents left comments at the end of the survey. Most were constructive, and others... well... lets look:

WTF, no C++ on the list of languages? What language do you think the bulk of geospatial software (from GDAL to ArcGIS) is written in? C# is just a evil marketing ploy from MS to try to deflate Java's market; nobody is expected to actually _use_ C#.

Reply: Not having C++ was an oversight. As for your issues with C#, can't help you there.

Summary:

Overall, this was an interesting experience. Clearly I could do a much better job on the questions, and have a much wider range of options on the answers. I think it does show that geospatial developers are adopting main stream techniques and tools, just at a somewhat slower pace. Thoughts?

Download the results (Excel 2007 format)

Wednesday, May 07, 2008
Posted on Wednesday, May 07, 2008 7:36:28 AM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: Fundamentals | Unit Testing

...from Jeff Atwood author of the (wildly popular) Coding Horror blog. Hopefully you all subscribe to his blog, but for those who may not, it's full of goodness, and you should check it out on a regular basis.

As for MVC - the results of the Geospatial Developer Survey show only about 50% of respondents are using patterns, and about 46% were not using any sort of Model View * patterns. This article is a great entry point to a pattern that can be applied to a very wide range of scenarios (including easing the creation of unit tests!)

Check it out at CodingHorror.com

Wednesday, November 28, 2007
Posted on Wednesday, November 28, 2007 6:01:20 AM (Mountain Standard Time, UTC-07:00)  Comments [0] | 
Categories: .NET | ArcDeveloper | Unit Testing

Tonight added a few more projects to the ArcDeveloper Subversion repository up at Assembla (http://svn2.assembla.com/svn/arcdeveloper).

Since the goal of the ArcDeveloper.net open-source projects is to streamline unit testing for the ArcGIS developer, the logical place to start is with a methodology for passing geometries into tests.

The code that's up there handles geometry serialization / deserialization. In addition to a set of classes which handle the "work", it also includes 3 ArcMap tools:

  1. Serializing selected geometries to a file,
  2. Serializing a sketch to a file, and
  3. Drawing serialized geometries on screen so you can be sure you captured the right thing.

It also has a simple example showing how to write tests using this methodology.

I'm not going to go into a full-blown "how to" at this point, but the general flow goes like this:

  1. Use the tools in ArcMap to create serialized geometry files
  2. Add these files into your Test assembly as Embedded Resources
  3. Pull the geometries out of the test assembly when the tests are run.

This allows you to store all sorts of complex geometry scenarios without being reliant on particular spatial data sets residing at fixed locations - the data is embedded into the test assembly.

I will be posting a much more detailed "how to", as well as adding content into the ArcDeveloper.net wiki.

Backlog Items

These will be added into TRAC when I get time, but here's the quick list

  • Enable serialization of entire features
  • Add tests for the actual utility classes themselves
  • Improve the messaging
  • Make the Extension be a "JIT" extension so it's easily enabled/disabled
  • Better exception handling (currently just MessageBoxes)

Project Status

If you are interested in following along with what's happening on the project, I'll be posting finer grained information on the "project flow" page, which like all good things has an RSS feed.

Monday, October 08, 2007
Posted on Monday, October 08, 2007 6:38:29 PM (Mountain Daylight Time, UTC-06:00)  Comments [2] | 
Categories: ArcGIS Devt | Unit Testing

I wanted to raise the coverage numbers noted in my last posting, so I jumped onto the code, looked at the coverage, and realized that I needed another test. I added this is, and my coverage jumped from 35% to ~70%. Good I thought - and went to look at the coverage output to see what other corner case I had not covered.

What I saw was very interesting. All the code was highlighted  as being run. Wha?

The SecurityManager.CanUserEditObject method basically does 3 levels of security checks - it checks the layer's "default policy", a layer-wide editor role, and finally a per-user, per-feature policy. Thus, the code is structured around 3 nested select blocks... (simplified example below)

            Select Case GetDefautlPolicy(obj)

                Case AccessGranted

                    Return True

                Case AccessDenied

                    Select Case CheckRolePolicy(obj)

                        Case AccessGranted

                            Return True

                        Case AccessDenied

                            Select Case CheckUserPolicy(obj)

                                Case AccessGranted

                                    Return True

                                Case Access Denied

                                    Return False

                            End Select

                    End Select

            End Select

 

What was interesting was that by directly returning from inside the case statements was causing the code coverage numbers to be lower than you would expect. Since this is a bit of a code-smell, I refactored the code to only have one return statement at the end. That alone got me 10% more coverage - no more actual code was run, but the coverage algorithm liked it better. Below is an image of the code-coverage highlighting.

 

code-coverage

Even at this point, the Visual Studio code coverage tool is reporting only 87.5% coverage for this block.

Anyhow - the take home here is that the code coverage algorithms are fickle, and even though you tests hit all the code, you may not get 100%.

Posted on Monday, October 08, 2007 6:28:21 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: .NET | ArcGIS Devt | Unit Testing

In response to my last post on Refactoring and Unit Testing, Morten posted a comment with some very good questions...

1. Should you really have multiple test assertions in the same test? (I know is convenient to do, but also very messy from a test driven development perspective).
2. What is the code coverage of the unit tests.

Instead of just answering in comments, I thought I'd provide some more information as a separate post.

Multiple Assertions in a Test

It's true that this is a bit of a code-smell, but I view this as an acceptable trade-off between making tests easy to author (ergo you actually write and maintain them), and "best practices". As long as the asserts have good messages, what you get back is informative. Given that the class I'm focusing most of this testing on is a singleton, running multiple tests in a row is  realistic in terms of run-time usage.

Code Coverage

I had not setup code coverage when I wrote the original post. After setting that up, here's what I found:

coverage

At first glance, 73% is not bad coverage. But let's look at the class model for the SecurityManager class.sec-model

Looking at the ISecurityManager interface, we can see that the most critical method is CanUserEditObject, and it's only at 35% coverage! It's good to know that the private methods have high coverage numbers - 100%, 94% and 72%, but the actual method that is used by the client objects still has a ways to go in terms of good coverage.

When authoring the tests, my gut feel was that I had pretty good coverage - certainly shows the value of running coverage! I'm going to add more tests to up the coverage on this method, and I'll be posting more about how I created the tests later this week.

Friday, October 05, 2007
Posted on Friday, October 05, 2007 9:21:56 PM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: ArcGIS Devt | Devt Tools | Unit Testing | Visual Studio 2005

I just finished off some burly refactoring of our security management code base so that it could be better unit tested. This subsystem essentially controls what tools a user has access to, as well as what layers / features a user can edit, so it's a pretty critical part of the infrastructure.

I'm working on some posts about how I did this, and should get them out next week, but for now, I'll just show this...

tests

Although there are only 16 tests listed, many of these methods actually contain a number of individual test assertions, and there are more than 80 tests that are actually run.

Tuesday, March 27, 2007
Posted on Tuesday, March 27, 2007 4:30:43 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: ASP.NET | Team System | Unit Testing
As if the title of the post is not painful enough, I thought I'd just whip up a quick post for others who have run into issues with getting debugging of ASP.NET unit tests working for classes in App_Code.

Just a quick note - ordinarily I'd create a separate assembly, but part of this code is working with the ProfileCommon class, which is created on the fly by ASP.NET based on settings in web.config, and as far as I could find, you can't access this class outside of an ASP.NET web app.

So - I've created myself some classes and had Visual Studio cook up some unit tests for me. I jumped in there and added some legit code, and went to run the test and... I was not getting an error per se - the break points were simply not being hit. In the border of the code, there was a small icon as shown below...


Mousing over this, I got the highly informative message: "The breakpoint will not currently be hit. No symbols have been loaded for this document". So the obvious thing you're thinking is that I need to attach the debugger to the ASP.NET Worker process. Anyhow, that's what some intensive Googling revealed.

The MSDN guidelines on setting up debugging of ASP.NET Unit Tests is here. And while it is conceptually correct, the only issue is that my version of Visual Studio 2005 (Team Edition) does not have "Attach to Process" on the debug menu (not sure why) . Which led to this article which notes that it may also found at "Tools --> Attach to Process". Armed with this, I was able to make some headway...

Here are the abridged steps:
  1. Write some classes in App_Code that you want to test
  2. Create a test project, and have it generate the tests - this is critical as it will build private accessors for you.
  3. Attach the VS debugger to aspnet_wp (XP) or w3wp.exe (Windows Svr 2003)
  4. Then run your test from the Test View (Test --> Windows --> Test Viewer)
Even like this, it's not exactly bomb-proof. I need to re-attach a lot, and start/stop standard debugging of the site occasionally. All the more reason to put your business logic in another assembly if at all possible!