The IT services industry has a terrible reputation for delivering unreliable projects, with issues popping up day to day whenever the system is worked on.
There’s a simple answer to this problem that we push as a core offering of our services, on new and old projects alike. Unit and integration tests.
Unit tests are like systems checks. All components of your system are tested to ensure they do what they are supposed to. The tests run automatically, all the time. There could be thousands of these tests to run in a big project.
Unit tests run almost instantly, and guarantee that all the code in your system still does what it’s supposed to.
Unit tests break off the smallest possible piece of functionality in your code. An input is supplied, and we confirm that the output matches what we expect. A unit test should run on hundreds of small parts of your project simultaneously — checking a user is added to a mailing list, a product is saved correctly, checking incorrect input is rejected.
Here’s a contrived example that checks a user can’t create a username of junk characters:
$this->assertFalse(\App\User::DisplayNameValid( "&^*$($" ));
If a junior developer works on the “DisplayNameValid” code in 5 years and accidentally breaks the functionality, the test will fail and they will be unable to commit their code.
Integration tests are special tests that act like a user in your system. The tests load a webpage, click a button, check an action occurs. Visit another page, check it has an entry on it.
Many of these integration tests run in parallel on your website, so often still take less than a minute to test many user paths on the site.
Integration tests are fantastic because they test the sum of the parts of your website/app. In an e-commerce app you’ll have integration tests for each of the paths a user can take through your website and check multiple parts of the page at each step.
If anything has been inadvertently changed or broken, the integration test will fail (and hopefully a unit test or two, if you have a comprehensive suite).
The integration tests save you time and money fixing errors and finding out from your users that your site or app is broken by identifying issues as the code is written.
Unit tests and integration tests are more code to write and maintain, and slow down a software development project by approximately 30% (thereby making it approximately 30% more expensive to build).
Unit tests can be tricky to keep working, and they take a certain knack to write in a resilient way. All project code grows, shrinks and evolves over time, and tests needs to be maintained accordingly. When a test breaks, it’s mission critical to get it up and running again. It’s important to remember a test can fail for very legitimate reasons. For example, if you have a test that checks for “Add to cart” on a product page, and a dev changes it to “add to basket” – once you’ve verified this is an approved change, the test needs to be updated to match.
This is a .. short section. Unit and Integration tests are essential, and the pros far outweigh the cons.
I just said it’s 30% more expensive to build! It certainly is.
A project with unit & integration tests is a fraction of the cost to maintain and extend as one without. Anybody can work on the project and make live changes, and know instantly if they’ve broken any functionality in the project. Speed of maintenance and bug fixes speeds up dramatically.
Developer confidence reaches a new high, because they know that they can push code to production and it’s going to work without a hitch. They have the tests to prove it.
Writing the first batch of tests for your project is a slow and painstaking process if it’s an existing project. As time goes on, your development team has a great collection of tests to refer to for the future.
It’s a drug.
As a developer, there’s nothing better than writing and deploying code that I know works, and will work for the life of the project. I know I’ll never get the dreaded Friday night call about that piece of code, and I know anyone that works on it in the future won’t be scared to break it.
The developers are empowered and the users are confident in the system. Updates get quicker and more reliable, leading to a happier relationship between all partners (developers <> business <> users)
It doesn’t sleep.
We schedule integration and unit tests to run 24 hours a day on our client projects at scheduled intervals, and to run automatically when developers work on and commit code. Code never gets to production that hasn’t passed all the tests.
It gets better and better.
Projects that are actively worked on have tests added all the time, so over time we get more and more confident in the accuracy of the system.
Very often, we find tests find issues that they weren’t even written to test – it’s a strange side effect that writing tests tends to find many more potential issues than the tests are written for.
Developers are cheaper.
If you teach your developers to prove their code is correct, they don’t need to be ninja superstars. They write code, write proof that it’s correct, and move on. This means you need less ninja rockstars flying by the seat of their pants.