wxWidgets: ¿Cómo inicializar wxApp sin usar macros y sin ingresar al bucle principal de la aplicación?

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

Pregunta

Necesitamos escribir pruebas unitarias para una aplicación wxWidgets usando Google Test Framework . El problema es que wxWidgets usa la macro IMPLEMENT_APP (MyApp) para inicializar e ingresar al bucle principal de la aplicación. Esta macro crea varias funciones, incluyendo int main () . El marco de prueba de Google también utiliza definiciones de macro para cada prueba.

Uno de los problemas es que no es posible llamar a la macro wxWidgets desde la macro de prueba, porque la primera crea funciones. Entonces, encontramos que podríamos reemplazar la macro con el siguiente código:

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

Es un buen reemplazo, pero la llamada wxEntry () ingresa al bucle de la aplicación original. Si no llamamos a wxEntry () todavía hay algunas partes de la aplicación no inicializadas.

La pregunta es cómo inicializar todo lo necesario para que se ejecute una wxApp, sin ejecutarlo realmente, de modo que podamos realizar pruebas unitarias de ella.

¿Fue útil?

Solución

Desea usar la función:

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

en lugar de wxEntry. No llama a OnInit () de su aplicación ni ejecuta el bucle principal.

Puede llamar a wxTheApp->CallOnInit() para invocar OnInit () cuando sea necesario en sus pruebas.

Tendrá que usar

void wxEntryCleanup()

cuando hayas terminado.

Otros consejos

Acabo de pasar por esto yo mismo con 2.8.10. La magia es 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();

Puede crear una instancia de wxApp en lugar de derivar su propia clase utilizando la técnica anterior.

No estoy seguro de cómo espera hacer una prueba unitaria de su aplicación sin ingresar al bucle principal, ya que muchos componentes de wxWidgets requieren la entrega de eventos para funcionar. El enfoque habitual sería ejecutar pruebas unitarias después de ingresar al bucle 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 hacer las pruebas en la función wxApp :: OnRun () puede funcionar. Aquí hay un código que prueba el título de un diálogo con 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(); 
}

Podría cambiar la situación:

Inicialice e inicie la aplicación wxPython, incluido el bucle principal, luego ejecute las pruebas unitarias desde la aplicación. Creo que hay una función llamada a la entrada del bucle principal, después de que todo el proceso de inicio se haya realizado.

¿Has probado la macro IMPLEMENT_APP_NO_MAIN? El comentario proporcionado arriba de la definición de macro sugiere que podría hacer lo que necesita.

De < directorio fuente de 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()); }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top