Я сталкиваюсь с неприятностью при кодировании моего использования модульных тестов UnitTest ++. Я задаюсь вопросом, как получить доступ к полям класса члена парламента, не занимающего официального поста в очевидном способе (или возможно любой путь...)
К настоящему времени у меня есть решение получить доступ к защищенным участникам, использующим приспособление класса, происходящее из класса под тестом. Следующий код показывает идею:
struct MyFixture : ClassUnderTest { };
TEST_FIXTURE(MyFixture, OneTest)
{
do_something();
CHECK(protected_field == true);
}
Тем не менее, я думаю, что это не очень чисто, потому что проблемы, связывающие наследование, могли возникнуть в некоторых конфигурациях и, так или иначе, просто защитили участников, может быть получен доступ и протестирован.
Я пытался объявить тестовые классы как друзья, но поскольку они создаются некоторым специальным способом UnitTest ++, мне не удалось сделать это все же.
У кого-либо есть какая-либо идея того, как завести тестовых друзей классов классы под тестом?
Есть ли другой способ приблизиться к этой проблеме более легким или другим способом?
Спасибо всем заранее.
Тестирование подразделения - это все о проверке ваших объектов через их общедоступный интерфейс. Тот факт, что это может быть трудно, поэтому писать , тестируемый код иногда упоминается как арт . Не каждый может сразу же написать тестичный код, поэтому люди изобрели XP приблизиться к тестам написания. Звучит нереально, работает в реальности.
Однако, если вы абсолютно необходимы для тестирования частных функций, вот список методов, которые я бы рассмотрел в порядке моих собственных предпочтений:
Частные переменные участника доступны через государственные сетры и Геттерс
Я бы порекомендовал сделать вас частным членом функцией нестатической функции не-члена в пространстве имен, который можно назвать E.g. Подробнее
или Внутренний
. Не объявляйте его в заголовочном файле, просто определите его в том же файле, где определены функции классных классов. Добавьте его декларацию в файл заголовка
MyClass_internal.h
в тестовом проекте устройства и проверьте его. Трудности вовлечены в значительной степени зависят от сложности вашей архитектуры.
Сделайте свой тестовый класс наследует от вашего тестируемого класса. Это не связано с изменением вашего кода много, но может потребовать использования многократного наследства, которое в некоторых местах даже запрещено.
Сделайте свой тест другу вашего тестируемого класса. Сложность зависит от того, что вы используете, которую вы используете. Скажем, с GTEST , которые я использую, это довольно сложно :)
Хак с переопределением публичных и частных должен быть вашим , в последнюю очередь , если все остальное не удалось. Несмотря на то, что я предпочел бы подумать об изменении дизайна до более поставленного вместо этого.
Есть один действительно безобразный, но удивительно полезный взлом, который я обычно использую для тестирования подразделения:
#define private public
#define protected public
#include "class_to_be_tested.h"
// and here, all class's methods and fields are public :P
Не используйте его для чего-либо еще, чем тестирование единиц!
Кроме того, этот метод имеет некоторые ограничения - во-первых, не все частное префиксировано с частным
. Во-вторых, один популярный компилятор покинул спецификатор доступа в символ линкера.
Другой, также не очень хороший метод - через кастинг. Вы создаете структуру, которая имеет одни и те же поля, но все публику, и отбрасывает его по указателю на вашу частную структуру. Это имеет недостаток, однако, что классы должны точно соответствовать:
class my_class
{
private:
char name[40];
char grade;
int age;
public:
//
}
struct my_class_hack
{
public:
char name[40];
char grade;
int age;
}
struct hack_it* my_class_hacked = (my_class_hack*)ptr;
... Вы можете получить неприятные сюрры, однако, если компилятор играет с вашим кодом, поэтому никогда не используйте это для кода производства.
Избегать, избегая тестирования частных вещей. Почему хочу проверить Private_field? Что становится ошибками, когда Private_field установлен на недопустимое значение? Можно ли проверить это неправильное поведение вместо того, чтобы утверждать на неправильном значении?
Другие варианты включают
PLAY с препроцессором, чтобы сделать его общественностью, когда код скомпилирован для тестирования подразделения
, извлечь личное поле и связанную с соответствующей логикой в новый класс, где он будет публичным, и делает Classundertest На этом новом классе.
Это был субъект горячей дебаты несколько лет назад, но общепринятый результат заключался в том, что вы должны проверить только внешне видимое поведение вашего класса, и так Доступ к его внутренним данным и поведению не требуется.
В то время как это может изначально звучать полезно, вы можете извлечь частные части вашего класса, которые вы хотите проверить на новые классы, внешнее поведение которых - это поведение, которое вы хотите проверить. Затем вы можете проверить эти классы обычным способом, и вы улучшите свой общий дизайн.
Я бы также выбрал #define Hack,
, но также поместил #define классовую структуру, чтобы получить неявные данные частного класса в открытый доступ.
Я должен не согласиться с Дмитрием:
1.) Это добавило бы интерфейсы в мой производственный код только для тестирования и нарушило бы мою инкапсуляцию. Я не хочу, чтобы клиенты снова имели доступ к моим приватным данным
2.), как показано в 1.). -> хорошая идея, если эти интерфейсы действительно открыты только для тестирования
3.) работает только в том случае, если доступ защищен, что так или иначе нарушает инкапсуляцию
4.) также означает модификацию моего производственного кода только для тестирования и даже создает связь между производственным кодом и моим тестовым кодом!!!!
5.) С вашей точки зрения, это правильно, у меня скорее уродливый тестирующий код, чем уродливый код производства :)
.