帮别人做网站怎么接单,c 做网站后台,淘宝网站建设可以申请赔款,一个页面多少钱其实无论用那种测试方法#xff0c;接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文#xff0c;服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端#xff0c;客户端接收应答报文这一个过程。一、基于通用http/html请求大家都知道LoadRun… 其实无论用那种测试方法接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端客户端接收应答报文这一个过程。一、基于通用http/html请求大家都知道LoadRunner是一种性能测试工具但它也可以用在我们做接口测试的时候。一接口使用说明书要求开发人员开发出来的接口提供给测试人员详细的接口使用说明书该说明书最基本的要求如下 接口测试地址/SNS/Publish 请求报文参数说明参数名称参数描述字符类型字符值SNSID社区IDString6UserID用户IDString10CommentsTypeID评论类型IDString2CommentsID评论IDString10AuthorID作者IDString10CommentsContent评论内容String50 请求报文格式?xml version1.0 encodingISO-8859-1? Publish SNSID123/SNSIDUserID456/ UserIDCommentsTypeID2/ CommentsTypeIDCommentsID123/CommentsIDAuthorID456/AuthorIDCommentsContentDont forget the meeting!/CommentsContent/Publish 应答报文的参数接口说明参数名称参数描述字符类型字符值UserID用户IDString10CommentsTypeID评论类型IDString2CommentsID评论IDString10CommentsContent评论内容String50StatusCode返回值Int0代表pass,非0代表failStatusText返回信息描述String ?xml version1.0 encodingISO-8859-1? Publish UserID456/ UserIDCommentsTypeID2/ CommentsTypeIDCommentsID123/CommentsIDCommentsContentDont forget the meeting!/CommentsContentStatusCode0/StatusCodeStatusText发送成功一条评论/StatusText/Publish二测试方式 有了上述的说明书之后测试人员可以根据文档的描述在LoadRunner书写相应的接口测试脚本。LoadRunner中涉及到向服务器发送请求的API方法包括web_url()web_submit_form()web_submit_data()web_custom_request()。下面介绍两种我常用的方法1、方法一使用web_submit_data()web_submit_data(insert, Actionhttp://116.211.23.123/SNS/Publish.htm , MethodPOST, Refererhttp://116.211.23.123/SNS/Publish.htm , ModeHTML, ITEMDATA, Name SNSID ,Value6601,ENDITEM, Name UserID ,Value123,ENDITEM, Name CommentsTypeID ,Value1,ENDITEM, Name CommentsID ,Value456,ENDITEM, Name AuthorID,Value789,ENDITEM, Name CommentsContent ,ValueJust for testing,ENDITEM, LAST);2、方法二使用web_custom_request()char str[1000];strcpy(str,SNSID7999UserID1CommentsTypeID1CommentsID1AuthorID1CommentsContent1);web_custom_request(Publish, Url http://116.211.23.123/SNS/Publish.htm, MethodPOST, Refererhttp://116.211.23.123/SNS/Publish.htm , ModeHTTP, str, LAST); 这也是一种写法可以跟web_submit_data互换。这种写法更利于拼接参数。 方法一适合一些xml结构的根元素下的子元素同处于根元素下面且子元素数目较少的情况下如果xml结构比较复杂比如说根元素下面有多级子元素或者xml树结构分叉较多的时候我们可以先把xml拼接成一个字符串然后通过web_custom_request()向服务器发送请求。 我们在做接口功能测试的时候会很注意接口的应答报文的信息这时候我们可以通过LoadRunner的日志信息查看或者可以通过web_reg_find()或者web_find()这样的API函数来统计接口的运行结果推荐使用web_reg_find()web_reg_find()和web_find()区别请大家百度一下详细信息太多在这里不便叙述。 因为web_reg_find()是注册型函数所以应该放在web_submit_data()或者web_custom_request()的前面。 如web_reg_find(TextStatusCode0/StatusCode,//应答报文里边的信息SaveCount StatusCodeCount, //统计查询字段的信息如果找到值为1如果未找到值为0LAST); 在脚本的最后我们可以对查询字段的信息进行统计// Check resultif (atoi(lr_eval_string({StatusCodeCount })) 0){ //判断如果Welcome字符串出现次//数大于0lr_output_message(Send out the comment successfully.); }//在日志中输出Send out //the comment successfullyelse{ //如果出现次数小于等于lr_error_message(Send out the comment unsuccessfully.); //在日志中输出Send out //the comment successfullyreturn(0);} 总结用LoadRunner做接口测试无法做到把接口参数和程序分理接口的参数可以通过参数化的方法来实现对同一个参数多个数据的测试。参数化后的测试数据保存在此脚本的保存位置下。 三、基于JSON格式的接口请求一接口使用说明书要求1、接口调用说明网际协议HTTP POSTPOST内容类型application/x-www-form-urlencoded或application/json字符集utf-8POST 内容jsonstr{method:接口名称, 接口名称参数}例jsonstr{ c:1001, p:{ code:9051, mobile:{phone}, pwd:123456, model:{model}, }}接口访问地址http://{ip}:{port}/ei/mcu/MCUServiceEx2、参数描述1输入参数描述输入格式描述json必填参数包括l c主体编号l 其中p列表参数中的必填参数为json数组code:主体编号mobile:电话号pwd:密码。 2返回参数描述返回值描述json操作成功则返回{ responseCode: 200, errorCode: 0, responseCode: 连接成功, saveCodeMsg:提交成功, result: { confId:909 }}网络连接失败返回{ responseCode: 500}业务操作失败返回{ responseCode: 200, errorCode:错误码, responseCode: 连接成功, saveCodeMsg:, result: } 二测试方式1、通用方法使用lr测试json接口向服务端发送json格式请求接收处理返回响应数据。主要用到函数 1web_custon_request 2web_reg_save_param 此函数常用户处理动态参数该方法在LoadRunner中被称为Correlation关联具体实例如下包含发送json获取响应数据设置关联、设置检查点/* 定义事务: 1用户注册 2用户登录 3用户签到 接口为application/json接口格式描述样例 { c:1001, p:{ code:9051, mobile:{phone}, pwd:123456, model:{model}, }} 思路 1app注册获到mobile 2使用获取到的mobile登录获取tokenid和userid。 参数化手机号码、设备号 */ Action(){ //定义接口url char *Interface_Url; lr_save_string(http://192.168.0.1:8080/action.a,Interface_Url); //注册事务开始 lr_start_transaction(用户注册); lr_rendezvous(register); //检查用户是否注册成功 web_reg_find(SearchBody, TextcreateTime, SaveCountcreateTime, LAST); //web_set_max_html_param_len(10000000); //获取用户注册后响应数据并传给mobile web_reg_save_param(mobile, LB\mobile\:\, //设置左边界 RB\,, //设置右边界 Ord1, Notfoundempty, SearchBody, LAST); web_custom_request(register, Url{Interface_Url}, //设置url MethodPOST, //设置方法post或get ModeHTTP, EncTypeapplication/json; charsetUTF-8 , //编码类型 RecContentTypeapplication/json, Body{\c\:\1001\,\p\:{\code\:\9051\,\mobile\:\{phone}\,\pwd\:\123456\,\model\:\{model}\,}}, //请求主体json格式双引号前需要加斜杠 LAST); lr_vuser_status_message(注册事务虚拟用户数#%s,lr_eval_string({phone})); lr_end_transaction(用户注册,LR_AUTO); //登录事务开始 lr_start_transaction(用户登录); lr_rendezvous(login); web_reg_find(SearchBody, TextlastLoginTime, SaveCountlastLoginTime, LAST); //获取用户登录后响应数据tokenId,并传给pdl_dynamic_tokenId web_reg_save_param(pdl_dynamic_tokenId, LB\tokenId\:\, RB\, Ord1, Notfoundempty, SearchBody, LAST); //从用户登录响应数据中获取pdl_user_id web_reg_save_param(pdl_user_id, NotFoundwarning, LB\id\:, RB,\inviteCode, Ord1, SearchBody, LAST); web_custom_request(login, Url{Interface_Url}, MethodPOST, ModeHTTP, EncTypeapplication/json, RecContentTypeapplication/json, Body{\c\:\1002\,\p\:{\mobile\:\{pdl_mobile}\,\pwd\:\123456\}}, LAST); lr_end_transaction(用户登录,LR_AUTO); //用户签到 lr_start_transaction(用户签到); lr_rendezvous(Sign_in); web_reg_find(SearchBody, TextsignDate, SaveCountsignDate, LAST); web_custom_request(pdl_Sign_in, Url{Interface_Url}, MethodPOST, ModeHTTP, EncTypeapplication/json, RecContentTypeapplication/json, Body{\c\:\1014\,\p\:{\userId\:\{pdl_user_id}\,\tokenId\:\{pdl_dynamic_tokenId}\}}, LAST);if(atoi(lr_eval_string({response}))0){ //通过检查点判断请求返回是否成功 lr_end_transaction(用户签到, LR_PASS);}else{ lr_end_transaction(用户签到, LR_FAIL);} return 0;}2、json数据参数化在做接口测试时可能使用到请求体式为json的数据可以通过将json数据参数化以便能方便的维护和管理接口请求数据而且更容易格式化数据。1在loadrunner中创建一个参数文件填入需要请求的json串数据如图所示。2请求时注意服务器支持的编码格式所有我先做一个数据读取并转换为UTF-8格式这里有个地方要注意转成utf-8后要再进行参数存储【lr_save_string(lr_eval_string({tmpParam}),tmpParam))】因为转换后字符串结束会多出来“\x00”3由于要进行json请求所有必须在请求头指定内容类型为json这个也是进行json请求的关键。3、json数据带中文编码参数Action(){ charstrs[1000]; char*buffer; //使用指针最好. buffer (char*)malloc(1024); //记得在vuser_end中释放指针 //charstrJson[]{\EntName_3\:\{EntName}\,\RegNo_3\:\\,\SubDateStart_3\:\\,\SubDateEnd_3\:\\,\InsDate\:\\,\InsType\:\\,\InsRes\:\\,\DataProWay_3\:\\,\ErrCode_3\:\\,\cb_gridTable3\:\0\,\undefined\:\10\,\EntName\:\\,\RegNo\:\\,\SubDateStart\:\\,\SubDateEnd\:\\,\DataProWay\:\\,\ErrCode\:\\,\PageType\:\3\}; //charstrs[200];//先定义不赋值再赋值时可以将参数转为变量 //postData{EntName_3:,RegNo_3:,SubDateStart_3:,SubDateEnd_3:,InsDate:,InsType:,InsRes:,DataProWay_3:,ErrCode_3:,cb_gridTable3:0,undefined:10,EntName:,RegNo:,SubDateStart:,SubDateEnd:,DataProWay:,ErrCode:,PageType:3}_searchfalsend1484875494234rows10page1sidxsordasc //方案一整个Json串定为参数 lr_convert_string_encoding(lr_eval_string({urlOptName}),LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8 , UnicodeStringOptName); lr_save_string (lr_eval_string({UnicodeStringOptName}),urlOptName); //去掉结尾的NULL web_convert_param(urlOptName,SourceEncodingPLAIN, TargetEncodingURL,LAST ); lr_log_message(获取转码后的get Json方案一:%s,lr_eval_string({urlOptName})); //---------------------------------------------------------------------- //方案二JSON将参数内容串联指针变量形式低效率方案 strcpy(buffer,{\EntName_3\:\); strcat(buffer,lr_eval_string({EntName})); strcat(buffer,\,\RegNo_3\:\\,\SubDateStart_3\:\\,\SubDateEnd_3\:\\,\InsDate\:\\,\InsType\:\\,\InsRes\:\\,\DataProWay_3\:\\,\ErrCode_3\:\\,\cb_gridTable3\:\0\,\undefined\:\10\,\EntName\:\\,\RegNo\:\\,\SubDateStart\:\\,\SubDateEnd\:\\,\DataProWay\:\\,\ErrCode\:\\,\PageType\:\3\}); lr_convert_string_encoding(buffer,LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8 , UnicodeStringOptName2); lr_save_string(lr_eval_string({UnicodeStringOptName2}),urlOptName2 );//去掉结尾的NULL web_convert_param(urlOptName2,SourceEncodingPLAIN, TargetEncodingURL,LAST ); lr_log_message(获取转码后的get Json方案二:%s,lr_eval_string({urlOptName2})); strcpy(buffer,lr_eval_string({urlOptName2})); strcat(buffer,_searchfalsend1484875494234rows10page1sidxsordasc); lr_log_message(完整GET请求串:%s,buffer); //方案三JSON整体内容部分参数化,指针变量形式最佳方案 buffer{\EntName_3\:\{EntName}\,\RegNo_3\:\\,\SubDateStart_3\:\\,\SubDateEnd_3\:\\,\InsDate\:\\,\InsType\:\\,\InsRes\:\\,\DataProWay_3\:\\,\ErrCode_3\:\\,\cb_gridTable3\:\0\,\undefined\:\10\,\EntName\:\\,\RegNo\:\\,\SubDateStart\:\\,\SubDateEnd\:\\,\DataProWay\:\\,\ErrCode\:\\,\PageType\:\3\}; lr_convert_string_encoding(lr_eval_string(buffer),LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8 , UnicodeStringOptName3); lr_save_string(lr_eval_string({UnicodeStringOptName3}),urlOptName3 );//去掉结尾的NULL web_convert_param(urlOptName3,SourceEncodingPLAIN, TargetEncodingURL,LAST ); lr_log_message(获取转码后的get Json方案三:%s,lr_eval_string({urlOptName3})); free(buffer );//可以放到vuser_end buffer NULL;//可以放到vuser_end //方案四JSON数据部分参数化数组变量形式普遍方案 strcpy(strs,{\EntName_3\:\{EntName}\,\RegNo_3\:\\,\SubDateStart_3\:\\,\SubDateEnd_3\:\\,\InsDate\:\\,\InsType\:\\,\InsRes\:\\,\DataProWay_3\:\\,\ErrCode_3\:\\,\cb_gridTable3\:\0\,\undefined\:\10\,\EntName\:\\,\RegNo\:\\,\SubDateStart\:\\,\SubDateEnd\:\\,\DataProWay\:\\,\ErrCode\:\\,\PageType\:\3\}); lr_convert_string_encoding(lr_eval_string(strs),LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8 , UnicodeStringOptName4); lr_save_string (lr_eval_string({UnicodeStringOptName4}),urlOptName4); //去掉结尾的NULL web_convert_param(urlOptName4,SourceEncodingPLAIN, TargetEncodingURL,LAST ); lr_log_message(获取转码后的get Json方案四:%s,lr_eval_string({urlOptName4})); memset(strs,0,sizeof(strs));//清空内存*/ //方案五Json部分内容替换为中文 /*ReplaceStr(strJson,{EntName},吉林省锐迅股份);//ReplaceStr是在globals.h中创建的自定义函数 lr_convert_string_encoding(strJson,LR_ENC_SYSTEM_LOCALE, LR_ENC_UTF8 ,UnicodeStringOptName3); lr_save_string(lr_eval_string({UnicodeStringOptName3}),urlOptName3 );//去掉结尾的NULL web_convert_param(urlOptName3,SourceEncodingPLAIN, TargetEncodingURL,LAST ); lr_log_message(获取转码后的get Json方案五:%s,lr_eval_string({urlOptName3})); memset(strJson,0,sizeof(strJson));//释放内存*/ return0;} 二、基于WebService以及Soap接口的测试一接口使用说明书要求1、调用方法GiftCardQueryServicestring userId,bool userIdSpecified,int days,bool daysSpecified,stringvalidateValue2、调用地址http://{IP}:{port}/WebServices/RandomFontsWebService.asmx?wsdl3、输入参数参数名称说明userId用户IDuserIdSpecifieddaysdaysSpecifiedvalidateValue4、返回值参数名称说明GetValidGiftCardNumForDayResult 二测试方式1、通过web_service_call函数具体可以参见网上的相关资料启动LR选择 Web Service协议并添加调用服务设置好传入参数及返回值LR自带函数web_service_call就封装好了本次传参及返回结果集举例如下 web_service_call(StepNameGetValidGiftCardNumForDay_101, SOAPMethodGiftCardQueryService|BasicHttpBinding_GiftCardQueryService|GetValidGiftCardNumForDay, ResponseParamresponse, ServiceGiftCardQueryService, ExpectedResponseSoapResult, Snapshott1340760446.inf, BEGIN_ARGUMENTS, userId{userid}, userIdSpecifiedtrue, days10, daysSpecifiedtrue, validateValue{key}, END_ARGUMENTS, BEGIN_RESULT, GetValidGiftCardNumForDayResultParam_GetValidGiftCardNumForDayResult, END_RESULT, LAST);2、通过soap_reques发送报文主体 Action() { int count; lr_start_transaction(oneSoapOrder); web_add_header(SOAPAction,); soap_request(StepNamecreateSoapOrder, URLhttp://192.168.101.1:8080/MySoapProj/services/SoapService, SOAPEnvelope?xmlversion\1.0\ encoding\GB2312\? soapenv:Envelopexmlns:soapenv\http://schemas.xmlsoap.org/soap/envelope/\ soapenv:Header Security UsernameToken Usernameusername/Username Passwordpassword/Password /UsernameToken /Security /soapenv:Header soapenv:Body msg:createSoapOrder msg:SoapOrder id987600001/id /msg:businessGroup /msg:createSoapOrder /soapenv:Body/soapenv:Envelope, ResponseParamresponse, LAST); count lr_xml_find(XML{response}, Query/Envelope/Body/createSoapOrderResponse/resultcode/value, Value0, NotFoundcontinue, LAST); if(count 0){ lr_end_transaction(oneSoapOrder,LR_PASS); } else{ lr_end_transaction(oneSoapOrder,LR_FAIL); } return 0; }这里需要注意1报文中节点的域名最好不要变动2SOAP的URL需要根据实际情况修改3在一个方法中的某个参数如果太长需要换行则每行单独用双引号括起来4lr_start_transaction(oneSoapOrder);方法是创建一个名为oneSoapOrder的事务。该事务的结束由lr_end_sub_transaction方法实现5soap_request方法中的ResponseParamresponse参数是将SOAP返回报文存放到response中6lr_xml_find方法是查找xml文件中某个指定节点的值。此例中XML文件存放在response的SOAP响应报文查找的节点是/Envelope/Body/createSoapOrderResponse/resultcode/value节点具体的响应返回路径请根据实际项目替换即返回码。预期结果Value0。该方法如果找到预期值则返回找到的预期值个数找不到的话则返回07根据count的值判断返回码是否是0操作成功从而决定事务是否成功。LR_PASS表示事务成功LR_FAIL表示事务失败8这个报文是静态的再多的虚拟用户执行也只是执行同一条指令。若想使参数能“动”起来如编号等取值不冲突的参数。 转载于:https://blog.51cto.com/10672221/1948597