Модульное тестирование с -fno-access-control - PullRequest
5 голосов
/ 14 мая 2009

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

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

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

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

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

Ответы [ 4 ]

6 голосов
/ 14 мая 2009

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

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

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

2 голосов
/ 14 мая 2009

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

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

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

1 голос
/ 04 февраля 2011

Ух ты, это прекрасно сработало для меня.

Я был обеспокоен, что это не так, поскольку моим юнит-тестам нужен доступ к закрытым членам классов, созданных в других динамических библиотеках (.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);
}
0 голосов
/ 14 мая 2009

Да, довольно полезная опция GCC, но MSVC не имеет ничего подобного.
Вместо этого мы используем макросы:

#define class struct
#define private public
#define protected public

^ _ ^

...