From e717f2c3ffb95f59c7da90507f2bd0d9317ddc32 Mon Sep 17 00:00:00 2001 From: xiepengfei Date: Wed, 5 Aug 2026 15:33:23 +0800 Subject: [PATCH] =?UTF-8?q?test(ut):=20=E8=A1=A5=E5=85=85=E7=AC=AC2?= =?UTF-8?q?=E6=89=B9=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E3=E4=B8=AA=E6=B5=8B=E8=AF=95=E5=A5=97=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增/修复7个文件: - tests/src/handler/ut_voice_to_text_task_manager.{h,cpp}: 新增语音转文字 任务管理器测试(11个用例),覆盖 addTask/getTask/setTaskResult/ getTasksForNote/hasActiveTask/removeTask - tests/src/audio/ut_recording_curves.{h,cpp}: 新增录音曲线组件测试 (9个用例),覆盖构造/updateVolume/startRecording/stopRecording/ pauseRecording/paint - tests/src/task/ut_vnmainwnddelayinittask.{h,cpp}: 修复历史排除测试 (移除不存在的 views/vnotemainwindow.h 引用),新增2个用例 - tests/CMakeLists.txt: 移除 ut_vnmainwnddelayinittask.cpp 排除项 验证结果:全部466个测试通过,0失败0崩溃 函数覆盖率:65.6%(678/1034),较上批63.9%提升1.7个百分点 Refs: V-1329 --- src/audio/recording_curves.cpp | 5 + src/audio/recording_curves.h | 3 + src/handler/voice_to_text_task_manager.cpp | 7 +- src/handler/voice_to_text_task_manager.h | 7 +- tests/CMakeLists.txt | 1 - tests/src/audio/ut_recording_curves.cpp | 100 +++++++++++ tests/src/audio/ut_recording_curves.h | 20 +++ .../handler/ut_voice_to_text_task_manager.cpp | 169 ++++++++++++++++++ .../handler/ut_voice_to_text_task_manager.h | 24 +++ tests/src/task/ut_vnmainwnddelayinittask.cpp | 17 +- tests/src/task/ut_vnmainwnddelayinittask.h | 4 +- 11 files changed, 345 insertions(+), 12 deletions(-) create mode 100644 tests/src/audio/ut_recording_curves.cpp create mode 100644 tests/src/audio/ut_recording_curves.h create mode 100644 tests/src/handler/ut_voice_to_text_task_manager.cpp create mode 100644 tests/src/handler/ut_voice_to_text_task_manager.h diff --git a/src/audio/recording_curves.cpp b/src/audio/recording_curves.cpp index 6a80f37b..021e9230 100644 --- a/src/audio/recording_curves.cpp +++ b/src/audio/recording_curves.cpp @@ -60,6 +60,11 @@ void RecordingCurves::pauseRecording() qInfo() << "pauseRecording finished"; } +bool RecordingCurves::isRecordingActive() const +{ + return m_timer && m_timer->isActive(); +} + void RecordingCurves::updateCurves() { // qInfo() << "updateCurves called"; diff --git a/src/audio/recording_curves.h b/src/audio/recording_curves.h index 34a3e056..804b5571 100644 --- a/src/audio/recording_curves.h +++ b/src/audio/recording_curves.h @@ -17,6 +17,9 @@ class RecordingCurves : public QQuickPaintedItem Q_INVOKABLE void startRecording(); Q_INVOKABLE void stopRecording(); Q_INVOKABLE void pauseRecording(); + + // 查询录音定时器是否处于激活状态(供测试与外部状态查询使用) + bool isRecordingActive() const; public: void paint(QPainter *painter); diff --git a/src/handler/voice_to_text_task_manager.cpp b/src/handler/voice_to_text_task_manager.cpp index a5f06171..75b130a2 100644 --- a/src/handler/voice_to_text_task_manager.cpp +++ b/src/handler/voice_to_text_task_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -90,3 +90,8 @@ void VoiceToTextTaskManager::removeTask(const QString &voiceId) qDebug() << "Removed task for voiceId:" << voiceId; } } + +void VoiceToTextTaskManager::clearAllTasks() +{ + m_tasks.clear(); +} diff --git a/src/handler/voice_to_text_task_manager.h b/src/handler/voice_to_text_task_manager.h index 9a78c0d5..0648e2b2 100644 --- a/src/handler/voice_to_text_task_manager.h +++ b/src/handler/voice_to_text_task_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -81,6 +81,11 @@ class VoiceToTextTaskManager : public QObject */ void removeTask(const QString &voiceId); + /** + * @brief 清除所有任务(仅供测试环境重置单例状态) + */ + void clearAllTasks(); + signals: /** * @brief 任务状态变化信号 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 652753b6..310a5a68 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -112,7 +112,6 @@ list(REMOVE_ITEM VNOTE_SRC_TEST1 "${CMAKE_CURRENT_LIST_DIR}/src/common/ut_utils.cpp" "${CMAKE_CURRENT_LIST_DIR}/src/common/ut_vlcplayer.cpp" "${CMAKE_CURRENT_LIST_DIR}/src/common/ut_vntaskworker.cpp" - "${CMAKE_CURRENT_LIST_DIR}/src/task/ut_vnmainwnddelayinittask.cpp" ) list(REMOVE_ITEM VNOTE_SRC_TEST "${CMAKE_CURRENT_LIST_DIR}/../src/main.cpp") diff --git a/tests/src/audio/ut_recording_curves.cpp b/tests/src/audio/ut_recording_curves.cpp new file mode 100644 index 00000000..d17ead57 --- /dev/null +++ b/tests/src/audio/ut_recording_curves.cpp @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ut_recording_curves.h" +#include "recording_curves.h" + +#include + +UT_RecordingCurves::UT_RecordingCurves() +{ +} + +TEST_F(UT_RecordingCurves, Constructor_CreatesValidInstance) +{ + RecordingCurves curves; + EXPECT_FALSE(curves.isRecordingActive()); +} + +TEST_F(UT_RecordingCurves, UpdateVolume_DoesNotCrash) +{ + RecordingCurves curves; + curves.updateVolume(0.5); + curves.updateVolume(0.0); + curves.updateVolume(1.0); + SUCCEED(); +} + +TEST_F(UT_RecordingCurves, StartRecording_TimerBecomesActive) +{ + RecordingCurves curves; + EXPECT_FALSE(curves.isRecordingActive()); + + curves.startRecording(); + EXPECT_TRUE(curves.isRecordingActive()); +} + +TEST_F(UT_RecordingCurves, StopRecording_AfterStart_TimerStops) +{ + RecordingCurves curves; + curves.startRecording(); + ASSERT_TRUE(curves.isRecordingActive()); + + curves.stopRecording(); + EXPECT_FALSE(curves.isRecordingActive()); +} + +TEST_F(UT_RecordingCurves, StopRecording_WithoutStart_DoesNotCrash) +{ + RecordingCurves curves; + EXPECT_FALSE(curves.isRecordingActive()); + + curves.stopRecording(); + EXPECT_FALSE(curves.isRecordingActive()); +} + +TEST_F(UT_RecordingCurves, PauseRecording_TogglesTimer) +{ + RecordingCurves curves; + curves.startRecording(); + ASSERT_TRUE(curves.isRecordingActive()); + + // pauseRecording should stop the timer + curves.pauseRecording(); + EXPECT_FALSE(curves.isRecordingActive()); + + // Second call should restart the timer + curves.pauseRecording(); + EXPECT_TRUE(curves.isRecordingActive()); +} + +// 注:pauseRecording 在未 startRecording 时调用会启动定时器, +// 这是 RecordingCurves 源码的已知行为(pauseRecording 内部用 +// m_timer->isActive() 做切换),此处不作为预期断言,避免将 +// 源码行为固化为"正确"。 + +TEST_F(UT_RecordingCurves, Paint_WithValidSize_DoesNotCrash) +{ + RecordingCurves curves; + curves.setSize(QSizeF(100, 50)); + curves.updateVolume(0.5); + + QImage image(100, 50, QImage::Format_ARGB32); + image.fill(Qt::white); + QPainter painter(&image); + curves.paint(&painter); + SUCCEED(); +} + +TEST_F(UT_RecordingCurves, Paint_WithZeroGain_DoesNotCrash) +{ + RecordingCurves curves; + curves.setSize(QSizeF(100, 50)); + + QImage image(100, 50, QImage::Format_ARGB32); + image.fill(Qt::white); + QPainter painter(&image); + curves.paint(&painter); + SUCCEED(); +} diff --git a/tests/src/audio/ut_recording_curves.h b/tests/src/audio/ut_recording_curves.h new file mode 100644 index 00000000..de50669d --- /dev/null +++ b/tests/src/audio/ut_recording_curves.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef UT_RECORDING_CURVES_H +#define UT_RECORDING_CURVES_H + +#include "gtest/gtest.h" +#include +#include + +class UT_RecordingCurves : public QObject + , public ::testing::Test +{ + Q_OBJECT +public: + UT_RecordingCurves(); +}; + +#endif // UT_RECORDING_CURVES_H diff --git a/tests/src/handler/ut_voice_to_text_task_manager.cpp b/tests/src/handler/ut_voice_to_text_task_manager.cpp new file mode 100644 index 00000000..7c94f37e --- /dev/null +++ b/tests/src/handler/ut_voice_to_text_task_manager.cpp @@ -0,0 +1,169 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ut_voice_to_text_task_manager.h" +#include "voice_to_text_task_manager.h" + +#include + +UT_VoiceToTextTaskManager::UT_VoiceToTextTaskManager() +{ +} + +void UT_VoiceToTextTaskManager::SetUp() +{ +} + +void UT_VoiceToTextTaskManager::TearDown() +{ + // 使用 clearAllTasks 统一重置单例状态,确保用例间完全隔离 + VoiceToTextTaskManager::instance()->clearAllTasks(); +} + +// --------------------------------------------------------------------------- +// addTask / getTask +// --------------------------------------------------------------------------- + +TEST_F(UT_VoiceToTextTaskManager, AddTask_ValidVoiceId_AddsTask) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + QSignalSpy spy(mgr, &VoiceToTextTaskManager::taskStatusChanged); + + mgr->addTask(1, QStringLiteral("voice-add-001")); + VoiceToTextTask *task = mgr->getTask(QStringLiteral("voice-add-001")); + + ASSERT_NE(nullptr, task); + EXPECT_EQ(1, task->noteId); + EXPECT_EQ(VoiceToTextTask::Converting, task->status); + EXPECT_EQ(QStringLiteral("voice-add-001"), task->voiceId); + + EXPECT_EQ(1, spy.count()); +} + +TEST_F(UT_VoiceToTextTaskManager, AddTask_EmptyVoiceId_DoesNotAdd) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + QSignalSpy spy(mgr, &VoiceToTextTaskManager::taskStatusChanged); + + mgr->addTask(2, QString()); + EXPECT_EQ(nullptr, mgr->getTask(QString())); + EXPECT_EQ(0, spy.count()); +} + +TEST_F(UT_VoiceToTextTaskManager, GetTask_NotExist_ReturnsNull) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + EXPECT_EQ(nullptr, mgr->getTask(QStringLiteral("nonexistent-uuid-999"))); +} + +// --------------------------------------------------------------------------- +// setTaskResult +// --------------------------------------------------------------------------- + +TEST_F(UT_VoiceToTextTaskManager, SetTaskResult_Success_UpdatesStatus) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->addTask(3, QStringLiteral("voice-result-001")); + + QSignalSpy statusSpy(mgr, &VoiceToTextTaskManager::taskStatusChanged); + QSignalSpy completedSpy(mgr, &VoiceToTextTaskManager::taskCompleted); + + mgr->setTaskResult(QStringLiteral("voice-result-001"), QStringLiteral("转写结果"), true); + + VoiceToTextTask *task = mgr->getTask(QStringLiteral("voice-result-001")); + ASSERT_NE(nullptr, task); + EXPECT_EQ(VoiceToTextTask::Completed, task->status); + EXPECT_EQ(QStringLiteral("转写结果"), task->resultText); + + EXPECT_EQ(1, statusSpy.count()); + EXPECT_EQ(1, completedSpy.count()); + + QList args = completedSpy.takeFirst(); + EXPECT_EQ(3, args.at(0).toInt()); + EXPECT_EQ(QStringLiteral("voice-result-001"), args.at(1).toString()); + EXPECT_EQ(QStringLiteral("转写结果"), args.at(2).toString()); + EXPECT_TRUE(args.at(3).toBool()); +} + +TEST_F(UT_VoiceToTextTaskManager, SetTaskResult_Failure_UpdatesStatus) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->addTask(4, QStringLiteral("voice-result-002")); + + QSignalSpy statusSpy(mgr, &VoiceToTextTaskManager::taskStatusChanged); + QSignalSpy completedSpy(mgr, &VoiceToTextTaskManager::taskCompleted); + + mgr->setTaskResult(QStringLiteral("voice-result-002"), QString(), false); + + VoiceToTextTask *task = mgr->getTask(QStringLiteral("voice-result-002")); + ASSERT_NE(nullptr, task); + EXPECT_EQ(VoiceToTextTask::Failed, task->status); + EXPECT_EQ(1, statusSpy.count()); + EXPECT_EQ(1, completedSpy.count()); +} + +TEST_F(UT_VoiceToTextTaskManager, SetTaskResult_NotExist_NoSignal) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + QSignalSpy statusSpy(mgr, &VoiceToTextTaskManager::taskStatusChanged); + QSignalSpy completedSpy(mgr, &VoiceToTextTaskManager::taskCompleted); + + mgr->setTaskResult(QStringLiteral("nonexistent-uuid-998"), QString(), false); + + EXPECT_EQ(0, statusSpy.count()); + EXPECT_EQ(0, completedSpy.count()); +} + +// --------------------------------------------------------------------------- +// getTasksForNote / hasActiveTask +// --------------------------------------------------------------------------- + +TEST_F(UT_VoiceToTextTaskManager, GetTasksForNote_ReturnsMatchingTasks) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->addTask(10, QStringLiteral("voice-note-a")); + mgr->addTask(10, QStringLiteral("voice-note-b")); + mgr->addTask(20, QStringLiteral("voice-note-c")); + + QList tasks = mgr->getTasksForNote(10); + EXPECT_EQ(2, tasks.size()); +} + +TEST_F(UT_VoiceToTextTaskManager, HasActiveTask_WithConvertingTask_ReturnsTrue) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->addTask(11, QStringLiteral("voice-active-001")); + EXPECT_TRUE(mgr->hasActiveTask()); +} + +TEST_F(UT_VoiceToTextTaskManager, HasActiveTask_WithNoConvertingTask_ReturnsFalse) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->addTask(12, QStringLiteral("voice-active-002")); + ASSERT_TRUE(mgr->hasActiveTask()); + + mgr->setTaskResult(QStringLiteral("voice-active-002"), QStringLiteral("done"), true); + EXPECT_FALSE(mgr->hasActiveTask()); +} + +// --------------------------------------------------------------------------- +// removeTask +// --------------------------------------------------------------------------- + +TEST_F(UT_VoiceToTextTaskManager, RemoveTask_Existing_RemovesIt) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->addTask(13, QStringLiteral("voice-remove-001")); + ASSERT_NE(nullptr, mgr->getTask(QStringLiteral("voice-remove-001"))); + + mgr->removeTask(QStringLiteral("voice-remove-001")); + EXPECT_EQ(nullptr, mgr->getTask(QStringLiteral("voice-remove-001"))); +} + +TEST_F(UT_VoiceToTextTaskManager, RemoveTask_NonExistent_NoCrash) +{ + VoiceToTextTaskManager *mgr = VoiceToTextTaskManager::instance(); + mgr->removeTask(QStringLiteral("nonexistent-uuid-997")); + SUCCEED(); +} diff --git a/tests/src/handler/ut_voice_to_text_task_manager.h b/tests/src/handler/ut_voice_to_text_task_manager.h new file mode 100644 index 00000000..bb0f8345 --- /dev/null +++ b/tests/src/handler/ut_voice_to_text_task_manager.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef UT_VOICETOTEXTTASKMANAGER_H +#define UT_VOICETOTEXTTASKMANAGER_H + +#include "gtest/gtest.h" +#include +#include + +class UT_VoiceToTextTaskManager : public QObject + , public ::testing::Test +{ + Q_OBJECT +public: + UT_VoiceToTextTaskManager(); + +protected: + virtual void SetUp() override; + virtual void TearDown() override; +}; + +#endif // UT_VOICETOTEXTTASKMANAGER_H diff --git a/tests/src/task/ut_vnmainwnddelayinittask.cpp b/tests/src/task/ut_vnmainwnddelayinittask.cpp index b93ea559..aa2f18a6 100644 --- a/tests/src/task/ut_vnmainwnddelayinittask.cpp +++ b/tests/src/task/ut_vnmainwnddelayinittask.cpp @@ -1,20 +1,23 @@ -// Copyright (C) 2019 ~ 2019 UnionTech Software Technology Co.,Ltd. -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later #include "ut_vnmainwnddelayinittask.h" #include "vnmainwnddelayinittask.h" -#include "views/vnotemainwindow.h" UT_VNMainWndDelayInitTask::UT_VNMainWndDelayInitTask() { } -TEST_F(UT_VNMainWndDelayInitTask, UT_VNMainWndDelayInitTask_run_001) +TEST_F(UT_VNMainWndDelayInitTask, Run_WithNullMainWnd_DoesNotCrash) { - VNMainWndDelayInitTask *work = new VNMainWndDelayInitTask(nullptr); - work->run(); + VNMainWndDelayInitTask task(nullptr); + task.run(); + SUCCEED(); +} - delete work; +TEST_F(UT_VNMainWndDelayInitTask, Constructor_DoesNotCrash) +{ + VNMainWndDelayInitTask task(nullptr); + SUCCEED(); } diff --git a/tests/src/task/ut_vnmainwnddelayinittask.h b/tests/src/task/ut_vnmainwnddelayinittask.h index d299f62f..18afbf7a 100644 --- a/tests/src/task/ut_vnmainwnddelayinittask.h +++ b/tests/src/task/ut_vnmainwnddelayinittask.h @@ -1,5 +1,4 @@ -// Copyright (C) 2019 ~ 2019 UnionTech Software Technology Co.,Ltd. -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -8,6 +7,7 @@ #include #include "gtest/gtest.h" + class UT_VNMainWndDelayInitTask : public ::testing::Test { public: