
1. LuckyFrame到底是什么先说结论LuckyFrame是一套开源的自动化测试平台分服务端和客户端两部分服务端叫LuckyFrameweb客户端叫LuckyFrameClient。它把测试用例管理、任务调度、执行机管理、报告展示全部集中到一个Web界面上客户端只需要在你的测试机上跑一个Agent就能接收服务端下发的任务执行完自动回传结果。我第一次接触这个项目是团队里手工回归测不过来了接口自动化脚本散落在各个开发本地没人统一管也不出统一报告。当时就想找一个能集中管理用例、能指定机器执行、能出漂亮报告的现成平台。调研了一圈比对了几个主流开源方案之后最终选了LuckyFrame。选它的理由很简单部署结构清晰服务端负责调度和展示客户端负责执行数据通过数据库和文件传输解耦出了问题分得清楚是哪一层的锅而且它天然支持接口自动化和UI自动化Selenium/Appium两种最常见场景团队成员上手门槛不算高。这篇文章我会从零开始完整讲一遍LuckyFrame的安装部署过程从JDK、MySQL、Redis这些基础环境到LuckyFrameweb服务端的部署再到LuckyFrameClient客户端的配置最后带着你跑通第一个自动化任务。全程覆盖我实际部署中踩过的坑和排查思路照着做基本能少走一周弯路。适合正在调研自动化测试平台、想搭一套自用平台、或者已经在部署LuckyFrame但卡在某一步的测试开发同学参考。2. 部署前的环境准备2.1 服务端与客户端的基础依赖清单LuckyFrame的服务端本质是一个Java Web应用客户端本质是一个Java进程。所以无论服务端还是客户端都绕不开JDK。再加上服务端要用MySQL存配置和用例数据、用Redis做缓存和排队所以整个平台最基础的依赖就这么几样。组件版本建议用途JDK1.864位服务端和客户端的运行环境MySQL5.7 或 8.0存储用户、项目、用例、任务、报告等数据Redis5.x 或 6.x任务排队、分布式锁、会话缓存Tomcat8.5 或 9.0部署LuckyFrameweb的Web应用Maven3.6源码打包如果下载源码自行构建Node.js可选如果前端部分需要重新构建实际操作中我强烈建议JDK用1.8。虽然高版本JDK在多数场景也能跑但LuckyFrame的客户端设计较早某些反射和字节码操作在高版本JDK下可能会遇到非法访问告警排查起来比较痛苦。MySQL我这边用的是5.7因为要保证字符集和排序规则好控制如果你用MySQL 8.0也没问题只是连接驱动版本需要配套后面配置里会提到。2.2 JDK安装与JAVA_HOME配置细节JDK安装本身不复杂复杂的是环境变量。很多部署问题最终定位出来都是因为JAVA_HOME没配好Tomcat和客户端进程用了不同版本的Java。Linux下的安装路径我一般放在/usr/local/java/jdk1.8.0_202然后编辑/etc/profile追加以下内容export JAVA_HOME/usr/local/java/jdk1.8.0_202 export PATH$JAVA_HOME/bin:$PATH export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar配置完执行source /etc/profile然后用java -version验证。这里有一个非常关键的细节不仅要在当前会话验证还要确保重启后依然有效。我的习惯是配置完再重新登录一次服务器看环境变量是否还在以免出现“当前能跑、重启就废”的尴尬。Windows下部署客户端时JAVA_HOME要配置到系统环境变量而不是用户环境变量因为LuckyFrameClient以Windows服务方式启动时服务的启动用户可能不是当前登录用户用户变量会失效。2.3 MySQL初始化与字符集陷阱数据库安装完成之后不能上来就直接建库要先把字符集规范好。LuckyFrame执行用例、保存断言结果时会有大量中文文本如果字符集不对报告里全是问号那基本等于白搭。我建议在MySQL配置文件my.cnfWindows下是my.ini中显式设置[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_general_ci init_connectSET NAMES utf8mb4 max_allowed_packet64M其中max_allowed_packet容易被人忽略。LuckyFrame在执行UI自动化时会截图截图以Base64形式存库如果这个值太小保存截图时会出现Packet for query is too large的报错。默认的4M往往不够用调成64M是起步。建库语句建议写成这样CREATE DATABASE IF NOT EXISTS luckyframe DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;不要直接去执行项目里自带的SQL脚本先建好库、选好库再导入脚本。如果你导入时看到中文乱码八成是SQL脚本文件的编码和数据库连接编码不一致把SQL文件用UTF-8编码重新保存再导入一次即可。3. LuckyFrameweb服务端安装部署3.1 项目获取Release包还是源码构建LuckyFrame的部署方式有两种主流选择直接使用官方发布的Release包或者从Gitee/GitHub拉源码自己用Maven打包。如果你是第一次部署我推荐直接用Release包。自己用Maven构建看着很“专业”但坑很多依赖下载慢、某个jar在中央仓库找不到、前后端版本不一致导致页面空白……这些都会消耗大量时间。Release包是官方验证过的组合拿来就能用。源码构建的路径大概是这样的git clone https://gitee.com/seagull1985/LuckyFrameWeb.git cd LuckyFrameWeb mvn clean package -DskipTests构建完成后在target目录下会生成一个LuckyFrameWeb.war文件这个就是服务端应用包。如果你不想折腾Maven去官方Release页面下载对应的war包即可。3.2 Tomcat部署war包放置与访问路径规划拿到war包之后把它放到Tomcat的webapps目录下。这里有一个决策点war包要不要改名决定了后续访问URL的路径。比如你不改名部署后访问地址是http://服务器IP:8080/LuckyFrameWeb你改成ROOT.war访问地址就是http://服务器IP:8080/更简短但访问路径不同客户端配置服务端地址时要对应调整。我的建议是不要改名为ROOT保留原有路径。原因是LuckyFrame有一些与路径相关的约定虽然改ROOT一般也能跑但一旦出现问题“是不是我改了路径导致的”这个排查变量会浪费很多时间。稳妥最重要。部署步骤如下把war包复制到apache-tomcat-8.5.x/webapps/下。启动Tomcatbin/startup.sh或bin/startup.bat启动时会自动解压war包。观察日志看到Deployment of web application archive [LuckyFrameWeb.war] has finished说明部署完成。此时先不要急着访问因为数据库还没初始化的话页面会报错。3.3 数据库初始化脚本导入与账号配置LuckyFrameWeb解压之后webapps目录下会有一个LuckyFrameWeb文件夹说明脚本一般放在webapps/LuckyFrameWeb/WEB-INF/classes/路径下。最常见的是一个luckyframe.sql文件还有一个quartz.sql。导入顺序是先导luckyframe.sql再导quartz.sql。Quartz是任务调度的表不导的话创建定时任务时会报找不到表这个属于我实际踩过的坑顺序错了也会导致外键关联异常。在MySQL里执行USE luckyframe; SOURCE /你的路径/luckyframe.sql; SOURCE /你的路径/quartz.sql;导入完成后检查一下相关的表是否创建成功SHOW TABLES;你会看到里面包含用户表、项目表、用例表、任务表、执行机表、报告表等。看到这些表之后数据库层面的初始化就完成了。3.4 配置文件修改数据库连接与Redis地址数据库导完接下来修改连接配置。LuckyFrameWeb的数据库配置文件位于webapps/LuckyFrameWeb/WEB-INF/classes/application.properties部分版本是application.yml取决于版本多看解压目录就明白。核心配置项如下spring.datasource.urljdbc:mysql://127.0.0.1:3306/luckyframe?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.password你的数据库密码 spring.redis.host127.0.0.1 spring.redis.port6379 spring.redis.password你的Redis密码没有就留空这里有一个细节连接URL里的serverTimezoneAsia/Shanghai必须显式声明。如果不加MySQL连接驱动在解析时间时可能会报时区异常进而导致整个服务起不来。这是MySQL 8.0驱动最常见的错误之一。Redis配好后要确认Redis服务能正常连接否则服务端启动会一直报连接不上虽然可能会启动成功但登录时会直接卡在验证码或会话环节。测试Redis连通性的方法很简单redis-cli -h 127.0.0.1 -p 6379 ping显示PONG就正常。3.5 启动服务端与首次访问验证配置完成后重启Tomcatbin/shutdown.sh bin/startup.sh然后看日志tail -f logs/catalina.out看到类似Started Application in xxx seconds或者Tomcat started on port(s): 8080说明启动成功。浏览器访问http://服务器IP:8080/LuckyFrameWeb正常会跳转到登录页。第一次访问系统自带默认账号不同版本可能不同但常见的默认账号密码是admin/admin如果不对去sys_user表里看一下初始化数据。登录成功之后第一件事不是急着创建用例而是去“系统管理”里把用户密码改掉然后把服务端地址确认好因为客户端要用这个地址注册。4. LuckyFrameClient客户端安装与配置4.1 客户端包结构解读LuckyFrameClient是控制执行端的Agent负责在指定机器上跑自动化测试。它的压缩包解压出来目录结构大概是这样的LuckyFrameClient/ ├── conf/ │ ├── config.properties │ └── log4j.properties ├── lib/ │ └── ...一堆jar包 ├── logs/ ├── start.sh ├── start.bat └── LuckyFrameClient.jar核心配置在conf/config.properties日志配置在conf/log4j.properties启动脚本分Windows和Linux版本。第一次部署时建议先看目录结构确认jar包都在避免因为传输损坏导致启动不了。4.2 config.properties核心参数逐项说明客户端连不上服务端的篇数最多绝大多数问题都出在这个配置文件。我逐个解释一下关键项。server.host192.168.1.100 server.port8080 server.web.path/LuckyFrameWeb client.nameTestMachine-01 client.group默认分组 client.port8082 jdk.pathC:/Program Files/Java/jdk1.8.0_202server.host服务端IP注意这里填的是IP或域名不带http协议头。server.portTomcat端口默认8080。server.web.path服务端Web应用的访问路径和war包名一致。client.name客户端唯一标识会显示在服务端的执行机列表里建议用能看懂主机用途的名字。client.group分组名称服务端调度任务的时候可以按组指定执行机。client.port客户端自身提供的一个端口用于接收服务端下发的执行指令。jdk.path客户端所在机器上JDK的安装路径如果本机配置了JAVA_HOME这一项通常可以留空但如果启动异常建议显式指定。我在第一次配置的时候把server.web.path写成了完整URL结果客户端一直注册不上服务端日志里全是连接拒绝。后来查文档才明白这里只需要填应用路径部分。4.3 Windows下客户端启动与注册Windows下启动客户端有两种方式前台启动和后台服务。前台启动双击start.bat好处是能直接看到控制台输出第一次启动推荐用这种方式方便排错。启动之后控制台会出现类似“客户端注册成功”的日志说明客户端和服务端已经建立连接。后台服务方式使用bin/installService.bat之类脚本不同版本脚本名可能不同把客户端注册成Windows服务。好处是机器重启后自动拉起不用手动管理。注册成功后在Windows服务管理器里能看到对应的服务名右键启动即可。这里必须注意一个细节两种启动方式不要混用。如果你注册了Windows服务又手动去双击start.bat会出现两个客户端进程同时注册服务端执行机列表里同一个名字出现两条记录调度时会出现重复执行的诡异问题。4.4 Linux下客户端部署与执行权限Linux下部署客户端时解压后第一件事是改执行权限chmod x start.sh然后编辑conf/config.properties配置服务端地址。启动方式nohup ./start.sh logs/nohup.out 21 启动后看日志tail -f logs/*.log看到注册成功的日志就说明没问题了。Linux部署比较容易犯的错是jdk.path配置错误。比如JDK装在/usr/local/java/jdk1.8.0_202但配置里写成了/usr/local/java启动时会直接报“找不到JVM”。此时去logs目录里的启动日志看一眼信息很明确。4.5 客户端注册成功的校验方法客户端启动后回到LuckyFrameWeb页面在“系统管理”或“测试执行机”菜单里刷新一下列表。如果配置正确能看到你刚配置的客户端名称状态显示为“在线”。如果列表里看不到按这个顺序排查客户端日志有没有异常有异常先看日志。服务端和客户端的网络是否互通用ping和telnet IP 8080验证。确认服务端Tomcat已经正常启动且LuckyFrameWeb路径能访问。确认客户端配置的server.web.path和实际访问路径一致。在线状态是自动化调度的基础客户端离线时任务会一直挂在等待队列里看起来像是系统卡死。所以这一步务必确认好再进入下一步。5. 从登录到跑通第一个自动化任务5.1 平台核心模块概览登录LuckyFrameWeb之后左侧菜单能看到几个核心模块项目管理、用例管理、任务管理自动化测试或定时任务、执行报告、系统管理等。不同版本菜单名称略有差异但整体结构大同小异。理解这个平台的运作方式可以拎一条主线项目是最顶层容器项目下建测试用例用例组织成测试任务任务指定执行机去跑跑完生成执行报告。弄清楚这条主线之后菜单再多也不乱。我建议新用户把精力集中在“用例管理”和“任务管理”两个菜单上。用例管理负责写测试逻辑任务管理负责把用例跑起来这两个掌握之后平台的核心价值就掌握了。5.2 创建项目与模块划分在“项目管理”菜单里点击“新增”输入项目名称、描述等信息。实际使用中项目名建议和被测系统对应比如“订单中心”、“用户中心”。这样报告列表一眼能看出来是哪个系统的测试结果。项目创建好之后在项目下面建模块。模块的意义是组织用例为后续筛选和执行提供粒度。以接口自动化为例模块可以按接口业务分类比如“用户接口”、“订单接口”、“支付接口”。UI自动化可以按页面或者功能流程划分。模块规划得好后续创建测试任务时会非常省心。因为任务可以按模块、按用例级别或者自定义套件来选择用例而不是每次手动一个用例一个用例勾选。5.3 接口自动化用例编写实战LuckyFrame的接口用例设计思路是一个用例对应一个请求你配置请求方法、URL、请求头、请求体然后通过断言校验返回结果。以登录接口为例用例配置大致如下。HTTP请求方式选POST接口路径填/api/login请求内容类型选application/json请求参数写上{ username: test, password: 123456 }断言类型选择“JSON解析”校验返回数据里的code字段是否等于200message是否等于success。这样一条接口用例就建好了。编写用例时有一个技巧LuckyFrame支持变量引用很多复杂场景需要把上一个请求的返回值作为下一个请求的入参。比如先调用登录接口从返回结果里提取token再将token放到下一个接口的请求头里。这个功能在不同版本中的操作方式有差异有的版本通过后置提取参数并存入变量然后在后续请求中以${变量名}的方式引用。建议先看官方文档确认版本支持的写法。5.4 UI自动化用例的关键配置UI自动化通过Selenium驱动浏览器执行。在LuckyFrame里编写UI用例核心要配置两类内容操作步骤和元素定位。操作步骤包括打开URL、输入文本、点击按钮、等待元素出现、断言文本等。元素定位方式支持ID、Name、XPath、CSS选择器等。以登录页面为例配置自动化步骤就是打开URLhttps://xxx/login定位用户名输入框比如XPath//input[nameusername]输入用户名定位密码输入框输入密码定位登录按钮点击断言登录成功后页面是否存在“欢迎”字样UI自动化有一个额外前提客户端所在的机器必须安装对应浏览器和驱动驱动版本和浏览器版本必须匹配。比如Chrome浏览器版本是120那chromedriver也必须是120的对应版本否则启动浏览器时会直接报SessionNotCreatedException。这个属于UI自动化最常见的坑先记在心里。5.5 创建测试任务与调度执行用例写完之后进入“任务管理”新建测试任务。任务配置核心是三点选执行机、选用例、选执行策略。执行机勾选你注册过且状态为“在线”的客户端主机。策略可以选择立即执行、按固定周期调度或者定时执行。LuckyFrame底层集成Quartz所以定时配置本质是Quartz cron表达式。第一次跑任务时建议用“立即执行”先验证链路再上定时。点击“执行”按钮之后任务状态会变成“执行中”此时客户端开始接收用例并执行。整个链路是服务端把用例数据下发到客户端客户端执行后将执行日志和截图回传服务端汇总成报告。5.6 查看执行报告与日志任务执行完成后进入“执行报告”菜单能看到每次任务的结果汇总。报告会展示用例总数、通过数、失败数、通过率、执行耗时等关键指标。点进单条用例还能看到每一步操作的详细日志。接口用例可以查看请求参数、响应结果、断言结果。UI用例通常还能看到执行截图。这些截图非常有用用例失败时先看截图和日志基本能定位问题是元素找不到还是页面未加载完成。日常使用中我习惯每天早晨看一眼前一天的定时任务报告。如果出现单条用例偶发失败先判断是不是环境问题如果大面积失败那基本可以确定被测系统本身出了状况。这个过程能显著提高回归测试的效率这也是LuckyFrame这类平台相比“脚本堆在本地”最大的价值体现。6. 高频问题与排查经验6.1 客户端注册不上服务端这个问题的排查路径很有规律我把它整理成了一张速查表。遇到问题时按顺序过一遍比乱猜要快得多。现象可能原因处理方式客户端日志显示连接超时网络不通或不稳定ping和telnet验证连通性客户端日志显示404server.web.path配置错误改为/LuckyFrameWeb服务端日志无任何记录客户端没连到服务端检查服务端启动状态和端口监听客户端启动即崩溃JDK路径配置错误或版本不对检查jdk.path确认用JDK 1.8客户端注册两次同时启动了前台和后台服务停掉一个保证单一进程第一次部署时我卡在“配置了正确IP但客户端始终注册不上”这个问题上很久。后来查TCP连接发现服务端防火墙没放行8080端口。Linux服务器上执行firewall-cmd --permanent --add-port8080/tcp firewall-cmd --reload放行之后客户端几秒钟内就注册成功了。所以部署时防火墙端口放行一定要提前做好否则客户端报的很多错会误导排查方向。6.2 中文乱码问题乱码多数出现在两个地方数据库里的中文显示乱码或执行报告里的中文乱码。数据库乱码的根源多半是建库时字符集没设置成utf8mb4。解决方法是重建数据库然后用ALTER DATABASE也可以但最干净的一劳永逸做法是删库重建导入脚本前确认字符集。报告里中文乱码还要考虑另一种可能用例里的中文断言环境乱码检查客户端的编码设置和JVM的默认编码。如果不是特殊需求客户端启动参数里显式加上-Dfile.encodingUTF-8能规避大多数因为操作系统默认编码不一致导致的乱码问题。6.3 JDK版本引发的真实告警前面提到JDK建议使用1.8很多新手不信邪装了JDK 11甚至JDK 17结果客户端启动后日志里出现大量Illegal reflective access警告。这个警告短期看可能不影响运行但某些版本组合下会导致UI自动化执行时操作浏览器异常。我在Linux客户端上就遇到过这种问题。当时用的JDK 11接口自动化没问题但UI自动化执行到一半浏览器就无响应了。排查了脚本代码、元素定位、浏览器驱动最后发现问题出在JDK版本上。换成JDK 1.8之后相同脚本稳定跑了一整轮回归都没再出问题。所以如果你准备在正式环境长期用直接把JDK版本控制在1.8能省掉后续大量潜在麻烦。6.4 定时任务不触发的自查路线定时任务不触发优先检查Quartz相关的表是否存在。如果执行SELECT * FROM QRTZ_TRIGGERS;提示表不存在说明quartz.sql没有导入成功。这个原因性最强。如果表存在但任务还是不触发去查看服务端日志观察启动时有没有Quartz相关的初始化异常。有时候是因为配置了Redis但Redis密码错误导致任务状态无法缓存。还有一种情况是时区不一致。服务端所在机器和MySQL数据库的时区不一致会导致 cron 表达式触发时间比预期早8小时或晚8小时。检查的方法很简单MySQL里执行SELECT NOW(); SELECT UTC_TIMESTAMP();如果两个时间差8小时说明时区没对齐此时在数据库连接URL里显式配置时区参数同时在启动命令里指定-Duser.timezoneAsia/Shanghai来固定时区。7. 实际使用中的几点建议最后说几个纯个人经验不一定写在官方文档里但实测对团队使用很有帮助。第一用例管理要规范命名。不要写“用例1”、“测试2”这种名字命名建议直接包含接口或功能名比如“登录接口-密码正确返回token”。因为报告里直接显示用例名规范命名能让报告的可读性提升一个档次不需要额外维护文档。第二定时任务执行时间要错峰。如果团队人多大家把定时任务都设在凌晨2点执行全是排队甚至出现资源争抢。建议把不同测试任务分散到不同时间段比如订单模块凌晨2点跑用户模块凌晨3点跑。执行机资源有限的情况下错峰比加机器更直接。第三客户端所在机器不要随便休眠或关机。很多团队用完测试机后直接合上笔记本盖子结果第二天的定时任务全挂在等待队列里。我在实践中的做法是给客户端机器配置好电源计划永远不休眠并且把启动客户端的脚本做到开机自启里。一个小改动能省掉无数个“为什么今天任务没跑”的早晨。第四备份要趁早。LuckyFrame的配置、用例、报告都存MySQL定期备份数据库非常有必要。我自己用crontab每天凌晨备份一次0 2 * * * mysqldump -uroot -p密码 luckyframe /backup/luckyframe_$(date \%Y\%m\%d).sql备份文件按日期命名保留最近30天。用到现在这套备份方案救过我两次一次是升级版本前做备份一次是误删用例后做恢复。LuckyFrame这套平台整体部署下来工作量集中在“认真准备环境”和“耐心排查端口、路径、字符集”上真正跑通后整个测试流程的效率和规范性会有非常明显的提升。希望这篇基于实际部署经验的教程能帮你在搭平台这条路上少踩几个坑。