Идиома pImpl значительно упрощает тестирование. Достаточно странно видеть набор ответов на тему «не проверяйте реализацию», чтобы мотивировать ответы так долго после ОП.
В обычном C ++, не основанном на pimpl, у вас есть класс с открытыми и закрытыми полями. Публичные поля легко проверить, частные поля несколько утомительнее. Разделение между публичным и частным очень важно, поскольку оно уменьшает ширину API и обычно облегчает последующие изменения.
При использовании этой идиомы доступна лучшая опция. Вы можете иметь точно такой же «публичный» интерфейс, как и с одним классом, но теперь есть только одно приватное поле, содержащее некоторый указатель, например
class my_things
{
public:
my_things();
~my_things();
void do_something_important(int);
int also_this();
private:
struct my_things_real;
std::unique_ptr<my_things_real> state;
};
Ожидается, что класс my_things_real будет виден в том же исходном файле, что и деструктор видимого извне класса, но не в заголовке. Он не является частью общедоступного интерфейса, поэтому все поля могут быть общедоступными.
void my_things::do_something_important(int x) { state->doit(x); } // etc
class my_things_real // I'd probably write 'struct'
{
public:
int value;
void doit(int x) { value = x; }
int getit() { return value; }
};
Затем пишутся юнит-тесты против реального класса. Тестируйте столько, сколько вам нужно. Я намеренно назвал это «реальным», а не «импл», чтобы убедиться, что его не принимают за простую деталь реализации.
Тестирование этого класса очень просто, поскольку все поля являются открытыми. Внешний интерфейс очень маленький, так как он определяется другим классом. Слой перевода тонкой пластины трудно ошибиться, но вы все равно можете тестировать и через внешний API. Это явный выигрыш от более значительного разделения интерфейса и реализации.
На неопределенно связанном замечании мне кажется абсурдным, что так много в целом непротиворечивых людей выступают за пропуск модульного тестирования для всего, что недоступно через внешний API. Функции самого низкого уровня вряд ли защищены от ошибок программиста. Проверка того, что API пригоден для использования, важна и ортогональна для проверки правильности деталей реализации.