How to design problems in ways that make them easier to test and debug?
The key to doing this is break- ing the program up into separate components that can be implemented, tested, and debugged independently of other components.
6.1 Testing
What is the most important thing to say about testing?
The most important thing to say about testing is that its purpose is to show that bugs exist, not to show that a program is bug-free. To quote Edsger Dijkstra, “Program testing can be used to show the presence of bugs, but never to show their absence!”39 Or, as Albert Einstein reputedly said, “No amount of experi- mentation can ever prove me right; a single experiment can prove me wrong.”
What is the key to testing?
The key to testing is finding a collection of inputs, called a test suite, that has a high likelihood of revealing bugs, yet does not take too long to run. The key to doing this is partitioning the space of all possible inputs into subsets that provide equivalent information about the correctness of the program, and then con- structing a test suite that contains at least one input from each partition. (Usually, constructing such a test suite is not actually possible. Think of this as an unachievable ideal.)
What are the positive features of the independence of black-box testing?
- It reduces the likelihood of generating test suites that exhib- it mistakes that are correlated with mistakes in the code.
- It is robust with respect to implementation changes.
What boundary condition should be tested?
When looking at lists, this often means looking at the empty list, a list with exactly one element, and a list con- taining lists. When dealing with numbers, it typically means looking at very small and very large values as well as “typical” values.
For sqrt, for example, it might make sense to try values of x and epsilon similar to those in here:
0.0 |
0.0001 |
25.0 |
0.0001 |
0.5 |
0.0001 |
2.0 |
0.0001 |
2.0 |
1.0/2.0**64 |
1.0/2.0**64 |
1.0/2.0**64 |
2.0**64.0 |
1.0/2.0**64 |
1.0/2.0**64 |
2.0**64.0 |
2.0**64.0 |
2.0**64.0 |
Another important boundary condition to think about is aliasing. Consider, for example, the code
def copy(L1, L2):
""" Assumes L1, L2 are lists
Mutates L2 to be a copy of L1"""
while len(L2) > 0: #remove all elements from L2
L2.pop() #remove last element of L2
for e in L1: #append L1's elements to initially empty L2
L2.append(e)
L = [1, 2, 3]
copy(L, L)
print(L)
If any of these tests fail, something needs to be fixed. Where do those “something” lie?
Perhaps there is a bug in the code that needs to be fixed, or perhaps the specification needs to be changed so that it is easier to meet. It might, for example, be unreasonable to expect to find an approximation of a square root when epsilon is ridiculously small.
Why it is rarely sufficient to do black-box testing?
Without looking at the internal structure of the code, it is impossible to know which test cases are likely to provide new information. Consider the trivial example:
def isPrime(x):
""" Assumes x is a nonnegative int
Returns True if x is prime; False otherwise"""
if x <= 2:
return False
for i in range(2, x):
if x%i == 0:
return False
return True
LS0tCnRpdGxlOiAwNiBURVNUSU5HIEFORCBERUJVR0dJTkcKc3VidGl0bGU6IAphdXRob3I6IOabsuaUvwpkYXRlOiAyMDIwLTA1LTI3CnNsdWc6IHRlc3RpbmctYW5kLWRlYnVnZ2luZwp0YWdzOgotIApjYXRlZ29yaWVzOgotIG1pdDYwMDAKLSBJQ1BQIGJvb2tub3Rlcwp0eXBvcmEtcm9vdC11cmw6IC4uLy4uL3N0YXRpYwpzaG93X3RvYzogeWVzCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIyBXaGF0IGlzIHRlc3RpbmcgYW5kIGRlYnVnZ2luZz8KClRlc3RpbmcgaXMgdGhlIHByb2Nlc3Mgb2YgcnVubmluZyBhIHByb2dyYW0gdG8gdHJ5IGFuZCBhc2NlcnRhaW4gd2hldGhlciBvciBub3QgaXQgd29ya3MgYXMgaW50ZW5kZWQuIERlYnVnZ2luZyBpcyB0aGUgcHJvY2VzcyBvZiB0cnlpbmcgdG8gZml4IGEgcHJvZ3JhbSB0aGF0IHlvdSBhbHJlYWR5IGtub3cgZG9lcyBub3Qgd29yayBhcyBpbnRlbmRlZC4KCiMjIyBIb3cgdG8gZGVzaWduIHByb2JsZW1zIGluIHdheXMgdGhhdCBtYWtlIHRoZW0gZWFzaWVyIHRvIHRlc3QgYW5kIGRlYnVnPwoKVGhlIGtleSB0byBkb2luZyB0aGlzIGlzIGJyZWFrLSBpbmcgdGhlIHByb2dyYW0gdXAgaW50byBzZXBhcmF0ZSBjb21wb25lbnRzIHRoYXQgY2FuIGJlIGltcGxlbWVudGVkLCB0ZXN0ZWQsIGFuZCBkZWJ1Z2dlZCBpbmRlcGVuZGVudGx5IG9mIG90aGVyIGNvbXBvbmVudHMuCgojIyA2LjEgVGVzdGluZwoKIyMjIFdoYXQgaXMgdGhlIG1vc3QgaW1wb3J0YW50IHRoaW5nIHRvIHNheSBhYm91dCB0ZXN0aW5nPwoKVGhlIG1vc3QgaW1wb3J0YW50IHRoaW5nIHRvIHNheSBhYm91dCB0ZXN0aW5nIGlzIHRoYXQgaXRzIHB1cnBvc2UgaXMgdG8gc2hvdyB0aGF0IGJ1Z3MgZXhpc3QsIG5vdCB0byBzaG93IHRoYXQgYSBwcm9ncmFtIGlzIGJ1Zy1mcmVlLiBUbyBxdW90ZSBFZHNnZXIgRGlqa3N0cmEsIOKAnFByb2dyYW0gdGVzdGluZyBjYW4gYmUgdXNlZCB0byBzaG93IHRoZSBwcmVzZW5jZSBvZiBidWdzLCBidXQgbmV2ZXIgdG8gc2hvdyB0aGVpciBhYnNlbmNlIeKAnTM5IE9yLCBhcyBBbGJlcnQgRWluc3RlaW4gcmVwdXRlZGx5IHNhaWQsIOKAnE5vIGFtb3VudCBvZiBleHBlcmktIG1lbnRhdGlvbiBjYW4gZXZlciBwcm92ZSBtZSByaWdodDsgYSBzaW5nbGUgZXhwZXJpbWVudCBjYW4gcHJvdmUgbWUgd3Jvbmcu4oCdCgojIyMgV2hhdCBpcyB0aGUga2V5IHRvIHRlc3Rpbmc/CgpUaGUga2V5IHRvIHRlc3RpbmcgaXMgZmluZGluZyBhIGNvbGxlY3Rpb24gb2YgaW5wdXRzLCBjYWxsZWQgYSAqKnRlc3Qgc3VpdGUqKiwgdGhhdCBoYXMgYSBoaWdoIGxpa2VsaWhvb2Qgb2YgcmV2ZWFsaW5nIGJ1Z3MsIHlldCBkb2VzIG5vdCB0YWtlIHRvbyBsb25nIHRvIHJ1bi4gVGhlIGtleSB0byBkb2luZyB0aGlzIGlzIHBhcnRpdGlvbmluZyB0aGUgc3BhY2Ugb2YgYWxsIHBvc3NpYmxlIGlucHV0cyBpbnRvIHN1YnNldHMgdGhhdCBwcm92aWRlIGVxdWl2YWxlbnQgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGNvcnJlY3RuZXNzIG9mIHRoZSBwcm9ncmFtLCBhbmQgdGhlbiBjb24tIHN0cnVjdGluZyBhIHRlc3Qgc3VpdGUgdGhhdCBjb250YWlucyBhdCBsZWFzdCBvbmUgaW5wdXQgZnJvbSBlYWNoIHBhcnRpdGlvbi4gKFVzdWFsbHksIGNvbnN0cnVjdGluZyBzdWNoIGEgdGVzdCBzdWl0ZSBpcyBub3QgYWN0dWFsbHkgcG9zc2libGUuIFRoaW5rIG9mIHRoaXMgYXMgYW4gdW5hY2hpZXZhYmxlIGlkZWFsLikgCgojIyMgSG93IHRvIHBhcnRpdGlvbiB0aGUgc2V0IG9mIHBvc3NpYmxlIGlucHV0cz8KCkEgKipwYXJ0aXRpb24qKiBvZiBhIHNldCBkaXZpZGVzIHRoYXQgc2V0IGludG8gYSBjb2xsZWN0aW9uIG9mIHN1YnNldHMgc3VjaCB0aGF0IGVhY2ggZWxlbWVudCBvZiB0aGUgb3JpZ2luYWwgc2V0IGJlbG9uZ3MgdG8gZXhhY3RseSBvbmUgb2YgdGhlIHN1YnNldHMuIElmIG9uZSB0ZXN0ZWQgdGhlIGltcGxlbWVudGF0aW9uIG9uIGF0IGxlYXN0IG9uZSB2YWx1ZSBmcm9tIGVhY2ggb2YgdGhlc2Ugc3Vic2V0cywgdGhlcmUgd291bGQgYmUgcmVhc29uYWJsZSBwcm9iYWJpbGl0eSAoYnV0IG5vIGd1YXJhbnRlZSkgb2YgZXhwb3NpbmcgYSBidWcgaWYgb25lIGV4aXN0cy4KCkZvciBtb3N0IHByb2dyYW1zLCBmaW5kaW5nIGEgZ29vZCBwYXJ0aXRpb25pbmcgb2YgdGhlIGlucHV0cyBpcyBmYXIgZWFzaWVyIHNhaWQgdGhhbiBkb25lLiBUeXBpY2FsbHksIHBlb3BsZSByZWx5IG9uIGhldXJpc3RpY3NbXmhldXJpc3RpY3NdIGJhc2VkIG9uIGV4cGxvcmluZyBkaWZmZXJlbnQgcGF0aHMgdGhyb3VnaCBzb21lIGNvbWJpbmF0aW9uIG9mIHRoZSBjb2RlIGFuZCB0aGUgc3BlY2lmaWNhdGlvbnMuIEhldXJpc3RpY3MgYmFzZWQgb24gZXhwbG9yaW5nIHBhdGhzIHRocm91Z2ggdGhlIGNvZGUgZmFsbCBpbnRvIGEgY2xhc3MgY2FsbGVkICoqZ2xhc3MtYm94IHRlc3RpbmcqKi4gSGV1cmlzdGljcyBiYXNlZCBvbiBleHBsb3JpbmcgcGF0aHMgdGhyb3VnaCB0aGUgc3BlY2lmaWNhdGlvbiBmYWxsIGludG8gYSBjbGFzcyBjYWxsZWQgKipibGFjay1ib3ggdGVzdGluZyoqLgoKW15oZXVyaXN0aWNzXTogaGV1cmlzdGljczogW0NvbXB1dGluZ10gcHJvY2VlZGluZyB0byBhIHNvbHV0aW9uIGJ5IHRyaWFsIGFuZCBlcnJvciBvciBieSBydWxlcyB0aGF0IGFyZSBvbmx5IGxvb3NlbHkgZGVmaW5lZC4KCiMjIyBXaGF0IGFyZSB0aGUgcG9zaXRpdmUgZmVhdHVyZXMgb2YgdGhlIGluZGVwZW5kZW5jZSBvZiBibGFjay1ib3ggdGVzdGluZz8KCjEuIEl0IHJlZHVjZXMgdGhlIGxpa2VsaWhvb2Qgb2YgZ2VuZXJhdGluZyB0ZXN0IHN1aXRlcyB0aGF0IGV4aGliLSBpdCBtaXN0YWtlcyB0aGF0IGFyZSBjb3JyZWxhdGVkIHdpdGggbWlzdGFrZXMgaW4gdGhlIGNvZGUuCjEuIEl0IGlzIHJvYnVzdCB3aXRoIHJlc3BlY3QgdG8gaW1wbGVtZW50YXRpb24gY2hhbmdlcy4KCiMjIyBXaGF0IGJvdW5kYXJ5IGNvbmRpdGlvbiBzaG91bGQgYmUgdGVzdGVkPwoKV2hlbiBsb29raW5nIGF0IGxpc3RzLCB0aGlzIG9mdGVuIG1lYW5zIGxvb2tpbmcgYXQgdGhlIGVtcHR5IGxpc3QsIGEgbGlzdCB3aXRoIGV4YWN0bHkgb25lIGVsZW1lbnQsIGFuZCBhIGxpc3QgY29uLSB0YWluaW5nIGxpc3RzLiBXaGVuIGRlYWxpbmcgd2l0aCBudW1iZXJzLCBpdCB0eXBpY2FsbHkgbWVhbnMgbG9va2luZyBhdCB2ZXJ5IHNtYWxsIGFuZCB2ZXJ5IGxhcmdlIHZhbHVlcyBhcyB3ZWxsIGFzIOKAnHR5cGljYWzigJ0gdmFsdWVzLgoKRm9yIHNxcnQsIGZvciBleGFtcGxlLCBpdCBtaWdodCBtYWtlIHNlbnNlIHRvIHRyeSB2YWx1ZXMgb2YgeCBhbmQgZXBzaWxvbiBzaW1pbGFyIHRvIHRob3NlIGluIGhlcmU6Cgp8ICAgICAgWCAgICAgIHwgICBFcHNpbG9uICAgfAp8IDotLS0tLS0tLS06IHwgOi0tLS0tLS0tLTogfAp8ICAgICAwLjAgICAgIHwgICAwLjAwMDEgICAgfAp8ICAgIDI1LjAgICAgIHwgICAwLjAwMDEgICAgfAp8ICAgICAwLjUgICAgIHwgICAwLjAwMDEgICAgfAp8ICAgICAyLjAgICAgIHwgICAwLjAwMDEgICAgfAp8ICAgICAyLjAgICAgIHwgMS4wLzIuMCoqNjQgfAp8IDEuMC8yLjAqKjY0IHwgMS4wLzIuMCoqNjQgfAp8ICAyLjAqKjY0LjAgIHwgMS4wLzIuMCoqNjQgfAp8IDEuMC8yLjAqKjY0IHwgIDIuMCoqNjQuMCAgfAp8ICAyLjAqKjY0LjAgIHwgIDIuMCoqNjQuMCAgfAoKQW5vdGhlciBpbXBvcnRhbnQgYm91bmRhcnkgY29uZGl0aW9uIHRvIHRoaW5rIGFib3V0IGlzIGFsaWFzaW5nLiBDb25zaWRlciwgZm9yIGV4YW1wbGUsIHRoZSBjb2RlCgpgYGB7cHl0aG9ufQpkZWYgY29weShMMSwgTDIpOgogICAgIiIiIEFzc3VtZXMgTDEsIEwyIGFyZSBsaXN0cwogICAgICAgIE11dGF0ZXMgTDIgdG8gYmUgYSBjb3B5IG9mIEwxIiIiCiAgICB3aGlsZSBsZW4oTDIpID4gMDogI3JlbW92ZSBhbGwgZWxlbWVudHMgZnJvbSBMMgogICAgICAgIEwyLnBvcCgpICNyZW1vdmUgbGFzdCBlbGVtZW50IG9mIEwyCiAgICBmb3IgZSBpbiBMMTogI2FwcGVuZCBMMSdzIGVsZW1lbnRzIHRvIGluaXRpYWxseSBlbXB0eSBMMgogICAgICAgIEwyLmFwcGVuZChlKQogICAgICAgIApMID0gWzEsIDIsIDNdCmNvcHkoTCwgTCkKcHJpbnQoTCkKYGBgCgoKIyMjIElmIGFueSBvZiB0aGVzZSB0ZXN0cyBmYWlsLCBzb21ldGhpbmcgbmVlZHMgdG8gYmUgZml4ZWQuIFdoZXJlIGRvIHRob3NlICJzb21ldGhpbmciIGxpZT8KClBlcmhhcHMgdGhlcmUgaXMgYSBidWcgaW4gdGhlIGNvZGUgdGhhdCBuZWVkcyB0byBiZSBmaXhlZCwgb3IgcGVyaGFwcyB0aGUgc3BlY2lmaWNhdGlvbiBuZWVkcyB0byBiZSBjaGFuZ2VkIHNvIHRoYXQgaXQgaXMgZWFzaWVyIHRvIG1lZXQuIEl0IG1pZ2h0LCBmb3IgZXhhbXBsZSwgYmUgdW5yZWFzb25hYmxlIHRvIGV4cGVjdCB0byBmaW5kIGFuIGFwcHJveGltYXRpb24gb2YgYSBzcXVhcmUgcm9vdCB3aGVuIGVwc2lsb24gaXMgcmlkaWN1bG91c2x5IHNtYWxsLgoKIyMjIFdoeSBpdCBpcyByYXJlbHkgc3VmZmljaWVudCB0byBkbyBibGFjay1ib3ggdGVzdGluZz8KCldpdGhvdXQgbG9va2luZyBhdCB0aGUgaW50ZXJuYWwgc3RydWN0dXJlIG9mIHRoZSBjb2RlLCBpdCBpcyBpbXBvc3NpYmxlIHRvIGtub3cgd2hpY2ggdGVzdCBjYXNlcyBhcmUgbGlrZWx5IHRvIHByb3ZpZGUgbmV3IGluZm9ybWF0aW9uLiBDb25zaWRlciB0aGUgdHJpdmlhbCBleGFtcGxlOgoKYGBge3B5dGhvbn0KZGVmIGlzUHJpbWUoeCk6CiAgICAiIiIgQXNzdW1lcyB4IGlzIGEgbm9ubmVnYXRpdmUgaW50CiAgICAgICAgUmV0dXJucyBUcnVlIGlmIHggaXMgcHJpbWU7IEZhbHNlIG90aGVyd2lzZSIiIiAKICAgIGlmIHggPD0gMjoKICAgICAgICByZXR1cm4gRmFsc2UKICAgIGZvciBpIGluIHJhbmdlKDIsIHgpOgogICAgICAgIGlmIHglaSA9PSAwOiAKICAgICAgICAgICAgcmV0dXJuIEZhbHNlCiAgICByZXR1cm4gVHJ1ZQpgYGAKCg==