wxWidgets ( текстовые файлы ):Как инициализировать wxApp без использования макросов и без входа в основной цикл приложения?
-
03-07-2019 - |
Вопрос
Нам нужно написать модульные тесты для wxWidgets ( текстовые файлы ) приложение, использующее Тестовый фреймворк Google.Проблема в том, что wxWidgets ( текстовые файлы ) использует макрос IMPLEMENT_APP (мое приложение) для инициализации и входа в основной цикл приложения.Этот макрос создает несколько функций, включая int main().Платформа Google Test Framework также использует определения макросов для каждого теста.
Одна из проблем заключается в том, что невозможно вызвать макрос wxWidgets из тестового макроса, потому что первый создает функции..Итак, мы обнаружили, что можем заменить макрос следующим кодом:
wxApp* pApp = new MyApp();
wxApp::SetInstance(pApp);
wxEntry(argc, argv);
Это хорошая замена, но вызов wxEntry() входит в исходный цикл приложения.Если мы не вызовем wxEntry(), некоторые части приложения все еще не инициализированы.
Вопрос в том, как инициализировать все, что требуется для запуска wxApp, фактически не запуская его, чтобы мы могли частично тестировать его?
Решение
Вы хотите использовать эту функцию:
bool wxEntryStart(int& argc, wxChar **argv)
вместо wxEntry.Он не вызывает OnInit() вашего приложения и не запускает основной цикл.
Ты можешь позвонить wxTheApp->CallOnInit()
вызывать OnInit(), когда это необходимо в ваших тестах.
Вам нужно будет использовать
void wxEntryCleanup()
когда ты закончишь.
Другие советы
Только что сам прошел через это с 2.8.10.Магия заключается в следующем:
// 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();
Вы можете просто создать экземпляр wxApp вместо того, чтобы создавать свой собственный класс, используя описанную выше технику.
Я не уверен, как вы собираетесь проводить модульное тестирование вашего приложения без входа в mainloop, поскольку многие компоненты wxWidgets требуют доставки событий для функционирования.Обычным подходом было бы запускать модульные тесты после входа в основной цикл.
IMPLEMENT_APP_NO_MAIN(MyApp);
IMPLEMENT_WX_THEME_SUPPORT;
int main(int argc, char *argv[])
{
wxEntryStart( argc, argv );
wxTheApp->CallOnInit();
wxTheApp->OnRun();
return 0;
}
Похоже, что выполнение тестов в функции wxApp:: OnRun (), возможно, сработает.Вот код, который проверяет заголовок диалогового окна с помощью 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(); }
Возможно, вы могли бы изменить ситуацию к лучшему:
Инициализируйте и запустите приложение wxPython, включая основной цикл, затем запустите модульные тесты из приложения.Я думаю, что есть функция, вызываемая при входе в основной цикл, после того, как все инициализации выполнены.
Вы пробовали использовать IMPLEMENT_APP_NO_MAIN
макрос?Комментарий, приведенный над определением макроса, предполагает, что он может делать то, что вам нужно.
От <wxWidgets' source="" dir="">\включить\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()); }