博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记我的第一次自动化尝试
阅读量:6414 次
发布时间:2019-06-23

本文共 13250 字,大约阅读时间需要 44 分钟。

因为要反复测试一个接口,手工慢慢执行效率太低,就打算自动化实现。下面记录一下整个实现的过程和遇到的问题。

因为开发同事有提供一个调用接口的测试方法,很自然的我就想到了要把这个方法改成用junit来实现。如果单纯一个@Test方法,那么和直接执行main方法差别不大,幸好junit提供了参数化的实现。我参考http://blog.csdn.net/zen99t/article/details/50572373之后,实现了简单的参数化,具体代码如下:

1 @RunWith(value=Parameterized.class) 2 public class TestTransationClient { 3     DictionUtil du; 4     TransactionClient tc; 5     String url = "https://接口地址"; 6     private String row; 7     private String authentType; 8     private String merNo; 9     private String IdNo;10     private String name;11     private String mobileNo;12     private String bankCardNo;13    16     public TestTransationClient(String row,String authentType,String merNo,String IdNo,String name,String mobileNo,String bankCardNo) {17         // TODO Auto-generated constructor stub18         this.row=row;19         this.authentType=authentType;20         this.merNo=merNo;21         this.IdNo=IdNo;22         this.name=name;23         this.mobileNo=mobileNo;24         this.bankCardNo=bankCardNo;25     }26     @Parameters(name="名字")27     public static Iterable
data(){28 return Arrays.asList(new Object[][]{29 {"11","123456","","roy","13312345678",""},30 {"12","123456","123456","李白","13800138000","62213466552222222"},31 {"21","123456","","roy","",""},32 {"21","123456","","","",""}33 });34 }

@Test方法会读取

return Arrays.asList(new Object[][]{29            {"11","123456","","roy","13312345678",""},30             {"12","123456","","","",""},31            {"21","123456","","roy","",""},32             {"21","123456","","","",""}33  }); 里面的数据,每次执行读取一行,算作一条测试用例。列表存在几行数据就执行了几条测试用例,现在已经比之前每执行一条测试用例就要改一次数据方便了些。但是这样还是不够智能,我决定让他直接读取excel里面的数据,然后将运行结果写入到excel测试结果列。 Excel的读写不难,我用的是jxl包。读excel 的方法如下
1 /** 2      * 读取测试用例第4列参数 3      * 参数格式为:认证类型|商户号|身份证号|姓名|手机号|银行卡号|code|codeno|value   4      * 例子:11|123456|123456|roy||||1|1 5      * @param ExcelLocation 测试用例存放路径 6      * @return 返回Junit参数化所需要的list 7      */ 8     @SuppressWarnings("unchecked") 9     public List readExcel(String ExcelLocation) {10         jxl.Workbook readWorkBook = null;11         String[] temp;12         List list = new ArrayList
();13 String oraginalData = null;14 int k = 0;15 try {16 InputStream input = new FileInputStream(ExcelLocation);17 readWorkBook = Workbook.getWorkbook(input);18 Sheet readSheet = readWorkBook.getSheet(1);19 for (int i = 0; i < readSheet.getRows(); i++) {20 Cell cellInput = readSheet.getCell(4, i);21 Cell dataSwitch=readSheet.getCell(3, i); //设置了控制是否执行案例的开关,填enable则执行22 if (cellInput.getContents().contains("|")&&dataSwitch.getContents().equals("enable")) {23 oraginalData = cellInput.getContents();24 // System.out.println(oraginalData);25 temp = oraginalData.split("\\|", 10); list.add(temp);26 int row=i+1;27 System.out.println("将第"+row+"行数据添加到list成功");28 // for (int j = 0; j < temp.length; j++) {29 // System.out.println(temp[j]);30 // }31 }32 33 } 34 35 } catch (Exception e) {36 // TODO Auto-generated catch block37 e.printStackTrace();38 } 39 return list;40 }

我将测试参数用“|”隔开,每个位置一个参数,读出单元格的数据后,用split方法将一串字符分割存到数组,然后再把数组存到list里面,作为junit执行需要的参数,每个数组作为一条测试用例的输入数据。

写入Excel的方法如下:

1 /** 2      * 往excel写数据 3      * @param data 需要写入的字符串 4      * @param column 目标单元格列号 5      * @param row     目标单元格行号 6      * @param ExcelName  文件路径 7      */ 8     public void writeExcel(String data,int column,int row,String ExcelName) { 9         try {10             InputStream input = new FileInputStream(ExcelName);11             Workbook readWorkBook = Workbook.getWorkbook(input);12             Sheet readSheet = readWorkBook.getSheet(1);13             WritableWorkbook wwb = Workbook.createWorkbook(new File(ExcelName), readWorkBook);14             WritableSheet ws = wwb.getSheet(1);15             Label label = new Label(column,row, data);16             ws.addCell(label);17             int ji=row+1;18             System.out.println("填充第"+ji+"行表格成功");            19             wwb.write();20             System.out.println("写入表格并保存成功");21             wwb.close();22         } catch (Exception e) {23             // TODO Auto-generated catch block24             e.printStackTrace();25         } 26     }

写这里我遇到了一个问题,就是一开始我是读取输入的文件A后重新创建一个新的文件B作为写的对象文件,每次创建的时候会把A所有的内容复制到B然后再写,这样的话导致了我执行下一条案例时也要重新创建B,那么上一条案例写入的执行结果就会丢失。解决办法是,把所有文件的命名改成一致,就是输入文件A,写完后的文件也命名为A,那么就会覆盖原来的输入文件作为新的输入文件,继续被下一条案例读取,就不会丢失之前的执行结果了。

做到这里,我已经能够实现自动读写和执行方法调用接口了,但是还漏了一步,就是执行前可能要配置数据字典。我想过找开发要一份这个功能的代码,但是考虑到方法依赖太多,太过复杂。师姐建议我用selenium在后台页面上改。代码如下:

public void editDiction(String code, String codeno, String value) throws InterruptedException {

login("账号","密码");
driver.switchTo().frame(1).findElement(By.linkText("数据字典管理")).click();
System.out.println("进入数据字典菜单,开始修改数据字典");
driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(By.xpath("//frame[@src=\"popedom/manage.jsp\"]"))).findElement(By.id("code")).clear();
driver.findElement(By.id("code")).sendKeys(code);
driver.findElement(By.cssSelector("input[type=\"image\"]")).click();

// driver.findElement(By.id("edit_2058595")).click();

driver.findElement(By.xpath("//*[@alt=\"修改\"]")).click();
driver.findElement(By.cssSelector("Input[id^=\"codeNo_\"]")).clear();
driver.findElement(By.cssSelector("Input[id^=\"codeNo_\"]")).sendKeys(codeno);
// Thread.sleep(11111);
// driver.findElement(By.id("codeNo_2058595")).clear();
// driver.findElement(By.id("codeNo_2058595")).sendKeys(codeno);
driver.findElement(By.cssSelector("Input[id^=\"value_\"]")).clear();
driver.findElement(By.cssSelector("Input[id^=\"value_\"]")).sendKeys(value);
// driver.findElement(By.id("value_2058595")).clear();
// driver.findElement(By.id("value_2058595")).sendKeys(value);
driver.findElement(By.xpath("//img[@alt=\"保存\"]")).click();
System.out.println("修改数据字典成功:" + code);
driver.quit();
}

实现过程中遇到两个问题,第一,我直接执行IDE录制(IDE真是个好东西)的脚本不成功,定位不到元素。原来页面使用了frame,参考http://blog.csdn.net/lykangjia/article/details/46348535后,完美解决问题。只要加一句

driver.switchTo().frame(1)切换frame后就能定位到了。第二,是元素ID是会变化的,类似于这种a_1、a_2,就是同一个输入框,列表不同行的ID是不一样的,为了能够复用代码,在网上找到了使用findElement(By.cssSelector("Input[id^=\"value_\"]"))的方法完美解决。
"Input[id^=\"value_\"表示,id的头为value_的input元素。详见https://www.cnblogs.com/sylvia-liu/p/4469597.html 类似的,我又写了个新增数据字典的方法
public void addDiction(String code, String codeno, String value) throws Exception{            login("账号","密码");            driver.switchTo().frame(1).findElement(By.linkText("数据字典管理")).click();            // ERROR: Caught exception [ERROR: Unsupported command [selectWindow | name=main | ]]            driver.switchTo().defaultContent();            driver.switchTo().frame(driver.findElement(By.xpath("//frame[@src=\"popedom/manage.jsp\"]"))).findElement(By.id("code")).clear();            driver.findElement(By.xpath("(//input[@type='image'])[2]")).click();            System.out.println("开始新增数据字典");//            Thread.sleep(5000);            driver.findElement(By.id("code")).clear();            driver.findElement(By.id("code")).sendKeys(code);            driver.findElement(By.id("value")).clear();            driver.findElement(By.id("value")).sendKeys(codeno);            driver.findElement(By.id("codeNo")).clear();            driver.findElement(By.id("codeNo")).sendKeys(value);            driver.findElement(By.cssSelector("input[type=\"image\"]")).click();//            Thread.sleep(5000);            System.out.println("新增数据字典成功:"+ code);            driver.quit();    }

login方法,调起火狐并登录系统

public void login(String account,String password){        System.setProperty("webdriver.firefox.bin", "D:\\Program Files (x86)\\Mozilla Firefox\\24.0\\firefox.exe");        driver = new FirefoxDriver();        baseUrl = "后台地址";        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);        driver.get(baseUrl + "/user/login.jsp");        // driver.manage().window().maximize();        driver.findElement(By.id("userName")).click();        driver.findElement(By.id("userName")).clear();        driver.findElement(By.id("userName")).sendKeys(account);        driver.findElement(By.id("UserPwd")).click();        driver.findElement(By.id("UserPwd")).clear();        driver.findElement(By.id("UserPwd")).sendKeys(password);        driver.findElement(By.cssSelector("input[type=\"image\"]")).click();    }

 

最后再遍历数据库数据字典表,遍历参数与要操作的参数做对比,参数存在则调用修改参数的方法,数据不存在则调用新增参数的方法。在使用JDBC的过程中,一开始报了DB2 SQL Error: SQLCODE=-204, SQLSTATE=42704, SQLERRMC=表名,原来是因为定位不到schema,增加 properties.setProperty("currentSchema","用户Schema");就可以了。参考链接http://bbs.csdn.net/topics/320197969

代码如下

public boolean dictionIsExist(String code){         Connection conn = null;          Statement stmt = null;          ResultSet rs = null;          boolean exist = false;          try {                                          Properties properties = new Properties();                properties.setProperty("user","登录名");                properties.setProperty("password","密码");                properties.setProperty("currentSchema","用户Schema");                Class.forName("com.ibm.db2.jcc.DB2Driver");                conn=DriverManager.getConnection("jdbc:db2://数据库链接", properties);                stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);//ResultSet.TYPE_SCROLL_SENSITIVE类型的ResultSet才能使用rs.isLast()
String sql="select * from dna_diction"; stmt.executeQuery(sql); rs=stmt.getResultSet(); int g=0; while(rs.next()){                String dbCode=rs.getString("code");                if (dbCode!=null&&code.equals(dbCode)){                   exist=true;                    System.out.println("数据字典已存在,调用修改数据字典的方法");                    break; }               if (rs.isLast()){               System.out.println("数据字典不存在,调用新增数据字典的方法");               exist=false; break; } }     rs.close();     stmt.close();     conn.close(); } catch (Exception e) {  e.printStackTrace(); } return exist; } }

最后的@Test方法如下

import java.util.Date;import java.util.List;import org.junit.After;import org.junit.Assert;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.Parameterized;import org.junit.runners.Parameterized.Parameters;@RunWith(value=Parameterized.class)public class TestTransationClient {    DictionUtil du;    TransactionClient tc;    String url = "接口api地址";    private String row;    private String authentType;    private String merNo;    private String IdNo;    private String name;    private String mobileNo;    private String bankCardNo;    private String code;    private String codeno;    private String value;    public TestTransationClient(String row,String authentType,String merNo,String IdNo,String name,String mobileNo,String bankCardNo,String code,String codeno,String value) {        // TODO Auto-generated constructor stub        this.row=row;        this.authentType=authentType;        this.merNo=merNo;        this.IdNo=IdNo;        this.name=name;        this.mobileNo=mobileNo;        this.bankCardNo=bankCardNo;        this.code=code;        this.codeno=codeno;        this.value=value;    }    @Parameters(name="名字{0}****")    public static Iterable
data(){ List list = null; list=new ExcelUtil().readExcel("E:\\test\\AS.xls"); return list; } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void test() throws Exception { tc=new TransactionClient(url); tc.setServerCert(Toolkit.getPropertyFromFile(); String encryptKey = Toolkit.random(24); tc.setMerchantNo(merNo); tc.setMerchantPwd("123456"); // tc.setTerminalNo("02028828");// String transactType = authentType;// String address = "";//// String accountno = bankCardNo;//// String idcardno=bankCardNo;// String name = name;// // String mobile = mobileNo; du=new DictionUtil(); if(du.dictionIsExist(code)){ du.editDiction(code,codeno,value); }else{ du.addDiction(code, codeno, value); } AuthentXmlImpl result=tc.a(Toolkit.yyyyMMddHHmmssSSS(new Date()), encryptKey, authentType, address, bankCardNo, IdNo, name, mobileNo); int rowIndex=Integer.valueOf(row)-1; new ExcelUtil().writeExcel(result.toString(),7,rowIndex,"E:\\test\\AS.xls"); if (authentType.equals("11")){ Assert.assertEquals("0000",result.getIDCardNameResult()); }else if(authentType.equals("12")){ Assert.assertTrue(result.getIDCardNameResult().equals("0000")); }else if(authentType.equals("21")){ Assert.assertEquals("0000", result.getIDCardNoResult()); } }}

至此,第一次自动化尝试成功,以后测试会方便很多,还可以根据需要再做调整,增加输入参数扩展都很方便。在此再次谢谢广大肯分享自己的心得体会和问题解决方案的网友们,特别感谢上述参考链接的作者们,谢谢。

代码已去掉一些敏感信息,不便之处,敬请谅解。

 
 

 

转载于:https://www.cnblogs.com/fpzh/p/7872869.html

你可能感兴趣的文章
Mac下cocoapods使用说明(2016版)
查看>>
nodejs - json序列化&反序列化示例
查看>>
DPM 2012 R2恢复Exchange 2013单用户邮箱
查看>>
div+css总结—FF下div不设置高度背景颜色或外边框不能显示
查看>>
nfs挂载及优化
查看>>
MySQL读写分离--mysql-proxy和amoeba
查看>>
[Swift]UIKit学习之警告框:UIAlertController和UIAlertView
查看>>
linux运维实战练习-2015年9月5日课程作业
查看>>
我的友情链接
查看>>
linux的selinux 状态以及关闭
查看>>
如何在win10系统上安装linux子系统
查看>>
XenApp服务器警报介绍
查看>>
20150910-Linux程序包管理
查看>>
matlab-线性代数 tril triu 对已知矩阵取上、下三角矩阵
查看>>
TurboGate全能邮件网关金融行业解决方案
查看>>
MySql实现远程连接访问
查看>>
AppRTC(WebRTC服务器)的编译安装
查看>>
CentOs操作RabbitMq常用命令
查看>>
Java并发编程:volatile关键字解析
查看>>
表单Form以及表单元素,框架集(了解)及iframe(重点)
查看>>