I find that there are a few basic principles of quality assurance that are universally applicable and cover a large portion of potential errors that can occur in software. These principles are useful to follow whether you are a tester doing manual testing or a developer writing unit tests. For the sake of illustrating them, lets use the following requirements for a fake company named LocalDeals:
AS A User signing up for LocalDeals
I WANT TO enter my ZIP
SO THAT I can find deals near me
- Validation: required, exactly 5 digits long
I always start with testing the Empty State to see how the software behaves in the absence of data. In our example, we would not enter any value into the ZIP input field and attempt to submit the form. We should expect to be notified that the ZIP field is required.
Equivalence Partitioning is the technique of dividing the range of all possible input data into multiple ranges where the values within each range are equivalent from a validation perspective. In our example, we would end up with the following partitions:
- Values less than 00000: invalid
- Values between 00000 and 99999: valid
- Values greater than 99999: invalid
To test using these partitions, we would select a value within each range which would act as a representative of the whole. When selecting a value, we should avoid the boundaries as these may act differently than values between them. The boundaries will be addressed in the next technique. This technique allows us to realistically test the complete range of possible input values (sans boundaries) without painstakingly testing every value. In our example, we could select the following inputs to represent each partition and the expected results:
- -99999: invalid
- 55555: valid
- 999999: invalid
Boundary Value Analysis
Boundary Value Analysis is the technique of identifying the boundaries between input partitions and testing the extremes of each partition. We do this to ensure that boundaries are properly respected. In our example, we would end up testing these values with their related expected results:
- -00001: invalid
- 00000: valid
- 99999: valid
- 100000: invalid
Now we just try to break it in the most obscure ways possible. In this example, I would try some of the following inputs:
- 1: a valid number but not a valid length.
- I1234: let’s try some characters from the alphabetic character set
- 1234*: let’s try some characters from the symbol character set
- 999e9: let’s try creating an exponent. HTML inputs of
type="number"will accept exponents while blocking characters from the alphabetic and symbol sets.
- 9999e: let’s try creating an invalid exponent.
- copy/paste: let’s try copy and pasting invalid values. Often developers overlook this when restricting inputs with a mask.
Be sadistically creative!
These principles are applicable whether you are a tester doing manual, black-box testing or a developer writing unit tests. They are relevant whether you are developing a complex algorithm or a simple marketing form. However, this is only a starting point. Each technology has its own peculiarities that influence how you test.
I like to keep a running list of common bugs that I find and how to test for them. For example, I find that web developers often forget to truncate lengthy text. So I like to test with really long input values in forms to see if they overflow when displayed as labels. That is just one of many common test cases that I keep on a list to remind myself and train developers and testers. I’d encourage you to start your own checklist and use it till it becomes second nature for you. Happy testing!
Erik is an agile software developer in Charlotte, NC. He enjoys working full-stack (CSS, JS, C#, SQL) as each layer presents new challenges. His experience involves a variety of applications ranging from developing brochure sites to high-performance streaming applications. He has worked in many domains including military, healthcare, finance, and energy.