Writing bug free code is something of a pie-in-the-sky prospect. Can anything truly be bug free? What's the point of writing tests if your code might still fail on prod?
It's actually relatively recently that I've discovered the utility of unit tests and mocks, after initially dismissing them as only useful for very specific kinds of code and certainly not usable for web development. I found them to be tedious and a waste of time, and am discouraged when programmers I work with have that attitude at the moment. Some teammates turned me around to the idea of testing web code when they showed me how Python 3's wonderful mock library works.
Not that proper unit testing requires mocking, but it was what opened me up to the idea of it.
Writing unit tests is analogous to having lost your keys in your apartment somewhere, and you're turning on each light one by one. With each light you turn on, you know where your keys aren't. Likewise, when an exception happens in production, you know where it didn't happen: your tested code.
It's not foolproof, and it doesn't need to be. Connections will fail. The user will do something that you didn't think of. But all that will happen already, in addition to your logic not being perfectly thought out. Ruling out a major potential for error is crucial, and when you write tests you do just that.
Google has a wonderful post called Just Say No to More End-to-End tests, and let me tell you, that one resonates with me. Often I will come across a codebase where the only tests are tests that actually screw with a live, hopefully-not-prod database.
def test_things_work(): my_client = MyClient('http://localhost:3953') assert my_client.has_no_data() # Just in case we accidentally point our tests at Prod ;) my_client.insert_something('I am data') assert my_client.has_entry('I am data')
Yikes! This test has little value, but it's often preferred over writing small unit tests over individual functions and blocks of code, because developers see it as a way of testing real scenarios over a real network and real databases. The reality is that these tests will take a long time to run, still won't cover significant portions of your behavior and your codebase, and will thus result in false positives. There are a million reasons why this test might pass for buggy code.
Rust sooorrrtaa has this problem. There aren't really mocks yet, so I see a lot of open source projects that create a TCP server for the sake of testing. Not sure how I feel about that.
There's still room for integration tests. I once wrote an app that was 100% tested with unit tests and mocks, and it didn't work! Turns out I was using the requests library wrong. It was an easy fix.
Writing high-quality (ie. tested) code ultimately improves the company you work for as a whole. It's not QA's job to find Null Pointer Exceptions, or Index Out-Of-Bounds exceptions. It's our job! Our code must work as expected, and it's QA's job to tell us when those expectations were wrong.
Libraries to check out
- Pytest (http://doc.pytest.org/en/latest/)
- unittest.mock (https://docs.python.org/3/library/unittest.mock.html)
- Usable in Python 2.7 via the