wxWidgets: как инициализировать wxApp без использования макросов и без входа в основной цикл приложения? - PullRequest
23 голосов
/ 16 октября 2008

Нам нужно написать модульные тесты для wxWidgets приложения с использованием Google Test Framework . Проблема в том, что wxWidgets использует макрос IMPLEMENT_APP (MyApp) для инициализации и входа в основной цикл приложения. Этот макрос создает несколько функций, включая int main () . Каркас тестирования Google также использует определения макросов для каждого теста.

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

wxApp* pApp = new MyApp(); 
wxApp::SetInstance(pApp);
wxEntry(argc, argv);

Это хорошая замена, но вызов wxEntry () входит в исходный цикл приложения. Если мы не вызываем wxEntry (), некоторые части приложения все еще не инициализированы.

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

Ответы [ 6 ]

12 голосов
/ 28 мая 2009

Только что через это прошел сам 2.8.10. Волшебство таково:

// MyWxApp derives from wxApp
wxApp::SetInstance( new MyWxApp() );
wxEntryStart( argc, argv );
wxTheApp->OnInit();

// you can create top level-windows here or in OnInit()
...
// do your testing here

wxTheApp->OnRun();
wxTheApp->OnExit();
wxEntryCleanup();

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

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

5 голосов
/ 10 октября 2013
IMPLEMENT_APP_NO_MAIN(MyApp);
IMPLEMENT_WX_THEME_SUPPORT;

int main(int argc, char *argv[])
{
    wxEntryStart( argc, argv );
    wxTheApp->CallOnInit();
    wxTheApp->OnRun();

    return 0;
}
3 голосов
/ 17 октября 2008

Вы хотите использовать функцию:

bool wxEntryStart(int& argc, wxChar **argv)

вместо wxEntry. Он не вызывает OnInit () вашего приложения и не запускает основной цикл.

Вы можете вызвать wxTheApp->CallOnInit(), чтобы вызвать OnInit (), когда это необходимо в ваших тестах.

Вам нужно будет использовать

void wxEntryCleanup()

когда вы закончите.

1 голос
/ 15 апреля 2011

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

 
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif
#include  "wx/app.h"  // use square braces for wx includes: I made quotes to overcome issue in HTML render
#include  "wx/Frame.h"
#include "../CppUnitLite2\src/CppUnitLite2.h"
#include "../CppUnitLite2\src/TestResultStdErr.h" 
#include "../theAppToBeTested/MyDialog.h"
 TEST (MyFirstTest)
{
    // The "Hello World" of the test system
    int a = 102;
    CHECK_EQUAL (102, a);
}

 TEST (MySecondTest)
 {
    MyDialog dlg(NULL);   // instantiate a class derived from wxDialog
    CHECK_EQUAL ("HELLO", dlg.GetTitle()); // Expecting this to fail: title should be "MY DIALOG" 
 }

class MyApp: public wxApp
{
public:
    virtual bool OnInit();
    virtual int OnRun();
};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{   
    return true;
}

int MyApp::OnRun()
{
    fprintf(stderr, "====================== Running App Unit Tests =============================\n");
    if ( !wxApp::OnInit() )
        return false;

    TestResultStdErr result;
    TestRegistry::Instance().Run(result);   
    fprintf(stderr, "====================== Testing end: %ld errors =============================\n", result.FailureCount() );

    return result.FailureCount(); 
}
0 голосов
/ 17 октября 2008

Вы пробовали макрос IMPLEMENT_APP_NO_MAIN? Комментарий, приведенный выше определения макроса, предполагает, что он может делать то, что вам нужно.

Из <исходного каталога wxWidgets> \ include \ wx.h:

// Use this macro if you want to define your own main() or WinMain() function
// and call wxEntry() from there.
#define IMPLEMENT_APP_NO_MAIN(appname)                                      \
   wxAppConsole *wxCreateApp()                                             \
    {                                                                       \
        wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,         \
                                        "your program");                    \
        return new appname;                                                 \
    }                                                                       \
    wxAppInitializer                                                        \
        wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);        \
    DECLARE_APP(appname)                                                    \
    appname& wxGetApp() { return *wx_static_cast(appname*, wxApp::GetInstance()); }
0 голосов
/ 16 октября 2008

Вы можете изменить ситуацию:

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

...