wxWidgets: Como inicializar wxApp sem usar macros e sem entrar no loop principal da aplicação?

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

Pergunta

Precisamos de escrever testes de unidade para um wxWidgets aplicativo usando Google framework de teste . O problema é que wxWidgets usa a macro IMPLEMENT_APP (MyApp) para inicializar e entrar no ciclo principal do aplicativo. Esta macro cria várias funções, incluindo int main () . O framework de teste do Google também usa definições de macro para cada teste.

Um dos problemas é que não é possível chamar os wxWidgets macro de dentro do macro teste, porque o primeiro cria funções .. Então, descobrimos que poderíamos substituir a macro com o seguinte código:

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

Isso é um bom substituto, mas wxEntry () chamada entra no loop de aplicação original. Se não chamar wxEntry () ainda existem algumas partes do aplicativo não inicializado.

A questão é como inicializar tudo o necessário para uma wxApp a prazo, sem realmente executá-lo, por isso somos capazes de porções de teste de unidade de ele?

Foi útil?

Solução

Você quer usar a função:

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

em vez de wxEntry. Ele não chama OnInit do seu aplicativo () ou executar o loop principal.

Você pode chamar wxTheApp->CallOnInit() para invocar OnInit () quando necessário em seus testes.

Você vai precisar usar

void wxEntryCleanup()

quando tiver terminado.

Outras dicas

Apenas passado por isso mesmo com 2.8.10. A magia é esta:

// 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();

Você pode apenas criar uma instância wxApp vez de derivar sua própria classe usando a técnica acima.

Eu não sei como você espera fazer o teste de unidade de sua aplicação, sem entrar no mainloop como componentes muitas wxWidgets requerem a entrega de eventos para a função. A abordagem usual seria para executar testes de unidade depois de entrar no circuito principal.

IMPLEMENT_APP_NO_MAIN(MyApp);
IMPLEMENT_WX_THEME_SUPPORT;

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

    return 0;
}

Parece que fazer os testes na função wxApp :: OnRun () pode, talvez, o trabalho. código de aqui que testa o título de uma caixa de diálogo com 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(); 
}

Você poderia reverter a situação:

Inicializar e iniciar o aplicativo wxPython incluindo o loop principal, em seguida, executar os testes de unidade de dentro do aplicativo. Acho que há uma função chamada na entrada loop principal, depois de todas as coisas init é feito.

Você já tentou a macro IMPLEMENT_APP_NO_MAIN? O comentário acima, desde a definição de macro sugere que ele pode fazer o que você precisa que ele.

De \ 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()); }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top