White-box testing focuses on testing implementation details of a component. Black-box testing sees a component as a black box accessible only via its API.
Both Lean and Agile software development focus on the value delivered to the customer (Lean calls everything else "waste").
Taking this seriously, white-box testing has no place in development as it doesn't represent any customer value:
Values are specified by requirements, requirements define contracts and contracts are implemented (for example) by interfaces:
interface MyUseCase {
int deliverySomeValue(String input);
}
class MyUseCaseImpl implements MyUseCase {
public int deliverySomeValue(String input) {
validate(input);
String valueAsString = transform(input);
return calculate(valueAsString);
}
void validate(String input) throws InvalidInputException { ... }
String transform(String input) { ... }
int calculate(String value) { ... }
}
If there is a test with all possible variants of input, testing whether the output is correct, it is actually not important whether any of methods validate
, transform
, calculate
doesn't work, as far as the result is right.
In fact, if there is a method which doesn't work and the result is still correct, the method is probably just unused or redundant - this should be addressed by refactoring, not testing.
A more difficult (to test) example could be:
interface MyRepository {
void save(String input);
}
The method save
doesn't return anything (void
), so the side effect cannot be tested just via this contract. Either I would expect a second method read
inside this or another interface. I can still use the read
method to create a black-box (integration) test.
Problematic could be this example:
interface EmailService {
void send(String to, String subject, String body);
}
The implementation is probably using some e-mail client and the naive approach to test it would be to create a mock of the client and verify, that a sending method was called. But what would be the point of such a test? Such a test brings me no guarantee that the e-mail was really sent. So, testing implementation doesn't help in this case as well. Probably only way how to test this would be to create a test mailbox and pull the sent e-mail with an e-mail client.
Are my assumptions correct? When does testing implementation make sense?