January 28, 2013

Always Be Testing

You're a developer and you get handed over shitty code. The only proof that the code works is someone who uses the software and complains to you that it's buggy. What's a developer to do?

Whether you're handling new or legacy code, first thing is to start testing.

When I first started writing software I thought testing was for the birds. Testing, in my mind, absorbed time and energy away from building features and shipping. But after supporting my own and others code, I realized a couple of things. Supporting software sucks and making bad code good is typically impossible without rewriting. This is true unless you have clear documentation and a test suite.

Testing code is about the end game. Would you rather be fixing bugs and rewriting months down the road or implementing new features? I'm guessing the latter.

Testing saves money, jobs, and lives. - Daniel Greenfeld

Further, Daniel Greenfeld (author of Two Scoops of Django) points out that the "lack of stability in a project can mean the loss of clients, contracts, and even employment." More important than implementing new features is reducing risks like those mentioned by Daniel. No developer wants to lose their job because they didn't tests their work.

I want to provide you tips...

In this post, I'd like to offer up testing habits that will make you a better developer.

1. Something is better than nothing

Make it a habit to start testing. If you don't know where to start, try testing code that is critical to your business like credit card processing, registering a user, or managing confidential information. Unit tests are your best friend for testing these type of tasks.

Remember that creating an automated test suite is not a waste of time, especially when it eliminates clicking through screens manually to resolve bugs.

2. Coverage isn't everything.

You may think that I'm a fan of 100% test coverage. Well, I'm not. 100% code coverage could be a recipe for failure because the tests may lack real-life use cases.

It's obvious that 0 percent coverage of a module indicates we have work to do. But what does it mean when we have 70 percent coverage? Do we need to code tests that go after the other 30 percent? - Greg L. Turnquist

When faced with partial to no test coverage, work towards increasing coverage by writing new tests that target scenarios the code is expected to handle. This doesn't mean create test cases just to say you have 100% coverage. Be smart and think about how your code is meant to operate then add tests that are useful.

In other words, effective coverage trumps 100% coverage.

3. Be willing to invest in test fixtures

A test fixture is code that typically supports your tests. For example, removing records from a database before running a unit test is a text fixture.

Spend time working on test fixtures and the investment will pay off. Not only will your unit tests pass, but you'll have better intuition on how your code should operate.

4. If you aren't convinced on the value of testing, your team won't be either.

You're only as strong as your weakest link. Expect problems if only part of your team believes in the value of testng.

5. Harvesting metrics

You can achieve incredible progress if you set a clear goal and find a measure that will drive progress toward that goal - Bill Gates

To get an idea of how testing helps improve code and reduce bugs you should harvest metrics for validation.

Here are steps on how to measure your testing taken from Python Testing Cookbook by Greg L. Turnquist:

  1. Create a spreadsheet to track number of test cases, time to run test suite, date of test run, bugs, and average time per test.
  2. Check the spreadsheet into your code base as another controlled artifact.
  3. Add some graphs to show the curve of test time versus test quantity.
  4. Add a new row of data at least every time you do a release. If you can capture data more often, like once/week or even once/day, that is better.

Harvesting metrics allows you to point to facts that show why your time writing tests is value added. It's a good reference to justify the importance of testing.

"Think of it as a backup for your assertion of quality." - Greg L. Turnquist

6. Capturing a bug in an automated test

Whenever a bug occurs in your software, look for an opportunity to write an automated unit test that recreates the error then work towards fixing the problem.

7. Pause to refactor when test suite takes too long to run

Tests are meant to be ran multiple times a day. If they take to long to run, you're probably going to run them less often. Take time to refactor when this happens. Profiling your code is just as important as making unit tests, which leads to better performance and costs savings.

8. Be willing to throw away an entire day of changes.

One day, you decided to refactor a bunch of code without running existing tests throughout the refactor. You find out that your code breaks unit tests and you have to work towards making things right.

If you don't commit early and often, code a little, and test a little then you pretty much wasted a day writing code that doesn't make the cut.

Remember to code a little, test a little coupled with commiting to your version control as often as possible.