wxWidgets: come inizializzare wxApp senza usare le macro e senza entrare nel ciclo principale dell'applicazione?

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

Domanda

Dobbiamo scrivere test unitari per un'applicazione wxWidgets utilizzando Google Test Framework . Il problema è che wxWidgets utilizza la macro IMPLEMENT_APP (MyApp) per inizializzare ed entrare nel ciclo principale dell'applicazione. Questa macro crea diverse funzioni tra cui int main () . Il framework di test di google utilizza anche definizioni macro per ogni test.

Uno dei problemi è che non è possibile chiamare la macro wxWidgets all'interno della macro di test, perché la prima crea funzioni. Quindi, abbiamo scoperto che potremmo sostituire la macro con il seguente codice:

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

È un buon rimpiazzo, ma la chiamata wxEntry () entra nel ciclo dell'applicazione originale. Se non chiamiamo wxEntry () ci sono ancora alcune parti dell'applicazione non inizializzate.

La domanda è come inizializzare tutto ciò che è necessario per l'esecuzione di una wxApp, senza eseguirla effettivamente, quindi siamo in grado di testare parti di essa?

È stato utile?

Soluzione

Si desidera utilizzare la funzione:

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

invece di wxEntry. Non chiama OnInit () della tua app né esegue il ciclo principale.

Puoi chiamare wxTheApp->CallOnInit() per invocare OnInit () quando necessario nei tuoi test.

Dovrai utilizzare

void wxEntryCleanup()

quando hai finito.

Altri suggerimenti

Sono appena stato io stesso con 2.8.10. La magia è questa:

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

Puoi semplicemente creare un'istanza di wxApp anziché derivare la tua classe usando la tecnica sopra.

Non sono sicuro di come ti aspetti di eseguire test unitari della tua applicazione senza entrare nel mainloop poiché molti componenti di wxWidgets richiedono il funzionamento degli eventi. L'approccio usuale sarebbe quello di eseguire unit test dopo essere entrati nel ciclo principale.

IMPLEMENT_APP_NO_MAIN(MyApp);
IMPLEMENT_WX_THEME_SUPPORT;

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

    return 0;
}

Sembra che fare i test nella funzione wxApp :: OnRun () possa forse funzionare. Ecco il codice che testa il titolo di una finestra di dialogo 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(); 
}

Potresti invertire la situazione:

Inizializza e avvia l'app wxPython incluso il ciclo principale, quindi esegui i test unitari dall'app. Penso che ci sia una funzione chiamata sulla voce del ciclo principale, dopo che tutte le cose di init sono state completate.

Hai provato la IMPLEMENT_APP_NO_MAIN macro? Il commento fornito sopra la definizione di macro suggerisce che potrebbe fare ciò di cui hai bisogno.

Dalla directory di origine < 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()); }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top