Unit Testing, Agile Development, Leadership & .NET - By Roy Osherove
Wonderful article. This could provide a blueprint for lowering barriers to entry and easing the burden on organizations and leagues of jaded and weary developers.
I'm happy more people are getting on-board with this mock overloading. We discussed that exact same point at the first altnetuk conf :)
I use Unit tests to drive out my design and use Rhino Mocks.
We use contractors a lot and I get a lot of resistance to writing unit tests.
I generally have to retrofit them after they have left.
I find it frustrating but I do see their argument. They are there to as they see it "get the job done".
Unit testing in my opinion is just not the norm. and until we lower the bar then it just will not be accepted.
I've recently moved to AAA with Rhino.Mocks but I have found more resistance with the lamda style Stub than with PlayBack and Record.
I much prefer stubbing via AAA and very rarely use expectations now.
The syntax is perhaps a bit cryptic for people who might not have used lamdas or for that matter .NET 3.5 before.
"To suggest that testability is impossible in your solution is to admit that maintainability is also impossible in your solution."
That is precisely the kind of purist view that drives me crazy.
and, yest. SOLID has been around for a long time, and people have not embraced it for a myriad of reasons. first of which is the high learning curve.
I agree that testability isn't an end goal, but many in the industry view it as such (you equate it with good design so achieving ones means the other). I don't view it as a bar to anything. it is simply a bi product of following SOLID rules. not the other way around.
Do you need to design for testability in ruby? or SmallTalk?
can you still get a good design in those languages?
First of all I found your post a very interesting / good read.
The reason for some good practices and principles not becoming main stream because of the learning curve, that doesn’t sound right to me. How can you expect improvement if you are not willing to invest? If you know that doing something this and that way is the proper way of doing it, why than not do it this and that way, even if it means a personal investment / learning. That is like saying that you would stick with technology A because that is what you know and feel comfortable with, not because it is the best answer to the problem. There are so many people that just don’t have an interest in learning new things; I think that is the reason for things not becoming more accepted. I think that for those types of people it doesn’t matter how low the learning curve is, they won’t do it anyway, only if it is enforced upon them.
The example of the external consultants not willing to make proper unit tests because they are there to get the job done, weird, if you specify that the job includes proper unit testing coverage than that is what they should do. Anybody can make software, writing good software that is maintainable and extendable that requires you to think, using principles like SOLID make you think about your design. Usually those projects that have good design and are maintainable and extendable are also very testable. I am surely not saying that I know exactly how to do these things, but I am saying that I am learning and improving.
Don’t you think that principles like SOLID and others help improve the design to become more maintainable and extendable? Don't you agree that a design that is maintainable usually also is extendable, because maintaining an application very often means extending it, or at the very least change certain behavior of it?
I am simply finding it really difficult to find developers (full time or contract) with any relevant tdd experience.
Either people do not see the benefit or are unwillining
To put the effort into learning it.
I simply cannot legislate the time in terms of money in getting contractors up
To speed with unit testing techniques like mocking.
I didn't mean to call names. Sorry. But I find that putting finalistic labels on things to be a bit arrogant (which I seem to be as well some times)
When you said
that is why I said you equate the two. You may not have meant it but it sure sounds like to you they are equal.
Ruby and smalltalk are "testable by default" because you can replace anything at runtime without needing to have a "replceable" design.
So the design and the testability aspects don't matter, depending on the technology.
The fact that we are treating testability as a first class citizen in .NET irks me because there are solutions to that.
oh and Jeremy:
sure, people have not problem *hearing* about solid, and understanding it's always been there, but if everyone were already practicing it, the issues we have today with testability wouldn't exist as much as they do.
not would learning how to make code testable, or all the IoC principles be so hard for so many people.
Nice read. And I agree on the KISS, though I wonder, are you just swapping out some labels, but still pushing the same tech? How does that solve the learning curve?
The biggest obstacle to learning is Yet Another Domain Specific Language.
Personally I've thrown mocks out the window, I'm getting better mileage out of tailoring stubs with embedded assertions.
Roy, congratulations on starting walking in right direction (simplification).
But you need to go much, much further.
Whole mocking concept could be safely thrown away for most of the real projects.
Only the simplest and the most efficient auto-testing methods deserve mass use.
It's important to admit, that for most of software projects even 30% of auto-test coverage is "good enough" coverage.
I think this is a great debate. For too long now everyone in the ALT.NET community has been stating and reiterating that TDD, BDD, whatever is just fantastic and we should all do it and anybody who is not, is obviously doing something wrong.
I do practice TDD for the design merits but it has taken me a long time to get up to speed with it. I made countless (and still do) mistakes at the start and the learning curve has been steep.
My first experience was that developers started with the best intentions but our initial tests were un-maintainable as they were affectively integration tests.
Using a mocking framework helped to write maintainable, fast running tests and I love the test first paradigm.
But I often wonder if I have actually got the return that my outlay warrants.
I use NHibernate and I rarely mock out ISession, ISessionFactory or ICriteria.
If I was after high code coverage, I would have to mock out these for no other reason than to get high code coverage. I use layering to hide this code behind its own abstracted dependency. What if I have a WCF or asmx proxy, then should I stub out each generated method? No.
A side effect of test first is you get unit tests to test your logic. If you are expecting unit tests to catch bugs and keep QA to a minimum then you are approaching the methodology wrong.
I also have a problem with new people coming onto the project who are inexperienced with TDD. They naturally write unmaintainable bad tests.
TDD is a massive outlay and we should and I am questioning its return.
Great article. Just this last week I've been trying to bring some other devs onto a project I've been working on. There's heavy use of mocking, DI, and IoC and I get the sense the new guys feel like they're drinking from the fire hose as you put it.
I think there is way too much emphasis put on Expectations in unit tests. The entire point of the mock, stub, test double is to Isolate the stuff I do care to test from the stuff I don't care about.
I had an ah-ha moment about a year ago when I realized how difficult it was to refactor code where my tests were full of Expectations. Tests were failing for the wrong reasons after doing refactoring. It was because of the heavy use of Expectations over Stubing in my test code. From that point on I only use Stubs unless I'm truly testing interaction of my objects.
It has made tests much more understandable. It has made refactoring much easier. It has isolated the rights tests that should fail from the refactoring or changes to my code.
I 100% agree with your ideas, and the direction you are heading.
I train co-op students all the time and they love TDD and get the concept quickly. With continuous integration in place with many developers, the tests that fail will tell the committer that he/she broke some code. Also, writing the tests first makes you think of a classes responsibility (SRP) and behaviour.
Fakeing? WTF is that? Mock stays.
Less interaction testing, more state based testing -> have you tried Mockito for Java? (www.mockito.org)
Interesting but annoying that you didn't run a spelling check before posting.
Nice article, and judging from the comments you have created a discussion.
I teach objects and TDD as part of my job (team lead/coach) and I wonder what some companies and schools teach when I have to tell someone what the difference is between passing by reference and passing by value. We can’t work for the lowest common denominator of the industry, we must drag the industry kicking and screaming up a notch.
Now, I also, I am afraid to say, dumb things down. I never use scary words like “mock” or “encapsulation” or, God forbid, “polymorphism” Well, not in the beginning at least. Because, as you said, you don’t want to put people off. But, I’ll be damned if it’s not my intention to pull everyone, and the companies I work with, up to higher levels. And that next level will include discovering interfaces a la TDD and mocking. So, I think we need to start slowly, for sure, but we also need to keep teaching, keep writing, and keep learning. I would be careful about diluting what developers need to do, know and learn - i.e. we should not enable bad behavior.
Good post, thanks, J