08 March 2008
Another round in the testability debate
This time a posting from Mark Seemann has raised a slew of comments.
One of them is a note from Colin Jack about the annoyance of producing interface/implementation pairs all the time. My first response is that that sounds to me a bit like a problem with style. Maybe it's just wordplay, but usually I don't extract interfaces from classes, I implement interfaces that I've already discovered in some previous test.
My second response is to wonder how much this is a tools issue. I don't believe there's anything in the .Net world that yet matches the responsiveness of the usual Java IDE's. It makes a difference as to what's plausible. I remember the huge shift in perception when first VisualAge for Java and then JetBrains' Idea came out. In retrospect, I always spent more on time on rework than many people I worked with 1 but it sure took a lot more time in emacs (and I was pretty good at it), even if I was working in a better language.
1) which is not to say who was right, I'm just wired that way...
Labels: design, ide, testability
I have been toying with the approach you guys use again. I can certainly see the advantages but in some cases I am producing interface-implementation pairs even when specifying the collaborations up front.
For example for a service that coordinates the creation of an XML file I specified that it would collaborate with a IXmlFileNameProvider. In reality though thats a pathetically small class and showing that the SUT has a dependency on it isn't as important as showing that it has a dependency on (for example) the file system (which I am wrapping).
It's not necessarily a good extension point either and if I did need to swap to a different name provider later I could have quickly extracted a suitable interface and injected at the time.
So really I'm thinking that the upfront collaboration tests can be useful but to me they are just one tool. I'm also still not convinced that mocking based testing/design is inherently better, to be honest I sometimes think concrete collaborations are fine (for now at least). I guess the key thing for me is that just because a class doesn't support one or more interfaces doesn't necessarily mean that it or related design is "legacy".
I'm also not sure what you mean on the tooling front.
It depends what your IXmlFileNameProvider is. If it's just a little policy object, then maybe you should enclose it in its caller. If it's protecting you from the file system (in the sense that it allows you unit test locally and split out the integration tests), then maybe it's serving a purpose. An uninformed guess would be that you could wrap up everything to do with streaming out XML into a larger type, which can be integration tested, rather than being so fine-grained.
My last experience of VisualStudio, even with Resharper, is that the environment gets in the way much more than Idea or Eclipse. It's just that little bit harder to make changes. And the 'I' wart on front of interfaces doesn't help...
> have to mock everything -- we
> even have a Test Smell for doing
> that. That said, there are quite
> a few people who have dismissed
> our approach without
> understanding it.
For sure, I've read that that and I wasn't intentionally saying that you do push for mocking everything. Plus I'd never mock a value object or a 3rd party API (I'd wrap it instead in most cases).
> It depends what your
> IXmlFileNameProvider is. If it's
> just a little policy object,
> then maybe you should enclose it
> in its caller. If it's
> protecting you from the file
> system
> ...
> An uninformed guess would be
> that you could wrap up
> everything to do with streaming
> out XML into a larger type,
> which can be integration tested,
> rather than being so fine-
> grained.
I agree completely, I already had the higher level type so I was thinking of doing what you suggest. The thing is though, I'm not 100% sure that this sort of decision making is clear from the documents you guys have so far put out (though I may not have read it all yet).
Anyway I'm encapsulating the file system seperately using an IFileSystem so it is just a Policy. My first version had this style of constructor for the higher level service (SUT):
// Forget the names, its a work in progress :)
public XmlFileBasedSender(IXmlFileNameProvider , IXmlFileConfigurationService ,
IFileSystem, INotificationToXmlConverter)
A couple of those are meaningful interfaces but two of them (IXmlFileNameProvider/INotificationToXmlConverter) are really trivial. Even for these later two cases I want seperate classes but as you say a little concrete coupling here seems to me to be OK.
In fact even if I did enclose them in the caller I could still write a collaboration test that showed the interactions with those concrete (and not injected) components using TypeMock (I think it might be more confusing than helpful though).
I'm also still not sold on using this approach for the domain model, I'm quite happy with *some* concrete coupling and the use of real domain entities in tests (object mother or builders). I guess thats what makes me (in Fowler speak) a classicist though.
So at the minute I'm trying to find out how to take what you guys are pushing for and fit into my own working, I have to say I'm looking forward to your book which I'm sure will clear things up a bit.
> My last experience of
> VisualStudio, even with
> Resharper, is that the
> environment gets in the way much
> more than Idea or Eclipse.
Could be, I've never done much Java so I'm not massively informed on the different IDE's. Personally its more about what I think is right rather than ease, but it wouldn't surprise me if Java IDE's were way ahead.
Links to this post:
<< Home
© The authors

