Here is a quick tip:
When a bug is found, DO NOT, run off to fix the bug immediately. Instead, I urge you to write a unit/acceptance test first which exposes the bug. Then and only then, should you go and fix the bug.
By following this mantra you can ensure that all bugs which have appeared in your system are documented by specifications (tests) which prove that they no longer exist.
Here is a quick example. Sally system user reports that the Change E-mail Address feature is saving data in the database replacing the @ symbol with %40. This is causing serious problems and she has requested an urgent fix be provided.
- First, identify and simulate the problem (i.e. - get your app up and try to change e-mail address, step through the execution and try to pinpoint where the issue exists).
- Next, automate your simulation steps through test (Unit testing, front-end testing using Selenium, WaitR/N, White… whatever it takes to simulate the users experience of entering an e-mail address and producing a record in the database containing %40 instead of @).
- Now, add a verification exposing the issue (query the database for your record and verify/assert that the e-mail address does not contain %40).
This test should FAIL right now (you haven’t gone ahead and fixed the issue already, have you?). - Lastly, go ahead and fix the issue then re-run the test. Once the issue has been resolved your test should pass.
Do your best to refactor the tests such that they align with the features behavior as opposed to its representation (i.e. if you are testing a web page, try not to rely on an elements position in the html tree as these can be volatile and are subject to change when rearranging the look and feel of the page, but normally will not change the way it behaves).
If you are using continuous integration and your build/deployment pipeline executes theses tests, your build should fail in the event that issue reoccur.
Happy coding!