接口测试工具

270 阅读7分钟

一、Postman工具

1.Base64加解密

Base64加密:

 //base64加密
 var username=CryptoJS.enc.Utf8.parse("admin");//先转为UTF-8格式
 var base64_username=CryptoJS.enc.Base64.stringify(username);//进行Base64加密
 console.log(base64_username);

Base64解密:

 //base64解密
 var username = CryptoJS.enc.Base64.parse("YWRtaW4=");//进行解密
 var utf8_username = username.toString(CryptoJS.enc.Utf8);//转为UTF-8格式
 console.log(utf8_username);

2.MD5加密

 //MD5加密(转换为MD5加密(32位小写),再转为字符串,并将转码后的字符串转换为32位大写)
 var MD5_username = CryptoJS.MD5("admin").toString().toUpperCase();
 console.log(MD5_username);

3.RSA加密解密

请求参数:

 {
     "code":"574526",
     "phone":"{{aes$17803878944}}",
     "cardId":"{{rsa$410922199008151440}}"
 }

Pre-request Script脚本

 ​
 // ------ 导入RSA ------
 if(!pm.globals.has("forgeJS")){
     pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", (err, res) => {
     if (!err) {
         pm.globals.set("forgeJS", res.text())
     }
 })}
  
 eval(postman.getGlobalVariable("forgeJS"));
 ​
 // ------------ AES 加密 ------------
 function aesEncrypt(content){
     //console.log('AES: ' + content);
     //密钥
     const key = CryptoJS.enc.Utf8.parse("Y5MUIOM7BUWI7BQR");
     //盐
     const iv = CryptoJS.enc.Utf8.parse('S41AXIPFRFVJL73Z');
     const encrypted = CryptoJS.AES.encrypt(content, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
     return encrypted.toString();
 }
  
 //设置公钥变量
 var RSA_Public_Key = "-----BEGIN PUBLIC KEY-----\n" +
                 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtamh2rXIlzOxWCdFeVzs\n" +
                 "+7yDlZnd+UmbsJ1JtGQ6tSxY0YgLzilWKSbCpyOXBDeU77WfgGOUW0XKAPZ+vI9e\n" +
                 "cvJrPWWEsaVM4liVrgpzOUeDeZYpPiYagUM2nsQ5iJ9lSGLdjIza1HC9xP0u3Soc\n" +
                 "MK3d2rImYfZAVwBeUSew11hwXc4tQWaig1RI2Wjzak6ED0kW3Cvew/C/q1zTiRvo\n" +
                 "8wH1OXDJ8kqGJylIRxKiFd2LaWerNtpQ4lGXZ+P8E3xkdIfpiNKOPbIosO1laf7d\n" +
                 "5xmSrvbteZ8Y1A6aqs6QwhkiSVmKTJNgIFoPboPRuAD3Vkm4CniMmoKULm6YBsn+\n" +
                 "VwIDAQAB\n" +
                 "-----END PUBLIC KEY-----";
 pm.collectionVariables.set("RSA_Public_Key", RSA_Public_Key);
 // ------------ RSA 加密 ------------
 function rsaEncrypt(content){
     const pubKey = pm.collectionVariables.get("RSA_Public_Key");
     if(pubKey){
         const publicKey = forge.pki.publicKeyFromPem(pubKey);
         const encryptedText = forge.util.encode64(
             publicKey.encrypt(content, 'RSAES-PKCS1-V1_5', {
               md: forge.md.sha1.create(),
               mgf: forge.mgf.mgf1.create(forge.md.sha1.create())
         }));
         return encryptedText;
     }
 }
 ​
 //对请求数据开始加密
 function getBracketStr(text) {
     let result = ''
     let regex = /{{(.+?)}}/g;
     let options = text.match(regex);
     if (options && options.length > 0) {
         let option = options[0];
         if (option) {
             result = option.substring(2, option.length - 2)
         }
     }
     
     return result
 }
 ​
 // ------ 存储所有未加密环境变量 ------
 if(!pm.environment.has('localStore')){
     pm.environment.set('localStore', '{}');
 }
 let localStore = JSON.parse(pm.environment.get('localStore'));
 // 获取当前请求中的加密变量
 let requestData; 
 if((typeof request.data) === 'string'){
     requestData = JSON.parse(request.data)
 } else {
     requestData = request.data;
 }
  
 requestData = Object.assign(requestData, request.headers);
 Object.keys(requestData).map(key => {
     let value = requestData[key] + ''; // 内容
     if (value.indexOf('{{') !== -1) { // 是否为变量
         let content = getBracketStr(value);
         // 判断是否加密
         if (content.indexOf('aes$') !== -1) {
             let c = content.split('aes$')[1];
             let encryptedContent = pm.environment.get(c); // 加密内容
             encryptedContent = encryptedContent ? encryptedContent : c;
             pm.environment.set(content, aesEncrypt(encryptedContent));
             localStore[content] = aesEncrypt(encryptedContent);
         } else if (content.indexOf('rsa$') !== -1) {
             let c = content.split('rsa$')[1];
             let encryptedContent = pm.environment.get(c); // 加密内容
             encryptedContent = encryptedContent ? encryptedContent : c;
             pm.environment.set(content, rsaEncrypt(encryptedContent));
             localStore[content] = rsaEncrypt(encryptedContent);
         }
     }
 });
  
 pm.environment.set('localStore', JSON.stringify(localStore));
 console.log(JSON.stringify(localStore))

服务端处理:

 AES aes = new AES("CBC", "PKCS7Padding",
                   // 密钥,可以自定义
                   "Y5MUIOM7BUWI7BQR".getBytes(),
                   // iv加盐,按照实际需求添加
                   "S41AXIPFRFVJL73Z".getBytes());
 log.info("phone解密前:【{}】", loginForm.getPhone());
 byte[] decryptPhone = aes.decrypt(loginForm.getPhone());
 log.info("phone解密后:【{}】", new String(decryptPhone));
 ​
 ​
 ​
 log.info("cardId解密前:【{}】", loginForm.getCardId());
 RSA rsa = new RSA(RSAEncryptConfig.PRIVATEKEY, null);
 byte[] cardId = rsa.decrypt(loginForm.getCardId(), KeyType.PrivateKey);
 log.info("cardId解密后:【{}】", new String(cardId));

4.接口关联

 //获取返回的json数据
 var jsonData = pm.response.json();
 var token = jsonData.token;
 pm.collectionVariables.set("token", token);

5.断言

 pm.test("Status code is 200", function () {
     pm.response.to.have.status(200);
 });
 ​
 pm.test("Your test name", function () {
     var jsonData = pm.response.json();
     pm.expect(jsonData.value).to.eql(100);
 });

6.解析请求数据和响应数据

 //解析请求数据
 var requestData = JSON.parse(request.data);
 ​
 //解析响应数据
 var responseData = JSON.parse(responseBody);

7.设置时间戳

 //设置当前时间戳毫秒
 postman.setGlobalVariable("timestamp",Math.round(new Date().getTime()));

8.加签和验签

加签

 //获取请求数据
 var data = JSON.parse(request.data)
 //请求时间戳
 var reqTime = Math.round(new Date().getTime());
 pm.collectionVariables.set("reqTime",reqTime);
 data.reqTime = reqTime;
 //连接符
 var join = '&';
 var result = '';
 //键按首字母排序
 let keys = Object.keys(data).sort();
 for(var i = 0; i < keys.length; i++){
     let key = keys[i];
     let value = data[key] + '';
     if(value.indexOf('{{') !== -1) continue;
     result = result + key + '=' + value + join;
 }
 ​
 //拼接支付宝沙箱应用公钥
 result = result + "key=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7o5JU5TxREr7Clea+aJSgpnF+vV12bLF9xngRZpHewZXNQJ5mTevPJloMcLZzwjKgisAib0hqQDc8pNW05d3x0u84aBQa/FK/C/xvfc+4krDFE6M/kHTZTW+RGX0bNDiXePVeb71Of6GEiiWvTG+j7nnjqVoRjL/+TX5ut8bkOgYIirhh+4VWndGjQQpHlK05m/fQckAS6qbk8/yZVeHswygfP/qqVc6BB2lDZVM3SBBx5DhPQjg1trUJQqA/AXtQmsKcVsSzTLyDRfenpt1NuGGSI+Ba1zwijB9m+Tuzdpv+rVet87bxcbbu1neEHuhzFWPLB1ZReezwfuGpgpKXAgMBAAECggEAUjpsdie/Nwgv8LYgWHEcMQq/0frKaotXfPbsxzNb2XKcY0ZeJBchr7Xu4GTEkBYaeaBUcsKxyV461qilvpC9oqv9iYqSxQCugmqORY2s6gXe0X65m7GCg3gb3Ep/ONy5sCeh37C4FR55ecvQl/G3Ou/XGp2siuRTfu4W6g4/auQCVAm1zefMhVEuIZLukIHLrxzAKF92X8RHNOWY/fvYI7dZiDX+CnWQdVdeuvdeJCi7ZR4bl89gVpM2bpNhVXwnrHI/szcyIDuk9CdNhDSjc5YqT6stkOnS+/3wMURb8X5F0WVO1rqkcB7WmbqdpYH4vnI0OitwVVW0QcOFn8qlgQKBgQDliQofNRnoezzsr8/JWW0H658Q5NQUAn0FeBTtnMTDczOYRcZ4EeFjEB4WEtXXBRSZG+tSNcEU3JiPOWCD8zKzhzFnboLIT8xfT0wZHqwMvvTPQ4aSqllf21MfxAC+l6dNMAv/lPirI6KU+w1zukqMVRXWeYzMOaPru1uUa01GdQKBgQDRRet5cjcXP81lbPGb4+IU93xozNDQFQop1ExSsspBIpFwwzr80MHDn+fcy6zIiWwW8el9XW+F/Ktd2FpWsM3OssoV9dw1zDQEWoQxuLzZnKejFYSnt2oAc5GZPmJWHyQ+RDD1cORFLucs24d8ukmblCGdLmXEIcPzBZOegYWLWwKBgQCQf2HQ3ZPux85FzjQHtHUv/EPJ1dQwuJRN4heCsiMoS5iabqqPoen6fAYErVzTHM6nyGyu90oSwQCFgYBh8LLlU+FlFKveQGYPRhNI6Qc0iu4AoKjSIc1by+2bXL9/PGdE709OWVDmI+vQz+7bANa3W0UBHMnnMw4fc3YmjBo8lQKBgQCyP3jS55rO/bQoGMQuQMrXivj3lsShB9qxSDd+FPU6x4PT5SZAIlt4EaJ/KShRYuOjI4f6FPShzlX0SAyiXFPgI98HF3PqirUfpC2G4FBSliEfQnvMEuiB2+3+9ejya/IF6zU8SVzVJJ8ZUR80+MMrdd+vrs5VYWEyhOR4lN+3kwKBgB471kJOZC9YMWfaXSyKSahnlBHQyuTzJZRaKUqrMquKFrbyXcEoevwCmVk5t1I+1nZ7gm1mXmhfmdIYPnOBBKD2pSrIn8aGGJmBp012yQEuIXiDQBLOjJKOjScvG8xJlm6waW7K+7BG51FkWKWcbDkq+BJ54xcZmIls/ILNWS8T";
 ​
 console.log(result)
 pm.collectionVariables.unset("sign");
 var sign = CryptoJS.MD5(result).toString().toUpperCase();
 console.log(sign)
 pm.collectionVariables.set("sign", sign);

验签

 ​
 pm.test("Status code is 200", function () {
     pm.response.to.have.status(200);
 });
 ​
 pm.test("检验业务响应码是否正常", function () {
     var jsonData = pm.response.json();
     pm.expect(jsonData.code).to.eql(0);
 });
 ​
 ​
 //验签
 pm.test("验签", function () {
     //获取响应内容
     var jsonData = pm.response.json();
     var data = jsonData.data;
     //字段按首字母排序
     let keys = Object.keys(data).sort();
     var result = '';
     var join = '&'; //连接符号
     for(var i = 0; i < keys.length; i++){
         let key = keys[i];
         result = result + key + '=' + data[key] + join;
     }
     //拼接支付宝沙箱应用公钥
 result = result + "key=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7o5JU5TxREr7Clea+aJSgpnF+vV12bLF9xngRZpHewZXNQJ5mTevPJloMcLZzwjKgisAib0hqQDc8pNW05d3x0u84aBQa/FK/C/xvfc+4krDFE6M/kHTZTW+RGX0bNDiXePVeb71Of6GEiiWvTG+j7nnjqVoRjL/+TX5ut8bkOgYIirhh+4VWndGjQQpHlK05m/fQckAS6qbk8/yZVeHswygfP/qqVc6BB2lDZVM3SBBx5DhPQjg1trUJQqA/AXtQmsKcVsSzTLyDRfenpt1NuGGSI+Ba1zwijB9m+Tuzdpv+rVet87bxcbbu1neEHuhzFWPLB1ZReezwfuGpgpKXAgMBAAECggEAUjpsdie/Nwgv8LYgWHEcMQq/0frKaotXfPbsxzNb2XKcY0ZeJBchr7Xu4GTEkBYaeaBUcsKxyV461qilvpC9oqv9iYqSxQCugmqORY2s6gXe0X65m7GCg3gb3Ep/ONy5sCeh37C4FR55ecvQl/G3Ou/XGp2siuRTfu4W6g4/auQCVAm1zefMhVEuIZLukIHLrxzAKF92X8RHNOWY/fvYI7dZiDX+CnWQdVdeuvdeJCi7ZR4bl89gVpM2bpNhVXwnrHI/szcyIDuk9CdNhDSjc5YqT6stkOnS+/3wMURb8X5F0WVO1rqkcB7WmbqdpYH4vnI0OitwVVW0QcOFn8qlgQKBgQDliQofNRnoezzsr8/JWW0H658Q5NQUAn0FeBTtnMTDczOYRcZ4EeFjEB4WEtXXBRSZG+tSNcEU3JiPOWCD8zKzhzFnboLIT8xfT0wZHqwMvvTPQ4aSqllf21MfxAC+l6dNMAv/lPirI6KU+w1zukqMVRXWeYzMOaPru1uUa01GdQKBgQDRRet5cjcXP81lbPGb4+IU93xozNDQFQop1ExSsspBIpFwwzr80MHDn+fcy6zIiWwW8el9XW+F/Ktd2FpWsM3OssoV9dw1zDQEWoQxuLzZnKejFYSnt2oAc5GZPmJWHyQ+RDD1cORFLucs24d8ukmblCGdLmXEIcPzBZOegYWLWwKBgQCQf2HQ3ZPux85FzjQHtHUv/EPJ1dQwuJRN4heCsiMoS5iabqqPoen6fAYErVzTHM6nyGyu90oSwQCFgYBh8LLlU+FlFKveQGYPRhNI6Qc0iu4AoKjSIc1by+2bXL9/PGdE709OWVDmI+vQz+7bANa3W0UBHMnnMw4fc3YmjBo8lQKBgQCyP3jS55rO/bQoGMQuQMrXivj3lsShB9qxSDd+FPU6x4PT5SZAIlt4EaJ/KShRYuOjI4f6FPShzlX0SAyiXFPgI98HF3PqirUfpC2G4FBSliEfQnvMEuiB2+3+9ejya/IF6zU8SVzVJJ8ZUR80+MMrdd+vrs5VYWEyhOR4lN+3kwKBgB471kJOZC9YMWfaXSyKSahnlBHQyuTzJZRaKUqrMquKFrbyXcEoevwCmVk5t1I+1nZ7gm1mXmhfmdIYPnOBBKD2pSrIn8aGGJmBp012yQEuIXiDQBLOjJKOjScvG8xJlm6waW7K+7BG51FkWKWcbDkq+BJ54xcZmIls/ILNWS8T";
 ​
     var sign = CryptoJS.MD5(result).toString().toUpperCase();
     console.log(sign)
     pm.expect(jsonData.sign).to.eql(sign);
 });
 ​

二、Jmeter工具

1.用户自定义变量

2.CSV批量添加

Snipaste_2024-11-08_16-41-24.png

2.png

Snipaste_2024-11-08_16-41-56.png

3.函数

1.计数器函数

image-20221031112533484.png 使用计数器变量

image-20221031112623362.png

2.随机数函数

image-20221031113116750.png

3.时间函数

image-20221031113953510.png

4.JDBC请求

第一步 添加数据库驱动包

image-20221031121022779.png 第二部 设置连接参数 image-20221031123735871.png 第三步 添加JDBC请求 image-20221031123840797.png 第四步 查看结果集合 image-20221031123923152.png

5. 使用JDBC中的请求结果作为接口参数

添加变量名 image-20221031125335766.png 添加调试取样器 image-20221031125411854.png 查看查询结果 image-20221031125515064.png 使用结果变量 image-20221031125442018.png

6.逻辑控制器

1.if逻辑控制器

创建if逻辑控制器,if逻辑控制器和http请求是父子关系 image.png

2.foreach控制器

添加一组变量 image.png 添加foreach控制器 image.png 添加请求 image.png

3.循环控制器

image.png

7.定时器

1.同步定时器

需求:同一时刻100个用户去访问系统的查询所有学院信息功能,统计高并发情况下平均响应时 间以及错误率(高并发)

设置100个线程

image.png

添加请求同步器

image.png

2.常数吞吐量定时器

需求:一个用户以20QPS(==20次/S)的频率访问学生管理系统服务器,持续15秒,统计服务器的平均 响应时间

image.png

image.png

实战

场景1:模拟半小时之内1000个用户访问服务器资源,要求平均响应时间在3000ms内,且措误率为0

image.png

场景2:模拟100个用户同时访问服务器资源,要求平均响应时间在3000s内,且错误率为0

image.png

image.png

场景3:模拟2个用户以20QPS的频率访问服务器资源持续10秒,要求平均响应时间在3000s内,错误率为0

image.png

image.png