task_auto_plan1/tests/basic_test.cpp

286 lines
8.3 KiB
C++
Raw Normal View History

2026-04-25 04:26:31 +00:00
#include "app.hpp"
#include <cassert>
#include <iostream>
2026-04-25 04:29:20 +00:00
#include <cstring>
// ============================================================
// 单元测试(使用标准库 assert无外部依赖
// ============================================================
static void testEmployeeManagement() {
AttendanceService svc;
// 添加员工
Employee e;
e.employeeId = "T001";
e.name = "测试员工";
e.department = "测试部";
e.position = "测试工程师";
e.shiftId = "S001";
e.phone = "13900001111";
e.role = RoleType::Employee;
svc.addEmployee(e);
// 查找
const Employee* found = svc.findEmployee("T001");
assert(found != nullptr);
assert(found->name == "测试员工");
assert(found->department == "测试部");
// 脱敏手机号
std::string masked = found->maskedPhone();
assert(masked == "*******1111");
std::cout << "[PASS] testEmployeeManagement: 员工管理正常" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
static void testDuplicateEmployee() {
AttendanceService svc;
Employee e;
e.employeeId = "T002";
e.name = "重复测试";
svc.addEmployee(e);
bool thrown = false;
try {
svc.addEmployee(e);
} catch (const std::runtime_error&) {
thrown = true;
}
assert(thrown);
std::cout << "[PASS] testDuplicateEmployee: 重复添加异常正常" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
static void testCheckInAndRecords() {
AttendanceService svc;
Employee e;
e.employeeId = "T003";
e.name = "打卡测试";
e.department = "测试部";
e.shiftId = "S001";
svc.addEmployee(e);
// 上班打卡
std::time_t now = std::time(nullptr);
auto rec1 = svc.processCheckIn("T003", CheckType::ClockIn, "DEVICE_TEST", now);
assert(rec1.employeeId == "T003");
assert(rec1.type == CheckType::ClockIn);
assert(rec1.verified == true);
2026-04-25 04:26:31 +00:00
assert(!rec1.recordId.empty());
2026-04-25 04:29:20 +00:00
// 下班打卡
auto rec2 = svc.processCheckIn("T003", CheckType::ClockOut, "DEVICE_TEST", now + 28800); // 8h后
assert(rec2.type == CheckType::ClockOut);
// 查询记录
auto records = svc.getRecords("T003");
assert(records.size() == 2);
assert(records[0].type == CheckType::ClockIn);
assert(records[1].type == CheckType::ClockOut);
// 未知员工打卡应抛异常
bool thrown = false;
try {
svc.processCheckIn("UNKNOWN", CheckType::ClockIn, "DEVICE", now);
} catch (const std::runtime_error&) {
thrown = true;
}
assert(thrown);
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
std::cout << "[PASS] testCheckInAndRecords: 打卡流程正常" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
static void testDailyCalculation() {
AttendanceService svc;
Employee e;
e.employeeId = "T004";
e.name = "核算测试";
e.department = "测试部";
e.shiftId = "S001";
svc.addEmployee(e);
// 模拟当日打卡8:30 上班18:00 下班
std::time_t now = std::time(nullptr);
std::tm* tm = std::localtime(&now);
std::tm tm_in = *tm;
tm_in.tm_hour = 8;
tm_in.tm_min = 30;
tm_in.tm_sec = 0;
std::time_t tIn = std::mktime(&tm_in);
std::tm tm_out = *tm;
tm_out.tm_hour = 18;
tm_out.tm_min = 0;
tm_out.tm_sec = 0;
std::time_t tOut = std::mktime(&tm_out);
svc.processCheckIn("T004", CheckType::ClockIn, "DEVICE", tIn);
svc.processCheckIn("T004", CheckType::ClockOut, "DEVICE", tOut);
// 获取核算结果
std::ostringstream oss;
oss << std::put_time(tm, "%Y-%m-%d");
std::string today = oss.str();
auto da = svc.calculateDaily("T004", today);
assert(!da.dateStr.empty());
assert(da.employeeId == "T004");
assert(da.expectedMinutes > 0);
assert(da.actualMinutes > 0);
// 实际工时应约为 8.5h - 1h(午休) = 7.5h = 450min有弹性
// 但至少大于0
assert(da.actualMinutes > 100);
std::cout << "[PASS] testDailyCalculation: 核算正常, 出勤 " << da.actualMinutes << " 分钟" << std::endl;
}
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
static void testAbnormalDetection() {
AttendanceService svc;
Employee e;
e.employeeId = "T005";
e.name = "异常测试";
e.department = "测试部";
e.shiftId = "S001";
svc.addEmployee(e);
// 没有打卡记录 -> 旷工
std::time_t now = std::time(nullptr);
std::tm* tm = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(tm, "%Y-%m-%d");
std::string today = oss.str();
auto da = svc.calculateDaily("T005", today);
assert(da.abnormal == AbnormalFlag::Absenteeism);
std::cout << "[PASS] testAbnormalDetection: 无打卡=旷工判定正常" << std::endl;
}
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
static void testReportGeneration() {
AttendanceService svc;
// 添加员工
Employee e1;
e1.employeeId = "T006";
e1.name = "报表A";
e1.department = "报表部";
svc.addEmployee(e1);
Employee e2;
e2.employeeId = "T007";
e2.name = "报表B";
e2.department = "报表部";
svc.addEmployee(e2);
// 添加打卡
std::time_t now = std::time(nullptr);
std::tm* tm = std::localtime(&now);
std::tm tm_in = *tm;
tm_in.tm_hour = 9;
tm_in.tm_min = 0;
std::time_t tIn = std::mktime(&tm_in);
std::tm tm_out = *tm;
tm_out.tm_hour = 18;
tm_out.tm_min = 0;
std::time_t tOut = std::mktime(&tm_out);
svc.processCheckIn("T006", CheckType::ClockIn, "DEVICE", tIn);
svc.processCheckIn("T006", CheckType::ClockOut, "DEVICE", tOut);
svc.processCheckIn("T007", CheckType::ClockIn, "DEVICE", tIn);
svc.processCheckIn("T007", CheckType::ClockOut, "DEVICE", tOut);
// 生成报表
std::ostringstream oss;
oss << std::put_time(tm, "%Y-%m-%d");
std::string today = oss.str();
auto report = svc.generateReport("报表部", today, today);
assert(!report.empty());
assert(report.size() == 2);
std::cout << "[PASS] testReportGeneration: 报表生成正常, 共 " << report.size() << " 条记录" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
static void testAlertCreation() {
AttendanceService svc;
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
// 创建预警
auto alert = svc.createAlert("T999", AbnormalFlag::Late);
assert(!alert.alertId.empty());
assert(alert.employeeId == "T999");
assert(alert.type == AbnormalFlag::Late);
assert(alert.status == AlertStatus::Pending);
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
// 查询
auto alerts = svc.getAlerts("T999");
assert(alerts.size() == 1);
assert(alerts[0].type == AbnormalFlag::Late);
std::cout << "[PASS] testAlertCreation: 预警创建与查询正常" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
static void testReportTask() {
AttendanceService svc;
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
auto task = svc.createReportTask("ADMIN", "部门X", "2025-01-01", "2025-01-31", ReportFormat::PDF);
assert(task.taskId.length() > 0);
assert(task.status == "Pending");
assert(task.format == ReportFormat::PDF);
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
svc.completeTask(task.taskId, "/download/test.pdf");
assert(task.status == "Done");
assert(task.downloadUrl == "/download/test.pdf");
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
std::cout << "[PASS] testReportTask: 报表任务流程正常" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
static void testMaskSensitive() {
assert(maskSensitive("12345678901", 3, 4) == "123****8901");
assert(maskSensitive("abc", 1, 1) == "abc"); // 太短时不脱敏
assert(maskSensitive("", 0, 0).empty());
std::cout << "[PASS] testMaskSensitive: 脱敏函数正常" << std::endl;
}
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
static void testShiftRule() {
ShiftRule rule;
rule.shiftId = "S999";
rule.startHour = 8;
rule.startMin = 30;
rule.endHour = 17;
rule.endMin = 30;
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
assert(rule.workStartMinutes() == 8 * 60 + 30); // 510
assert(rule.workEndMinutes() == 17 * 60 + 30); // 1050
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
std::cout << "[PASS] testShiftRule: 排班规则计算正常" << std::endl;
2026-04-25 04:26:31 +00:00
}
2026-04-25 04:29:20 +00:00
// ============================================================
// 主测试入口
// ============================================================
2026-04-25 04:26:31 +00:00
2026-04-25 04:29:20 +00:00
int main() {
std::cout << "============================================" << std::endl;
std::cout << " 智能考勤管理系统 - 单元测试" << std::endl;
std::cout << "============================================" << std::endl;
testEmployeeManagement();
testDuplicateEmployee();
testCheckInAndRecords();
testDailyCalculation();
testAbnormalDetection();
testReportGeneration();
testAlertCreation();
testReportTask();
testMaskSensitive();
testShiftRule();
std::cout << "============================================" << std::endl;
std::cout << "所有测试通过!" << std::endl;
std::cout << "============================================" << std::endl;
2026-04-25 04:26:31 +00:00
return 0;
}