Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
The all positive post

I'm a month into our new project and working with a lot of new technologies.  When I moved from the desktop back to the web I got some condolences from friends, but it's always fun to do different things and web development with .Net is much different than when I left.  I thought I'd take a timeout from the EF controversy and mention the things that I do like:

  • Doing backend development  with .Net again.  It was interesting(?) to do server side Java last year, but I'm happy to be back.

  • Linq for NHibernate.  We're not pushing it that hard, but it's doing everything I wanted it for.  We're setup to swap out our normal Repository with an InMemoryRepository that relies on Linq to Objects behind the scenes.  I think that's going to end up being huge for testability.  I really like being able to put the query logic directly into business layer code instead of being hidden away deep in the bowels of one off Repositories or services -- without sacrificing testability in the domain and service layers.

  • jQuery is amazing.  The whole "unobtrusive JavaScript" thing is brilliant.  I was a JavaScript whiz in the early days of IE 4 & 5, but the elegance of the jQuery solution for tabs as an example, blows away the drudgery of my old JavaScript TabManager class.

  • We're utilizing some of the new stuff in RhinoMocks 3.5.  I love some of the new features like the Arrance, Act, and Assert style testing.  We've started writing some of our own specific BDD style context superclasses for testing Controllers in the MVC framework, and the new RhinoMocks plays very well into this strategy.

  • BDD.  I resisted it for awhile because, quoting a friend who shall remain nameless, "TDD, but with 'Should' instead of 'Assert.'"  Ok, the shift to "Should" from "Assert" is actually worthy on its own merit, but I think BDD and its concentration on semantics and context is a better way to organize and express tests (specifications).  I even think that BDD does really help in the design process.

  • The ASP.NET MVC framework is okay.  I didn't like the way it did some things, and I think the testability out of the box isn't what it could be.  However, it was an easy matter to write our own infrastructure on top of the MVC that took the testability pain and some repetitive grunt work away.  The fact that it was not only possible, but easy to change its behavior is a major point in the positive column for me on MVC.  I love that you can get the code for it too.  I don't think we could have rapidly done the things we did if all we had was Reflector.  The things in the MVC that I'm still unhappy with I would blame on ASP.NET in general rather than the MVC itself. 

  • QUnit for JavaScript unit testing.  Very cool, and a touch easier to use than jsUnit.  I love the model.

  • WatiN for web testing.  We're gambling a bit that its FireFox support is going to be satisfactory, but otherwise, I think WatiN has been exceptionally smooth to use.  The fact that it's callable from .Net code is letting us do some Lambda-fu to closely hook up our tests to the underlying model of the web pages.

  • C# 3.5.  We're barely using Linq, but all the features they stuck in there to support Linq are making a huge splash in our code.  There are so many times when a judicious extension method eliminates some grunt work or makes code easier to read.  Lambda expressions make a lot of code declarative.  Object initializers tighten up the code and make unit testing more efficient.

Posted 06-27-2008 1:03 PM by Jeremy D. Miller

[Advertisement]

Comments

JH wrote re: The all positive post
on 06-27-2008 2:53 PM

Similar to yourself, I started doing .net web dev after much time  working on native clients. We went to MVC as well but chose to use YUI and YUI Test. The nifty thing was that we built a small, self-hosted WCF service that the YUI tests could write their output to that could then integrate our js testing into our CI process.

I share your favor for a js framework that abstracts all the browser semantics out. It certainly makes developing responsive sites a whole load easier.

Haacked wrote re: The all positive post
on 06-27-2008 2:56 PM

Agreed on MVC. There are some things I'm unhappy with too because of things in ASP.NET we can't really change.

But do let me know if you run into things that are MVC itself that could be improved. :)

Mike D wrote re: The all positive post
on 06-27-2008 3:13 PM

Rolled our own MVC because of the ASP.NET leak, it's lean and mean, does exactly what we need.

Great post

Jeremy D. Miller wrote re: The all positive post
on 06-27-2008 3:21 PM

@Mike D,

We're kinda veering off that way for the same reason, but we've tabled that for awhile.  That just seems extreme.  Then again...

Ayende Rahien wrote re: The all positive post
on 06-27-2008 3:29 PM

Jeremy,

Before writing your own MVC, take a look at MonoRail

Jeremy D. Miller wrote re: The all positive post
on 06-27-2008 3:30 PM

Ok, the one thing I don't like today.

Apparently, there's more than one browser in the world, and they don't do everything identically.  Consider yourself warned.

Must get multi-browser testing going in build....

Jeremy D. Miller wrote re: The all positive post
on 06-27-2008 3:31 PM

@Ayende,

I'm going to do that anyway.  We're not so far into the project that we can't change yet.

Chad Myers wrote re: The all positive post
on 06-27-2008 4:16 PM

@Haacked:

- HtmlHelper, UrlHelper, etc are dependent upon ViewContext which is ultimately dependent upon HttpContext.

- The Routing stuff is heavily dependent upon HttpContext which is kind of a shame because it makes testing a pain. As far as I can tell, there's not a huge reason why it needs to be so coupled to HttpContext, but i could be missing something

- All the %(*&$&( private/internal/protected-internal stuff throughout the API. There's some good stuff tucked away in various nooks and cranny and I'll stumble into it view Reflector or the source only to find it's protected internal or it's a sealed class. D'oh!  Please stop this. If it's good enough for you guys to use, it's good enough for us too :)

ASP.NET MVC Archived Blog Posts, Page 1 wrote ASP.NET MVC Archived Blog Posts, Page 1
on 06-27-2008 4:16 PM

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

Ben Hall wrote re: The all positive post
on 06-27-2008 4:19 PM

Hi Jeremy,

Have you found your having to do a lot of work to keep your tests up to date with Watin?

Comments about MVC are interesting, might have to take a much closer look at Monorail.

Ben

Jeremy D. Miller wrote re: The all positive post
on 06-27-2008 4:34 PM

@Ben,

It's too early for us to get cocky about this (very real) issue, but here's our approach so far for smaller integration tests -->

1.) We only use strongly typed ViewPage<T> views with our own base class.  Nothing, and I mean nothing, comes through the ViewData dictionary collection.

2.) Inside the page, all the input controls are written out as:

<%= this.TextBoxFor(m => m.Site.Identifier)%>

or

<%= this.DropDownListFor(m => m.Site.SiteType.Key).FillWith(m => m.SiteTypeList)%>

where "m" is the Model coming into the page.  The control naming is all based on the property name it's "bound" to (we handle the m.prop.prop.prop case).

3.)  In the Watin tests, we can then use a little homegrown base class that "knows" the Model type from above:

public class ViewContext<VIEW, MODEL> where MODEL : class, new() where VIEW : DovetailViewPage<MODEL>

Now, I can get to controls on the screen by:

       [Test]

       public void has_textboxes_for_identifier_and_name_and_other_properties()

       {

           TextboxFor(x => x.Site.Identifier).ShouldExist();

           TextboxFor(x => x.Site.Name).ShouldExist();

           TextboxFor(x => x.Site.Fax).ShouldExist();

           TextboxFor(x => x.Site.Notes).ShouldExist();

           TextboxFor(x => x.Site.Phone).ShouldExist();

           TextboxFor(x => x.Site.Name).ShouldExist();

       }

and exploit the fact that the controls are named to match the property on the Model.

So, long story short, I think this approach will go a long ways towards solving the problem you're describing.

Jeremy Gray wrote re: The all positive post
on 06-27-2008 4:46 PM

Agreed on all points, but I feel compelled to call out BDD. For the longest time the only thing that stuck with me about BDD was the seemingly needless renaming of terminology. Having used the approach for a while now, it turns out I was right: the renaming of terminology was needless... for _me_. For the rest of my team, however...

I suppose I am usually pretty good about not just testing code but instead testing contracted behaviour in various scenarios. Where BDD really seems to have helped, however, is with those developers on the team that were having a hard time doing more than plain-old code testing, and those having a hard time doing testing at all (often because they can't for some reason figure out how something should be tested.) Forcing the alternate viewpoint and terminology has done remarkable things for their test output and the quality of our test automation. Simply remarkable.

For those who have not yet tried it because they feel it unnecessary like I once did, try a pilot adoption in a team environment and you might end up as surprised as I did. It might not markedly help you, but there's a good chance it'll help the collective.

Jeremy D. Miller wrote re: The all positive post
on 06-27-2008 4:50 PM

@Jeremy,

I don't entirely disagree with you, but I really do think that the change in test organization plus the focus on the semantics of the test specifications is a big deal.

Vladan Strigo wrote re: The all positive post
on 06-27-2008 5:23 PM

Hi Jeremy,

Could you please give some more words on some of the concrete issues you've had with ASP.NET MVC (are the ones mentioned by Chad those or)?

I am in the crossroads currently because I am embarking in a month on a new project which will last for a while and am thinking Monorail or ASP.NET MVC.

Your notes from the trenches could be of great help :)

(I am leaning currently on Monorail side because of maturity of the framework, but as this is a long term project I am rethinking of cutting into a few risks and starting using ASP.NET MVC from the start)

Thanks,

Vladan Strigo

Chad Myers wrote re: The all positive post
on 06-27-2008 5:35 PM

@Vladan: Please don't read my list as too harsh. Like Jeremy said, there's a lot we like and MVC does a lot for us and has a lot of extensibility points. There are a few pinch points for testing, but overall it's getting the basic things done we need it to do. Like Jeremy said, we're going to take a hard look at MonoRail and see what it offers us above or below MVC and go from there. I'm thinking we'll probably end up using bits and pieces from both, but I'm not sure who the main request processor will be under the hood. We'll see, I guess.

At this point, we're fairly decoupled from MVC, so implementing MonoRail should be relatively easy (hah!).

I would encourage you to at least give MVC a serious look.

Vladan Strigo wrote re: The all positive post
on 06-28-2008 2:34 AM

Don't get me wrong. I did have a very serious look (did some pet applications, built some of my *frameworkish* bits around, did presentations on it...)at MVC and it looks good enough (maybe not mature enough, but that a whole other ball game)

But still, I believe that there are issues I see and don't see (the ones I do see are currently acceptible to me. I still am to build a real big project on it which will no doubt shed a completly different light on it), the ones I don't... well that's why I am asking :)

Thanks,

Vladan Strigo

Dew Drop - June 29, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop - June 29, 2008 | Alvin Ashcraft's Morning Dew
on 06-29-2008 8:00 AM

Pingback from  Dew Drop - June 29, 2008 | Alvin Ashcraft's Morning Dew

ftorres wrote re: The all positive post
on 06-29-2008 11:47 AM
Colin Jack wrote re: The all positive post
on 06-30-2008 8:16 AM

Really interesting stuff, I have a question about one aspect...

"I really like being able to put the query logic directly into business layer code instead of being hidden away deep in the bowels of one off Repositories or services -- without sacrificing testability in the domain and service layers."

I'm interested what you mean here, where do you end up putting the actual query methods/specifications and do you just end up with ultra-generic repositories?

Jeremy D. Miller wrote re: The all positive post
on 06-30-2008 9:03 AM

"ultra-generic repositories" -- That's exactly what we're aiming for.  Our repository interface is this:

   public interface IRepository

   {

       T Find<T>(long id) where T : Entity;

       void Delete<T>(T target);

       T[] Query<T>(Expression<System.Func<T, bool>> where);

       T FindBy<T, U>(Expression<System.Func<T, U>> expression, U search) where T : class;

       T FindBy<T>(Expression<System.Func<T, bool>> where);

       void Save<T>(T target);

   }

Look at the Query<T>() method.  On the last go around I thought we were spending too much energy on rolling repositories.  I like to use in memory repositories for whitebox integration testing, and we were spending more time writing test harness code for that.  

The actual queries will be in either Controller's or in service layer classes.  Eventually, we need to build a rules engine that will also consume IRepository.

Colin Jack wrote re: The all positive post
on 06-30-2008 11:13 AM

Interesting.

I guess I think one of the powers of repositories is there ability to encapsulate the semantics related to querying (regardless of testing), I've thus always been a bit put off by moving the queries out to higher layers.

Get you about it being nice to plug in an InMemoryRepository though, but there are other ways of allowing that. Guess I need to experiment with both approaches to see if I'm swayed.

Ta.

Igor Brejc wrote re: The all positive post
on 07-05-2008 12:14 PM

Hi Jeremy,

Regarding web testing: I think you should really invest an hour or two investigating Selenium. I've been using it for almost a year now and it has proved to be very useful. There is a stable .NET library for it which enables writing unit tests. The best thing of all is its browser transparency - the same test code can be used to run tests in various browsers (IE x, FF, ...). I don't know about lambda though.

DotNetKicks.com wrote The all positive post
on 07-09-2008 3:45 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Recent Links Tagged With "rhinomocks" - JabberTags wrote Recent Links Tagged With "rhinomocks" - JabberTags
on 08-26-2008 12:45 AM

Pingback from  Recent Links Tagged With "rhinomocks" - JabberTags

Add a Comment

(required)  
(optional)
(required)  
Remember Me?