Black-box testing chooses inputs and expected outputs from the public specification without using the implementation's control structure. Equivalence class testing partitions the input space into classes expected to exercise similar specified behavior, then chooses representatives; boundary cases test where that behavior changes. For equal-range search, use these concrete representatives:
- Empty array:
([], 4)gives(0,0). - One entry, with the target below, equal, and above it:
([4],3),([4],4),([4],5)give(0,0),(0,1),(1,1). - An absent interior value:
([1,3,5],4)gives(2,2). - One interior match:
([1,3,5],3)gives(1,2). - A repeated interior block:
([1,3,3,3,5],3)gives(1,4). - A repeated block touching the left or right boundary:
([3,3,5],3)and([1,3,3],3)give(0,2)and(1,3). - Every entry equal:
([3,3,3],3)gives(0,3); targets two and four give(0,0)and(3,3). - Extreme keys:
([Int.MinValue,0,Int.MaxValue],Int.MaxValue)gives(2,3), and searching forInt.MinValuegives(0,1).
For each result independently check , the strict inequalities outside the returned interval, and equality inside it. Unsorted inputs violate the precondition; they are not ordinary members of the specified valid-input classes. Software testing supplies evidence about implementations, while the loop invariant proof explains correctness for every valid input.
Test-driven development interleaves three small steps: write a test expressing the next required behavior and observe that it fails, implement enough behavior to make it pass, then improve the code's structure while keeping the tests passing. The retained tests become a regression suite. For example, before implementing a book deletion, test that deleting an existing contact removes it and returns true; later add the absent-name case. Each test guides a small implementation step rather than waiting for a finished component.[ref]
Test-driven development in the Agile Alliance glossary. What is TDD?: interleaving unit tests, implementation and refactoring in a short cycle
Compared with a traditional write-the-component-then-test workflow, tests guide the design before each increment is implemented. This does not imply that all non-TDD testing is postponed until a whole product is finished, or that TDD eliminates broader integration testing.
The test-first behavioral core is naturally black-box testing: expected outcomes come from the operation's contract. Later tests can use internal control flow or representation cases, becoming white-box testing. Thus a complete practice can use a mixture, with mainly contract-based black-box tests driving the next behavior. The classification depends on how test cases are chosen, not on whether the programmer personally knows the implementation. Passing a finite suite is not a proof of universal correctness.
Test-driven development uses a repeating sequence: write a small test for the next required behaviour, observe it fail for the expected reason, add enough implementation to make it pass, and refactor while keeping the tests passing. The initial failure checks that the test can actually detect the absent behaviour. This differs from writing a whole implementation first and only then constructing tests for it; it also uses the tests to guide interface and design decisions rather than only to inspect a finished program.[ref]
Test-driven development in the Agile Alliance glossary. Meaning of TDD and its short test/implementation/refactoring cycle
A mixture of test-selection styles is possible; the defining test-first step is normally behaviour-driven. Choosing inputs and expected results from a public contract is black-box testing with respect to the implementation, even if the developer writes the test. Knowing the internal branches can then motivate white-box tests for boundary paths or exceptional cases. TDD specifies the order of development activities, not a rule forbidding either source of test cases. It therefore does not guarantee branch coverage, and passing the growing test suite is not a proof of correctness for untested inputs.