Black box testing is different from white box
testing. The kind of testing that you can perform on the code
determines, among other things, the complexity of the unit test.
A black box test (also known as a "functional test") is one in which
you feed it inputs and verify the outputs without being able to inspect
the internal workings. Furthermore, one doesn't usually have
information regarding:
- how the box handles errors
- whether your inputs are executing all code pathways
- how to modify your inputs so that all code pathways are executed
- dependencies on other resources
Black box testing limits your ability to thoroughly test the code,
primarily because the you don't know if you're testing all the code
pathways. Typically, a black box test only verifies that good inputs
result in good outputs (hence the term "functional test").
Classes are often implemented as black boxes, giving the "user" of
the class access only to the public methods and properties that the
implementer selected.
A white box provides the information necessary to test all the
possible pathways. This includes not only correct inputs, but
incorrect inputs, so that error handlers can be verified as well. This
provides several advantages:
- you know how the box handles errors
- you can usually write tests that verify all code pathways
- the unit test, being more complete, is a kind of documentation
guideline that the implementer can use when actually writing the code
in the box
- resource dependencies are known
- internal workings can be inspected
In the "write the test first" scenario, the ability to write
complete tests is vital information to the person that ultimately
implements the code, therefore a good white box unit test must ensure
that, at least conceptually, all the different pathways are exercised.
Another benefit of white box testing is the ability for the unit
test to inspect the internal state of the box after the test has been
run. This can be useful to ensure that internal information is in the
correct state, regardless of whether the output was correct. Even
though classes are often implemented with many private methods and
accessors. with C# and reflection, unit tests can be written which
provide you the ability to invoke private methods and set/inspect
private properties.