Introduction
Software testing is a complex set of actions with one main goal which is establishing a belief that the software does only things it is meant to do. This is not it's only function but the most important one. Testing is of course also used for evaluating the performance of the software, its functionality, helps in verification of the system if it achieves the requested or at least acceptable results, etc. It is also essential for code analysis with the attempt to find all weak or buggy spots, potential future problems of bottlenecks. Also helps sell the product for a software that is proven to be 99.9% tested is more likely to be sold than the one without testing.
The importance and reason for testing has changed dramatically during time for in 1960s tests we used mostly for demonstration purposes. Their goal was to show the client what the software is capable of. Soon developers realized (possibly because some of the demonstrations didn't end as expected -
Bill Gates' BSOD) that testing can provide them with a way of finding defects in the software that were later debugged. Since 1990s the usage of testing is mostly prevention for as mentioned several times the earlier we discover a defect in the software the less money it costs to repair it. Although a defect is not always that critical it needs to be resolved.
Testing is a complex process that is not related only to code but also to all the aspects of software creation. Design assumptions and interconnection of objects needs to be tested as well as the GUI design/prototypes, functionality and specification (by reviews to verify we are really doing what the client asks).
Testing
Every single test should have one single objective that should be as specific as possible. In case we need to test 2 or more similar objectives then it is usually better to create individual tests or a parametrized test. Complex tests can be composed of several simpler ones by creating advanced test plans and scenarios.
The testing of a software is somehow tricky because to test a software in a way to assure its quality we usually require loads of tests and some advanced management is required. For this purposes we should always have a "test plan" that describes which parts of the system will/won't be tested, how will the tests be conducted (what tools and methods will be used), who is going to be in charge for the tests (setting up responsibilities). Each test consists of 3 basic parts:
- execution (prepare the software for testing, setup context, etc.)
- testing (run the test)
- evaluation (gather statistics and inform about the success/failure of the test)
Every test or a set of tests should be associated to a "test case" which describes the conditions that determine if the test passed or failed. This is quite critical for every test should attempt to cover all the possible contexts and act accordingly. This is a common place for mistakes for every assumption about an impossible case that certainly will never happen needs to be based on some invariants that usually come from the design and implementation of the overall system. So a tip is to "never make assumptions about anything and if we want to do them make damn sure they are right and wont change in time".
Basic principles
When testing a software we should try to keep in mind the following simple facts:
- there is no such thing as "complete testing"
- to create a test requires experience and creativity
- testing is driven by potential risks (more important parts should be more tested)
- tests are based on the analysis, design and specification
- tests require time, money and motivation
- tests should be prepared and run at the right time
- keeping track of statistics and code coverage is as important as testing itself
The tests and their creation can be divided into 2 simple groups based on the knowledge base of the subject in charge of the creation. On one hand we have tests created by people that understand the software and are quite familiar with the implementation and how thing really work inside. This is called "white-box testing" and is usually done by developers themselves at the time of the implementation as part of the debugging process just to test if the piece of code they just wrote does what is supposed to do. The other approach is called "black-box testing" and logically it's the exact opposite. The test designer knows nothing about the code internals and all he knows is the interface and what it's functionality ought to be based on the specifications or application design. This sort of testing is usually done by professional testers, users or by other developers and is better in a way that the tester can't make any assumptions based on the implementation. One great benefit over "white-box testing" is that implementation changes don't break the test if the interface remains the same which is a useful feature.
As mentioned in the facts about testing one crucial aspect is the exact timing of tests meaning good time planning is essential for the tests to play they part in the overall process so we can benefit from these. Simply said if we start testing late then there's quite a big chance we won't test the software properly mostly due to time pressure because deadlines need to be fulfilled. On the other hand if we start testing too early there is a possibility we'll be testing an unfinished and unstable piece of software which would result in a waste of time, money and testers work. To know when to test what part is some sort of magic and a sign of a good and experienced IT manager but a nice hint is the "V-model".
To avoid problems with test planning we need to remember that tests are created and performed by humans which means that no tests can be absolute, no good testing can be done without adequate resources. Good testing requires excellent cooperation between testers, developers and most of all management. A common mistake is the belief that testers are the ones responsible for the quality of the product. This is not really true for they are usually under pressure from the management that schedules test runs and deliveries without taking into account the real-life project limitations. Also lots of companies don't really invest into qualifying testers or they rate their performance by the number of "bugs" they found which leads to their focus on small and not-critical problems just to earn enough points. Another bad testing practice is limiting tests to a specific area of interest (specification based testing, function testing, etc.) or by exactly specifying which atomic parts to test and how leaving little space for testers creativity. Over-detailed tests cause lots of trouble too for they are hard to maintain and usually redundant which leads to too long test runs.
Another thing that should be taken into consideration are the mentioned resources that management needs to provide for the testing to have effect. To create an adequate estimate is also a great problem and sometimes people tend to under or over estimate these. As an example there have been quite a lot of studies with similar results that say that the amount of users testing an application is related to the quality of the testing and that to have more than 5 users test your product is unnecessary for it doesn't provide such extra benefits.
Basic testing strategies
It is not easy to create a universal guideline for creating test plans and making thus testing effective independent on the type or extent of a project. This is probably the reason why are experienced IT managers so important for this is some sort of magic that requires lots of experience on various projects. Anyway there are some tips that might be a nice to follow for starters:
- Begin with the basic tests. Test with values you know shouldn't break anything just to verify everything does what it should. Most software products work for quite some time without breaking anything and Windows users are used to restart the service from time to time. Anyway you can blame Windows if thats your softwares main platform.
- Test slightly everything first. You should always run some preliminary tests first to make sure the whole system works as expected most of the time. If it does there is just a slim chance there's something wrong with the design which are the worst problems to solve.
- Run complex and detailed tests as soon as possible. If the software passed all the basic tests it's the right time to start testing in a more aggressive fashion. Create detailed tests based on the simple ones, create complex testing scenarios with contexts that are not so likely to happen. This usually discovers small implementation mistakes, bugs and possible weak points of your software.
- Modify test boundaries. After some time the amount of tests is more than overwhelming and their execution takes quite a lot of time. Also there probably is quite a lot of redundance for many complex tests do the same job as the a set of simpler ones. The elimination of unnecessary tests will improve the situation significantly.
- Exploratory testing. The most useful testing advice is to keep creating new tests all the time. A nice practice is let every developer create a new test or a set of tests on weekly basis. That way we can discover forgotten untested places.
Reporting
Testing would be almost useless without reports that record the test results as well as all the defects software has. These reports should have a standardized form which can be easily achieved by the usage of a bug-tracking system (BugZilla, Trac). The basic and simple rule is that every issue should be reported and ideally traceable by connecting it to the version of code currently tested. The issue needs to be reported in such a way that enables others to reconstruct and simulate it and most of all repair it. This can be achieved by appending logs, scenarios, detailed results, etc. Also a note describing it's relevance and effect it has on the system is advisable.
Automating tests and regression testing
Ever since testing became an integral part of software development people though of ways how to make the testing process automatic for several reasons. First people needn't to run the tests by hand every time something changed, tests could be reused and of course test runs could be planned in advance for times when the system was not overused. Today regression tests (running old test scenarios on new versions of code) is one of the basic ways to determine new changes are consistent with the rest of the system. This leads to the principles of "continuous integration" (smoke testing), configuration testing on various software/hardware, stress and load testing, etc. Some specialized tools can be used (for example Hudson) to do the job.
Conclusion
Testing helps create a good and high-quality product if the resources are provided. Many people think of testing as an easy click-and-see job for they don't see the experience and creativity required. Also it is important to attempt to have a high "test code coverage" (some norms require a percentage) but we need to keep in ming there is no such thing as 100% test coverage for we may never know what can happen and we usually don't test the platform and tools we use. Anyway even the testing software we use might be buggy!
Articles
Checklists and templates