mirror of
https://gitee.com/270580156/weiyu.git
synced 2025-12-30 02:42:25 +00:00
update
This commit is contained in:
@@ -0,0 +1,560 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Bytedesk Login Performance Test" enabled="true">
|
||||
<stringProp name="TestPlan.comments">Bytedesk登录性能测试计划</stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">localhost</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">9003</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="protocol" elementType="Argument">
|
||||
<stringProp name="Argument.name">protocol</stringProp>
|
||||
<stringProp name="Argument.value">http</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="base_url" elementType="Argument">
|
||||
<stringProp name="Argument.name">base_url</stringProp>
|
||||
<stringProp name="Argument.value">${protocol}://${host}:${port}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<!-- HTTP请求默认值 -->
|
||||
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP请求默认值" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port">${port}</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol">${protocol}</stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
|
||||
<stringProp name="HTTPSampler.path"></stringProp>
|
||||
<stringProp name="HTTPSampler.concurrentPool">6</stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout">5000</stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout">30000</stringProp>
|
||||
</ConfigTestElement>
|
||||
<hashTree/>
|
||||
|
||||
<!-- HTTP头管理器 -->
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP头管理器" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">application/json;charset=UTF-8</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Accept</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">User-Agent</stringProp>
|
||||
<stringProp name="Header.value">JMeter/5.5</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 获取验证码线程组 -->
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="获取验证码" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">100</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<!-- 获取验证码请求 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="获取验证码" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/kaptcha/api/v1/get</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<!-- JSON提取器 -->
|
||||
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="提取验证码信息" enabled="true">
|
||||
<stringProp name="JSONPostProcessor.referenceNames">captchaUid,captchaImage</stringProp>
|
||||
<stringProp name="JSONPostProcessor.jsonPathExprs">$.data.captchaUid,$.data.captchaImage</stringProp>
|
||||
<stringProp name="JSONPostProcessor.match_numbers"></stringProp>
|
||||
<stringProp name="JSONPostProcessor.defaultValues"></stringProp>
|
||||
<boolProp name="JSONPostProcessor.compute_concat">false</boolProp>
|
||||
</JSONPostProcessor>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
|
||||
<!-- 用户名密码登录线程组 -->
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="用户名密码登录" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">500</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">30</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<stringProp name="ThreadGroup.duration">600</stringProp>
|
||||
<stringProp name="ThreadGroup.delay">0</stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<!-- CSV数据文件配置 -->
|
||||
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="用户数据" enabled="true">
|
||||
<stringProp name="delimiter">,</stringProp>
|
||||
<stringProp name="fileEncoding">UTF-8</stringProp>
|
||||
<stringProp name="filename">users.csv</stringProp>
|
||||
<boolProp name="ignoreFirstLine">true</boolProp>
|
||||
<boolProp name="quotedData">false</boolProp>
|
||||
<boolProp name="recycle">true</boolProp>
|
||||
<stringProp name="shareMode">shareMode.all</stringProp>
|
||||
<boolProp name="stopThread">false</boolProp>
|
||||
<stringProp name="variableNames">username,password,email,mobile</stringProp>
|
||||
</CSVDataSet>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 用户名密码登录请求 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="用户名密码登录" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"username": "${username}",
|
||||
"password": "${password}",
|
||||
"captchaUid": "${captchaUid}",
|
||||
"captchaCode": "1234",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB",
|
||||
"device": "JMeter Test"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/login</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<!-- JSON提取器 - 提取token -->
|
||||
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="提取登录token" enabled="true">
|
||||
<stringProp name="JSONPostProcessor.referenceNames">accessToken,refreshToken</stringProp>
|
||||
<stringProp name="JSONPostProcessor.jsonPathExprs">$.data.accessToken,$.data.refreshToken</stringProp>
|
||||
<stringProp name="JSONPostProcessor.match_numbers"></stringProp>
|
||||
<stringProp name="JSONPostProcessor.defaultValues"></stringProp>
|
||||
<boolProp name="JSONPostProcessor.compute_concat">false</boolProp>
|
||||
</JSONPostProcessor>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
|
||||
<!-- 手机验证码登录线程组 -->
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="手机验证码登录" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">200</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">20</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<stringProp name="ThreadGroup.duration">300</stringProp>
|
||||
<stringProp name="ThreadGroup.delay">0</stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<!-- 发送手机验证码 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="发送手机验证码" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"mobile": "${mobile}",
|
||||
"captchaUid": "${captchaUid}",
|
||||
"captchaCode": "1234",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB",
|
||||
"type": "mobile"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/send/mobile</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 手机验证码登录 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="手机验证码登录" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"mobile": "${mobile}",
|
||||
"code": "123456",
|
||||
"captchaUid": "${captchaUid}",
|
||||
"captchaCode": "1234",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB",
|
||||
"device": "JMeter Test"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/login/mobile</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
|
||||
<!-- 邮箱验证码登录线程组 -->
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="邮箱验证码登录" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">100</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<stringProp name="ThreadGroup.duration">300</stringProp>
|
||||
<stringProp name="ThreadGroup.delay">0</stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<!-- 发送邮箱验证码 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="发送邮箱验证码" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"email": "${email}",
|
||||
"captchaUid": "${captchaUid}",
|
||||
"captchaCode": "1234",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB",
|
||||
"type": "email"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/send/email</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 邮箱验证码登录 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="邮箱验证码登录" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"email": "${email}",
|
||||
"code": "123456",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB",
|
||||
"device": "JMeter Test"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/login/email</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
|
||||
<!-- AccessToken登录线程组 -->
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AccessToken登录" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">300</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">15</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<stringProp name="ThreadGroup.duration">300</stringProp>
|
||||
<stringProp name="ThreadGroup.delay">0</stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<!-- AccessToken登录 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="AccessToken登录" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"accessToken": "${accessToken}",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/login/accessToken</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
|
||||
<!-- 监听器 -->
|
||||
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>true</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>true</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>false</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<sentBytes>true</sentBytes>
|
||||
<url>true</url>
|
||||
<threadCounts>true</threadCounts>
|
||||
<idleTime>true</idleTime>
|
||||
<connectTime>true</connectTime>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
|
||||
<ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合报告" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>true</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>true</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>false</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<sentBytes>true</sentBytes>
|
||||
<url>true</url>
|
||||
<threadCounts>true</threadCounts>
|
||||
<idleTime>true</idleTime>
|
||||
<connectTime>true</connectTime>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
|
||||
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="汇总报告" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>true</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>true</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>false</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<sentBytes>true</sentBytes>
|
||||
<url>true</url>
|
||||
<threadCounts>true</threadCounts>
|
||||
<idleTime>true</idleTime>
|
||||
<connectTime>true</connectTime>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 响应断言 -->
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="响应断言" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">8</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
|
||||
<!-- JSON断言 -->
|
||||
<JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="JSON断言" enabled="true">
|
||||
<stringProp name="JSON_PATH">$.success</stringProp>
|
||||
<stringProp name="EXPECTED_VALUE">true</stringProp>
|
||||
<boolProp name="JSONVALIDATION">true</boolProp>
|
||||
<boolProp name="EXPECT_NULL">false</boolProp>
|
||||
<boolProp name="INVERT">false</boolProp>
|
||||
<boolProp name="ISREGEX">false</boolProp>
|
||||
</JSONPathAssertion>
|
||||
<hashTree/>
|
||||
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
|
||||
#### 6.1.1 JMeter脚本结构
|
||||
|
||||
```
|
||||
```bash
|
||||
jmeter/
|
||||
├── scripts/
|
||||
│ ├── 01_login_test.jmx
|
||||
|
||||
262
jmeter/quick_test.jmx
Normal file
262
jmeter/quick_test.jmx
Normal file
@@ -0,0 +1,262 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Bytedesk Quick Login Test" enabled="true">
|
||||
<stringProp name="TestPlan.comments">Bytedesk快速登录功能验证测试</stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">localhost</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">9003</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="protocol" elementType="Argument">
|
||||
<stringProp name="Argument.name">protocol</stringProp>
|
||||
<stringProp name="Argument.value">http</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<!-- HTTP请求默认值 -->
|
||||
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP请求默认值" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port">${port}</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol">${protocol}</stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
|
||||
<stringProp name="HTTPSampler.path"></stringProp>
|
||||
<stringProp name="HTTPSampler.concurrentPool">6</stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout">5000</stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout">30000</stringProp>
|
||||
</ConfigTestElement>
|
||||
<hashTree/>
|
||||
|
||||
<!-- HTTP头管理器 -->
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP头管理器" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">application/json;charset=UTF-8</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Accept</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">User-Agent</stringProp>
|
||||
<stringProp name="Header.value">JMeter/5.5</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 快速验证测试线程组 -->
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="快速验证测试" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">5</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<!-- 获取验证码 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="获取验证码" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/kaptcha/api/v1/get</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<!-- JSON提取器 -->
|
||||
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="提取验证码信息" enabled="true">
|
||||
<stringProp name="JSONPostProcessor.referenceNames">captchaUid,captchaImage</stringProp>
|
||||
<stringProp name="JSONPostProcessor.jsonPathExprs">$.data.captchaUid,$.data.captchaImage</stringProp>
|
||||
<stringProp name="JSONPostProcessor.match_numbers"></stringProp>
|
||||
<stringProp name="JSONPostProcessor.defaultValues"></stringProp>
|
||||
<boolProp name="JSONPostProcessor.compute_concat">false</boolProp>
|
||||
</JSONPostProcessor>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
|
||||
<!-- 用户名密码登录 -->
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="用户名密码登录" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"username": "admin",
|
||||
"password": "admin123",
|
||||
"captchaUid": "${captchaUid}",
|
||||
"captchaCode": "1234",
|
||||
"platform": "BYTEDESK",
|
||||
"channel": "WEB",
|
||||
"device": "JMeter Quick Test"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/auth/v1/login</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<!-- JSON提取器 - 提取token -->
|
||||
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="提取登录token" enabled="true">
|
||||
<stringProp name="JSONPostProcessor.referenceNames">accessToken,refreshToken</stringProp>
|
||||
<stringProp name="JSONPostProcessor.jsonPathExprs">$.data.accessToken,$.data.refreshToken</stringProp>
|
||||
<stringProp name="JSONPostProcessor.match_numbers"></stringProp>
|
||||
<stringProp name="JSONPostProcessor.defaultValues"></stringProp>
|
||||
<boolProp name="JSONPostProcessor.compute_concat">false</boolProp>
|
||||
</JSONPostProcessor>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
|
||||
<!-- 监听器 -->
|
||||
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>true</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>true</subresults>
|
||||
<responseData>true</responseData>
|
||||
<samplerData>true</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>true</responseHeaders>
|
||||
<requestHeaders>true</requestHeaders>
|
||||
<responseDataOnError>true</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<sentBytes>true</sentBytes>
|
||||
<url>true</url>
|
||||
<threadCounts>true</threadCounts>
|
||||
<idleTime>true</idleTime>
|
||||
<connectTime>true</connectTime>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
|
||||
<ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合报告" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>true</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>true</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>false</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<sentBytes>true</sentBytes>
|
||||
<url>true</url>
|
||||
<threadCounts>true</threadCounts>
|
||||
<idleTime>true</idleTime>
|
||||
<connectTime>true</connectTime>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
|
||||
<!-- 响应断言 -->
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="响应断言" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">8</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
|
||||
<!-- JSON断言 -->
|
||||
<JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="JSON断言" enabled="true">
|
||||
<stringProp name="JSON_PATH">$.success</stringProp>
|
||||
<stringProp name="EXPECTED_VALUE">true</stringProp>
|
||||
<boolProp name="JSONVALIDATION">true</boolProp>
|
||||
<boolProp name="EXPECT_NULL">false</boolProp>
|
||||
<boolProp name="INVERT">false</boolProp>
|
||||
<boolProp name="ISREGEX">false</boolProp>
|
||||
</JSONPathAssertion>
|
||||
<hashTree/>
|
||||
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
||||
259
jmeter/readme.md
259
jmeter/readme.md
@@ -1,53 +1,238 @@
|
||||
<!--
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-07-09 16:47:04
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2024-12-24 17:10:29
|
||||
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
|
||||
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
|
||||
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
|
||||
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
|
||||
* contact: 270580156@qq.com
|
||||
* 联系:270580156@qq.com
|
||||
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
|
||||
-->
|
||||
# JMeter Performance Tests
|
||||
# Bytedesk登录性能测试
|
||||
|
||||
This folder contains JMeter test plans for testing the visitor flow functionality.
|
||||
本目录包含用于测试Bytedesk系统登录功能的JMeter测试脚本。
|
||||
|
||||
## Test Files
|
||||
## 文件说明
|
||||
|
||||
- `visitor_flow_test.jmx`: Tests single visitor flow
|
||||
- `multiple_visitors_test.jmx`: Tests multiple concurrent visitors
|
||||
- `01_login.jmx` - JMeter测试计划文件,包含多种登录方式的测试
|
||||
- `users.csv` - 测试用户数据文件
|
||||
- `run_login_test.sh` - 测试执行脚本
|
||||
- `README.md` - 本说明文件
|
||||
|
||||
## Running Tests
|
||||
## 测试覆盖范围
|
||||
|
||||
1. Create a `report` folder in the same directory as the .jmx files:
|
||||
### 1. 获取验证码测试
|
||||
- **接口**: `GET /kaptcha/api/v1/get`
|
||||
- **并发用户**: 100
|
||||
- **加压时间**: 10秒
|
||||
- **测试目的**: 验证验证码生成服务的性能
|
||||
|
||||
### 2. 用户名密码登录测试
|
||||
- **接口**: `POST /auth/v1/login`
|
||||
- **并发用户**: 500
|
||||
- **加压时间**: 30秒
|
||||
- **持续时间**: 10分钟
|
||||
- **测试目的**: 测试传统用户名密码登录的性能
|
||||
|
||||
### 3. 手机验证码登录测试
|
||||
- **发送验证码接口**: `POST /auth/v1/send/mobile`
|
||||
- **登录接口**: `POST /auth/v1/login/mobile`
|
||||
- **并发用户**: 200
|
||||
- **加压时间**: 20秒
|
||||
- **持续时间**: 5分钟
|
||||
- **测试目的**: 测试手机验证码登录流程的性能
|
||||
|
||||
### 4. 邮箱验证码登录测试
|
||||
- **发送验证码接口**: `POST /auth/v1/send/email`
|
||||
- **登录接口**: `POST /auth/v1/login/email`
|
||||
- **并发用户**: 100
|
||||
- **加压时间**: 10秒
|
||||
- **持续时间**: 5分钟
|
||||
- **测试目的**: 测试邮箱验证码登录流程的性能
|
||||
|
||||
### 5. AccessToken登录测试
|
||||
- **接口**: `POST /auth/v1/login/accessToken`
|
||||
- **并发用户**: 300
|
||||
- **加压时间**: 15秒
|
||||
- **持续时间**: 5分钟
|
||||
- **测试目的**: 测试Token验证登录的性能
|
||||
|
||||
## 环境要求
|
||||
|
||||
### 软件要求
|
||||
- Apache JMeter 5.5+
|
||||
- Java 8+
|
||||
- Bash shell (用于执行脚本)
|
||||
|
||||
### 系统要求
|
||||
- 内存: 至少4GB可用内存
|
||||
- 磁盘: 至少1GB可用空间用于存储测试结果
|
||||
- 网络: 稳定的网络连接到测试目标服务器
|
||||
|
||||
## 安装和配置
|
||||
|
||||
### 1. 安装JMeter
|
||||
|
||||
#### Linux/macOS
|
||||
```bash
|
||||
mkdir report
|
||||
# 下载JMeter
|
||||
wget https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.5.tgz
|
||||
|
||||
# 解压
|
||||
tar -xzf apache-jmeter-5.5.tgz
|
||||
|
||||
# 移动到合适位置
|
||||
sudo mv apache-jmeter-5.5 /usr/local/
|
||||
```
|
||||
|
||||
2. Run the tests using JMeter GUI or command line:
|
||||
#### Windows
|
||||
1. 下载JMeter: https://jmeter.apache.org/download_jmeter.cgi
|
||||
2. 解压到合适目录
|
||||
3. 将bin目录添加到PATH环境变量
|
||||
|
||||
```bash
|
||||
jmeter -n -t visitor_flow_test.jmx -l report/visitor_flow.log -e -o report/visitor_flow_dashboard
|
||||
jmeter -n -t multiple_visitors_test.jmx -l report/multiple_visitors.log -e -o report/multiple_visitors_dashboard
|
||||
### 2. 配置测试环境
|
||||
|
||||
#### 修改测试目标地址
|
||||
编辑 `01_login.jmx` 文件中的用户定义变量:
|
||||
```xml
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">your-server-host</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">9003</stringProp>
|
||||
</elementProp>
|
||||
```
|
||||
|
||||
## Test Results
|
||||
#### 准备测试数据
|
||||
确保 `users.csv` 文件包含有效的测试用户数据:
|
||||
```csv
|
||||
username,password,email,mobile
|
||||
testuser1,password123,testuser1@example.com,13800138001
|
||||
...
|
||||
```
|
||||
|
||||
Results are stored in the `report` folder:
|
||||
## 执行测试
|
||||
|
||||
- `*_results.jtl`: Detailed test results
|
||||
- `*_aggregate.jtl`: Aggregate statistics
|
||||
- `*_graph.jtl`: Performance graphs
|
||||
- `*_dashboard`: HTML dashboard reports
|
||||
### 方法1: 使用脚本执行(推荐)
|
||||
|
||||
## Report Structure
|
||||
```bash
|
||||
# 使用默认JMeter路径
|
||||
./run_login_test.sh
|
||||
|
||||
- Response times
|
||||
- Throughput
|
||||
- Error rates
|
||||
- Detailed request/response data
|
||||
- Performance graphs
|
||||
# 指定JMeter路径
|
||||
./run_login_test.sh /path/to/jmeter/bin
|
||||
```
|
||||
|
||||
### 方法2: 直接使用JMeter命令
|
||||
|
||||
```bash
|
||||
# 进入jmeter目录
|
||||
cd jmeter
|
||||
|
||||
# 执行测试
|
||||
jmeter -n -t 01_login.jmx -l results/test_result.jtl -e -o reports/test_report
|
||||
```
|
||||
|
||||
### 方法3: 使用JMeter GUI
|
||||
|
||||
1. 启动JMeter GUI
|
||||
```bash
|
||||
jmeter
|
||||
```
|
||||
|
||||
2. 打开测试计划文件 `01_login.jmx`
|
||||
3. 点击运行按钮开始测试
|
||||
|
||||
## 测试结果分析
|
||||
|
||||
### 结果文件
|
||||
- `results/` - 原始测试结果文件(.jtl)
|
||||
- `reports/` - HTML格式的测试报告
|
||||
|
||||
### 关键指标
|
||||
- **响应时间**: 平均响应时间、90/95/99百分位响应时间
|
||||
- **吞吐量**: 每秒处理的请求数(TPS)
|
||||
- **错误率**: 请求失败的比例
|
||||
- **并发用户数**: 系统能够支持的最大并发用户数
|
||||
|
||||
### 性能基准
|
||||
根据测试计划文档,建议的性能基准:
|
||||
- 登录响应时间 < 2秒
|
||||
- 错误率 < 1%
|
||||
- 支持500并发用户登录
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 1. JMeter找不到
|
||||
```
|
||||
错误: 找不到JMeter可执行文件
|
||||
```
|
||||
**解决方案**: 确保JMeter已正确安装,或通过参数指定正确的路径
|
||||
|
||||
#### 2. 测试数据文件不存在
|
||||
```
|
||||
错误: 找不到测试数据文件: users.csv
|
||||
```
|
||||
**解决方案**: 确保 `users.csv` 文件存在于当前目录
|
||||
|
||||
#### 3. 网络连接失败
|
||||
```
|
||||
错误: 连接被拒绝
|
||||
```
|
||||
**解决方案**:
|
||||
- 检查目标服务器是否运行
|
||||
- 验证端口配置是否正确
|
||||
- 检查防火墙设置
|
||||
|
||||
#### 4. 验证码错误
|
||||
```
|
||||
错误: 验证码验证失败
|
||||
```
|
||||
**解决方案**:
|
||||
- 检查验证码接口是否正常工作
|
||||
- 确认验证码缓存服务配置正确
|
||||
|
||||
### 调试技巧
|
||||
|
||||
1. **启用详细日志**
|
||||
```bash
|
||||
jmeter -n -t 01_login.jmx -l results/test_result.jtl -e -o reports/test_report -L DEBUG
|
||||
```
|
||||
|
||||
2. **查看JMeter日志**
|
||||
```bash
|
||||
tail -f jmeter.log
|
||||
```
|
||||
|
||||
3. **使用JMeter GUI调试**
|
||||
- 在GUI模式下运行单个请求
|
||||
- 查看请求和响应详情
|
||||
|
||||
## 扩展和定制
|
||||
|
||||
### 添加新的登录方式
|
||||
1. 在测试计划中添加新的线程组
|
||||
2. 配置相应的HTTP请求
|
||||
3. 添加必要的断言和提取器
|
||||
|
||||
### 修改测试参数
|
||||
- 调整并发用户数
|
||||
- 修改加压时间
|
||||
- 更改测试持续时间
|
||||
|
||||
### 集成到CI/CD
|
||||
```bash
|
||||
# 在CI/CD流水线中执行测试
|
||||
./run_login_test.sh
|
||||
# 检查测试结果
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "性能测试通过"
|
||||
else
|
||||
echo "性能测试失败"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## 联系和支持
|
||||
|
||||
如有问题或建议,请联系开发团队或提交Issue。
|
||||
|
||||
## 更新日志
|
||||
|
||||
- v1.0 - 初始版本,支持基本登录功能测试
|
||||
- 支持用户名密码、手机验证码、邮箱验证码、AccessToken四种登录方式
|
||||
- 包含完整的测试数据准备和结果分析
|
||||
|
||||
81
jmeter/run_login_test.sh
Executable file
81
jmeter/run_login_test.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bytedesk登录性能测试执行脚本
|
||||
# 使用方法: ./run_login_test.sh [JMeter安装路径]
|
||||
|
||||
# 设置默认JMeter路径
|
||||
DEFAULT_JMETER_PATH="/usr/local/apache-jmeter-5.5/bin"
|
||||
JMETER_PATH=${1:-$DEFAULT_JMETER_PATH}
|
||||
|
||||
# 测试配置
|
||||
TEST_PLAN="01_login.jmx"
|
||||
RESULTS_DIR="results"
|
||||
REPORT_DIR="reports"
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
|
||||
# 创建结果目录
|
||||
mkdir -p "$RESULTS_DIR"
|
||||
mkdir -p "$REPORT_DIR"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Bytedesk登录性能测试开始"
|
||||
echo "时间: $(date)"
|
||||
echo "JMeter路径: $JMETER_PATH"
|
||||
echo "测试计划: $TEST_PLAN"
|
||||
echo "=========================================="
|
||||
|
||||
# 检查JMeter是否存在
|
||||
if [ ! -f "$JMETER_PATH/jmeter" ]; then
|
||||
echo "错误: 找不到JMeter可执行文件: $JMETER_PATH/jmeter"
|
||||
echo "请确保JMeter已正确安装,或通过参数指定正确的路径"
|
||||
echo "使用方法: $0 [JMeter安装路径]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查测试计划文件是否存在
|
||||
if [ ! -f "$TEST_PLAN" ]; then
|
||||
echo "错误: 找不到测试计划文件: $TEST_PLAN"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查测试数据文件是否存在
|
||||
if [ ! -f "users.csv" ]; then
|
||||
echo "错误: 找不到测试数据文件: users.csv"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "开始执行测试..."
|
||||
|
||||
# 执行JMeter测试
|
||||
"$JMETER_PATH/jmeter" -n \
|
||||
-t "$TEST_PLAN" \
|
||||
-l "$RESULTS_DIR/login_test_${TIMESTAMP}.jtl" \
|
||||
-e -o "$REPORT_DIR/login_test_${TIMESTAMP}"
|
||||
|
||||
# 检查测试执行结果
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "=========================================="
|
||||
echo "测试执行完成!"
|
||||
echo "结果文件: $RESULTS_DIR/login_test_${TIMESTAMP}.jtl"
|
||||
echo "报告目录: $REPORT_DIR/login_test_${TIMESTAMP}"
|
||||
echo "=========================================="
|
||||
|
||||
# 显示测试结果摘要
|
||||
echo "测试结果摘要:"
|
||||
echo "------------------------------------------"
|
||||
if [ -f "$RESULTS_DIR/login_test_${TIMESTAMP}.jtl" ]; then
|
||||
echo "总请求数: $(grep -c "200" "$RESULTS_DIR/login_test_${TIMESTAMP}.jtl" 2>/dev/null || echo "0")"
|
||||
echo "成功请求: $(grep -c "200" "$RESULTS_DIR/login_test_${TIMESTAMP}.jtl" 2>/dev/null || echo "0")"
|
||||
echo "失败请求: $(grep -v "200" "$RESULTS_DIR/login_test_${TIMESTAMP}.jtl" | grep -c "HTTP" 2>/dev/null || echo "0")"
|
||||
fi
|
||||
else
|
||||
echo "=========================================="
|
||||
echo "测试执行失败!"
|
||||
echo "请检查错误信息并重试"
|
||||
echo "=========================================="
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "测试完成时间: $(date)"
|
||||
echo "可以在浏览器中打开 $REPORT_DIR/login_test_${TIMESTAMP}/index.html 查看详细报告"
|
||||
84
jmeter/run_quick_test.sh
Executable file
84
jmeter/run_quick_test.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bytedesk快速登录功能验证测试
|
||||
# 使用方法: ./run_quick_test.sh [JMeter安装路径]
|
||||
|
||||
# 设置默认JMeter路径
|
||||
DEFAULT_JMETER_PATH="/usr/local/apache-jmeter-5.5/bin"
|
||||
JMETER_PATH=${1:-$DEFAULT_JMETER_PATH}
|
||||
|
||||
# 测试配置
|
||||
TEST_PLAN="quick_test.jmx"
|
||||
RESULTS_DIR="quick_results"
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
|
||||
# 创建结果目录
|
||||
mkdir -p "$RESULTS_DIR"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Bytedesk快速登录功能验证测试"
|
||||
echo "时间: $(date)"
|
||||
echo "JMeter路径: $JMETER_PATH"
|
||||
echo "测试计划: $TEST_PLAN"
|
||||
echo "=========================================="
|
||||
|
||||
# 检查JMeter是否存在
|
||||
if [ ! -f "$JMETER_PATH/jmeter" ]; then
|
||||
echo "错误: 找不到JMeter可执行文件: $JMETER_PATH/jmeter"
|
||||
echo "请确保JMeter已正确安装,或通过参数指定正确的路径"
|
||||
echo "使用方法: $0 [JMeter安装路径]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查测试计划文件是否存在
|
||||
if [ ! -f "$TEST_PLAN" ]; then
|
||||
echo "错误: 找不到测试计划文件: $TEST_PLAN"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "开始执行快速验证测试..."
|
||||
|
||||
# 执行JMeter测试
|
||||
"$JMETER_PATH/jmeter" -n \
|
||||
-t "$TEST_PLAN" \
|
||||
-l "$RESULTS_DIR/quick_test_${TIMESTAMP}.jtl"
|
||||
|
||||
# 检查测试执行结果
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "=========================================="
|
||||
echo "快速验证测试完成!"
|
||||
echo "结果文件: $RESULTS_DIR/quick_test_${TIMESTAMP}.jtl"
|
||||
echo "=========================================="
|
||||
|
||||
# 显示测试结果摘要
|
||||
echo "测试结果摘要:"
|
||||
echo "------------------------------------------"
|
||||
if [ -f "$RESULTS_DIR/quick_test_${TIMESTAMP}.jtl" ]; then
|
||||
total_requests=$(grep -c "HTTP" "$RESULTS_DIR/quick_test_${TIMESTAMP}.jtl" 2>/dev/null || echo "0")
|
||||
success_requests=$(grep -c "200" "$RESULTS_DIR/quick_test_${TIMESTAMP}.jtl" 2>/dev/null || echo "0")
|
||||
failed_requests=$((total_requests - success_requests))
|
||||
|
||||
echo "总请求数: $total_requests"
|
||||
echo "成功请求: $success_requests"
|
||||
echo "失败请求: $failed_requests"
|
||||
|
||||
if [ $failed_requests -eq 0 ]; then
|
||||
echo "✅ 所有请求都成功了!登录功能正常工作。"
|
||||
else
|
||||
echo "❌ 有 $failed_requests 个请求失败,请检查系统配置。"
|
||||
echo "详细错误信息请查看结果文件。"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "=========================================="
|
||||
echo "快速验证测试失败!"
|
||||
echo "请检查错误信息并重试"
|
||||
echo "=========================================="
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "测试完成时间: $(date)"
|
||||
echo ""
|
||||
echo "如果快速测试通过,可以运行完整性能测试:"
|
||||
echo " ./run_login_test.sh"
|
||||
101
jmeter/users.csv
Normal file
101
jmeter/users.csv
Normal file
@@ -0,0 +1,101 @@
|
||||
username,password,email,mobile
|
||||
testuser1,password123,testuser1@example.com,13800138001
|
||||
testuser2,password123,testuser2@example.com,13800138002
|
||||
testuser3,password123,testuser3@example.com,13800138003
|
||||
testuser4,password123,testuser4@example.com,13800138004
|
||||
testuser5,password123,testuser5@example.com,13800138005
|
||||
testuser6,password123,testuser6@example.com,13800138006
|
||||
testuser7,password123,testuser7@example.com,13800138007
|
||||
testuser8,password123,testuser8@example.com,13800138008
|
||||
testuser9,password123,testuser9@example.com,13800138009
|
||||
testuser10,password123,testuser10@example.com,13800138010
|
||||
testuser11,password123,testuser11@example.com,13800138011
|
||||
testuser12,password123,testuser12@example.com,13800138012
|
||||
testuser13,password123,testuser13@example.com,13800138013
|
||||
testuser14,password123,testuser14@example.com,13800138014
|
||||
testuser15,password123,testuser15@example.com,13800138015
|
||||
testuser16,password123,testuser16@example.com,13800138016
|
||||
testuser17,password123,testuser17@example.com,13800138017
|
||||
testuser18,password123,testuser18@example.com,13800138018
|
||||
testuser19,password123,testuser19@example.com,13800138019
|
||||
testuser20,password123,testuser20@example.com,13800138020
|
||||
testuser21,password123,testuser21@example.com,13800138021
|
||||
testuser22,password123,testuser22@example.com,13800138022
|
||||
testuser23,password123,testuser23@example.com,13800138023
|
||||
testuser24,password123,testuser24@example.com,13800138024
|
||||
testuser25,password123,testuser25@example.com,13800138025
|
||||
testuser26,password123,testuser26@example.com,13800138026
|
||||
testuser27,password123,testuser27@example.com,13800138027
|
||||
testuser28,password123,testuser28@example.com,13800138028
|
||||
testuser29,password123,testuser29@example.com,13800138029
|
||||
testuser30,password123,testuser30@example.com,13800138030
|
||||
testuser31,password123,testuser31@example.com,13800138031
|
||||
testuser32,password123,testuser32@example.com,13800138032
|
||||
testuser33,password123,testuser33@example.com,13800138033
|
||||
testuser34,password123,testuser34@example.com,13800138034
|
||||
testuser35,password123,testuser35@example.com,13800138035
|
||||
testuser36,password123,testuser36@example.com,13800138036
|
||||
testuser37,password123,testuser37@example.com,13800138037
|
||||
testuser38,password123,testuser38@example.com,13800138038
|
||||
testuser39,password123,testuser39@example.com,13800138039
|
||||
testuser40,password123,testuser40@example.com,13800138040
|
||||
testuser41,password123,testuser41@example.com,13800138041
|
||||
testuser42,password123,testuser42@example.com,13800138042
|
||||
testuser43,password123,testuser43@example.com,13800138043
|
||||
testuser44,password123,testuser44@example.com,13800138044
|
||||
testuser45,password123,testuser45@example.com,13800138045
|
||||
testuser46,password123,testuser46@example.com,13800138046
|
||||
testuser47,password123,testuser47@example.com,13800138047
|
||||
testuser48,password123,testuser48@example.com,13800138048
|
||||
testuser49,password123,testuser49@example.com,13800138049
|
||||
testuser50,password123,testuser50@example.com,13800138050
|
||||
testuser51,password123,testuser51@example.com,13800138051
|
||||
testuser52,password123,testuser52@example.com,13800138052
|
||||
testuser53,password123,testuser53@example.com,13800138053
|
||||
testuser54,password123,testuser54@example.com,13800138054
|
||||
testuser55,password123,testuser55@example.com,13800138055
|
||||
testuser56,password123,testuser56@example.com,13800138056
|
||||
testuser57,password123,testuser57@example.com,13800138057
|
||||
testuser58,password123,testuser58@example.com,13800138058
|
||||
testuser59,password123,testuser59@example.com,13800138059
|
||||
testuser60,password123,testuser60@example.com,13800138060
|
||||
testuser61,password123,testuser61@example.com,13800138061
|
||||
testuser62,password123,testuser62@example.com,13800138062
|
||||
testuser63,password123,testuser63@example.com,13800138063
|
||||
testuser64,password123,testuser64@example.com,13800138064
|
||||
testuser65,password123,testuser65@example.com,13800138065
|
||||
testuser66,password123,testuser66@example.com,13800138066
|
||||
testuser67,password123,testuser67@example.com,13800138067
|
||||
testuser68,password123,testuser68@example.com,13800138068
|
||||
testuser69,password123,testuser69@example.com,13800138069
|
||||
testuser70,password123,testuser70@example.com,13800138070
|
||||
testuser71,password123,testuser71@example.com,13800138071
|
||||
testuser72,password123,testuser72@example.com,13800138072
|
||||
testuser73,password123,testuser73@example.com,13800138073
|
||||
testuser74,password123,testuser74@example.com,13800138074
|
||||
testuser75,password123,testuser75@example.com,13800138075
|
||||
testuser76,password123,testuser76@example.com,13800138076
|
||||
testuser77,password123,testuser77@example.com,13800138077
|
||||
testuser78,password123,testuser78@example.com,13800138078
|
||||
testuser79,password123,testuser79@example.com,13800138079
|
||||
testuser80,password123,testuser80@example.com,13800138080
|
||||
testuser81,password123,testuser81@example.com,13800138081
|
||||
testuser82,password123,testuser82@example.com,13800138082
|
||||
testuser83,password123,testuser83@example.com,13800138083
|
||||
testuser84,password123,testuser84@example.com,13800138084
|
||||
testuser85,password123,testuser85@example.com,13800138085
|
||||
testuser86,password123,testuser86@example.com,13800138086
|
||||
testuser87,password123,testuser87@example.com,13800138087
|
||||
testuser88,password123,testuser88@example.com,13800138088
|
||||
testuser89,password123,testuser89@example.com,13800138089
|
||||
testuser90,password123,testuser90@example.com,13800138090
|
||||
testuser91,password123,testuser91@example.com,13800138091
|
||||
testuser92,password123,testuser92@example.com,13800138092
|
||||
testuser93,password123,testuser93@example.com,13800138093
|
||||
testuser94,password123,testuser94@example.com,13800138094
|
||||
testuser95,password123,testuser95@example.com,13800138095
|
||||
testuser96,password123,testuser96@example.com,13800138096
|
||||
testuser97,password123,testuser97@example.com,13800138097
|
||||
testuser98,password123,testuser98@example.com,13800138098
|
||||
testuser99,password123,testuser99@example.com,13800138099
|
||||
testuser100,password123,testuser100@example.com,13800138100
|
||||
|
Reference in New Issue
Block a user