In the recent work, frustration is great, I did a profound reflection, come out a truth: so look, seek truth from facts.
The reasons are complicated, one of which is that a certain batch of interface tests have relatively tight requirements. My previous thinking is to simulate real data as much as possible and conduct performance tests with multiple users. Generally, a large amount of data preparation is needed before tests. But this time it did not work, the parameter dependency between interfaces is too complex, if really written, it is really to do the work on the end again, not worth it.
So I took the trick of copying the interface request in the browser directly when simulating user creation, and then constantly brushing the interface to create data, instead of having to write requests one parameter at a time. By the way, I can also write a simple performance test tool Demo for the students on the end, which is convenient for them to do some simple performance tests.
First I parse the GET and POST requests, then generate an HttpRequestBase from the utility class FunRequest, verify the request, and proceed to the normal performance testing phase.
Copy the request
Here, I adopted the format of copying curl, because other methods have too much data and are complicated, difficult to parse and prone to bugs.
A GET request
Share the result of the replication, deleting the domain name.
curl 'https://j****.cn/home/course_list?_=1611648498164&custom_directory_id=4630377&origin=0&page=1&page_size=10' \ -H 'Connection: keep-alive' \ -H 'sec-ch-ua: "Chromium"; v="88", "Google Chrome"; v="88", "; Not A Brand"; v="99"' \ -H 'DNT: 1' \ -H 'sec-ch-ua-mobile: ? 0' \ -h 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' \ -h 'requestid: 010427916771' \ -H 'Accept: application/json, text/javascript, */*; Q =0.01' \ -h 'x-requisition-with: XMLHttpRequest' \ -h 'is_new_okay: 1' \ -h' sec-fetch -Site: same-origin' \ -H 'Sec-Fetch-Mode: cors' \ -H 'Sec-Fetch-Dest: empty' \ -H 'Referer: https://jiaoshi-dev.xk12.cn/' \ -H 'Accept-Language: zh-CN,zh; Q = 0.9, en. Q =0.8' \ -h 'Cookie: db_log=1; org_id=640; user_action_cookie=user_action_87cf9c4d-1e22-4c8c-982e-a4419fa6dc1b_62951571858; teacher_id=9fec845f498a47abb68426c14f90693e' \ --compressedCopy the code
A POST request
Share the result of the replication, delete the domain name, too!
curl 'https://j****.cn/myResourcePool/deleteResource' \ -H 'Connection: keep-alive' \ -H 'sec-ch-ua: "Chromium"; v="88", "Google Chrome"; v="88", "; Not A Brand"; v="99"' \ -H 'DNT: 1' \ -H 'sec-ch-ua-mobile: ? 0' \ -h 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' \ -h 'requestid: 011342477158' \ -H 'Accept: application/json, text/javascript, */*; Q =0.01' \ -h 'x-requisition-with: XMLHttpRequest' \ -h' is_new_OKAY: 1' \ -h 'content-type: application/x-www-form-urlencoded; charset=UTF-8' \ -H 'Origin: https://jiaoshi-dev.xk12.cn' \ -H 'Sec-Fetch-Site: same-origin' \ -H 'Sec-Fetch-Mode: cors' \ -H 'Sec-Fetch-Dest: empty' \ -H 'Referer: https://jiaoshi-dev.xk12.cn/myResourcePool_vm/my_resources' \ -H 'Accept-Language: zh-CN,zh; Q = 0.9, en. Q =0.8' \ -h 'Cookie: db_log=1; org_id=640; user_action_cookie=user_action_87cf9c4d-1e22-4c8c-982e-a4419fa6dc1b_62951571858; teacher_id=9fec845f498a47abb68426c14f90693e' \ --data-raw 'res_id=2317045&res_type=3' \ --compressedCopy the code
Generates an HttpRequestBase object
Here I write the copied request to a local text file, read it first, and then iterate over it.
public static HttpRequestBase getRequest(String path) {
def fileinfo = WriteRead.readTxtFileByLine(LONG_Path + path).stream().map {it.trim()}
def base = new CurlRequestBase()
fileinfo.each {
if (it.startsWith("curl")) {
def split = it.split("".2)
def type = split[0]
def value = split[1]
base.url = value.substring(value.indexOf('h'), value.lastIndexOf("'"))}else if (it.startsWith("-H")) {
def split = it.split("".2) [1].split(":")
base.headers << getHeader(split[0].substring(1), split[1].substring(0, split[1].lastIndexOf("'")))}else if (it.startsWith("--data-raw")) {
base.params = getJson(it.substring(it.indexOf("'") + 1, it.lastIndexOf("'")).split("&"))
base.type = RequestType.POST
}
}
base.type == RequestType.GET ? FunRequest.isGet().setUri(base.url).addHeader(base.headers).getRequest() : FunRequest.isPost().setUri(base.url).addHeader(base.headers).addParams(base.params).getRequest()
}
Copy the code
A CurlRequestBase internal static class is used in the middle.
static class CurlRequestBase {
String url
RequestType type =RequestType.GET
List<Header> headers = new ArrayList<>()
JSONObject params = new JSONObject()
}
Copy the code
The performance test
This is easy to do by plugging into the previous performance testing framework.
public static void main(String[] args) {
def request = getRequest("get")
output FanLibrary.getHttpResponse(request)
def thread = new RequestThreadTimes<HttpRequestBase>(request, 100)
new Concurrent(thread,30."FunTester get request test").start()
testOver()
}
Copy the code
Console output
The amount of data in the response is a little bit large, so instead of showing the response results, I’m going to show the performance test results.
INFO-> GC collection thread started! INFO-> Thread :FunTester get request test16, times of execution:100, number of errors:0, total time:12.92INFO-> Thread :FunTester Get request test19, times of execution:100, number of errors:0, total time:14.017S the INFO - > total30Number of threads, shared time:14.033S, total number of executions:3000, error number:0, number of failures:0INFO-> Data saved successfully! Name of the file: / Users/fv/Documents/workspace/fun /long/data/FunTester Get request test2021012617384730INFO - > ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ JSON ~ ☢ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ~ > {> (1)."rt":132> 1)."total":3000> 1)."qps":225.86109542631283> 1)."failRate":0.0> 1)."threads":30> 1)."startTime":"The 2021-01-26 17:38:47"> 1)."endTime":"The 2021-01-26 17:39:01"> 1)."errorRate":0.0> 1)."executeTotal":3000> 1)."mark":"FunTester get request test 20210126173847"> 1)."table":"\ r \ n \ t \ t \ \ t tFunTester get request testing 30... ellipsis, see below... \ r \ n">} ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ~ JSON ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ ~ ☢ ☢ ~ ~ ~ the INFO - > FunTester get request test30>> Response time distribution diagram, the ordinal number of buckets sorted on the horizontal axis, median of each bucket on the vertical axis << --< the minimum value of median data is:93Ms, maximum value:204Ms > - █ █ █ █ █ █ ▅ ▅ █ █ ▃ ▃ █ █ █ █ ▃ ▃ █ █ █ █ █ █ ▂ ▂ ▇ ▇ █ █ █ █ █ █ █ █ ▁ ▁ ▄ ▄ ▇ ▇ █ █ █ █ █ █ █ █ █ █ █ █ ▂ ▂ ▅ ▅ ▇ ▇ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ▁ ▁ ▄ ▄ ▅ ▅ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ▃ ▃ ▅ ▅ ▇ ▇ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ▂ ▂ ▅ ▅ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ▃ ▃ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ INFO - > gc thread is over! Process finished with exit code0
Copy the code
The final response result can only be viewed using a monospaced font. If the default word is non-monospaced, please refer to the following figure:
For information on how to use the performance testing framework and generate performance test results, check out the previous articles.
FunTester, non-famous test development, the article records learning and comprehension, welcome to pay attention to, exchange growth.
Gitee
addressGitee.com/fanapi/test…GitHub
addressGithub.com/JunManYuanL…
- 2020 FunTester self-summary
- Best practices for avoiding PPT automation
- Fixed QPS pressure test
- How do I test a probabilistic business interface
- JSON objects mark syntax validation classes
- There is no data to drive automated tests
- Understand stress and load testing in test models
- Simplify test cases
- Agile testing is two or three things
- Automated test lifecycle
- Moco fixed QPS interface upgrade compensation mechanism
- Pressure test results were corrected using microreference tests