2008-09-17 9 views
3

Учитывая такой код:Как проверить порядок вызова функции

class ToBeTested { 
public: 
    void doForEach() { 
    for (vector<Contained>::iterator it = m_contained.begin(); it != m_contained.end(); it++) { 
     doOnce(*it); 
     doTwice(*it); 
     doTwice(*it); 
    } 
    } 
    void doOnce(Contained & c) { 
    // do something 
    } 
    void doTwice(Contained & c) { 
    // do something 
    } 

    // other methods 
private: 
    vector<Contained> m_contained; 
} 

Я хочу, чтобы проверить, что если я заполняю вектор с 3-мя значениями мои функции будут вызываться в правильном порядке и количестве. Например, мой тест может выглядеть примерно так:

tobeTested.AddContained(one); 
tobeTested.AddContained(two); 
tobeTested.AddContained(three); 

BEGIN_PROC_TEST() 
SHOULD_BE_CALLED(doOnce, 1) 
SHOULD_BE_CALLED(doTwice, 2) 
SHOULD_BE_CALLED(doOnce, 1) 
SHOULD_BE_CALLED(doTwice, 2) 
SHOULD_BE_CALLED(doOnce, 1) 
SHOULD_BE_CALLED(doTwice, 2) 

tobeTested.doForEach() 
END_PROC_TEST() 

Как вы рекомендуете это проверять? Существуют ли какие-либо средства для этого с помощью фреймворков CppUnit или GoogleTest? Может быть, какая-то другая единичная тестовая среда позволяет выполнять такие тесты?

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

UPD: Я пытаюсь проверить не только состояния самолета Ан объектов, но и порядок выполнения, чтобы избежать проблем с производительностью на ранних этапах (и вообще я хочу знать, что мой код выполняется точно так, как я ожидал).

ответ

1

Если вы заинтересованы в производительности, я рекомендую вам написать тест, который измеряет производительность.

Проверьте текущее время, запустите метод, о котором вы беспокоитесь, затем проверьте время снова. Утвердите, что общее время, затраченное на меньшее, меньше некоторого значения.

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

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

  1. Переместить их в другой класс, назовем его коллаборатора
  2. Добавить экземпляр этого другого класса к классу ToBeTested
  3. Используйте насмешливые рамки для установки переменного экземпляра на ToBeTested быть макетом класса Collborator
  4. вызова метода тестируемого
  5. Используйте свою насмешливую структуру, чтобы утверждать, что методы были вызваны на ваш макет в правильном порядке.

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

+0

благодарит за полезные ответы. теперь я знаю, что мой путь - насмешливые рамки. относительно времени: во-первых, я не знаю целевого времени для сравнения. во-вторых: неожиданный порядок выполнения на ранней стадии, может привести к неправильным результатам позже, с добавлением других классов к модели, так почему я должен ждать? – cos 2008-09-17 02:30:29

0

Некоторые издевательские рамки позволяют настраивать упорядоченные ожидания, что позволяет точно сказать, какую функцию вы ожидаете в определенном порядке. Например, RhinoMocks для C# позволяет это.

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

1

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

Однако, как правило, вы не проверяете, что один метод вызывает некоторые вызовы для других методов в одном классе ... зачем вам?

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

Я мог бы предоставить дополнительную помощь, но я не думаю, что ваш пример согласован (где реализация метода AddContained?).

+0

«пример согласован» - AddContained() относится к «// другим методам» :) «общедоступное состояние» - ненужные вызовы могут не влиять на состояние объекта, но могут замедлить выполнение. «... почему бы вам?» - Вы хотите проверить вызов функции? Это было бы здорово. – cos 2008-09-17 01:19:15

0

http://msdn.microsoft.com/en-au/magazine/cc301356.aspx

Это хорошая статья о Context Bound Objects. Он содержит некоторые настолько продвинутые вещи, но если вы не ленивы и действительно хотите понять такие вещи, это будет действительно полезно.

В конце концов вы будете иметь возможность написать что-то вроде: [CallTracingAttribute()] общественного класса TraceMe: ContextBoundObject {...}

+0

спасибо за ответ. Я чувствую, что .NET с отражением может помочь, но я использую простой cpp (иногда даже без RTTI). – cos 2008-09-17 02:25:09

1

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

+0

Порядок и количество вызовов не могут влиять на внутреннее состояние, а просто приводят к медленному выполнению в будущем. это может быть проверено позже, конечно, с помощью тестов производительности, но это может быть слишком поздно и сложно – cos 2008-09-17 01:28:48

0

Вы можете использовать рамки отладки ACE (или аналогичных), а в вашем тесте настройте объект отладки на поток в файл.Тогда вам просто нужно проверить файл.

+0

Я не вижу существенных отличий от вызова trace() в моих функциях для stdout или stderr, а затем проверки этих журналов. Я хочу выполнить такой тест автоматически после каждой сборки, например, вместе с другими модульными тестами. – cos 2008-09-17 01:34:28

Смежные вопросы