4个步骤掌握MaaFramework自动化测试:Python|Node.js|C全攻略

张开发
2026/4/6 11:22:35 15 分钟阅读

分享文章

4个步骤掌握MaaFramework自动化测试:Python|Node.js|C全攻略
4个步骤掌握MaaFramework自动化测试Python|Node.js|C#全攻略【免费下载链接】MaaFramework基于图像识别的自动化黑盒测试框架 | An automation black-box testing framework based on image recognition项目地址: https://gitcode.com/gh_mirrors/ma/MaaFramework1. 框架概述MaaFramework是一款基于图像识别的自动化黑盒测试框架通过多语言绑定为开发者提供灵活的自动化测试解决方案。该框架核心优势在于其跨平台能力、多语言支持以及强大的图像识别引擎能够模拟人工操作完成复杂的UI交互测试。[!TIP] MaaFramework采用模块化设计主要包含资源管理、任务调度、图像识别和设备控制四大核心模块支持自定义识别算法和操作逻辑扩展。核心架构资源管理层负责测试资源模板图像、配置文件的加载与缓存任务引擎解析并执行测试流程支持条件分支和循环控制图像识别集成多种识别算法模板匹配、OCR、特征检测设备控制支持多种控制方式ADB、模拟输入、远程控制 重点总结MaaFramework适用于需要视觉交互的自动化测试场景支持Windows/macOS/Linux多平台部署提供Python/Node.js/C#等多语言API可通过自定义识别和操作扩展框架能力2. 环境配置操作指南2.1 基础环境准备# 克隆项目仓库 git clone https://gitcode.com/gh_mirrors/ma/MaaFramework # 进入项目目录 cd MaaFramework[!TIP] 建议使用Python虚拟环境或Node.js版本管理工具(nvm/nodenv)隔离项目依赖避免版本冲突。2.2 依赖安装Python环境# 安装Python依赖 pip install -r sample/python/requirements.txtNode.js环境# 安装Node.js依赖 cd source/binding/NodeJS npm install npm run buildC#环境# 还原NuGet包 dotnet restore sample/csharp2.3 验证安装# 验证Python环境 python sample/python/demo1.py # 验证Node.js环境 cd sample/nodejs npm install node main.js 重点总结确保CMake 3.24和对应语言环境已正确配置安装过程中若出现编译错误可参考官方构建指南首次运行需下载必要的资源文件确保网络通畅Windows系统可能需要安装Visual C运行时库3. Python语言专题 Python绑定提供了最简洁的API接口适合快速原型开发和小规模自动化测试脚本编写。3.1 核心特性简洁的同步API设计降低使用门槛完善的异常处理机制支持装饰器风格的自定义识别与操作注册内置事件回调系统3.2 快速上手from maa import MaaResource, MaaTasker, MaaController import logging # 配置日志 logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) def main(): try: # 初始化资源管理器 resource MaaResource(../resource) if not resource.load(): raise RuntimeError(资源加载失败) # 初始化控制器 (以ADB为例) controller MaaController(adb, 127.0.0.1:5555) if not controller.connect(): raise RuntimeError(设备连接失败) # 创建任务器 tasker MaaTasker() tasker.set_resource(resource) tasker.set_controller(controller) # 添加任务 task_id tasker.append_task(LoginTask, { action: click, target: login_button, timeout: 10000 }) # 执行任务并等待完成 result tasker.wait_task(task_id) if result ! 0: logger.error(f任务执行失败错误码: {result}) else: logger.info(任务执行成功) except Exception as e: logger.error(f发生错误: {str(e)}) finally: # 确保资源正确释放 if tasker in locals(): del tasker if controller in locals(): controller.disconnect() if resource in locals(): del resource if __name__ __main__: main()3.3 进阶应用自定义识别实现from maa import register_custom_recognition, MaaImage, Rect register_custom_recognition(CustomButtonRecognizer) def recognize_button(context, image: MaaImage): 自定义按钮识别器 # 获取图像尺寸 width, height image.size # 模拟识别逻辑在图像中心区域查找红色按钮 # 实际应用中应替换为真实的图像识别算法 found False if width 0 and height 0: # 模拟识别到按钮 found True x, y, w, h width//2 - 50, height//2 - 25, 100, 50 if found: return { rect: Rect(x, y, w, h), confidence: 0.95, detail: {button_type: primary} } return None任务流程控制# 创建条件任务流程 def create_workflow(tasker): # 登录任务 login_task tasker.append_task(Login, {action: custom_recognition, name: CustomButtonRecognizer}) # 条件分支登录成功后执行主任务 main_task tasker.append_task(Main, {action: sequence}, [login_task]) # 条件分支登录失败后执行重试 retry_task tasker.append_task(RetryLogin, {action: delay, duration: 3000}, [login_task], successFalse) # 将重试任务连接回登录任务形成循环 tasker.set_task_dependency(login_task, [retry_task]) return main_task # 使用工作流 main_task create_workflow(tasker) tasker.wait_task(main_task)性能优化技巧# 启用资源预加载 resource MaaResource(../resource) resource.set_option(preload, True) resource.load() # 设置图像缓存策略 tasker.set_option(image_cache, True) tasker.set_option(cache_ttl, 5000) # 缓存有效期5秒 # 批量添加任务减少通信开销 tasks [ {name: Task1, params: {action: click, target: btn1}}, {name: Task2, params: {action: input, text: test}}, {name: Task3, params: {action: screencap}} ] task_ids tasker.batch_append_tasks(tasks) 重点总结Python API适合快速开发和原型验证自定义识别和操作通过装饰器注册使用灵活任务依赖机制支持复杂流程控制资源预加载和图像缓存可显著提升性能4. Node.js语言专题 Node.js绑定提供异步非阻塞API适合构建高性能的自动化测试服务和长时间运行的测试任务。4.1 核心特性全异步API设计提高并发处理能力基于EventEmitter的事件驱动架构TypeScript类型定义提供良好的开发体验支持Promise和async/await语法4.2 快速上手const { MaaResource, MaaTasker, MaaController, LoggingLevel } require(maa-node); const path require(path); async function runAutomation() { // 配置日志级别 MaaTasker.setGlobalOption(stdout_level, LoggingLevel.Debug); let resource, controller, tasker; try { // 初始化资源 resource new MaaResource(path.resolve(__dirname, ../resource)); const loadResult await resource.load(); if (!loadResult) { throw new Error(资源加载失败); } // 初始化控制器 controller new MaaController(adb, 127.0.0.1:5555); const connectResult await controller.connect(); if (!connectResult) { throw new Error(设备连接失败); } // 创建任务器 tasker new MaaTasker(); tasker.setResource(resource); tasker.setController(controller); // 注册事件监听 tasker.on(task_start, (taskId, taskName) { console.log(任务开始: ${taskName} (ID: ${taskId})); }); tasker.on(task_complete, (taskId, status, message) { console.log(任务完成: ID ${taskId}, 状态: ${status}, 消息: ${message}); }); // 添加任务 const taskId await tasker.appendTask(MainTask, JSON.stringify({ action: screencap, save_path: ./screenshot.png })); // 等待任务完成 const result await tasker.waitTask(taskId); if (result ! 0) { console.error(任务执行失败错误码: ${result}); } else { console.log(任务执行成功); } } catch (error) { console.error(自动化过程出错:, error.message); } finally { // 清理资源 if (tasker) { tasker.destroy(); } if (controller) { await controller.disconnect(); } if (resource) { resource.destroy(); } } } runAutomation();4.3 进阶应用自定义操作实现const { registerCustomAction } require(maa-node); // 注册自定义操作 registerCustomAction(SwipeAction, async (context, params) { try { const { startX, startY, endX, endY, duration 500 } params; // 获取控制器实例 const controller context.getController(); // 执行滑动操作 await controller.swipe(startX, startY, endX, endY, duration); // 等待滑动完成 await new Promise(resolve setTimeout(resolve, duration 100)); return { success: true, message: 滑动操作完成: (${startX},${startY}) - (${endX},${endY}) }; } catch (error) { return { success: false, message: 滑动操作失败: ${error.message} }; } }); // 使用自定义操作 async function useCustomAction(tasker) { const taskId await tasker.appendTask(SwipeTask, JSON.stringify({ action: custom, custom_action: SwipeAction, startX: 500, startY: 800, endX: 500, endY: 300, duration: 800 })); return tasker.waitTask(taskId); }任务队列管理class TaskQueue { constructor(tasker) { this.tasker tasker; this.queue []; this.running false; } enqueue(taskName, params) { return new Promise((resolve) { this.queue.push({ taskName, params, resolve }); if (!this.running) { this.processQueue(); } }); } async processQueue() { this.running true; while (this.queue.length 0) { const { taskName, params, resolve } this.queue.shift(); try { const taskId await this.tasker.appendTask(taskName, JSON.stringify(params)); const result await this.tasker.waitTask(taskId); resolve({ success: result 0, taskId, result }); } catch (error) { resolve({ success: false, error: error.message }); } } this.running false; } } // 使用任务队列 async function runTaskQueue() { const tasker new MaaTasker(); // ... 初始化资源和控制器 ... const queue new TaskQueue(tasker); // 添加多个任务到队列 const results await Promise.all([ queue.enqueue(Task1, { action: click, target: btn1 }), queue.enqueue(Task2, { action: input, text: hello }), queue.enqueue(Task3, { action: custom, custom_action: SwipeAction }) ]); console.log(所有任务完成:, results); }性能调优// 配置任务执行选项 tasker.setOption(max_concurrent_tasks, 2); // 限制并发任务数 tasker.setOption(image_compression, true); // 启用图像压缩 tasker.setOption(recognition_timeout, 3000); // 设置识别超时 // 使用任务批处理 const batchTasks [ { name: TaskA, params: { action: screencap } }, { name: TaskB, params: { action: ocr, region: [100, 200, 300, 50] } }, { name: TaskC, params: { action: click, target: ok_btn } } ]; // 批量添加任务 const taskIds await tasker.batchAppendTasks(batchTasks); // 等待所有任务完成 const results await Promise.all( taskIds.map(id tasker.waitTask(id)) ); 重点总结Node.js异步API适合构建高性能测试服务事件驱动模型便于监控任务执行过程任务队列可有效管理复杂测试流程批量任务处理能显著提升执行效率5. C#语言专题 C#绑定提供强类型支持和面向对象设计适合构建大型、可维护的自动化测试项目。5.1 核心特性强类型API设计编译时类型检查基于IDisposable接口的资源管理事件驱动架构支持多线程操作与.NET生态系统无缝集成5.2 快速上手using System; using System.Threading.Tasks; using MaaFramework.Binding; using MaaFramework.Binding.Control; using MaaFramework.Binding.Resource; using MaaFramework.Binding.Tasker; class AutomationRunner : IDisposable { private readonly MaaResource _resource; private readonly MaaController _controller; private readonly MaaTasker _tasker; private bool _disposed false; public AutomationRunner(string resourcePath, string deviceAddress) { // 初始化资源 _resource new MaaResource(resourcePath); if (!_resource.Load()) throw new InvalidOperationException(资源加载失败); // 初始化控制器 _controller MaaController.CreateAdbController(deviceAddress); if (!_controller.Connect().Result) throw new InvalidOperationException(设备连接失败); // 初始化任务器 _tasker new MaaTasker(); _tasker.Resource _resource; _tasker.Controller _controller; // 注册事件 _tasker.TaskStarted OnTaskStarted; _tasker.TaskCompleted OnTaskCompleted; } private void OnTaskStarted(object? sender, TaskStartedEventArgs e) { Console.WriteLine($任务开始: {e.TaskName} (ID: {e.TaskId})); } private void OnTaskCompleted(object? sender, TaskCompletedEventArgs e) { Console.WriteLine($任务完成: ID {e.TaskId}, 状态: {e.Status}, 消息: {e.Message}); } public async Taskint RunTask(string taskName, string parameters) { if (_disposed) throw new ObjectDisposedException(nameof(AutomationRunner)); var taskId await _tasker.AppendTaskAsync(taskName, parameters); return await _tasker.WaitTaskAsync(taskId); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { // 释放托管资源 _tasker.TaskStarted - OnTaskStarted; _tasker.TaskCompleted - OnTaskCompleted; _tasker.Dispose(); _controller.Dispose(); _resource.Dispose(); } _disposed true; } ~AutomationRunner() { Dispose(false); } } // 使用示例 class Program { static async Task Main(string[] args) { try { using var runner new AutomationRunner( ../resource, 127.0.0.1:5555 ); var result await runner.RunTask(MainTask, {action: screencap, save_path: screenshot.png}); if (result ! 0) Console.WriteLine($任务执行失败错误码: {result}); else Console.WriteLine(任务执行成功); } catch (Exception ex) { Console.WriteLine($发生错误: {ex.Message}); } } }5.3 进阶应用自定义识别组件using MaaFramework.Binding.Custom; using MaaFramework.Binding.Image; public class QRCodeRecognizer : IMaaCustomRecognition { public string Name QRCodeRecognizer; public bool Analyze(IMaaContext context, in AnalyzeArgs args, in AnalyzeResults results) { try { // 获取图像数据 using var image args.Image; // 实际应用中应替换为真实的QR码识别逻辑 var qrCodeRegion new Rect(200, 300, 400, 400); // 模拟识别到的QR码区域 // 设置识别结果 results.Box.SetValue(qrCodeRegion); results.Confidence.SetValue(0.98); results.Detail.SetValue(QRCode content here); return true; } catch (Exception ex) { Console.WriteLine($QR码识别失败: {ex.Message}); return false; } } } // 注册自定义识别器 var recognizer new QRCodeRecognizer(); MaaCustomRecognition.Register(recognizer); // 使用自定义识别器 var taskParams new { action custom_recognition, name QRCodeRecognizer, timeout 5000 }; var result await runner.RunTask(QRCodeTask, JsonSerializer.Serialize(taskParams));任务流程控制public class TaskFlowManager { private readonly MaaTasker _tasker; private Dictionarystring, TaskNode _taskNodes new(); public TaskFlowManager(MaaTasker tasker) { _tasker tasker; } public void AddTask(string taskName, string parameters, IEnumerablestring dependencies null, bool onSuccess true) { _taskNodes[taskName] new TaskNode { Name taskName, Parameters parameters, Dependencies dependencies?.ToList() ?? new Liststring(), OnSuccess onSuccess }; } public async Task RunFlow(string startTask) { if (!_taskNodes.ContainsKey(startTask)) throw new ArgumentException($任务 {startTask} 不存在); await ProcessTask(startTask); } private async Task ProcessTask(string taskName) { var node _taskNodes[taskName]; // 等待所有依赖任务完成 foreach (var dep in node.Dependencies) { await ProcessTask(dep); } // 执行当前任务 var taskId await _tasker.AppendTaskAsync(node.Name, node.Parameters); var result await _tasker.WaitTaskAsync(taskId); // 根据结果决定是否继续执行后续任务 if ((result 0 node.OnSuccess) || (result ! 0 !node.OnSuccess)) { var nextTasks _taskNodes.Values .Where(n n.Dependencies.Contains(taskName)) .Select(n n.Name); foreach (var nextTask in nextTasks) { await ProcessTask(nextTask); } } } private class TaskNode { public string Name { get; set; } public string Parameters { get; set; } public Liststring Dependencies { get; set; } public bool OnSuccess { get; set; } true; } } // 使用任务流程管理器 var flowManager new TaskFlowManager(tasker); flowManager.AddTask(Login, {action: login}); flowManager.AddTask(Home, {action: goto_home}, new[] { Login }); flowManager.AddTask(RetryLogin, {action: retry_login}, new[] { Login }, onSuccess: false); await flowManager.RunFlow(Login);性能优化// 配置全局选项 MaaFrameworkConfig.SetGlobalOption(GlobalOption.StdoutLevel, (int)LoggingLevel.Info); MaaFrameworkConfig.SetGlobalOption(GlobalOption.CachePath, .cache); MaaFrameworkConfig.SetGlobalOption(GlobalOption.MaxCacheSize, 1024 * 1024 * 100); // 100MB // 资源预加载 _resource.SetOption(ResourceOption.Preload, true); _resource.SetOption(ResourceOption.PipelineCache, true); // 图像识别优化 _tasker.SetOption(TaskerOption.RecognitionThreadCount, Environment.ProcessorCount); _tasker.SetOption(TaskerOption.TemplateCache, true); _tasker.SetOption(TaskerOption.FeatureDetector, fast); // 使用快速特征检测算法 重点总结C#绑定适合构建大型、结构化的测试项目IDisposable接口确保资源安全释放强类型设计减少运行时错误任务流程管理器可实现复杂的测试逻辑6. 实战技巧与最佳实践6.1 通用最佳实践[!TIP] 自动化测试成功的关键在于良好的资源管理和错误处理。始终确保在测试完成后正确释放所有资源避免内存泄漏。资源管理策略采用工厂模式创建和管理MaaFramework核心对象使用try-finally或using语句确保资源释放实现资源池以复用频繁创建的对象对大型资源如图像模板采用延迟加载策略错误处理模式# Python错误处理示例 def safe_operation(operation, *args, **kwargs): max_retries 3 for attempt in range(max_retries): try: return operation(*args, **kwargs) except Exception as e: if attempt max_retries - 1: raise time.sleep(1) # 重试前等待 print(f操作失败重试 {attempt 1}/{max_retries})6.2 性能优化指南图像识别优化合理设置识别区域减少处理范围根据场景选择适当的识别算法模板匹配/OCR/特征检测对高频识别任务启用结果缓存调整识别阈值平衡准确率和性能任务执行优化批量执行相似任务减少通信开销合理设置任务超时时间利用并行任务处理提高执行效率对长时间运行的任务实现进度监控6.3 常见陷阱与解决方案识别精度问题问题在不同设备或分辨率下识别准确率下降解决方案使用多分辨率模板、动态调整识别区域、增加置信度阈值性能瓶颈问题连续识别操作导致CPU占用过高解决方案实现识别结果缓存、降低识别频率、使用异步识别设备兼容性问题不同设备控制方式差异导致兼容性问题解决方案抽象设备控制接口、实现设备适配层、提供多种控制方案6.4 调试与日志日志配置// Node.js日志配置示例 const { LoggingLevel } require(maa-node); // 设置全局日志级别 MaaTasker.setGlobalOption(stdout_level, LoggingLevel.Debug); MaaTasker.setGlobalOption(log_file, automation.log); MaaTasker.setGlobalOption(log_file_level, LoggingLevel.Trace);调试技巧启用详细日志记录所有操作保存识别过程中的中间图像使用回调函数跟踪任务执行流程实现任务执行时间统计MaaFramework自动化测试过程中的界面截图示例 重点总结资源管理和错误处理是自动化测试稳定性的关键针对不同场景选择合适的识别算法和参数合理使用缓存和批处理提升性能完善的日志和调试机制有助于问题定位7. 资源与参考7.1 官方文档集成文档docs/zh_cn/2.1-集成文档.md任务流水线协议docs/zh_cn/3.1-任务流水线协议.md构建指南docs/zh_cn/4.1-构建指南.md7.2 API参考Python APIsource/binding/Python/maa/Node.js APIsource/binding/NodeJS/src/apis/C# APIsample/csharp/【免费下载链接】MaaFramework基于图像识别的自动化黑盒测试框架 | An automation black-box testing framework based on image recognition项目地址: https://gitcode.com/gh_mirrors/ma/MaaFramework创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

更多文章