When testing is not fun enough
On regular basis, some colleague starts complaining in an informal discussion about the low quality of some project he's working on. It has to do with code quality, or lack of tests, or both. Every time, I end up asking why he doesn't add tests in the first place, and hear one of a few answers.
For personal projects, people often respond that writing tests is just not fun enough. Understandable—while some TDD can be a lot of fun, there is a lot more to testing that can be plain boring. I myself have dozens of personal projects which have no tests at all, or extremely few tests even when the code could be quite complex.
The “not fun enough” reason, however, hardly works for the projects done for an employer or a customer. You're paid to do work which may not always be fun. Developers, therefore, revert to a few different answers:
- Nobody writes tests in my team. Why would I be the only one? Or a different variant: it's not the corporate culture. Who am I to go against it?
- If I do tests, I spend more time shipping a feature compared to my colleagues who don't test anything, and so I look bad.
- Management/stakeholders need features fast. They can't wait for me to write tests.
Let's discuss those three reasons.
Over my career, I've been to many places. I worked with amazing teams and developers much more skillful than I am, and I also worked in companies filled with programmers who don't know how to program. In every case I tried to be professional, that is, to deliver tested, correctly written, refactored code. No one complained that I wasn't following crappy corporate culture.
Corporate culture is one thing; professionalism is another. Think about it this way: you'll spend maybe a year or two in a company, and then you'll go somewhere else. The corporate culture, you'll leave it behind. What you'll keep is (1) the skills you got, (2) the good or bad habits, (3) in some cases the source code that you will be able to show to a recruiter, and (4) the feeling that you did a great job, or the lack of thereof. Corporate culture doesn't matter—it's not your corporation, and therefore it's not your culture. What matters is what you did, personally. If you don't like it, ignore it.
There are cases where wrong corporate culture is so strong, that you can't possibly ignore it. Obviously, if your salary is proportional to the number of lines of code (LOC) you write per month, you can't imagine yourself refactoring the code base in order to get rid of twenty thousand LOCs: if you do it, you will have to give money to your employer. In this situation, you have to weight your chances to get a better job, and the impact this one could have on your career. Such companies could damage your skills, your motivation, and your reputation; make sure you understand the potential impact when working there. Imagine you're a salesman, and you are hired to sell stuff. In a matter of days, you learn that the product you have to sell sucks, and that all the marketing is a lie. You can stay and spend the next few years deceiving people, or you can leave. If you leave, you'll have to look for another job while having no income. If you stay, you'll have to look for another job eventually, and “I worked ten years for a bunch of liars” may not be the best thing on your resume.
Fast, faster, fastest
Math time. Jeff and Mary are asked to implement, in parallel, the same feature to a project as fast as they can. They work on different repositories, so changes performed by one person won't affect the code base of the other. They both have similar skills, and similar knowledge of the code base.
- Reads the description of the feature.
- Starts typing right away.
- Reads the description.
- Goes for a chat with the stakeholder to clarify a few aspects.
- Talks with a colleague about the possible ways to implement the feature.
- Checks the code base and adds some tests on a part which was, for some reason, untested and which will be affected by the new feature.
- Refactors the logic which was particularly cryptic—it would be much easier now to add the feature.
- Asks another colleague to do a pair programming session with her to implement the feature.
- Makes a call to the stakeholder when she finds a thing which doesn't seem right.
- Ensures the feature is tested.
- Asks her lead to review the change, especially the thing she's not sure about.
Question: who would deliver first?
In fact, the answer depends of what we consider as delivered. Two hours later, Jeff could commit his changes, and call it a day, considering that the work is finished. And then, maybe, the build will fail. But it doesn't matter if we consider that the feature is finished as soon as the developer told us that he finished it.
Or we can consider a feature as finished when it actually works as expected in production, and matches the original requirements. And here, I doubt Jeff would win over Mary. I even bet that Mary will ship the feature by the end of the day, while Jeff would still be working on it weeks later, because he would have to solve all the misunderstandings between him and the stakeholder, fix all the regressions he introduced, rework the code several times until he gets it in a working state, etc.
In some companies, stakeholders don't grasp the notion of delivered. Something may make them think that Jeff's definition of done is the correct one, and therefore Mary is not doing a good job. It takes time, and it requires a good skills in politics, to make the stakeholders to understand what's right, and what's wrong.
In most companies, however, stakeholders don't even think about the definition of done. They don't care. They want their features, they want them to be finished yesterday, and they want them to work as expected. In those cases, there is no need for special skills in politics to explain that Mary is doing great, and Jeff is not.
Eventually, there is a deadline to meet, such as a release announced publicly. Or a given feature is really important to the loudest stakeholder, and so you need to ship it fast if you want the guy to shut up and stop bothering everyone.
However, shipping code that doesn't work has more often than not the opposite effect. The loudest stakeholder doesn't shut up, and starts complaining even louder that the feature doesn't work. And the fact that your company for the first time didn't miss a deadline doesn't prevent it from losing all credibility by shipping a piece of software which crashes as soon as it starts.
Usually, stakeholders pay your salary. This makes one think that whatever the stakeholder decided is an absolute truth. The reality is slightly different. Stakeholders do decide things, but they don't decide how you do your job: it belongs to you to do it professionally.
Imagine that you're in a plane for a business trip. You're in a hurry: in three hours, you have an important meeting in Los Angeles: you have to be there, no matter what. Unfortunately, as the plane is ready to take off, the pilot tells that the flight would be delayed. In fact, some flight controls don't seem right, and it is unsafe to fly until the issues are fixed. You're angry, and you don't hesitate to explain to the flight attendant how are you disappointed with the airline. After all, you're a paying customer, and it's your choice to avoid this airline in the future. Now, would you prefer the pilot to take off and see if the plane crashes or not, or would you rather prefer if he does what he is supposed to do by the protocol, that is, keep the plane on the ground until he's absolutely sure that it is perfectly safe to fly?
Stakeholders know about programming as much as we know about planes, and as pilots have procedures, so do we have our own procedures. As pilots need to be sure the plane is safe to fly before taking off, we, developers, have to be sure the code we release is decent enough and won't crash.
As a customer who's pissed off by a delayed flight can decide that he would avoid the airline in the future, a stakeholder may be pissed off because the feature haven't been delivered on time, and fire you. This is a very concrete risk, but what one shouldn't forget that the alternative can also have some nasty consequences. Developers have been fired after delivering broken features, and having the boss storming in because you shipped on time something which also destroyed your corporate database is not fun at all.
There is reputation involved too. It should be quite challenging to find a job after you have been fired for breaking something. It should be much easier to find one after you have been fired for behaving professionally.
It all comes to the fun factor. Many developers don't enjoy testing. It's not fun. It's not as fun as pondering five hundred lines of code in an afternoon, drafting some super complicated algorithm which makes you proud (especially if none of your colleagues can understand it). This is wrong, but understandable.
The fact is, developers don't want to admit that they don't test code because they don't enjoy it. And so they find excuses. The best way for an excuse is to move the responsibility to somebody else. “They told me that I don't need to test” sounds just perfect: I, the developer, would rather do a good job, but somebody else who pretends that he can decide what I do told me that I shouldn't do a good job. Good try, but the fact is, if testing was fun, you would be testing no matter the corporate culture, no matter how fast your colleagues ship features, and no matter what stakeholders tell you.
So, please, go add some tests. Now.