Модульное тестирование с -fno-access-control

Я видел много сумасшедших способов получить доступ к закрытым переменным при модульном тестировании. Самое умопомрачительное, что я видел, это #define private public.

Однако я никогда не видел, чтобы кто-то предлагал отключить частные переменные на уровне компилятора. Я всегда просто предполагал, что ты не можешь. Я жаловался многим разработчикам, что модульное тестирование было бы намного проще, если бы вы могли просто сказать компилятору отступить для этого одного файла.

Затем я натыкаюсь на параметр компилятора -fno-access-control GCC. Очевидно, что это идеальный способ модульного тестирования. Ваши оригинальные исходные файлы не изменены, нет добавленных друзей только для модульного теста, нет перекомпиляции с причудливой магией препроцессора. Просто нажмите переключатель «нет контроля доступа» при компиляции модульных тестов.

Я что-то упускаю? Я надеюсь, что это модульное тестирование серебряной пули?

Единственный недостаток, который я вижу, - это специфичный для GCC характер метода. Однако я предполагаю, что MSVS имеет аналогичный флаг.


person deft_code    schedule 13.05.2009    source источник
comment
Вы пробовали эту технику? Действительно ли это работает?   -  person UncleZeiv    schedule 14.05.2009
comment
Я составил простой тестовый пример, прежде чем опубликовать вопрос. Это действительно работает. Я не пробовал его ни с одним реальным или крупным проектом, но я предполагаю, что он отлично масштабируется.   -  person deft_code    schedule 14.05.2009
comment
-fno-access-control не работает с частным/защищенным наследованием. Я застрял с #defines.   -  person Xeverous    schedule 18.01.2018


Ответы (3)


Я бы сказал, что модульным тестам не нужен доступ к закрытым членам.

Как правило, модульные тесты предназначены для проверки интерфейса ваших классов, а не внутренней реализации. Таким образом, изменения во внутренних компонентах сломают тесты только в том случае, если интерфейс был скомпрометирован.

Взгляните на мой ответ на аналогичный вопрос и последующее обсуждение. Конечно, это спорная тема, но это мои 0,02 доллара.

person e.James    schedule 14.05.2009

Обычно я стараюсь использовать только общедоступный интерфейс своих классов в модульных тестах. Разработка/дизайн, управляемая тестированием, очень помогает здесь, поскольку результирующие классы, как правило, включают этот стиль модульного тестирования.

Однако иногда вам нужно разрешить модульному тесту доступ к закрытым членам, например, заменить содержимое Singleton экземпляром Fake. Для этого я использую защиту пакетов в Java и друзей в C++.

Некоторые люди, кажется, из кожи вон лезут, чтобы избежать друзей, но их следует использовать, когда это уместно, и их использование не ставит под угрозу дизайн. Они также являются декларативными и позволяют другим программистам знать, что вы делаете.

person iain    schedule 14.05.2009

Вау, это отлично сработало для меня.

Я был обеспокоен тем, что моим юнит-тестам нужен доступ к закрытым членам классов, созданным в других динамических библиотеках (файлы .so), но это именно то, что мне нужно.

Мне нужно только объявить флаг в моей компиляции модульного теста .so (каждый тест является .so). Даже в библиотеках, где определены объекты, к которым осуществляется доступ.

Мне это нужно для доступа к внутренним виджетам в форме для заполнения их значений; они не видны остальной части программы, но необходимы, если мои тесты должны представлять ввод данных пользователем. Просто подумал, что поделюсь примером использования для тех, кто скептиков с частным доступом :)

Также для полноты, вот мой класс формы, показывающий личное поле name_:

struct EditProduct : public widgets::BusinessObjForm<model::Product> {
public:
    EditProduct (WContainerWidget *parent=0);
protected:
    void fillObjFields();
private:
    // Consts
    static const double minPrice = 0.0;
    static const double maxPrice = 10000.0;
    // Fields
    WLineEdit* name_;
    WTextEdit* description_;
    WSpinBox* price_;
    WFileUpload* image_;
    // Methods
    bool validate();
    void saveProduct(const WString& message);
};

и вот начало моего модульного теста доступа к этому виджету:

BOOST_AUTO_TEST_CASE( form_save_test )
{
    EditProduct form(app.root());
    string txt = "this is a product";
    form.name_->setText(txt);
    BOOST_CHECK_EQUAL(form.name_->text(), txt);
}
person matiu    schedule 03.02.2011