【问题标题】:How to write GUI tests for wxWidgets如何为 wxWidgets 编写 GUI 测试
【发布时间】:2021-12-18 06:52:52
【问题描述】:

我想为我的 C++ wxWidgets 应用程序创建一个测试套件,但在弄清楚如何测试 GUI 组件时遇到了麻烦。关于如何编写单元测试的article in the docs 是从扩充现有单元测试的角度编写的,但没有解决如何开始新的单元测试。

我能够使用 Catch 创建一个测试套件(这似乎是推荐的方法),但在 GUI 端开始时遇到了麻烦。

在非 GUI 方面,我创建了一个看起来像这样的测试

#include "catch.hpp"

#include "wx/wx.h"

TEST_CASE("wx", "[wx]") {
    wxPoint p = wxPoint(10, 10);
    REQUIRE(p.x == 10);
}

和一个看起来像这样的 CMakeLists 文件(只是相关部分):

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})

这工作得很好。所以链接 wxWidgets 库没有问题。我相信问题在于创建 wxApp 或事件循环。但我不确定如何纠正。

当我创建一个尝试创建按钮的测试时(例如在文档中建议用作示例的buttontest.cpp),我收到了Segmentation violation signal

TEST_CASE("wx", "[wx]") {
    wxButton* button = new wxButton(wxTheApp->GetTopWindow(), wxID_ANY, "wxButton");
    wxYield();
}

有没有一个地方可以演示如何从头开始为 wxWidgets 创建 GUI 测试,而不仅仅是添加到 wxWidgets 测试本身?

【问题讨论】:

    标签: c++ unit-testing wxwidgets catch2


    【解决方案1】:

    不幸的是,编写 GUI 测试不是很简单,但可以做到。基本思想是您使用wxUIActionSimulator 来触发您要测试的用户操作,然后检查UI 是否已按预期更新,这通常涉及调用wxYield() 来处理所有事件。 wxWidgets 自己的 GUI 测试自己展示了如何做到这一点,但也经常有一些额外的复杂性,只需在 tests 下搜索 wxUIActionSimulator 即可查看其使用示例。

    您还可以查看 this test 以查看如何使用 wxTEST_DIALOG 测试导致模态对话框的操作的示例,这通常会阻止 GUI 并阻止您的程序继续运行。

    【讨论】:

    • 我只想指出,您所说的不是单元测试。您在谈论端到端测试 - 据我了解,这不是 OP 所要求的。
    【解决方案2】:

    请不要为 GUI 连接单元测试,这完全违反了Clean Code 的规则。有几个原因:

    1. 各种 GUI 框架(包括)wxWidgets 中的大多数方法都是私有的(这是正确的)。 Clean Code 的规则说我们不应该为私有方法编写单元测试——它们只是实现细节。
    2. 开发 GUI 应用程序需要分离视图 (GUI) 逻辑和业务(例如:数据库访问)逻辑。最好的方法是使用MVVM 设计模式。

    另外,我会推荐一本好书:Clean Code。它是关于清洁代码的书。它还涉及TDD - Test Driven Development - 这也是与您的问题密切相关的一个重要主题。

    根据@VZ 的 cmets,我想在单元测试、集成测试和端到端测试之间添加以下区别:

    • 单元测试 - 始终使用模拟。测试的“单元”是一种方法。
    • 集成测试 - 永远不要使用模拟。测试的“单元”是一个类。
    • 端到端测试 - 使用实际程序。测试的“单元”是一个单一的“快乐路径”。

    【讨论】:

    • 我同意 - 业务逻辑应该分开并自行测试。但是,我也创建了需要测试的自定义 UI 元素。我想确保在修改自定义元素时不会破坏它们的行为。
    • @DHamrick 自定义 GUI 元素,就像任何其他 GUI 部分一样。它们应该在考虑 MVVM 的情况下编写,然后单元测试变得显而易见。让我举个例子:假设您有一个自定义 GUI 小部件,它显示数据库中的行。负责从数据库中获取数据并对其进行解析和预处理的类需要与自定义小部件控件分离(例如,作为参数注入到自定义小部件控件的ctor中)。
    • 这是一个非常糟糕的答案。您应该为您的业务逻辑进行测试,但您应该为您的 GUI 进行测试,绝对没有理由“克制”不编写此类测试。
    • @VZ “绝对没有理由“避免”编写此类测试。” --> 是的,有。请看我的回答,第 1 点。但是,也许我明白我们为什么存在分歧:我在谈论单元测试,而您在谈论端到端测试。我会及时改写我的答案以更准确。你是对的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    • 2021-02-03
    • 2015-09-11
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多