Compare commits
1 Commits
main
...
test_20260
| Author | SHA1 | Date |
|---|---|---|
|
|
9a0269bba3 |
|
|
@ -0,0 +1,25 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10.0)
|
||||||
|
project(test_plan_execute_t1)
|
||||||
|
include(FetchContent)
|
||||||
|
if (MSVC)
|
||||||
|
add_compile_options(/utf-8)
|
||||||
|
endif()
|
||||||
|
FetchContent_Declare(
|
||||||
|
googletest
|
||||||
|
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||||
|
)
|
||||||
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_MakeAvailable(googletest)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
add_executable(test_plan_execute_t1 test_app.cpp ../src/app.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(test_plan_execute_t1 gtest gmock gtest_main)
|
||||||
|
include(GoogleTest)
|
||||||
|
gtest_discover_tests(test_plan_execute_t1)
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "app.hpp"
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 测试夹具:CmsEngineTest
|
||||||
|
// ============================================================
|
||||||
|
class CmsEngineTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
CmsEngine engine;
|
||||||
|
|
||||||
|
void SetUp() override {
|
||||||
|
// 每个测试用例开始前重置引擎状态
|
||||||
|
// 注意:CmsEngine 构造函数已初始化,但 plans_ 为空
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
// 清理(如果需要)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 测试用例:createTaskPlan
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requirement(name="任务方案创建", id="REQ-PLAN-CREATE-001")
|
||||||
|
* 系统需校验方案名称非空后,为其分配系统 ID 并存入方案库,
|
||||||
|
* 确保方案数据的完整性和可追溯性。
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 正常输入测试:创建有效方案
|
||||||
|
TEST_F(CmsEngineTest, testCreateTaskPlanNormal) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "TestPlan";
|
||||||
|
plan.type = PlanType::Centralized;
|
||||||
|
plan.status = PlanStatus::Drafting;
|
||||||
|
plan.resourceQuota = 0.8;
|
||||||
|
plan.constraints = "无约束";
|
||||||
|
|
||||||
|
bool result = engine.createTaskPlan(plan);
|
||||||
|
EXPECT_TRUE(result);
|
||||||
|
EXPECT_FALSE(plan.id.empty());
|
||||||
|
EXPECT_EQ(plan.name, "TestPlan");
|
||||||
|
EXPECT_EQ(plan.type, PlanType::Centralized);
|
||||||
|
EXPECT_EQ(plan.status, PlanStatus::Drafting);
|
||||||
|
EXPECT_EQ(plan.resourceQuota, 0.8);
|
||||||
|
EXPECT_EQ(plan.constraints, "无约束");
|
||||||
|
|
||||||
|
// 验证方案已存入引擎
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
ASSERT_EQ(plans.size(), 1);
|
||||||
|
EXPECT_EQ(plans[0].id, plan.id);
|
||||||
|
EXPECT_EQ(plans[0].name, "TestPlan");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:名称为空字符串
|
||||||
|
TEST_F(CmsEngineTest, testCreateTaskPlanEmptyName) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "";
|
||||||
|
plan.type = PlanType::Centralized;
|
||||||
|
plan.status = PlanStatus::Drafting;
|
||||||
|
|
||||||
|
bool result = engine.createTaskPlan(plan);
|
||||||
|
EXPECT_FALSE(result);
|
||||||
|
EXPECT_TRUE(plan.id.empty()); // 不应分配 ID
|
||||||
|
|
||||||
|
// 验证方案未存入引擎
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
EXPECT_EQ(plans.size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:名称为空白字符串(仅空格)
|
||||||
|
TEST_F(CmsEngineTest, testCreateTaskPlanWhitespaceName) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = " ";
|
||||||
|
plan.type = PlanType::Centralized;
|
||||||
|
plan.status = PlanStatus::Drafting;
|
||||||
|
|
||||||
|
bool result = engine.createTaskPlan(plan);
|
||||||
|
EXPECT_TRUE(result); // 空白字符串不为空,应视为合法
|
||||||
|
EXPECT_FALSE(plan.id.empty());
|
||||||
|
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
ASSERT_EQ(plans.size(), 1);
|
||||||
|
EXPECT_EQ(plans[0].name, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:名称长度极长
|
||||||
|
TEST_F(CmsEngineTest, testCreateTaskPlanLongName) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = std::string(1000, 'A'); // 1000 个字符
|
||||||
|
plan.type = PlanType::Centralized;
|
||||||
|
plan.status = PlanStatus::Drafting;
|
||||||
|
|
||||||
|
bool result = engine.createTaskPlan(plan);
|
||||||
|
EXPECT_TRUE(result);
|
||||||
|
EXPECT_FALSE(plan.id.empty());
|
||||||
|
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
ASSERT_EQ(plans.size(), 1);
|
||||||
|
EXPECT_EQ(plans[0].name, std::string(1000, 'A'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常输入测试:创建多个方案,验证 ID 唯一性
|
||||||
|
TEST_F(CmsEngineTest, testCreateTaskPlanMultiplePlans) {
|
||||||
|
TaskPlan plan1;
|
||||||
|
plan1.name = "Plan1";
|
||||||
|
TaskPlan plan2;
|
||||||
|
plan2.name = "Plan2";
|
||||||
|
TaskPlan plan3;
|
||||||
|
plan3.name = "Plan3";
|
||||||
|
|
||||||
|
EXPECT_TRUE(engine.createTaskPlan(plan1));
|
||||||
|
EXPECT_TRUE(engine.createTaskPlan(plan2));
|
||||||
|
EXPECT_TRUE(engine.createTaskPlan(plan3));
|
||||||
|
|
||||||
|
// 验证 ID 唯一性
|
||||||
|
EXPECT_NE(plan1.id, plan2.id);
|
||||||
|
EXPECT_NE(plan1.id, plan3.id);
|
||||||
|
EXPECT_NE(plan2.id, plan3.id);
|
||||||
|
|
||||||
|
// 验证方案数量
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
ASSERT_EQ(plans.size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊场景测试:创建方案后,验证 createTime 被设置
|
||||||
|
TEST_F(CmsEngineTest, testCreateTaskPlanCreateTimeSet) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "TimeTest";
|
||||||
|
plan.type = PlanType::Centralized;
|
||||||
|
plan.status = PlanStatus::Drafting;
|
||||||
|
|
||||||
|
auto before = std::chrono::system_clock::now();
|
||||||
|
bool result = engine.createTaskPlan(plan);
|
||||||
|
auto after = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
EXPECT_TRUE(result);
|
||||||
|
EXPECT_GE(plan.createTime, before);
|
||||||
|
EXPECT_LE(plan.createTime, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 测试用例:getAllPlans
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requirement(name="任务方案列表查询", id="REQ-PLAN-LIST-001")
|
||||||
|
* 系统需返回全部任务方案列表的引用,以支撑方案全局视图展示。
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 正常输入测试:空列表
|
||||||
|
TEST_F(CmsEngineTest, testGetAllPlansEmpty) {
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
EXPECT_TRUE(plans.empty());
|
||||||
|
EXPECT_EQ(plans.size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正常输入测试:包含多个方案
|
||||||
|
TEST_F(CmsEngineTest, testGetAllPlansWithPlans) {
|
||||||
|
TaskPlan plan1;
|
||||||
|
plan1.name = "Plan1";
|
||||||
|
TaskPlan plan2;
|
||||||
|
plan2.name = "Plan2";
|
||||||
|
TaskPlan plan3;
|
||||||
|
plan3.name = "Plan3";
|
||||||
|
|
||||||
|
engine.createTaskPlan(plan1);
|
||||||
|
engine.createTaskPlan(plan2);
|
||||||
|
engine.createTaskPlan(plan3);
|
||||||
|
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
ASSERT_EQ(plans.size(), 3);
|
||||||
|
EXPECT_EQ(plans[0].name, "Plan1");
|
||||||
|
EXPECT_EQ(plans[1].name, "Plan2");
|
||||||
|
EXPECT_EQ(plans[2].name, "Plan3");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:验证返回的是常量引用,不可修改
|
||||||
|
TEST_F(CmsEngineTest, testGetAllPlansConstReference) {
|
||||||
|
// 编译时验证:const auto& 可以绑定,auto& 会编译错误
|
||||||
|
const auto& plans = engine.getAllPlans();
|
||||||
|
EXPECT_TRUE(plans.empty());
|
||||||
|
|
||||||
|
// 以下代码如果取消注释,编译会失败(因为返回 const 引用)
|
||||||
|
// plans.push_back(TaskPlan()); // 编译错误
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊场景测试:多次调用返回相同引用
|
||||||
|
TEST_F(CmsEngineTest, testGetAllPlansSameReference) {
|
||||||
|
const auto& plans1 = engine.getAllPlans();
|
||||||
|
const auto& plans2 = engine.getAllPlans();
|
||||||
|
EXPECT_EQ(&plans1, &plans2); // 应为同一对象
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 测试用例:findPlanById
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requirement(name="任务方案查找", id="REQ-PLAN-FIND-001")
|
||||||
|
* 系统需支持根据任务 ID 在方案库中遍历查找对应方案,
|
||||||
|
* 找到返回方案指针,未找到返回 nullptr。
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 正常输入测试:查找存在的方案
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdExisting) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "TestPlan";
|
||||||
|
plan.type = PlanType::Centralized;
|
||||||
|
plan.status = PlanStatus::Drafting;
|
||||||
|
engine.createTaskPlan(plan);
|
||||||
|
|
||||||
|
const TaskPlan* found = engine.findPlanById(plan.id);
|
||||||
|
ASSERT_NE(found, nullptr);
|
||||||
|
EXPECT_EQ(found->id, plan.id);
|
||||||
|
EXPECT_EQ(found->name, "TestPlan");
|
||||||
|
EXPECT_EQ(found->type, PlanType::Centralized);
|
||||||
|
EXPECT_EQ(found->status, PlanStatus::Drafting);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:查找不存在的 ID
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdNonExisting) {
|
||||||
|
const TaskPlan* found = engine.findPlanById("NON_EXISTENT_ID");
|
||||||
|
EXPECT_EQ(found, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:查找空字符串 ID
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdEmptyId) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "TestPlan";
|
||||||
|
engine.createTaskPlan(plan);
|
||||||
|
|
||||||
|
const TaskPlan* found = engine.findPlanById("");
|
||||||
|
EXPECT_EQ(found, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边界值测试:在空列表中查找
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdEmptyList) {
|
||||||
|
const TaskPlan* found = engine.findPlanById("ANY_ID");
|
||||||
|
EXPECT_EQ(found, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常输入测试:查找 ID 格式异常
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdInvalidFormat) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "TestPlan";
|
||||||
|
engine.createTaskPlan(plan);
|
||||||
|
|
||||||
|
// 查找类似但不同的 ID
|
||||||
|
const TaskPlan* found = engine.findPlanById(plan.id + "_extra");
|
||||||
|
EXPECT_EQ(found, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊场景测试:多个方案中查找特定方案
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdMultiplePlans) {
|
||||||
|
TaskPlan plan1;
|
||||||
|
plan1.name = "Plan1";
|
||||||
|
TaskPlan plan2;
|
||||||
|
plan2.name = "Plan2";
|
||||||
|
TaskPlan plan3;
|
||||||
|
plan3.name = "Plan3";
|
||||||
|
|
||||||
|
engine.createTaskPlan(plan1);
|
||||||
|
engine.createTaskPlan(plan2);
|
||||||
|
engine.createTaskPlan(plan3);
|
||||||
|
|
||||||
|
// 查找中间方案
|
||||||
|
const TaskPlan* found = engine.findPlanById(plan2.id);
|
||||||
|
ASSERT_NE(found, nullptr);
|
||||||
|
EXPECT_EQ(found->name, "Plan2");
|
||||||
|
|
||||||
|
// 查找最后一个方案
|
||||||
|
found = engine.findPlanById(plan3.id);
|
||||||
|
ASSERT_NE(found, nullptr);
|
||||||
|
EXPECT_EQ(found->name, "Plan3");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊场景测试:查找后修改方案(通过非 const 方法)
|
||||||
|
TEST_F(CmsEngineTest, testFindPlanByIdAndModify) {
|
||||||
|
TaskPlan plan;
|
||||||
|
plan.name = "TestPlan";
|
||||||
|
engine.createTaskPlan(plan);
|
||||||
|
|
||||||
|
// 通过 findPlanById 获取 const 指针,不能修改
|
||||||
|
const TaskPlan* found = engine.findPlanById(plan.id);
|
||||||
|
ASSERT_NE(found, nullptr);
|
||||||
|
EXPECT_EQ(found->status, PlanStatus::Drafting);
|
||||||
|
|
||||||
|
// 通过 updatePlanStatus 修改状态
|
||||||
|
bool updated = engine.updatePlanStatus(plan.id, PlanStatus::Completed);
|
||||||
|
EXPECT_TRUE(updated);
|
||||||
|
|
||||||
|
// 再次查找,验证状态已更新
|
||||||
|
found = engine.findPlanById(plan.id);
|
||||||
|
ASSERT_NE(found, nullptr);
|
||||||
|
EXPECT_EQ(found->status, PlanStatus::Completed);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue