I have written a Command Line Interface, where the user has to construct an object basically by providing input to a bunch of questions. I have a hard time testing these functions as there is too much happening in there. Basically for every input, there is some validation and it will loop forever, print error message, asks again until the user enters a correct input.
A quite simplified case might look something like this:
// CommandLineInterface.h
void createPerson(DatabaseClass database, std::ostream ostream, std::istream istream)
// CommandLineInterface.cpp
namespace {
std::string getPersonNameInput(std::ostream ostream, std::istream istream) {
while(true) {
ostream << "Enter Person Name";
std::string name;
istream >> name;
if(someOtherFunctionToValidateName(name))
return name;
ostream << "Some error message";
}
}
}
void createPerson(DatabaseClass database, std::ostream ostream, std::istream istream) {
auto name = getPersonNameInput(ostream, istream);
auto age = getPersonAgeInput();
database.addPerson(Person { name, age });
}
So there is one function part of the public interface, which delegates input, error handling, validation to some helper function in an anonymous namespace.
I've learnt that you shouldn't test Implementation Details (such as functions in an anonymous namespace or private functions), but only test the public Interface, which will call these directly. But I also learnt to test only one noticeable end result per unit (the big end result here is the successful call of some function with the constructed object ... but there are loads of other noticeable results such as the error messages). This might be an indicator that my function does to many things and does not separate concerns.
One "fix" would be to put getPersonNameInput
in the header as well and make it part of the public interface and then unit test separately. I could then test createPerson
by mocking this function.
But that seems wrong to me as well. Making helper functions part of the public interface.
Is my design just bad here? If yes what would be ways to do improve the design, separate concerns, make it more testable? If no how would I test it then best? (Btw: I now that it's sometimes possible to test private functions or function in anonymous namespaces, but as said above you usually would not want to test these)
Thanks for help!