手把手教你接口自动化测试 – SoapUI & Groovy

转自 http://www.cnblogs.com/wade-xu/p/4236295.html  Wade Xuhtml

手把手教你接口自动化测试 – SoapUI & Groovyjava

 

 

关键词:SoapUI接口测试,接口自动化测试,数据驱动测试,SoapUI进阶使用, Groovy in SoapUI, SoapUI中Groovy的使用,数据分离。node

 

阅读这篇文章须要必定的SoapUI基础,至少入过门,另外还须要一些Groovy的知识,固然若是你会java 也能够,这里用到的Groovy知识和Java很相似。web

另外,本文的思路和我上一篇文章<零成本实现接口自动化测试 – Java+TestNG 测试Restful service>很类似,只不过把Java+TestNG的组合换成了SoapUI+Groovy, 另外测试对象也换成了基于Soap的web service, 依旧用Excel来管理数据,作到数据分离。数组

因为我用到的SoapUI是免费版本,相比Pro版,少不少的功能,像DataLoop之类的,因此只能经过Groovy写一些脚原本作数据驱动的测试。app

 

首先打开SoapUI, 新建一个Workspace 名为Demoide

 

 

而后点击File->New soapUI Projectoop

 

而后输入你的Project Name, WSDL 地址 点击OK测试

 

 

输入服务的用户名密码 点击OKui

 

项目工程建好了

 

右击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文件

/*Check the log file, create folder and file if necessary*/
import java.io.*;

def cal = Calendar.instance;
def sysdate = cal.getTime();
def Y = cal.get(Calendar.YEAR); 
def M = cal.get(Calendar.MONTH)+1; 
def D = cal.get(Calendar.DATE);
if (D<10) D = "0"+D; 
if (M<10) M = "0"+M; 
date = Y+"-"+M+"-"+D;
time=sysdate.toString().replaceAll(':','-')

def testSuites=testRunner.testCase.getTestSuite();
def testcase = testRunner.testCase;

def logFolder = new File(context.expand('${#Project#LogFolder}'));
def responseLogName = (context.expand('${#Project#LogFolder}')+date+'\\'+testSuites.name+' - '+ testcase.name +' - ' + time+".log");
def responseDetailLogName = (context.expand('${#Project#LogFolder}')+date+'\\'+testSuites.name+' - ' + testcase.name +' - ' + time + " Response Detail.log");
def responseLogFile = new File(responseLogName);
def responseDetailLogFile = new File(responseDetailLogName);
def subFolder= new File (context.expand('${#Project#LogFolder}')+date+'\\')

/*Set date and Log Name to Project - Testcase Properties*/
testcase.setPropertyValue('date', date);
testcase.setPropertyValue('LogFile - Check Response', responseLogName);
testcase.setPropertyValue('LogFile - Response Detail', responseDetailLogName);

if(!logFolder.exists()){
    logFolder.mkdirs();
    }

if(!subFolder.exists()){
    subFolder.mkdirs();
    }

/*Check the file, create a new one if not found*/
if(!responseLogFile.exists()){
    responseLogFile.createNewFile();
    }
responseLogFile.append("---------------Test Start on "+sysdate+" ------------------------"+'\n');

if(!responseDetailLogFile.exists()){
    responseDetailLogFile.createNewFile();
    }
responseDetailLogFile.append("---------------Test Start on "+sysdate+" ------------------------"+'\n');
View Code

 

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.testCase
def 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');
View Code

 

Check Response 顾名思义,用来检查返回结果, 经过XmlHolder getNodeValue 来取response各节点的值,而且填入Output Properties已做对比之用。

import java.lang.*;
import java.util.*;
import groovy.lang.*;
import groovy.util.*;
import com.eviware.soapui.support.XmlHolder

baselineSheet = "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 response
respXmlHolder.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');
         }
 }
View Code

 

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');
View Code

 

配置

双击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

 

是否是跟我上一篇文章殊途同归?

相关文章
相关标签/搜索