Возможно ли в Qt модульное тестирование (доступ к) закрытых методов?

StackOverflow https://stackoverflow.com/questions/7394240

Вопрос

Я пишу модульные тесты для своего приложения, и теперь я наткнулся на класс, в котором я должен тестировать частные методы.Это может быть результатом плохого дизайна определенного класса, но я должен это сделать.Есть ли какой-нибудь способ в Qt вызывать частные методы, возможно, используя QMetaObject или что-то подобное?

Для модульного тестирования я использую QTestLib framework.

Это было полезно?

Решение

Правильный (читай раздражающий) ответ заключается в том, что вы не должны тестировать частные методы, это детали реализации ;-).

ОТОХ - думали ли вы об условном объявлении их защищенными / приватными в зависимости от того, участвуете ли вы в тестировании или нет, а затем расширении?Я использовал это, чтобы выпутаться из подобной передряги в прошлом.

#ifdef TESTING
// or maybe even public!
#define ACCESS protected
#else
#define ACCESS private
#endif

/* your class here */
class Foo {
ACCESS
    int fooeyness;
}

// or better yet, place this in a different file!
#ifdef TESTING
/*
    class which extends the tested class which has public accessors
*/
#endif

Другие советы

Решение 1, быстрое и простое:сделайте тестовый класс (классы) другом общедоступного.

class Foo {
   // ...
private:
   friend class FooTest;
};

Таким образом, ваш FooTest класс может получить доступ ко всем членам общедоступного класса.Однако таким образом вам нужно изменять исходный класс каждый раз, когда вы хотите получить доступ к личным данным из другого теста, и вы сливаете информацию о тестах в общедоступный API, и вы, возможно, открываете конфликты именования классов (что, если есть / другой / класс FooTest?), и так далее.


Решение 2, иначе говоря, правильно выполненное:не помещайте частные методы в открытый класс, а создайте закрытый класс с открытыми методами.

class Foo {
    // 
private:
    friend class FooPrivate;
    FooPrivate *d;
};

FooPrivate объявляется в своем собственном заголовке, который может быть не установлен или оставаться в include-privates / подкаталоге или что-то еще, т.Е.он остается в стороне при нормальном использовании.Таким образом, открытый класс остается чистым.

class FooPrivate {
public:
    // only public stuff in here;
    // and especially this:
    static FooPrivate *get(Foo *f) { return f->d; }
};

Затем тест включает в себя закрытый заголовок и вызовы FooPrivate::get(fooObj) получить экземпляр частного класса, а затем с удовольствием использовать его.

Я не согласен с «частными членами», являются деталями реализации «Менталитет, в мой взгляд, что примерно переводит на« тестирование только часть вашего кода ».

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

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

  1. Всегда объявляйте членов, которые вы хотите проверить как protected вместо private в вашем коде.
  2. Подкласс ваш класс в TestCode и просто сделайте необходимые вами селекторы или просто напишите тестовый код непосредственно в качестве членов в реализации этого подкласса.

    Примечание. Вы должны быть осторожны с классами, которые полагаются на сложные шаблоны по созданию геологоразведочных, чтобы убедиться, что вы их правильно построили (прочитайте: позвоните в конструктор исходного класса из подкласса CTOR).

Я нашел более удобный способ сделать это.Во-первых, все частные методы должны быть частными слотами. Затем вы создаете экземпляр класса:

Foo a;
.

Тогда мы можем использовать QmetaObject :: invokeMethod, чтобы вызвать любой слот, который имеет метод (публичный или частный).Так что, если мы хотим вызвать тест метода, мы можем сделать это так:

QMetaObject::invokeMethod(&a, "Test", Qt::DirectConnection);
.

Также мы можем получить возврат стоимости и отправлять аргументы ... На самом деле все ответили здесь: http://doc.qt.nokia.com/stable/qmetaObject.html#invokemethod

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

Ваш класс должен просто вести себя прямо снаружи.Если внесение стратегии реализации изменяется, ваш класс тестирования подразделения все еще одинаково.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top