Testing is one of the most important practices in software development. And with automated test runners like Travis, there’s no reason not to write tests.
In this article, I talk about the testing ideas that have helped me in my developer life.
Test external dependencies periodically
External APIs can break anytime. They don’t actually "break" but the API you expect it to provide and the API it provides can mismatch anytime. So, you can’t relax while using them.
One way to reduce this risk is by running tests against them periodically. You can use the cron feature of TravisCI to do so. For example, in GoRemote, I use these tests to make sure that StackOverflow doesn’t “break for me”.
Test close negative cases as well
Many developers only test the positive cases of a test. That is, this should work like that. But they should test the negative cases as well. This is especially true when it's quite easy for the tested function to be buggy.
function hasUnicodeOne(string) {
return string.match(/¹1️⃣/)
}
test('', () => {
expect(hasUnicodeOne('¹')).toBe(true)
// negative test case below
expect(hasUnicodeOne('1')).toBe(false)
})
There’s a chance the above function includes numeric 1 in the regex. So we test the negative case for it to make sure it doesn’t happen.
When in doubt, test
Many times you won’t be sure if you want to test that code or not. It might be too trivial. Or you would think you don’t need to check it because it would never happen. In that case, write the test. Writing tests never did any harm.
Backend tests > Frontend tests, usually
Backend tests are usually more important than frontend tests. More so if backend handles all the data manipulation. So make sure to test the backend. If you have limited time to give on tests, prefer backend.
Yes, I know that we should test everything. But when working on a tight schedule, it can be challenging to justify time writing less critical tests. So this is what you do then.
Don’t delete or comment a test
At times, you might want to delete a test because it isn’t adding value. Or a test failed and you think you don’t need it and so you comment it out. Don’t do that, ever. This starts the bad habit of commenting or removing tests and after a while, your code is left untested. Instead, take the time and fix the test.
Don’t leave your project with failing builds
Don’t leave your project with failing tests. It doesn’t matter if the test that is failing is non-critical. Fix it! Now. Otherwise, it will envelop a critical failing test later on. And you won’t know because you will think that it’s the non-critical test that is causing the build to fail.
Try to practice TDD
I recommend TDD. But I know it’s hard to follow when working on a deadline, trying to ship that feature. So yeah, try to do it. But if not, still okay.
Many a time, I don’t do TDD because I don’t need to run the tests every time to check. I know that the new test will fail and adding this optimized logic to the code will fix it. So I write the finished code and test only in the end instead of testing three times — one fail, one pass, one refactor.
Use tests as you use insurance
You have insurance for your health, life, and house. Tests are the same. They are insurance for your code. Also, insurance costs money in real life. But software tests usually don’t cost anything. So use it.
You can say writing tests take time but it prevents you from getting on that Saturday evening call because of a critical bug discovered in production. So I will say the time spent is worth it.
And it saves money as well since you will lose business if your product is buggy. So, writing tests is value for time and money spent.
Prefer integration tests over unit tests, when in a bind
Many times, you don’t have the time to test everything. Or you don’t want to. Whatever it is, in that case, prefer integration tests over unit tests. By their nature, they cover a larger surface area of the code. So they have more chance of finding a non-trivial bug. Note that they won’t find all the bugs in your code. Only the outstanding ones.
Don’t test like a robot
Testing is as much art as science. You need to know what to test.
Trying to reach 100% coverage will take a lot of time and you may still leave bugs if you don’t know what to test.
So chill out, put on your creative hat, and write tests that can catch bugs. One way to do this is by starting to notice where you discover bugs in software applications and writing tests to capture those.
First posted on my blog
Top comments (2)
This is solid advice, especially with fixing broken builds as soon as possible. I've seen test suites with broken builds for weeks with no one doing a thing about it because "there's no time", which is a lousy excuse.
One thing I don't particularly agree with in this article is where you mention backend tests are better than frontend tests. It all depends on your application. I've worked on applications with excellent test coverage on the backend and lots of bugs sneaked through out testing pipeline because of the frontend. Depending on your application, I'd argue over spending a little more time on UI tests if your time is very limited, because it will cover more than just the backend.
Also, I would add that keeping your tests running fast is essential. Minimize overhead like too many database connections, mock external services when it makes sense, etc. If your tests are too slow, devs will stop paying attention to them and your test suite will break down quickly.
In any case, this is a great article with a lot of good tips for developers and testers to improve their testing skills!
Thanks, Dennis. You mention valid points.
I didn't look it this way. Agreed.
Good point. I should have included this. :)