TESTLOG

  !   Данная информация предназначена только только для IT-специалистов по системной интеграции модулей БИОСОФТ-М. (см. Руководства пользователя к программным продуктам)

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

       TESTLOG("LogName", "application state (change) at this point\n");

и

       TESTVAR("LogName", nMyValueToTrace);

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

Такую запись можно ставить где угодно в приложении, срабатывать будет только в режиме тестов

Потери в быстродействии:

Минимальные - на один if с локальным в модуле статическим флагом:

        #define TESTLOG(sLogName, sAppend) \
            { if (debug::IsInsideClassTests()) \
                debug::_internal_GTestLog((sLogName), (sAppend)); }

Замечаем что sAppendНЕ вычисляется вне тестов и может быть достаточно сложным сочетанием сложений строк.

Выключение

Логи можно выключать

class debug
{
    // Log can be disabled
    static void EnableTestLog(
            str sLogName);
    static void DisableTestLog(
            str sLogName);
    static bool IsTestLogEnabled(
            str sLogName);

или с более надежным восстановлением предыдущего состояния лог можно выключить в локальном блоке

    disablelog disablelogFlood("LogName");

пример: 

 Детали

Переадресация

Переадресация логов

Схема применения

Общий принцип:

void CMyClass::Foo()
{
    TESTLOG("", "We are in foo: " + this->GetSomeState());
    TESTVAR("", m_nXxxx);
}
 
void CMyClass::OnTestClass()
{
    Foo();
}

всё!

Естественно остается проблема не забывать проверять все ветвления кода:

void CMyClass::Foo(
        bool bBeGood)
{
    if (bBeGood)
    {
        TESTLOG("", "we got good results");
    }
    else
    {
        TESTLOG("", "we got bad errors!");
    }
}
 
void CMyClass::OnTestClass()
{
    // Normal execution
    {
        ref<CMyClass> rMe;
        rMe->Foo(true);
    }
 
    // Alternate execution
    {
        ref<CMyClass> rMe;
        rMe->Foo(false);
    }
}
Локализация логов библиотек

В библиотеках есть смысл предусматирвать имя лога для некоторых объектов как в PexContact:

class CPexApiBaseConnectionIfaceGp : public object
{
public:
...
 
    // Your application may want to redirect PexContact log into a different file
    str x_sPexApiLogName = "",
            auto(Get, Set),
            assert(true);
 
void CPexApiBaseConnectionImpl::OnLogPexApiCall(
        str sFunction,
        str sArguments,
        str sNotes)
{
    TESTLOG(
        x_sPexApiLogName,
        sFunction +
            " ----- \n" +
            sArguments +
            "\n // " +
            sNotes +
            "\n" "\n");
}
Замена глобальных системных операций на логи

Операции которые нельзя выполнять при тестах, но которые хочет вызывать приложение можно протоколировать так:

void sys::PostQuitMessage(int nRetCode)
{
    TESTVAR("", nRetCode);
 
    if (!debug::IsInsideClassTests())
    {
        ::PostQuitMessage(nRetCode);
    }
}

Это даст строчку в логе: "sys::PostQuitMessage: nRetCode: 1234"

см. Виртуализация LL инкапсуляторов в библиотеках для режима тестов

Эта категория в данный момент пуста.