主动化压测工具开发(MFC)

打印 上一主题 下一主题

主题 624|帖子 624|积分 1872

1. 背景

为了减轻测试人员在进行MFC程序压力测试时的重复手动操作,本文档描述了开发一个主动化压力测试工具的过程。该工具可以或许根据程序界面某块地区的预定状态变化,主动执行鼠标点击或键盘输入操作。
2. 技能概览



  • 串口控制:用于控制外部设备,如继电器。
  • MFC CRectTracker:实现截图功能,创建简单的截图对话框。
  • GDI+:用于图像处理和屏幕捕获。
  • mouse_event:模仿鼠标点击。
  • keybd_event:模仿键盘输入。
  • MD5:用于图像内容校验。
3. 串口通信控制

串口通光荣于控制继电器的上下电状态,进而控制USB设备的电源。
3.1 串口初始化

  1. bool CComTest::InitialCom(int iComID, int iComPort, DWORD iBaudRate) {
  2.     // 省略部分错误检查和资源清理代码...
  3.     // 配置串口参数
  4.     DCB dcbSerialParams = {0};
  5.     GetCommState(m_hCom, &dcbSerialParams);
  6.     dcbSerialParams.BaudRate = iBaudRate;
  7.     dcbSerialParams.ByteSize = 8;
  8.     dcbSerialParams.StopBits = STOPBITS_ONE;
  9.     dcbSerialParams.Parity = NOPARITY;
  10.     SetCommState(m_hCom, &dcbSerialParams);
  11.     // 设置串口超时
  12.     COMMTIMEOUTS timeouts = {0};
  13.     timeouts.ReadIntervalTimeout = MAXDWORD;
  14.     SetCommTimeouts(m_hCom, &timeouts);
  15.     // 完成串口初始化
  16.     return TRUE;
  17. }
复制代码
3.2 读取串口

  1. DWORD CComTest::ReadCom(BYTE *pBuff, int nCount) {
  2.     DWORD dwRead = 0;
  3.     ReadFile(m_hCom, pBuff, nCount, &dwRead, NULL);
  4.     return dwRead;
  5. }
复制代码
3.3 写串口

  1. BOOL CComTest::WriteCom(BYTE *pBuff, int nCount) {
  2.     DWORD dwWritten = 0;
  3.     return WriteFile(m_hCom, pBuff, nCount, &dwWritten, NULL);
  4. }
复制代码
3.4 发送串口命令示例

  1. BYTE pData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
  2. WriteCom(m_iComID, pData, sizeof(pData));
复制代码
4. 程序界面状态监控

通过截图对话框实现地区状态监控,主动执行下一步动作。
4.1 截图对话框初始化

  1. BOOL CCaptureDlg::OnInitDialog() {
  2.     CDialog::OnInitDialog();
  3.     // 屏幕截图并设置窗口大小
  4.     copyScreenToBitmap(m_ScreenBmp);
  5.     MoveWindow(-3, -3, GetSystemMetrics(SM_CXSCREEN) + 6, GetSystemMetrics(SM_CYSCREEN) + 6);
  6.     // 初始化橡皮筋跟踪器
  7.     m_rectTracker.m_nStyle = CRectTracker::resizeOutside | CRectTracker::dottedLine;
  8.     m_rectTracker.m_rect.SetRect(0, 0, 0, 0);
  9.     return TRUE;
  10. }
复制代码
4.2 截图对话框背景绘制

  1. BOOL CCaptureDlg::OnEraseBkgnd(CDC *pDC) {
  2.     CDC memDC;
  3.     memDC.CreateCompatibleDC(pDC);
  4.     memDC.SelectObject(&m_ScreenBmp);
  5.     pDC->BitBlt(0, 0, GetClientRect().Width(), GetClientRect().Height(), &memDC, 0, 0, SRCCOPY);
  6.     memDC.DeleteDC();
  7.     return TRUE;
  8. }
复制代码
4.3 鼠标消息处理

  1. void CCaptureDlg::OnLButtonDown(UINT nFlags, CPoint point) {
  2.     if (m_rectTracker.HitTest(point) == CRectTracker::hitNothing) {
  3.         m_rectTracker.TrackRubberBand(this, point, TRUE);
  4.     } else {
  5.         m_rectTracker.Track(this, point, TRUE);
  6.         m_rectTracker.m_rect.NormalizeRect();
  7.     }
  8.     Invalidate(TRUE);
  9.     CDialog::OnLButtonDown(nFlags, point);
  10. }
复制代码
4.4 双击变乱处理

  1. void CCaptureDlg::OnLButtonDblClk(UINT nFlags, CPoint point) {
  2.     if (m_rectTracker.HitTest(point) != CRectTracker::hitMiddle) {
  3.         MessageBox(_T("截图失败,请重新截图!"));
  4.         return;
  5.     }
  6.       // 检查双击是否在橡皮筋跟踪器的中间区域
  7.     if (m_rectTracker.HitTest(point) != CRectTracker::hitMiddle)
  8.     {
  9.         MessageBox(_T("截图失败, 请重新截图!"));
  10.         return;
  11.     }
  12.   // 保存双击时坐标
  13. m_startPointX = point.x;
  14. m_startPointY = point.y;
  15.     // 获取当前屏幕设备上下文
  16.     CDC* pScreenDC = GetDC();
  17.     if (!pScreenDC)
  18.     {
  19.         MessageBox(_T("无法获取屏幕设备上下文"));
  20.         return;
  21.     }
  22.     // 创建内存设备上下文与屏幕DC兼容,并选择m_ScreenBmp位图进该内存DC
  23.     CDC memDC;
  24.     memDC.CreateCompatibleDC(pScreenDC);
  25.     CBitmap* pOldBitmap = memDC.SelectObject(&m_ScreenBmp);
  26.     // 获取橡皮筋跟踪器定义的区域
  27.     CRect captureRect = m_rectTracker.m_rect;
  28.     // 创建一个兼容的位图用于保存截取的区域
  29.     CBitmap captureBmp;
  30.     captureBmp.CreateCompatibleBitmap(pScreenDC, captureRect.Width(), captureRect.Height());
  31.     // 创建另一个内存DC,选择刚才创建的兼容位图进这个DC
  32.     CDC captureDC;
  33.     captureDC.CreateCompatibleDC(pScreenDC);
  34.     CBitmap* pOldCaptureBmp = captureDC.SelectObject(&captureBmp);
  35.     // 从原屏幕位图中截取定义区域的图像到captureDC
  36.     captureDC.BitBlt(0, 0, captureRect.Width(), captureRect.Height(), &memDC, captureRect.left, captureRect.top, SRCCOPY);
  37.     // 使用CImage类来保存位图到文件
  38.     CImage img;
  39.     img.Attach(captureBmp);
  40.     CString strCapturePath = _T("你想要保存的路径\\capture1.jpg");
  41.     img.Save(strCapturePath);
  42.     // 清理资源
  43.     captureDC.SelectObject(pOldCaptureBmp);
  44.     memDC.SelectObject(pOldBitmap);
  45.     captureBmp.DeleteObject();
  46.     memDC.DeleteDC();
  47.     captureDC.DeleteDC();
  48.     ReleaseDC(pScreenDC);
  49.     // 截图操作完成后关闭对话框
  50.     CDialog::OnCancel();
  51. }
复制代码
在压测前,将被压测程序运行到指定状态,用上述[截图窗口]截取指定地区的位图(目标状态),在压测时,不停的检测此地区的变化,如达到目标状态,则执行模仿点击等操作。

4.5 截取屏幕上指定地区的图像

下面函数用于截取屏幕上指定地区的图像,在压测时,可用于实时检测指定地区的位图。
  1. void CCaptureDlg::Screen(const CRect& cRect, int iNumber)
  2. {
  3.     // 使用局部函数来自动释放资源
  4.     struct AutoRelease
  5.     {
  6.         HDC hDC;
  7.         ~AutoRelease() { if (hDC) ::ReleaseDC(NULL, hDC); }
  8.     } autoReleaseDC;
  9.     // 获取屏幕设备上下文
  10.     autoReleaseDC.hDC = ::GetDC(NULL);
  11.     if (!autoReleaseDC.hDC)
  12.     {
  13.         MessageBox(_T("无法获取屏幕设备上下文。"));
  14.         return;
  15.     }
  16.     CDC memDC;
  17.     memDC.CreateCompatibleDC(NULL); // 创建与屏幕兼容的内存设备上下文
  18.     // 创建与屏幕兼容的位图
  19.     CBitmap memBitmap;
  20.     memBitmap.CreateCompatibleBitmap(autoReleaseDC.hDC, cRect.Width(), cRect.Height());
  21.     // 将新创建的位图选入内存设备上下文中
  22.     CBitmap* pOldBitmap = memDC.SelectObject(&memBitmap);
  23.     // 从屏幕设备上下文中复制图像到内存设备上下文中的位图
  24.     memDC.BitBlt(0, 0, cRect.Width(), cRect.Height(), CDC::FromHandle(autoReleaseDC.hDC), cRect.left, cRect.top, SRCCOPY);
  25.     // 使用CImage类来操作和保存位图
  26.     CImage img;
  27.     if (!img.Attach(memBitmap))
  28.     {
  29.         MessageBox(_T("无法将位图附加到CImage对象。"));
  30.         return;
  31.     }
  32.     // 构造文件保存路径
  33.     CString strCapturePath;
  34.     strCapturePath.Format(_T("保存路径\\capture%d.jpg"), iNumber);
  35.     // 保存位图到文件
  36.     if (!img.Save(strCapturePath))
  37.     {
  38.         AfxMessageBox(_T("保存图像失败。"));
  39.     }
  40.     // 清理资源
  41.     memDC.SelectObject(pOldBitmap); // 恢复原始位图
  42.     img.Detach(); // 从CImage对象中分离位图
  43. }
复制代码
5. 模仿输入操作

5.1 模仿鼠标点击

  1. void SimulateMouseClick(int x, int y) {
  2.     SetCursorPos(x, y);
  3.     mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
  4.     mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
  5. }
复制代码
5.2 模仿键盘输入

  1. void SimulateKeyboardInput(const char *szInput) {
  2.     for (int i = 0; szInput[i] != '\0'; ++i) {
  3.         keybd_event(szInput[i], 0, 0, 0);
  4.         keybd_event(szInput[i], 0, KEYEVENTF_KEYUP, 0);
  5.     }
  6. }
复制代码
结束语

本文档提供了一个主动化压力测试工具的底子实现,包括串口通信、截图监控、状态校验和模仿输入操作。根据详细需求,可进一步扩展和优化工具的功能。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张国伟

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表