I’ve recently done a piece of work around OAuth and integration with DotNetOpenAuth. I wanted to build up the system doing the simplest thing at all times with the hopes of achieving the leanest, meanest code that I could for the implementation. This worked well overall.
But… when building up a certain repository call to get a user – it was only being used by one controller (and still is) so I did the simplest thing and only built what that controller needed. Life was good.
Then I changed my mind. And I assumed that because my tests passed that my code was all working. So I started using another user field that wasn’t being populated as it needed an additional DB call, and wasn’t needed initially. And I got an unexpected bug.
But I do TDD. My tests passed. All should be awesome. I have the green light. I can deploy.
Doing the simplest thing I violated the principle of least surprise. I was surprised to not get a fully formed user from the user repository. That was wrong. Yes, the tests very clearly show me not testing the specific field and adding the test showed it wasn’t being set. But the repository should always be returning a fully formed user object always. Yes, I should have remembered, but I’ve got a pretty good memory and I still assumed it was all working.
So what should I have done?
a) Not violated the principle of least surprise!!
b) Actually checked what the tests did – they are the specification
c) Test higher up at the controller level where possible.
d) Introduce integration tests
The problem with integrating to DotNetOpenAuth is that the controllers call it and then it calls us. And there is very little code in the controller that we control in order to make it all happen. But there is some. In this case the combination of the login page and the resource fetch (after the OAuth interaction) broke. But setting up a controller to have the correct stuff on it in order to give DotNetOpenAuth would involve me going very deep into understanding DotNetOpenAuth and what it needs. I don’t actually wanting to test DotNetOpenAuth. I do want to test my code around it. As a result the controllers are being kept as simple as possible, but there is no automated testing around them. And now I’ve been provably bitten for not having those.
And maybe I should actually want to test the interaction with DotNetOpenAuth – at least at the basic level. An automated simple happy flow integration test would be useful here. I’ve already got a manual test, but of course I got lazy.
So in future I plan to:
– Not violate the principle of least surprise… it isn’t worth it even if it is less code / simpler.
– Dig deeper into the synergy between unit tests – testing the code I’m writing – and integration tests – testing the full stack integration particularly the parts that are harder to validate otherwise.
And of course, continue to write the simplest code I can and retrospect when I get bitten next.