2008-10-16 16 views
23

Necesitamos escribir pruebas unitarias para una aplicación wxWidgets usando Google Test Framework. El problema es que wxWidgets utiliza la macro IMPLEMENT_APP (MyApp) para inicializar e ingresar el bucle principal de la aplicación. Esta macro crea varias funciones incluyendo int main(). El marco de prueba de google también usa definiciones de macro para cada prueba.wxWidgets: cómo inicializar wxApp sin usar macros y sin ingresar el bucle principal de la aplicación?

Uno de los problemas es que no es posible llamar a la macro wxWidgets desde dentro de la macro de prueba, porque el primero crea funciones .. Por lo tanto, 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 a 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 que se requiere para ejecutar una aplicación wx, sin realmente ejecutarla, entonces ¿podemos probar partes de ella?

Respuesta

4

Usted desea utilizar la función:

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

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

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

Tendrá que utilizar

void wxEntryCleanup() 

cuando haya terminado.

+0

En realidad, esto no funciona. La aplicación aún no se ha inicializado –

+0

¿Puede ser más específico sobre qué significa "no inicializado"? Si lee el código fuente, verá que wxEntry realmente no hace mucho más que invocar wxEntryStart() y luego llamar a "OnInit()" y "OnRun()". Creo que querrías llamar a OnInit() manualmente en tus pruebas. – kbluck

+0

OK, eso es algo que eché de menos - OnInit(). Lo intentaré. –

-1

Usted podría cambiar la situación:

inicializar y comenzar la aplicación wxPython incluyendo el bucle principal, a continuación, ejecutar las pruebas de unidad dentro de la aplicación. Creo que hay una función llamada en la entrada del bucle principal, después de que todo lo de init haya terminado.

+0

El objetivo es probar la aplicación con UT, no UT con aplicación –

+0

A menos que encuentre una manera de hacer la inicialización completa (y hasta ahora nadie sugirió una solución viable) El objetivo que se declarado en un comentario anterior se puede lograr de esta manera. Ya he hecho cosas similares en wxPython. – Ber

+0

+1 de mí, así es como hice mis pruebas en wxWidgets después de tratar de resolver el problema yo mismo. – SteveL

-2

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

Desde < wxWidgets' dir > \ 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

Esta macro se reduce a las dos primeras líneas de código en la pregunta. El problema es que antes de llamar a wxEntry() hay algunas partes de wxApp que aún no se han inicializado. wxEntry() ingresa al bucle de la aplicación y el control pasa a wxWidgets. Me gustaría iniciar el wxApp, sin ejecutarlo. –

10

Acabo de atravesar esto yo mismo con 2.8.10. La magia es la siguiente:

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

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

No estoy seguro de cómo espera hacer las pruebas unitarias de su aplicación sin ingresar al enlace principal, ya que muchos componentes wxWidgets requieren la entrega de eventos para funcionar. El enfoque habitual sería ejecutar pruebas unitarias luego de ingresar al ciclo principal.

1

Parece que hacer las pruebas en la función wxApp :: OnRun() quizás funcione. Aquí está el 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(); 
} 
2
IMPLEMENT_APP_NO_MAIN(MyApp); 
IMPLEMENT_WX_THEME_SUPPORT; 

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

    return 0; 
} 
Cuestiones relacionadas