Ignoring tests spreads a disease
“a piece of code which is capable of copying itself and typically has a detrimental effect, such as corrupting the system or destroying data.”
This definition of a computer virus is not put here by accident. There are a few equivalents in the testing world such as:
@Ignore -DskipTests=true @ConditionalIgnore (AlwaysWithMeAlwaysWithYou.class) :S
If any of such start to pop up in your test codebase or has started to be a suggested practice, you can be sure you are heading for the flu or even something worse in your project shortly.
Ignoring your tests leads not only to the loss of quality but also to something more detrimental in the long run… team morale and its frame of mind.
On the battleground
You have got your gun, your uniform, your helmet, your ammo. Just lock and load and you are ready to dive straight into the battle ahead of you. You have it all figured out in your head, you are not going to fall back, you are going to fight for your beliefs, for your team, for yourself. You feverishly start to climb that hill, eagerly wanting to jump into the action on the other side.
As you approach the top, you start hearing noises. They get louder and louder. Something is not right, you say to yourself. Instead of battle shouts heating each other to move forward and conquer new enemy posts, you hear squeaking noises. They are full of fear, pain, and panic. It's not your enemy that is making that noise. You reach the top few moments later. To you bewilderment all of your allied troops are running away from the battle, ignoring their duty completely, not even trying to regroup.
Now it’s you, standing on the top, seeing all of this, trying to get your head around your feelings. They are a mix of what you see, what are your beliefs and original plans. What do you do now?
Still on the battleground
You have been assigned to a new project that has been there for a while. Help has been requested as the team has lost their top Java dev that just got that contract everyone else has been talking about in the city centre (happens all the time…). Project lead has given you the analysis and free hand to implement this rather complex solution.
You are pumped up to get that new feature implemente. You have planned your fantastic solution, you have thought about all of the possible exceptions, you see all of those tests covering most of your newly implemented code. You are going to prove that it is rock-solid.
You decide that you are going to jump straight into it. You pull that project from your remote repository (fingers crossed its Git) that you are going to work on. You kick off the standard
“mvn clean install”
So that you are sure that everything builds properly and all the tests pass. The tests.. you glance at the logs of each of the submodules flying by. All of the builds pass so far, but something is wrong. There are at least a hundred classes per module, but the test goals look a bit dodgy, to say the least:
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ web --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 104 source files to C:\new-awesome-project\target\classes
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ web --- [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- Running com.newproject.service.ServiceOne Tests run: 20, Failures: 0, Errors: 0, Skipped: 15, Time elapsed: 0.110 sec Running com.newproject.service.ServiceTwo Tests run: 5, Failures: 0, Errors: 0, Skipped: 35, Time elapsed: 0.110 sec Running com.newproject.service.ServiceThree Tests run: 2, Failures: 0, Errors: 0, Skipped: 28, Time elapsed: 0.110 sec
No errors, but that skipped part is starting to get quite distressing.
At some point the expected happens during the test goal execution for one of the submodules:
Results: Tests in error: ServiceFactoryTest>ServiceFactoryTest.shouldGetInstanceAGivenCollectionInput: 120 ServiceFactoryTest>ServiceFactoryTest.shouldGetInstanceBGivenIntegerInput: 160 ServiceFactoryTest>ServiceFactoryTest.shouldGetInstanceCGivenStringInput: 220 Tests run: 40, Failures: 0, Errors: 3, Skipped 15 [INFO] ------------------------------------------------------- [INFO] BUILD FAILURE [INFO] -------------------------------------------------------
At this point, you are like that soldier who reached the top of the hill and is not quite sure what the hell is going on here. You head to the projects technical lead for a little chat to gain some insight. You want to know what actions can you undertake to get that project built with the tests passed on my machine. As you are sure, this has to be happening only on your local.
A few minutes later you come back to your desk with your head down. The news you just got are buzzing in your head making you at least confused:
“The test suite was started by one guy more than a year ago, but no one was really willing to write them and when he left nothing more has been added test-wise.”
“Not sure why we keep them. I guess the developers are less ashamed of themselves when they add that small @Ignore tag than when they remove a large chunk of test code.”
“You have missed one of the starter guide points where it is explicitly stated that you always have to build the project with the tests skipped.”
mvn install -Dmaven.test.skip=true
“Do not really bother to write anymore as no one will ever review them and if so you will only confuse the reviewer what should he do about those new lines under the src/test/java.“
Sitting at your desk, just like that soldier standing on the top of the hill you feel defeated before you even started. What do you do now?
I am quite sure that at some point in your career you have stumbled upon a project like that.
Many ambitious developers that consider themselves as software craftsman and not merely typewriters struggle after being thrown to such an environment. This has happened to me many times, and I have heard dozens of stories about why the test suite has been abandoned, or it has never been put to life in the first place.
You can hide your head in the sand and conform to the reality just like most of the developers in that situation (sorry, but that is just my experience) and wait for that magical turnaround of events. A decision from higher management that tests automation is now mandatory across all of the projects from now on. Let's be frank here, this only happens in movies. Oh sorry, I forgot they don’t make movies about developers.
From my experience, if you try to fight against the resistance in a way that you just write the automation suite yourself anyway, regardless of all the ignorance you see all over the place, other people will start to notice.
At first your manager or team lead will be a bit resistant as in his mind you will be wasting around 20-30% extra time on useless code that will not be beneficial anyway. Keep on pushing.
I did quick presentations for management pointing out the benefits in the long run.
I was coaching the team every other week for 3 hours just to get them accustomed to the notion of automated testing and gaining great joy and satisfaction that your code is rock-solid and verifiable. I still did not get a pay check for those sessions… anyway…
I created project-oriented testing utility libraries to make it even more accessible for the newbies to get on the boat.
The only time I did fail, was in a project where there was one person responsible for managing the project, being an architect and the only reviewer of any of the changes. He was old school, and a unit test was an arcane subject for him. Every time I tried to add some automation code/libraries, he would not even bother to discuss the review with me. He would just remove all the automation and merge the sources only, just treating the automation code as a fifth wheel in the wagon. People like that happen, but even so, you can still write tests for your solution locally to keep your skill sharp and know that your code is of the highest quality.
There is always a way.
When ignoring a test is excused
Sorry but it is not... It's like trying to make an excuse not to get out of bed straight after the first time your alarm clock rings. No matter what you are trying to tell yourself if you snooze you are just lazy.