官网:http://www.liumatest.cn/代码地址:https://github.com/Chras-fu/Liuma-platform部署文档:https://docs.qq.com/doc/p/c989fa8bf467eca1a1e0fa59b32ceab017407168使用手册:https://docs.qq.com/doc/p/1e36932d41b40df896c1627a004068df9a28fc3f平台技术栈:前端VUE+ElementUI,后台Java+SpringBoot,测试引擎Python。


| 机器/系统 | 部署环境 | 说明 |
| 192.168.1.123,CentOS7 | JDK8MySQL8Nginx | CentOS7内网服务器:
|
| 192.168.1.131,Windows10 | GitJDK8MavenIDEA编辑器NodeJS | 个人Windows10办公电脑:
|
| 192.168.1.188,Windows7 | Python3SeleniumChromeChromeDriver | 同一内网下的其他Windows主机:
|
安装脚本下载:https://share.weiyun.com/6JMLvSyKJDK包下载地址:https://share.weiyun.com/mKDxXd1x
source jdk_install.sh # 通过source命令安装,省去配置环境变量步骤docker run -d --restart always --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 mysql:8.0.28docker exec -it mymysql shmysql -uroot -p # 登录mysql,根据提示输入密码123456mysql> create database liuma character set utf8 collate utf8_general_ci;nginx安装脚本下载地址:https://share.weiyun.com/HLuVRTO2nginx安装包下载地址:https://share.weiyun.com/uhffdijl将其下载下来,上传到服务器,执行以下命令安装:
source nginx_install.sh下载地址:https://share.weiyun.com/NJBlZGmE
下载地址:https://share.weiyun.com/2PpWyXkz,下载下来后双击安装即可。
npm --registry https://registry.npm.taobao.org install node-sass(要安装的模块)npm config set registry https://registry.npm.taobao.org
npm config get registry # 查看是否更换成功npm install -g cnpm --registry=https://registry.npm.taobao.orggit clone https://github.com/Chras-fu/Liuma-platform.git # 克隆平台代码
git clone https://github.com/Chras-fu/Liuma-engine.git # 克隆引擎代码
npm install # 安装相关依赖
npm run build # 构建
构建成功后,目录下会生成dist文件目录,可以将其打包成.zip格式并上传至服务器,然后再解压

# database
spring.datasource.password=123456
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3307/liuma?serverTimezone=UTC&characterEncoding=utf-8# aliyun 阿里云
# 阿里云邮件key
aliyun.email.accessKey = LTAI5tDVn8kT1avi84cFX8TT
# 阿里云邮件secret
aliyun.email.accessSecret = Dq8pm0DkZSqeMwRKOQhEid3fGPkL09
# 发送人邮箱地址
aliyun.email.runnerSenderAddress = jigang.chen@1897745962796526.onaliyun.com
aliyun.email.runnerSenderName = 执行通知机器人# 七牛云配置,全部改成你自己的
# 七牛云ak
qiniu.cloud.ak = xxxxxx
# 七牛云sk
qiniu.cloud.sk = xxxxxx
# 七牛云空间名
qiniu.cloud.bucket = xxxxxx
# 七牛云加速域名
qiniu.cloud.downloadUrl = xxxxxx
qiniu.cloud.uploadUrl = xxxxxx
nohup java -jar LiuMa-1.0.3.jar > logs.log 2>&1 &
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8888;
server_name 192.168.1.122;
location / {
index index.html index.htm;
root /usr/local/nginx/html/dist;
}
location /autotest {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Origin "";
}
location /openapi {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Origin "";
}
access_log /usr/local/nginx/html/wwwlogs/access.log;
}
}nginx -t -c /usr/local/nginx/conf/nginx_liuma.conf
③ 指定配置文件启动nginxnginx -c /usr/local/nginx/conf/nginx_liuma.conf
登录后的页面如下所示:
firewall-cmd --permanent --add-port=8888/tcp
firewall-cmd --reload
测试引擎可以理解为接口测试和UI自动化测试的运行环境。测试引擎可以选择部署在Linux系统,也可以选择使用个人Windows电脑,最好处于同一局域网下。当然如果服务端是部署在云服务上,有公网IP地址,Windows是个人办公电脑也可以,只要引擎电脑能要连上部署后端服务的那台服务器就行。以下是引擎部署过程:pip install -r requirements.txt
② 配置引擎服务器编辑liuma-engine/config目录下的配置文件config.ini,进行配置,几个重要配置如下:[Platform]
url = http://192.168.1.122:8888
enable-proxy = false
enable-stderr = true
[Engine]
engine-code = 9d4358f0c8a34a2ab7e4c297949149fa
engine-secret = 86a2f8f8bd654e03a60da9f19cdec017
[Header]
content-type = application/json;charset=utf-8
token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjI2Mjk4OTQsImVuZ2luZVNlY3JldCI6IjVhM2ZhYzdlYzJiODQ4NDlhYzJhNjY4ZGRlNjRhMDk0IiwiaWF0IjoxNjYyMDI1MDk0LCJlbmdpbmVJZCI6ImU3ZWMzOTllZDdkZDRkMmFiZWIxNGNiNTE2NGNiNGVkIn0._LVsCKIauFxV4IKAUNgYS1lVbD5twO_2E39QCOufKH8
[WebDriver]
options = normal
path = chromedriver.exe
[PlatformProxy]
url = http://0.0.0.0:80
username = ****
password = ****python startup.py


注册完成后,登录管理员账号,在【系统管理-用户管理】中能看到注册的用户:

② 新增环境添加好域名标识,就可以新增环境了,添加环境的目的主要是为了后面运行测试用例的时候是基于哪套环境,比如同一个项目,可能会有开发环境、测试环境、预发环境等等:环境中心-环境管理-新增环境,输入环境名称、环境描述,确认。
③ 新增域名在刚新增的环境下新增域名,匹配类型选择“域名标识”,匹配标识选择第一步新建的域名标识的名称,域名填写接口请求的URL地址。同Metersphere的环境管理类似,此处新建环境后,后面发起的接口测试请求,就是基于这个环境的URL发起。
② 新增接口新增接口可以选择手动新增和导入两种方式,导入的方式支持文件导入、postman、swagger导入,此处我选择的是手动新增,以登录接口为例:
基础信息部分就是接口地址、描述、名称等信息,各个字段简洁明了,不再赘述;请求参数部分主要涉及到请求头、接口的请求体等。为了满足不同用户的登录需求,我的接口请求参数是采用引用变量的形式来传参。提到变量就不得不提到下面的公共参数。
② 流马公共参数引用Metersphere对于公共参数的引用与Jmeter一致,都是采用${name}的形式,而在流马中,则是通过{{$username}}形式进行引用,与postman类似,但比postman多了个$符,postman是{{username}}。请求头和请求体中都可以通过此种方式引用公共参数,但是要注意参数的类型,请求头中一般都是string类型的参数。
比如我的某个接口传参中需要一些指定长度的随机数字,那么则可以使用random_number函数,引用方式见下图标:
① 创建自定义函数例如我想生成随机手机号,则可以通过如下方式常见:公共组件-函数管理-新增函数,内容如下:
可以看出,语法其实就是Python语法,只不过最后的返回值使用了sys_return代替。② 引用自定义函数添加完自定义函数,就可以在接口传参中引用,方式为:{{@function()}}
其实上述三个参数:姓名、手机号、身份证号我都是通过自定义函数来生成的。最后发起请求时,通过日志可以看到生成的参数值:
假如值没加双引号的话,传参的时候不会自动带上引号(通过执行打印结果可以看出),哪怕定义时选择的是string类型,被测接口的服务端也会认为它不是一个string类型
如果我们在公共参数中手动给它加上双引号,此时执行引擎Python那边就会报错JSONDecodeError:
解决办法是在定义公共参数时不加引号,在接口中引用参数时,加上引号
此时就会识别成合法的string类型值:
一条用例是由一个or多个接口组合而成,从而形成不同场景的业务流。前面接口管理中新建接口后,就可以在用例中选择添加该接口,一次可选择单个或多个。


② 引用返回值与前面引用公共参数不同,引用返回值的{{}}内不需要加$符号,直接填写变量名即可:

分别看下各个接口的执行结果,并做一些简单的解读,看其是否符合最初的流程设计:① 登录接口账号登录成功,并获取到返回值,返回账号的user id及token信息。
② 新增商品新增商品成功,返回d节点为商品的ID。
接口断言返回值的d节点为整数,断言成功。关联参数会提取d节点的值,作为后面接口的入参。
③ 获取商品详情上一个接口提取的商品ID,已经传入请求体,并获取到了商品详情。
接口断言返回值的d节点的aa节点与商品ID变量数字相等,断言成功。
④ 删除商品此处接口传参使用的也是新增商品返回的商品ID作为入参,删除成功d节点返回值为1
接口断言返回值的d节点数字恒等于1,断言成功
表达式直接填写元素属性值,比如ID定位,搜索框的ID属性值是kw
如果选择name定位,表达式就填wd


当然在操作设置页面、勾选元素后面的按钮后,也可以新建页面元素对象:



创建完的集合,可以手动执行,也可以创建测试计划定期或周期性执行

执行频率有多种方式可供选择,类似于Jenkins或是Linux crontab的定时任务:


② 如果通过'{{user_id}}'引用提取的变量值的话,B接口请求时就会报错502;
目前作者给的解决方案是在前置脚本里处理,或是写个自定义转换的函数
如果能在编辑用例---添加请求头的时候直接选择类型就好了,类似于编辑接口管理下这样:






| 测评维度 | 详细说明 | 评分(星级越高,得分越高) |
| 环境搭建 | 1.依赖环境:较多,支持容器化部署,传统部署相对较繁琐些2.搭建难度(难度越大、星级越低):对新手来说难度会较大,因为涉及的工具和服务比较多 | ☆☆☆ |
| 用例管理 | 1.是否支持导入用例:支持多种平台及格式导入2.用例执行顺序编排:支持,可以拖动 | ☆☆☆☆☆ |
| 接口测试 | 1.单接口测试:支持,不过没看到导入CSV入口,参数化和数据驱动支持情况不详2.接口流程测试:支持,多种参数提取方式,支持测试集合、测试计划,可以定期或周期性执行3.自动生成测试报告:支持,简洁 | ☆☆☆☆☆ |
| UI自动化测试 | 1.APP:支持2.Web:支持 | ☆☆☆☆☆ |
| 性能测试 | 不支持 | 无 |
| 扩展功能 | 1.是否支持二开:支持2.是否支持定时任务:支持3.是否支持接入CICD:支持4.是否支持测试结果度量:支持5.用户权限配置:支持,不同用户不同权限6.测试管理:不支持,平台定位不是如此7.缺陷跟踪:不支持,平台定位不是如此 | ☆☆☆☆☆ |
| 其他 | 1.文档支持(部署教程、操作手册):不够详细2.代码更新维护频率:长期维护3.社区活跃度:中等4.易用性:上手成本略高5.稳定性:目前暂未发现bug | ☆☆☆☆ |

很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel