手把手教你接口自动化测试 – SoapUI & Groovy
来源:互联网 发布:阿尔法go算法论文 编辑:程序博客网 时间:2024/06/04 18:45
手把手教你接口自动化测试 – SoapUI & Groovy
http://www.cnblogs.com/wade-xu/p/4236295.html
关键词:SoapUI接口测试,接口自动化测试,数据驱动测试,SoapUI进阶使用, Groovy in SoapUI, SoapUI中Groovy的使用,数据分离。
阅读这篇文章需要一定的SoapUI基础,至少入过门,另外还需要一些Groovy的知识,当然如果你会java 也可以,这里用到的Groovy知识和Java很类似。
另外,本文的思路和我上一篇文章<零成本实现接口自动化测试 – Java+TestNG 测试Restful service>很相似,只不过把Java+TestNG的组合换成了SoapUI+Groovy, 另外测试对象也换成了基于Soap的web service, 依旧用Excel来管理数据,做到数据分离。
由于我用到的SoapUI是免费版本,相比Pro版,少很多的功能,像DataLoop之类的,所以只能通过Groovy写一些脚本来做数据驱动的测试。
首先打开SoapUI, 新建一个Workspace 名为Demo
然后点击File->New soapUI Project
然后输入你的Project Name, WSDL 地址 点击OK
输入服务的用户名密码 点击OK
项目工程建好了
右击ServicePort 建立TestSuite
以其中一个接口为例 来生成用例
输入TestSuite name 然后确认
工程结构如下
通过右击TestCase -> Add Step 增加 Groovy Script 和 Properties
增加四个Groovy Script, 并且命名成 Start, Process, Check Response, End
增加5个 Properties, 并且命名成Input, Baseline, Output, Result, fieldResult
调整它们的顺序,最后形成下图的工程目录结构
Start脚本主要创建log文件
Process脚本是整个工程的核心,读取Excel数据文件的Input, Baseline 放入二维数组,然后循环读入Input和Baseline这两个Properties, 调用request, 取到Ouput和Result Properties的值放入Output, Result数组,最后更新Excel的Output, Result, Comparison sheet。
import java.io.*;import jxl.*;import java.text.DecimalFormat;def readInput(workbook,inputSheetName){ Sheet sheet=workbook.getSheet(inputSheetName); rows = sheet.getRows(); columns = sheet.getColumns(); /*Get content into array*/ input = new Object [columns][rows] for (a=0;a<columns;a++) { for (b=0;b<rows;b++) { input[a][b]= sheet.getCell(a,b).getContents(); } }}def readBaseline(workbook,sheetName){ Sheet sheet=workbook.getSheet(sheetName); Rows = sheet.getRows(); Columns = sheet.getColumns(); /*Get content into array*/ baseline = new Object [Columns][Rows] for (a=0;a<Columns;a++) { for (b=0;b<Rows;b++) { baseline[a][b]= sheet.getCell(a,b).getContents(); } }}def updateOutput(writableWorkbook,sheetName,start_row,rows,columnNo,result,resultTag){ Sheet[] sheet= writableWorkbook.getSheets(); ws = writableWorkbook.getSheet(sheetName); if(ws==null){ ws = writableWorkbook.createSheet(sheetName,sheet.length) } for (a=0;a<columnNo;a++) { ws.addCell(new jxl.write.Label(a,0,result[a][0])); for (b=start_row;b<rows;b++) { wc = new jxl.write.WritableCellFormat(); if (resultTag[a][b]=='PASS') { wc.setBackground(jxl.format.Colour.WHITE); ws.addCell(new jxl.write.Label(a,b,result[a][b],wc)); } else if(resultTag[a][b]=='FAIL'){ wc.setBackground(jxl.format.Colour.RED); ws.addCell(new jxl.write.Label(a,b,result[a][b],wc)); } } }}def updateResult(writableWorkbook,sheetName,start_row,rows,columnNo,result){ Sheet[] sheet= writableWorkbook.getSheets(); ws = writableWorkbook.getSheet(sheetName); if(ws==null){ ws = writableWorkbook.createSheet(sheetName,sheet.length) } for (a=0;a<columnNo;a++) { ws.addCell(new jxl.write.Label(a,0,result[a][0])); for (b=start_row;b<rows;b++) { wcf = new jxl.write.WritableCellFormat(); wcf.setBackground(jxl.format.Colour.RED); if(result[a][b] == 'FAIL'){ ws.addCell(new jxl.write.Label(a,b,result[a][b],wcf)); } else ws.addCell(new jxl.write.Label(a,b,result[a][b])); } } wc = new jxl.write.WritableCellFormat(); wcc = new jxl.write.WritableCellFormat(); wc.setBackground(jxl.format.Colour.GRAY_25); wcc.setBackground(jxl.format.Colour.LIGHT_TURQUOISE); ws.addCell(new jxl.write.Label(0,rows-3,result[0][rows-3],wcc)); ws.addCell(new jxl.write.Label(0,rows-2,result[0][rows-2],wc)); ws.addCell(new jxl.write.Label(0,rows-1,result[0][rows-1],wc)); }def updateComparison(writableWorkbook,sheetName,start_row,rows,columnNo,output,outputTag,result,baseline){ Sheet[] sheet= writableWorkbook.getSheets(); ws = writableWorkbook.getSheet(sheetName); if(ws==null){ ws = writableWorkbook.createSheet(sheetName,sheet.length) } for (a=0;a<columnNo;a++) { ws.addCell(new jxl.write.Label(a,0,output[a][0])); x= 1; for (b=start_row;b<rows;b++) { if(result[1][b] == 'FAIL'){ wc = new jxl.write.WritableCellFormat(); if (outputTag[a][b]=='PASS') { wc.setBackground(jxl.format.Colour.WHITE); ws.addCell(new jxl.write.Label(a,x,output[a][b],wc)); } else { wc.setBackground(jxl.format.Colour.RED); ws.addCell(new jxl.write.Label(a,x,output[a][b],wc)); } wbc = new jxl.write.WritableCellFormat(); wbc.setBackground(jxl.format.Colour.ICE_BLUE); ws.addCell(new jxl.write.Label(a,x+1,baseline[a][b],wbc)); x+=2; } } }}def removeSheetByName(writableWorkbook, name){ Sheet[] sheet= writableWorkbook.getSheets(); ws = writableWorkbook.getSheet(name); if(ws != null){ for (i = 0; i < sheet.length; i++) { sheetName = writableWorkbook.getSheet(i).getName(); if (sheetName.equalsIgnoreCase(name)) { writableWorkbook.removeSheet(i); } } }}def setProperties(Name,Value,Place){ name = Name; target = testRunner.testCase.getTestStepByName(Place); target.setPropertyValue(name,Value); }def cleanProperty(PropertyListName){ PropertyList = testRunner.testCase.getTestStepByName(PropertyListName); size=PropertyList.getPropertyCount(); if (size!=0) { for (i=0;i<size;i++) { PropertyList.removeProperty(PropertyList.getPropertyAt(0).name); } }}def logFile = new File(context.expand('${#TestCase#LogFile - Check Response}'));def xlsName = context.expand('${#TestCase#Workbook}');def project = testRunner.testCase.getTestSuite().getProject();def testSuite = testRunner.testCase.getTestSuite();def testcase = testRunner.testCasedef requests = testcase.getTestStepsOfType( com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.class )def request = requests[0];inputSheetName = "Input";baselineSheet = "Baseline";outputSheet = "Output";resultSheet = "Result";fieldResult = testcase.getTestStepByName('fieldResult');ComparisonSheet = "Comparison";Baseline = testcase.getTestStepByName(baselineSheet);baselineSize = Baseline.getPropertyCount();Output = testcase.getTestStepByName(outputSheet);def cal = Calendar.instance;def sysdate = cal.getTime();sleepTime=context.expand('${#Project#sleepTime}').toInteger()try{ Workbook workbook=Workbook.getWorkbook(new File(xlsName)); cleanProperty(inputSheetName); readInput(workbook,inputSheetName); for (i=0;i<columns;i++) { setProperties(input[i][0],'',inputSheetName) } cleanProperty(baselineSheet); readBaseline(workbook,baselineSheet); for (i=0;i<Columns;i++) { setProperties(baseline[i][0],'',baselineSheet) } workbook.close(); }catch(Exception e){ e.printStackTrace();} /*-----------Set runSelect as 'true' in Project property to run selected test cases from startTag till endTag-------*/def runSelected = context.expand('${#Project#runSelected}')start_Test=1;end_Test=rows-1;def passNumbers = 0;def decFormat = new DecimalFormat("##.00%"); if ('true'.equalsIgnoreCase(runSelected)){ startTag=context.expand('${#Project#startTag}').toInteger(); endTag=context.expand('${#Project#endTag}').toInteger(); if((0<startTag)&&(startTag<rows)&&(endTag>=startTag)&&(rows>endTag)){ start_Test=startTag; end_Test=endTag; }} result = new Object [2][rows+3] result[0][0]='Case Description'; result[1][0]='Result' result[0][rows+1]='Start Time:'; result[1][rows+1]=sysdate.toString(); /*--New object and put the output name and value into this list--*/ output = new Object [baselineSize][rows] outputTag = new Object [baselineSize][rows] for (i=0;i<baselineSize;i++) { output[i][0]= Baseline.getPropertyAt(i).name; outputTag[i][0]= 'PASS'; } for (m=start_Test;m<=end_Test;m++) { logFile.append('\n'+ testcase.name + ": "+m+" "+ ". "+sysdate+'\n'); for (i=0;i<columns;i++) { setProperties(input[i][0],input[i][m],inputSheetName) } for (j=0;j<Columns;j++) { setProperties(baseline[j][0],baseline[j][m],baselineSheet) } testRunner.runTestStepByName(request.name); Thread.sleep(sleepTime); testRunner.runTestStepByName("Check Response"); result[0][m]=context.expand('${'+inputSheetName+'#Case Description}') result[1][m]=context.expand('${'+resultSheet+'#result}') if(result[1][m] == 'PASS'){ passNumbers++; } for (i=0;i<baselineSize;i++) { output[i][m]= Output.getPropertyAt(i).value; outputTag[i][m]= fieldResult.getPropertyAt(i).value; }} result[0][rows+2]='End Time:'; result[1][rows+2]=sysdate.toString(); result[0][rows]='Pass Percentage:'; passPercentage = decFormat.format(passNumbers/(end_Test-start_Test+1)); result[1][rows] = passPercentage/*--------------Update Output, Result, Comparison sheet---------*/ try{ workbook = Workbook.getWorkbook(new File(xlsName)); writableWorkbook = Workbook.createWorkbook(new File(xlsName), workbook); updateOutput(writableWorkbook,outputSheet,start_Test,end_Test+1,baselineSize,output,outputTag); updateResult(writableWorkbook,resultSheet,start_Test,rows+3,2,result); removeSheetByName(writableWorkbook,ComparisonSheet); if(passPercentage != '100.00%'){ updateComparison(writableWorkbook,ComparisonSheet,start_Test,end_Test+1,baselineSize,output,outputTag,result,baseline); } writableWorkbook.write(); writableWorkbook.close(); workbook.close(); }catch(Exception e){ e.printStackTrace(); } setProperties('passPercentage', passPercentage ,'Result'); testRunner.gotoStepByName('End');
Check Response 顾名思义,用来检查返回结果, 通过XmlHolder getNodeValue 来取response各节点的值,并且填入Output Properties已作对比之用。
import java.lang.*;import java.util.*;import groovy.lang.*;import groovy.util.*;import com.eviware.soapui.support.XmlHolderbaselineSheet = "Baseline";outputSheet = "Output";resultSheet = "Result";def testcase = testRunner.testCase;Baseline = testcase.getTestStepByName(baselineSheet)baselineSize = Baseline.getPropertyCount();Output = testcase.getTestStepByName(outputSheet);def requests = testcase.getTestStepsOfType( com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.class )def request = requests[0];def response = request.testRequest.response;respXmlHolder = new XmlHolder(response.contentAsXml)//declare namespace in xml responserespXmlHolder.declareNamespace("ns1", "http://schemas.xxx.com/v201203/yourservice")def statusCode = request.testRequest.response.responseHeaders["#status#"].toString();def setProperties(Name,Value,Place){ name = Name; target = testRunner.testCase.getTestStepByName(Place); target.setPropertyValue(name,Value);}def getspecifiedValue(field){ prefix = "//ns1:"; nodePath = "${prefix}${field}" specifiedValue = respXmlHolder.getNodeValue("${nodePath}")}testRunner.testCase.getTestStepByName(outputSheet).clearPropertyValues();//normal output, status = '200 OK'if(statusCode.contains('200 OK')){ for (i=1;i<baselineSize;i++) { specifiedName = Baseline.getPropertyAt(i).name; specifiedValue = getspecifiedValue(specifiedName); if(specifiedValue != null){ setProperties(specifiedName,specifiedValue,outputSheet) } else { setProperties(specifiedName,'',outputSheet) } } } else { setProperties(Baseline.getPropertyAt(0).name,Baseline.getPropertyAt(0).value,outputSheet); setProperties(Baseline.getPropertyAt(1).name,statusCode,outputSheet); for(t=2; t<baselineSize; t++){ setProperties(Baseline.getPropertyAt(t).name, '' ,outputSheet); }}setProperties(Baseline.getPropertyAt(0).name,Baseline.getPropertyAt(0).value,outputSheet);setProperties('result','PASS', resultSheet);logFile = new File(context.expand('${#TestCase#LogFile - Check Response}'));responseDetailLogFile= new File(context.expand('${#TestCase#LogFile - Response Detail}'));logFile.append(" ------ Start Response Check "+ " @ "+Calendar.instance.getTime()+"\n");responseDetailLogFile.append("\n"+ testcase.name + " -- " + Baseline.getPropertyAt(0).value+ "\n" + response+"\n");/*--------Compare the result with Baseline and update the result accordingly---------*/for (i=0;i<baselineSize;i++){ if (Baseline.getPropertyAt(i).value==Output.getPropertyAt(i).value) { setProperties(Baseline.getPropertyAt(i).name,'PASS','fieldResult'); } else { setProperties(Baseline.getPropertyAt(i).name,'FAIL','fieldResult'); setProperties('result','FAIL','Result'); } }
End脚本 在log上打时间戳
def cal = Calendar.instance;def sysdate = cal.getTime();responseLogFile = new File(context.expand('${#TestCase#LogFile - Check Response}'));responseDetailLogFile= new File(context.expand('${#TestCase#LogFile - Response Detail}'));responseLogFile.append('\n'+ "---------------Test End on " + sysdate.toString() + " ------------------------"+'\n');responseDetailLogFile.append('\n'+ "---------------Test End on " + sysdate.toString() + " ------------------------"+'\n');
配置
双击DemoProject, 点击下方的Properties tab
然后 Add property
Add 如下图所示的5个Property
双击项目工程列表里的'Demo TestCase'
点击Properties tab
Add Property 如图
Value 填Excel 的路径
Excel数据工作簿里的Input sheet 如图
接下来需要把Input里的column name 与 Soap request里的input 字段映射起来
双击Test Steps 里的request
将xml文件里的?用参数来代替
左下角的TestRequest Properties 要填上用户名 密码
Baseline sheet里要把输出结果的字段名都定义好, 因为是根据字段名去response里取结果的
每条用例期望结果都写好,用作和实际结果对比
另外Check Response里的脚本需要设置一下
假设你的response xml文件结构如下
如果你需要检查Soap body标签下的内容, 则你需要配置一下Check Response的脚本
将xml namespace的路径配置一下
右击Project Save一下Project
最后可以运行了 双击Demo TestSuite 点击Run
注意:Groovy脚本也是用第三方的jxl.jar操作excel文件的,所以这个jar需要放到SoapUI安装目录的\lib下面,才能运行成功。
打开Workbook 数据工作簿查看结果
Output
Result
Comparison
是不是跟我上一篇文章异曲同工?
- 手把手教你接口自动化测试 – SoapUI & Groovy
- 手把手教你接口自动化测试 – SoapUI & Groovy
- soapui+groovy进行接口自动化测试浅谈
- soapui + groovy 接口自动化测试 第一章
- soapui + groovy 接口自动化测试 第二章
- SoapUI + Groovy 接口自动化
- SoapUI & Groovy接口自动化测试的简单扩展
- SoapUI接口自动化测试
- soapUI+groovy 接口测试之部分groovy使用记录
- SOAPUI 使用groovy发送http请求 自动化测试
- 手把手教你TestComplete_自动化测试流程示例
- 手把手教你ranorex_android自动化测试第一个示例
- 手把手教你uiautomator_android自动化测试第一个示例
- 手把手教你搭建Robot Framework自动化测试环境
- SOAPUI 接口自动化学习笔记节选 如何用Groovy 脚本读取CSV 文件
- SOAPUI 接口自动化学习笔记节选 如何用Groovy 脚本读取CSV 文件
- SoapUI自动化--Groovy脚本常用操作
- 使用SoapUI 测试接口
- hdu 2717 Catch That Cow(广搜bfs)
- 内部类
- TableView
- hdu 1159 Common Subsequence(最长公共子序列 DP)
- 抓其根本(一)(hdu2710 Max Factor 素数 最大公约数 最小公倍数.....)
- 手把手教你接口自动化测试 – SoapUI & Groovy
- 抓起根本(二)(hdu 4554 叛逆的小明 hdu 1002 A + B Problem II,数字的转化(反转),大数的加法......)
- hdu 1081 To The Max(dp+化二维为一维)
- hdu 1200 To and Fro(简单模拟或DP)
- 中南oj String and Arrays
- PHP文件缓存类
- Contest2073 - 湖南多校对抗赛(2015.04.06)
- hdu 1556 Color the ball (线段树之扫描线)
- hdu 1166敌兵布阵(线段树)