wxWidgets: Comment initialiser wxApp sans utiliser de macros et sans entrer dans la boucle principale de l'application?

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

Question

Nous devons écrire des tests unitaires pour une application wxWidgets utilisant Google Test Framework . Le problème est que wxWidgets utilise la macro IMPLEMENT_APP (MyApp) pour initialiser et entrer dans la boucle principale de l'application. Cette macro crée plusieurs fonctions, notamment int main () . Le cadre de test de Google utilise également des définitions de macros pour chaque test.

Un des problèmes est qu’il n’est pas possible d’appeler la macro wxWidgets depuis la macro test, car la première crée des fonctions. Nous avons donc constaté que nous pouvions remplacer la macro par le code suivant:

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

C'est un bon remplacement, mais l'appel wxEntry () entre dans la boucle d'application initiale. Si nous n'appelons pas wxEntry (), certaines parties de l'application ne sont pas encore initialisées.

La question est de savoir comment initialiser tout ce qui est nécessaire à l’exécution d’une wxApp, sans l’exécuter réellement, afin que nous puissions en tester des parties?

Était-ce utile?

La solution

Vous souhaitez utiliser la fonction:

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

au lieu de wxEntry. Il n'appelle pas OnInit () de votre application ni n'exécute la boucle principale.

Vous pouvez appeler wxTheApp->CallOnInit() pour appeler OnInit () si nécessaire dans vos tests.

Vous aurez besoin d'utiliser

void wxEntryCleanup()

quand vous avez terminé.

Autres conseils

Je viens de passer par moi-même avec 2.8.10. La magie est la suivante:

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

Vous pouvez simplement créer une instance wxApp plutôt que dériver votre propre classe en utilisant la technique ci-dessus.

Je ne sais pas comment vous prévoyez de tester un peu votre application sans entrer dans mainloop car de nombreux composants wxWidgets nécessitent la livraison d'événements pour fonctionner. L’approche habituelle consiste à exécuter des tests unitaires après être entré dans la boucle 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;
}

On dirait que faire les tests dans la fonction wxApp :: OnRun () peut peut-être fonctionner. Voici le code qui teste le titre d'un dialogue avec 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(); 
}

Vous pourriez éventuellement renverser la situation:

Initialisez et démarrez l'application wxPython, y compris la boucle principale, puis exécutez les tests unitaires à partir de l'application. Je pense qu’il existe une fonction appelée entrée de la boucle principale, après que tout ce qui a été initié soit terminé.

Avez-vous essayé la macro IMPLEMENT_APP_NO_MAIN? Le commentaire fourni au-dessus de la définition de macro suggère qu'il peut faire ce que vous souhaitez.

De < répertoire source 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()); }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top