I would like to create a test suite for my C wxWidgets app and am having trouble with figuring out how to test GUI components. The article in the docs about how to write unit tests is written from the perspective of augmenting the existing unit tests but doesn't address how to start new ones.
I was able to create a test suite using Catch (which appears to be the recommended approach) but am having trouble getting started on the GUI side.
On the non-GUI side, I created a test that looks like this
#include "catch.hpp"
#include "wx/wx.h"
TEST_CASE("wx", "[wx]") {
wxPoint p = wxPoint(10, 10);
REQUIRE(p.x == 10);
}
and a CMakeLists file that looks like this (just the relevant section):
set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wxWidgets/3rdparty/catch/include/)
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
# Make test executable
set(TEST_SOURCES
test.cpp
)
add_executable(tests ${TEST_SOURCES})
target_link_libraries(tests Catch ${wxWidgets_LIBRARIES})
And this worked just fine. So there is no problem linking against the wxWidgets libraries. I believe the problem is in creating a wxApp or an event loop. But I'm unsure of how to rectify that.
When I create a test that attempts to create a button (like in buttontest.cpp
that is suggested in the docs to use as an example), I receive a Segmentation violation signal
.
TEST_CASE("wx", "[wx]") {
wxButton* button = new wxButton(wxTheApp->GetTopWindow(), wxID_ANY, "wxButton");
wxYield();
}
Is there a place that demonstrates how to create GUI tests for wxWidgets from scratch instead of just adding to the wxWidgets tests themselves?
CodePudding user response:
Writing GUI tests is unfortunately not very simple, but can be done. The basic idea is that you use wxUIActionSimulator to trigger the user action that you want to test and then check that the UI has been updated as expected, which often involves calling wxYield()
to let all the events be processed. wxWidgets own GUI tests themselves show how to do it, but also that there are often some additional complications, just search for wxUIActionSimulator
under tests
to see many example of its use.
You can also look at this test to see an example of how you can use wxTEST_DIALOG
to test actions resulting in modal dialog, that would normally block the GUI and prevent your program from continuing.
CodePudding user response:
Please refrain from wiring Unit Tests for GUI, this goes completely against the rules of Clean Code. There are several reasons for it:
- Most of the methods in the various GUI frameworks (including) wxWidgets are private (and rightly so). And the rules of Clean Code say we should not write Unit Tests for private methods - they are simply implementation details.
- Developing GUI application requires seperation of View (GUI) Logic and Business (for example: data base access) Logic. The best way to do it is to use the MVVM design pattern.
Also, I would suggest a good book: Clean Code. Its THE book on Clean Code. It also touches on TDD - Test Driven Development - which is also an important subject strongly related to your question.
Following @VZ's comments, I wanna add the following differences between Unit Tests, Integration Tests, and End-to-End tests:
- Unit tests - always use mock. The "unit" of test is a method.
- Integration tests - never use mock. The "unit" of test is a class.
- End-to-end tests - uses the actual program. The "unit" of test is a single "happy path".