Skip to content

test(frame): add GTest unit tests for core framework classes (100 tests) - #1703

Draft
MyLeeJiEun wants to merge 2 commits into
linuxdeepin:masterfrom
MyLeeJiEun:test/frame-gtest-core-classes
Draft

test(frame): add GTest unit tests for core framework classes (100 tests)#1703
MyLeeJiEun wants to merge 2 commits into
linuxdeepin:masterfrom
MyLeeJiEun:test/frame-gtest-core-classes

Conversation

@MyLeeJiEun

@MyLeeJiEun MyLeeJiEun commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds 100 GTest unit tests for the frame/ core framework of dde-shell, which previously had zero test coverage. Delivered in two batches on this single branch.

Test scope (10 core classes, 100 tests)

Batch 1 (74 tests):

Class Source Tests
DPluginMetaData frame/pluginmetadata.cpp 19
DAppletData frame/appletdata.cpp 16
DAppletItemModel frame/appletitemmodel.cpp 11
KExtraColumnsProxyModel frame/models/kextracolumnsproxymodel.cpp 17
ListToTableProxyModel frame/models/listtotableproxymodel.cpp 8
DAppletFactory frame/pluginfactory.cpp 3

Batch N+1 (26 tests):

Class Source Tests
Types frame/dstypes.cpp 3
DApplet frame/applet.cpp 9
DAppletMetaProxy frame/appletproxy.cpp 8
Utility frame/dsutility.cpp (base, non-X11) 6

All 100 tests pass (0 failed / 0 skipped / 0 crash) on Qt 6.8 + GTest 1.12.1 + GCC 12.3 + DTK6 Core. The remaining 17 frame/ .cpp files were assessed as not unit-testable without a mock framework or a Wayland/X11 runtime (global DPluginLoader singleton, QML engine, or Qt/Wayland private APIs) and are out of scope for this PR.

Build

# Configure + build + run the tests (9 executables)
cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build build
ctest --test-dir build -R '^frame_' --output-on-failure   # 100/100 passed

Sources under test are compiled once into a single OBJECT library frame_test_objects, linked into the 9 test executables. utility_tests spins up an offscreen QGuiApplication via a GTest global test environment (QT_QPA_PLATFORM=offscreen), so no X11/Wayland runtime is required.

dsutility.cpp uses QGuiApplication/qGuiApp but does not directly #include <QGuiApplication> (a src robustness gap masked by the default BUILD_WITH_X11=ON). Since this test OBJECT lib intentionally does not define BUILD_WITH_X11, tests/frame/CMakeLists.txt force-includes qguiapplication.h as a test-side workaround (tracked in DDE-141; once fixed in src, the workaround block can be removed). This PR does not modify src/.

Coverage

Enable coverage through the build-system target:

cmake -B build -DBUILD_TESTING=ON -DFRAME_BUILD_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build build --target frame_coverage
# report: build/frame_coverage/html/index.html

lcov results (generated code excluded):

Metric Coverage Target (≥70%)
Line 95.5%
Function 88.5%
Branch 56.3% ❌ (<70%)

Every covered source file has line coverage ≥ 80% (e.g. applet 84.7% / appletproxy 89.5% / dstypes 100% / dsutility 90.6%, plus Batch 1 files). Branch coverage is below 70% exclusively due to structurally unreachable branches; all reachable branches are essentially fully covered:

  • fromJsonString dead code in frame/pluginmetadata.cpp — a src defect: QJsonParseError is declared but never passed to QJsonDocument::fromJson, so if(error.error) is always false. Tracked for the maintainers in DDE-132.
  • dsutility.cpp missing direct #include <QGuiApplication> robustness gap → DDE-141 (test-side forced-include workaround applied here; removable once src is fixed).
  • Q_ASSERT abort branches (~9 sites in kextracolumnsproxymodel.cpp) — triggering aborts the process, unreachable on normal paths.
  • QExplicitlySharedDataPointer::operator=/detach if(d) template false branches — d is always non-null after construction.
  • DAppletItemModel::data / DApplet defensive dead code (row >= size, if(m_rootObject) destructor false branch).
  • Utility #ifdef BUILD_WITH_X11 compile-excluded block (X11Utility path).
  • KExtraColumnsProxyModel combination-unreachable branches, plus lambda / metaObject() macro-expansion branch inflation.

This PR does not modify src/, debian/, or the top-level CMakeLists.txt — tests only. Both src defects are tracked separately for the maintainers and are out of scope here.

Notes

  • Tests follow the existing tests/panels/dock/taskmanager pattern (BUILD_TESTING gate + gtest_discover_tests), registered with a frame_ ctest prefix so ctest -R '^frame_' runs only this batch.
  • The branch keeps both batches as separate commits (Batch 1 → Batch N+1) for reviewable incremental history.

Tracking issue: DDE-107 补充 dde-shell 项目测试代码

1. Add 74 GTest unit tests covering 6 frame/ core classes
2. Cover DPluginMetaData, DAppletData, DAppletItemModel
3. Cover KExtraColumnsProxyModel, ListToTableProxyModel, DAppletFactory
4. Use OBJECT lib frame_test_objects linked into 5 test executables
5. Add FRAME_BUILD_COVERAGE option and frame_coverage target
6. Gate tests behind BUILD_TESTING following taskmanager pattern
7. frame/ core framework had zero test coverage before this change

Influence:
1. Run ctest -R '^frame_' to execute all 74 unit tests
2. Enable FRAME_BUILD_COVERAGE=ON and build frame_coverage target
3. Verify coverage report at build/frame_coverage/html/index.html

test(frame): 为6个核心类添加GTest单元测试

1. 为 frame/ 6 个核心类添加 74 个 GTest 单元测试
2. 覆盖 DPluginMetaData、DAppletData、DAppletItemModel
3. 覆盖 KExtraColumnsProxyModel、ListToTableProxyModel、DAppletFactory
4. 通过 OBJECT 库 frame_test_objects 链入 5 个测试可执行
5. 新增 FRAME_BUILD_COVERAGE 选项与 frame_coverage target
6. 以 BUILD_TESTING 门控,沿用 taskmanager 的 gtest_discover_tests 模式
7. frame/ 核心框架此前测试覆盖为零

Influence:
1. 通过 ctest -R '^frame_' 运行全部 74 个单元测试
2. 启用 FRAME_BUILD_COVERAGE=ON 并构建 frame_coverage target
3. 在 build/frame_coverage/html/index.html 查看覆盖率报告
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: MyLeeJiEun

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-ci-robot

Copy link
Copy Markdown

Hi @MyLeeJiEun. Thanks for your PR.

I'm waiting for a linuxdeepin member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@sourcery-ai

sourcery-ai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a new GTest-based unit test suite for dde-shell's frame/ core framework (6 core classes, 74 tests), wired via a new tests/frame CMake subtree that builds a shared OBJECT library for the frame sources, defines five test executables, and optionally provides an lcov/genhtml-based coverage target.

File-Level Changes

Change Details Files
Introduce a shared OBJECT library for frame/ sources under test and hook a new tests/frame subtree into the global tests build.
  • Add tests/frame/CMakeLists.txt to define frame_test_objects as an OBJECT library containing pluginmetadata, appletdata, appletitemmodel, kextracolumnsproxymodel, listtotableproxymodel, and pluginfactory sources
  • Set DS_LIB for frame_test_objects and export include paths matching the frame/ layout
  • Introduce a frame_add_test helper that links each test binary against frame_test_objects, Qt Core/Gui/Test, and GTest, and registers tests via gtest_discover_tests with a frame_ prefix
  • Wire tests/frame into the overall tests build by adding add_subdirectory(frame) to tests/CMakeLists.txt
tests/CMakeLists.txt
tests/frame/CMakeLists.txt
Add high-coverage unit tests for DPluginMetaData and DAppletData, including construction paths, JSON/file parsing, value accessors, copy/move semantics, equality, and destructor safety.
  • pluginmetadatatests.cpp exercises fromJsonString/fromJsonFile on valid/missing/malformed inputs, pluginDir/url resolution, root plugin helpers, value() defaults, implicit sharing, equality, and destructor behavior
  • appletdatatests.cpp covers default and QVariantMap-based construction, pluginId/id accessors, value()/toMap(), groupList/setGroupList (including nested DAppletData), fromPluginMetaData, implicit sharing, equality, and destructor behavior
tests/frame/pluginmetadatatests.cpp
tests/frame/appletdatatests.cpp
Add unit tests for DAppletItemModel covering append/remove semantics, role metadata, data() behavior, and Qt model invariants via QAbstractItemModelTester.
  • appletitemmodeltests.cpp validates empty model state and roleNames, append() growth and rowsInserted signals, data() for valid/invalid rows and unknown roles, remove() shrink behavior and no-op removal, rootObjects() consistency, and model invariants under various append/remove sequences using QAbstractItemModelTester
tests/frame/appletitemmodeltests.cpp
Add comprehensive tests for KExtraColumnsProxyModel and ListToTableProxyModel, including index/parent mapping, extra column behavior, selection and layout handling, and internal role/column mapping logic.
  • kextracolumnsproxymodeltests.cpp defines a concrete TestExtraColumnsModel subclass plus a TestLayoutSourceModel to expose layout signals, then covers append/remove of extra columns, data/setData/flags/hasChildren/headerData routing between source and extra columns, mapToSource/buddy/sibling/mapSelectionToSource behavior, extraColumnDataChanged notifications, source model replacement, QAbstractItemModelTester validation, and layout change handlers with persistent indexes
  • listtotableproxymodeltests.cpp uses a scoped #define private/protected public around listtotableproxymodel.h to access m_roles and m_sourceColumn, then tests rolesChanged-driven extra column creation and titling, extraColumnData for normal/invalid/QVariantList values, source column data routing, sourceModelChanged retitling, dataChanged-triggered model resets, and sourceColumn-based read selection
tests/frame/kextracolumnsproxymodeltests.cpp
tests/frame/listtotableproxymodeltests.cpp
Add focused tests for DAppletFactory registration and creation logic using per-test factory subclasses to exercise the global registration map safely.
  • pluginfactorytests.cpp introduces unique Q_OBJECT subclasses (InvokeFactory, DuplicateFactory) and tests registerInstance/create behavior for successful invocation, unregistered factories returning nullptr, and duplicate registrations being ignored while the first registration remains effective
tests/frame/pluginfactorytests.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

1. Add 26 GTest unit tests for 4 more frame/ core classes
2. Cover dstypes, applet, appletproxy, dsutility (Batch N+1)
3. Extend OBJECT lib with 4 sources + link Dtk6::Core and Qt6::Gui
4. Add 4 test executables types/applet/appletproxy/utility tests
5. Force-include qguiapplication.h for dsutility.cpp workaround
6. Brings frame/ coverage to 100 tests across 10 core classes

Influence:
1. Run ctest -R '^frame_' to execute all 100 unit tests
2. Build requires DTK6 Core + Qt6 Gui (dsutility uses QGuiApplication)
3. utility_tests runs offscreen QGuiApplication via global environment

test(frame): 为4个核心类新增GTest单元测试

1. 为 4 个 frame/ 核心类新增 26 个 GTest 单元测试
2. 覆盖 dstypes、applet、appletproxy、dsutility(Batch N+1)
3. OBJECT 库追加 4 源并链接 Dtk6::Core 与 Qt6::Gui
4. 新增 4 个测试可执行 types/applet/appletproxy/utility tests
5. 为 dsutility.cpp 强制包含 qguiapplication.h 规避编译
6. frame/ 覆盖增至 100 测试,覆盖 10 个核心类

Influence:
1. 通过 ctest -R '^frame_' 运行全部 100 个单元测试
2. 构建需 DTK6 Core 与 Qt6 Gui(dsutility 使用 QGuiApplication)
3. utility_tests 经全局测试环境运行 offscreen QGuiApplication
@MyLeeJiEun MyLeeJiEun changed the title test(frame): add GTest unit tests for core framework classes (74 tests) test(frame): add GTest unit tests for core framework classes (100 tests) Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants