Android WebApp & NativeApp 适配测试自动化平台GoGo实现 东海陈光剑
时间:2014-04-29 19:00:18
收藏:0
阅读:1100
Android WebApp & NativeApp 适配测试自动化平台GoGo实现
东海陈光剑
2014年3月6日 18:27:55
源代码:
GoGo平台架构:
运行结果:
性能分析CPU%:( 用highcharts做成图形化的报告形式 )
运行日志:
生成报告代码:
资源上传服务器:
/**
* Upload.java etao.test.fileload
UploadFileToServer 下午1:38:59 2014年4月20日 2014
*/
package
etao.test.fileload;
/**
* @author
东海陈光剑
* 2014年4月20日 下午1:38:59
*/
import java.io.File;
import java.io.IOException;
import
java.util.Iterator;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.apache.commons.fileupload.FileItem;
import
org.apache.commons.fileupload.disk.DiskFileItemFactory;
import
org.apache.commons.fileupload.servlet.ServletFileUpload;
@SuppressWarnings("serial")
public
class Upload extends HttpServlet {
private String uploadPath = "C:\\autoTest\\httpd\\htdocs\\img"; // 上传文件的目录
private String tempPath = "c:\\buffer\\"; // 临时文件目录
File
tempPathFile;
@SuppressWarnings("unchecked")
public void
doPost(HttpServletRequest request, HttpServletResponse
response)
throws IOException, ServletException
{
try {
// Create a factory for disk-based file
items
DiskFileItemFactory factory = new
DiskFileItemFactory();
// Set factory
constraints
factory.setSizeThreshold(4096); //
设置缓冲区大小,这里是4kb
factory.setRepository(tempPathFile);//
设置缓冲区目录
// Create a new file upload
handler
ServletFileUpload upload = new
ServletFileUpload(factory);
// Set overall request size
constraint
upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB
List<FileItem> items = upload.parseRequest(request);//
得到所有的文件
Iterator<FileItem> i =
items.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem) i.next();
String fileName = fi.getName();
if
(fileName != null) {
File
fullFile = new
File(fi.getName());
File savedFile = new
File(uploadPath, fullFile.getName());
fi.write(savedFile);
}
System.out.println(fileName +
" upload successfully!");
}
// System.out.println("upload
succeed");
} catch
(Exception e) {
// 可以跳转出错页面
e.printStackTrace();
}
}
public void
init() throws ServletException
{
File uploadFile = new
File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdirs();
}
File tempPathFile
= new
File(tempPath);
if (!tempPathFile.exists()) {
tempPathFile.mkdirs();
}
}
}
public static void genReport(String run_stamp, String runningSec,
String runningMin) {
/**
* 调用系统默认浏览器打开链接
* http://10.73.72.122:88/report.html?run_stamp=20140302023811
* &sec=250&min=4
*/
if (java.awt.Desktop.isDesktopSupported()) {
try {
String reportUriStr = "http://10.73.72.122:88/report.html?run_stamp="
+ run_stamp
+ "&sec="
+ runningSec
+ "&min="
+ runningMin;
// 创建一个URI实例
java.net.URI reportUri = java.net.URI.create(reportUriStr);
// String uri1Str =
// "http://10.73.72.122:8080/Report/go?run_stamp="
// + run_stamp;
//
// java.net.URI uri1 = java.net.URI.create(uri1Str);
// 获取当前系统桌面扩展
java.awt.Desktop dp = java.awt.Desktop.getDesktop();
// 判断系统桌面是否支持要执行的功能
if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
// 获取系统默认浏览器打开链接
dp.browse(reportUri);
// dp.browse(uri1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}report.html放到Apache
httpd Server下面:D:\Apache2.2\htdocs
<!doctype
html>
<html>
<head>
<meta charset="UTF-8">
<title>适配测试报告</title>
<script src="http://g.tbcdn.cn/kissy/k/1.4.0/seed-min.js"></script>
<style type="text/css">
body {
background-color: #EEFFFF;
}
p.serif{font-family:"Times
New Roman",Georgia,Serif}
p.sansserif{font-family:Arial,Verdana,Sans-serif}
</style>
</head>
<body class="serif">
<br><br><br><br>
<h1 align="center"style=font-family:微软雅黑>一淘android客户端适配测试报告</h1>
<p
align="right">
<label for="issue_issue_author_id">联系人:陈光剑</label>
<a href="http://www.taobao.com/webww/ww.php?ver=3&touid=universsky1&siteid=cntaobao&status=2&charset=utf-8"
class="inline-item" target="_blank" title="universsky1"><img alt="universsky1" border="0" src="http://amos.alicdn.com/realonline.aw?v=2&uid=universsky1&site=cntaobao&s=2&charset=utf-8"
/></a><a href="http://amos.alicdn.com/msg.aw?v=2&uid=universsky1&site=cnalichn&s=11&charset=UTF-8"
class="inline-item" target="_blank" title="universsky1"></a>
</p>
<div id=time
align="right"
style=font-family:Verdana></div>
<script>setInterval("time.innerHTML=‘今天是‘+new Date().toLocaleString()+‘
星期‘+‘日一二三四五六‘.charAt(new Date().getDay())+‘ ‘;",1000);</script>
<script>
KISSY.ready(function(S){
var
path="http://10.125.1.58:88/img/";
var href =
location.href;
/**
*
调用系统默认浏览器打开链接 Apache httpd
*
http://127.0.0.1:88/report.html?run_stamp=20140302023811
* &sec=250&min=4
*/
var m,
run_stamp;
m = href.match(/stamp=(\d+)/);
if(!m) run_stamp
= "20140421122151";
else run_stamp =
m[1] ;
var sec
;
sec = href.match(/sec=(\d+)/);
if(!sec) se = 0;
else se=sec[1];
var min;
min =
href.match(/min=(\d+)/);
if(!min) mi=0;
else mi = min[1];
/*
请求报告资源接口,tomcat在8888端口监听 */
S.use("node,io", function(S, Node, IO){
IO({
url:
"http://10.125.1.58:8888/Report/go?run_stamp="
+ run_stamp,
dataType: "jsonp",
jsonpCallback: "report",
success: function(data) {
var report=data;
var
runtime_log = path +
run_stamp + "$runtime.log";
var
cpu_log = path + run_stamp + "$cpu_usage.log";
var bodyContent="<p><font face=\"verdana\">开始时间:" + run_stamp +"</font></p>";
bodyContent = bodyContent + "<p><font
face=\"verdana\">运行时间: " + se + "s ( " +
mi + " min )
</font></p>";
bodyContent = bodyContent + "<p
align=center ><font face=\"verdana\"><a href=\""+runtime_log+"\">测试运行记录(点击查看)</a></font></p>";
bodyContent = bodyContent +
"<p align=center ><font face=\"verdana\"><a
href=\""+cpu_log +"\">CPU使用情况(点击查看)</a></font></p>";
bodyContent = bodyContent + "<hr noshade size=5 align=center width=100%
/>";
bodyContent = bodyContent +
"<table style=\"table-layout:fixed\"
border=\"0\">";
/*表格总开始*/
// 遍历DeviceID
for (var i
= 0; i <
report.result.length; i++) {
bodyContent=bodyContent+"<tr><td width=\"80\"
scope=\"col\"><font face=\"verdana\"
>DeviceId(日志)</font></td>";
for (var j
= 0; j <
report.result[i].img_timestamp.length; j++)
{
bodyContent =
bodyContent+"<td
style=\"word-break : break-all\"; \"overflow:hidden\"; width=\"100\"
scope=\"col\"><font face=\"verdana\" >"+report.result[i].url[j]+"</font></td>";
}
bodyContent = bodyContent+"</tr>";
/*以上是urls行*/
/*这里是log记录*/
var log_url = path
+ run_stamp + "$" +
report.result[i].device_id + "$runtime.log";
bodyContent =
bodyContent+ "<tr><td scope=\"row\"><font face=\"verdana\"
>"+report.result[i].device_id + "</font></td>";
//bodyContent = bodyContent+ "<tr><td
scope=\"row\"><font face=\"verdana\" ><a
href=\""+log_url+"\">"+report.result[i].device_id +
"</a></font></td>";
/*下面是imgsrc行*/
for (var j
= 0; j <
report.result[i].img_timestamp.length; j++)
{
var imgsrc_url = path
+ report.run_stamp+"$"+
report.result[i].device_id+"$"+
report.result[i].img_timestamp[j]+"$"+
report.result[i].img_name[j];
bodyContent = bodyContent+
"<td><a href=\""+ imgsrc_url +"\"><img src=\"" +imgsrc_url+
"\" width=\"200\"
height=\"300\"></td>";
}
bodyContent = bodyContent+"</tr>";
};
/********************************************************************************************************************/
/*总表格结束*/
bodyContent=bodyContent+"</table>";
/*输出总的报告*/
//
document.write("<html><head><title>适配测试报告 " + report.run_stamp
+ "</title></head><body>" + bodyContent);
//
document.write("</body></html>");
S.one("body").append(bodyContent);
}
})
});
});
</script>
</body>
</html>
报告url,img资源获取http接口:
- Request URL:http://10.73.72.122:8080/Report/go?_ksTS=1394101086006_19&callback=report&run_stamp=20140306052855
- Request Method:GET
- Status Code:
200 OK
-
接口实现代码:
/**
* Report.java ct.report Report 下午7:38:18 2014年2月28日 2014
*/
package ct.report;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import ct.dao.ReportDao;
/**
* @author 东海陈光剑 2014年2月28日 下午7:38:18
*/
public class Report extends HttpServlet {
/**
* serialVersionUID long
*/
private static final long serialVersionUID = -7282812094112943289L;
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
run_stamp = req.getParameter("run_stamp");
callback = req.getParameter("callback");
ReportDao dao = new ReportDao();
Gson gson = new Gson();
String json = gson.toJson(dao);
// 在console上打印记录
System.out.println(callback + "(" + json + ")");
PrintWriter out = resp.getWriter();
out.print(callback + "(" + json + ")");
out.flush();
}
public String getRun_stamp() {
return run_stamp;
}
public void setRun_stamp(String run_stamp) {
Report.run_stamp = run_stamp;
}
static String run_stamp;
static String callback;
}
/**
* ReportDao.java ct.dao Report 下午9:32:16 2014年2月28日 2014
*/
package ct.dao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import ct.report.Report;
/**
* @author 东海陈光剑 2014年2月28日 下午9:32:16
*/
public class ReportDao {
// Report report = new Report();
private String run_stamp = (new Report()).getRun_stamp();
// private ArrayList<String> deviceList = (new Report()).getDeviceList();
// private String device_id = (new Report()).getDevice_id();
// QueryResult qr = new QueryResult();
// Map<String, ArrayList<String>> result = (new QueryResult()).query(
// run_stamp, device_id);
List<HashMap<String, ArrayList<String>>> result = (new QueryResult())
.query(run_stamp);
}
/**
* QueryResult.java ct.dao Report 下午10:14:57 2014年2月28日 2014
*/
package ct.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 东海陈光剑 2014年2月28日 下午10:14:57
*/
public class QueryResult {
/**
* @param args
* void main
*/
public static void main(String[] args) {
String run_stamp = "20140228041020";
QueryResult qr = new QueryResult();
// Map<String, ArrayList<String>> result = qr.query(run_stamp,
// device_id);
List<HashMap<String, ArrayList<String>>> result = qr.query(run_stamp);
System.out.println(result);
}
List<HashMap<String, ArrayList<String>>> query(String run_stamp) {
ArrayList<String> deviceList = getDeviceList(run_stamp);
List<HashMap<String, ArrayList<String>>> result = new ArrayList<HashMap<String, ArrayList<String>>>();
// Map<String, ArrayList<String>> imgName = new HashMap<String,
// ArrayList<String>>();
// Map<String, ArrayList<String>> imgTimeStamp = new HashMap<String,
// ArrayList<String>>();
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载MYSQL JDBC驱动程序
System.out.println("Success loading mysql driver!");
} catch (Exception e) {
System.out.print("Error loading mysql driver!");
e.printStackTrace();
}
try {
Connection connect = DriverManager.getConnection(
"jdbc:mysql://10.73.72.122:3306/test", "root", "isword");
// 连接URL为 jdbc:mysql//服务器地址/数据库名 ,后面的2个参数分别是登陆用户名和密码
System.out.println("Success connect mysql server!");
Statement stmt = connect.createStatement();
for (String device_id : deviceList) {
String queryCmd = "SELECT * FROM ct_pic where run_stamp=‘"
+ run_stamp + "‘ and device_id=‘" + device_id
+ "‘ ORDER BY img_timestamp";
System.out.println(queryCmd);
ResultSet rs = stmt.executeQuery(queryCmd);
ArrayList<String> urlList = new ArrayList<String>();
ArrayList<String> imgNameList = new ArrayList<String>();
ArrayList<String> imgTimeStampList = new ArrayList<String>();
HashMap<String, ArrayList<String>> deviceMap = new HashMap<String, ArrayList<String>>();
while (rs.next()) {
System.out.println(rs.getString("url"));
urlList.add(rs.getString("url"));
System.out.println(rs.getString("img_name"));
imgNameList.add(rs.getString("img_name"));
System.out.println(rs.getString("img_timestamp"));
imgTimeStampList.add(rs.getString("img_timestamp"));
}
ArrayList<String> d = new ArrayList<String>(1);
d.add(device_id);
deviceMap.put("device_id", d);
deviceMap.put("url", urlList);
deviceMap.put("img_name", imgNameList);
deviceMap.put("img_timestamp", imgTimeStampList);
result.add(deviceMap);
}// end for
} catch (Exception e) {
e.printStackTrace();
}
// Map<String, ArrayList<String>> result = new HashMap<String,
// ArrayList<String>>();
// result.put("device_list", deviceList);
// result.put("url", urlList);
// result.put("img_name", imgNameList);
// result.put("img_timestamp", imgTimeStampList);
return result;
}
Map<String, ArrayList<String>> query(String run_stamp, String device_id) {
ArrayList<String> deviceList = getDeviceList(run_stamp);
ArrayList<String> urlList = new ArrayList<String>();
ArrayList<String> imgNameList = new ArrayList<String>();
ArrayList<String> imgTimeStampList = new ArrayList<String>();
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载MYSQL JDBC驱动程序
System.out.println("Success loading mysql driver!");
} catch (Exception e) {
System.out.print("Error loading mysql driver!");
e.printStackTrace();
}
try {
Connection connect = DriverManager.getConnection(
"jdbc:mysql://10.73.72.122:3306/test", "root", "isword");
// 连接URL为 jdbc:mysql//服务器地址/数据库名 ,后面的2个参数分别是登陆用户名和密码
System.out.println("Success connect mysql server!");
Statement stmt = connect.createStatement();
String queryCmd = "SELECT * FROM ct_pic where run_stamp=‘"
+ run_stamp + "‘ and device_id=‘" + device_id
+ "‘ ORDER BY img_timestamp";
System.out.println(queryCmd);
ResultSet rs = stmt.executeQuery(queryCmd);
while (rs.next()) {
System.out.println(rs.getString("img_name"));
imgNameList.add(rs.getString("img_name"));
System.out.println(rs.getString("url"));
urlList.add(rs.getString("url"));
System.out.println(rs.getString("img_timestamp"));
imgTimeStampList.add(rs.getString("img_timestamp"));
}
} catch (Exception e) {
e.printStackTrace();
}
Map<String, ArrayList<String>> result = new HashMap<String, ArrayList<String>>();
result.put("device_list", deviceList);
result.put("url", urlList);
result.put("img_name", imgNameList);
result.put("img_timestamp", imgTimeStampList);
return result;
}
public ArrayList<String> getDeviceList(String run_stamp) {
ArrayList<String> deviceList = new ArrayList<String>();
try {
Connection connect = DriverManager.getConnection(
"jdbc:mysql://10.73.72.122:3306/test", "root", "isword");
// 连接URL为 jdbc:mysql//服务器地址/数据库名 ,后面的2个参数分别是登陆用户名和密码
System.out.println("Success connect mysql server!");
Statement stmt = connect.createStatement();
String queryCmd = "SELECT device_id FROM ct_pic"
+ " where run_stamp=‘" + run_stamp
+ "‘ GROUP BY device_id;";
System.out.println(queryCmd);
ResultSet rs = stmt.executeQuery(queryCmd);
while (rs.next()) {
System.out.println(rs.getString("device_id"));
deviceList.add(rs.getString("device_id"));
}
} catch (Exception e) {
e.printStackTrace();
}
return deviceList;
}
}
测试xUnit代码:
package ct4taobaoh5.test;
import java.net.URL;
import java.util.ArrayList;
import
java.util.Arrays;
import
java.util.Collection;
import
java.util.List;
import
junit.framework.TestCase;
import
org.junit.After;
import
org.junit.Before;
import
org.junit.BeforeClass;
import
org.junit.runner.RunWith;
import
org.junit.runners.Parameterized;
import
org.junit.Test;
import
org.openqa.selenium.By;
import
org.openqa.selenium.Keys;
import
org.openqa.selenium.OutputType;
import
org.openqa.selenium.WebDriver;
import
org.openqa.selenium.WebElement;
import
org.openqa.selenium.android.AndroidDriver;
import
org.openqa.selenium.remote.DesiredCapabilities;
import
org.openqa.selenium.support.events.WebDriverEventListener;
import
ct4h5.Init;
import
ct4h5.config.Const;
import
ct4h5.util.EventListener;
import
ct4h5.util.Util;
/**
*
*
@author 东海陈光剑 2014年2月21日
下午11:13:59
*/
@SuppressWarnings("deprecation")
@RunWith(Parameterized.class)
public class
SearchTest extends TestCase
{
String deviceId;
AndroidDriver
driver;
public
SearchTest(String deviceId) {
this.deviceId =
deviceId;
}
@Before
public void init() {
/**
* forward tcp
*/
// Init.forward(deviceId);
Init.init(deviceId);
}
/**
* <p>
* The custom runner
<code>Parameterized</code> implements
parameterized
* tests. When running a parameterized
test class, instances are created for
* the
cross-product of the test methods and the test data
elements.
* </p>
*
* For example, to test a Fibonacci
function, write:
*
* <pre>
*
@RunWith(Parameterized.class)
* public class
FibonacciTest {
*
@Parameters
* public static
Collection<Object[]> data() {
* return Arrays.asList(new
Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
*
{ 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }
});
*
}
*
* private int fInput;
* private int fExpected;
*
* public
FibonacciTest(int input, int expected) {
* fInput =
input;
*
fExpected = expected;
*
}
*
* @Test
* public void test() {
* assertEquals(fExpected,
Fibonacci.compute(fInput));
* }
*
}
* </pre>
*
* <p>
* Each instance of <code>FibonacciTest</code> will be
constructed using the
* two-argument constructor and
the data values in the
*
<code>@Parameters</code> method.
*
</p>
*/
@Parameterized.Parameters
public static
Collection deviceIds() {
List<String> deviceList
= Util.getDeviceList();
List<String[]>
col = new
ArrayList<String[]>(); //
List
//
[4d004077b4369049,
//
Coolpad5890-a1a1314a]
// 把List<String> 转换成
List<String[]>
for (String e :
deviceList) {
String[] el = new String[] { e };
col.add(el);
}
return
col; // 字符串数组
[[Ljava.lang.String;@b4e29b,
// [Ljava.lang.String;@18941f7, null, null,
null]
}
@Test
public void testSearch() throws Exception {
// String remote_driver_url =
"http://localhost:5555/h5";
// WebDriverEventListener eventListener = new
EventListener();
// WebDriver driver = new EventFiringWebDriver(new
RemoteWebDriver(
//
new URL(remote_driver_url),
DesiredCapabilities.android()))
// .register(eventListener);
/**
* getDefaultUrl: return new
URL("http://localhost:8080/wd/hub");
*/
// driver = new AndroidDriver(new URL("http://localhost:" +
port
// +
"/wd/hub"), DesiredCapabilities.android());
driver = new AndroidDriver();
/**
* 首次打开“首页”
*/
driver.get(Const.urlTaobaoOnline);//
线上
//
driver.get(Const.urlPre);//预发
Thread.sleep(2000);
Util.record(driver, deviceId);
/**
* 点击 搜索框
*/
Util.click(driver,
"//INPUT[@id=\"J_searchtext\"]");
Util.record(driver, deviceId);
/**
* 在搜索框"//FORM/INPUT[1]"输入query
keys
*/
WebElement e = driver
.findElementByXPath("//INPUT[@id=\"J_searchtext\"]");
e.sendKeys("iphone5s");
Util.record(driver, deviceId);//
搜索下拉推荐
//
e.submit();// 提交搜索
e.sendKeys(Keys.ENTER);
/**
* 2s等待SRP加载渲染出来
*/
Thread.sleep(2000);
Util.record(driver, deviceId);
/**
* 点击“分类”
*/
Util.click(driver,
"//SPAN[@id=\"J_selt\"]");
Thread.sleep(1000);
Util.record(driver, deviceId);
/**
*
子类目可点击
*/
Thread.sleep(1000);
Util.click(driver, "//LI[1]/H2[1]");
Util.record(driver, deviceId);
//
//////////////////////////////////////////////////////////////////////////////////
/**
* 打开“首页”
*/
driver.get(Const.urlTaobaoOnline);//
线上
//
driver.get(Const.urlPre);//预发
Thread.sleep(2000);
Util.record(driver, deviceId);
/**
* 点击 搜索框
*/
Util.click(driver,
"//INPUT[@id=\"J_searchtext\"]");
Util.record(driver, deviceId);
/**
* 在搜索框"//FORM/INPUT[1]"输入query
keys
*/
driver.findElementByXPath("//INPUT[@id=\"J_searchtext\"]").sendKeys(
"iphone5s");
Util.record(driver, deviceId);//
搜索下拉推荐
//
e.submit();// 提交搜索
e.sendKeys(Keys.ENTER);
/**
* 2s等待SRP加载渲染出来
*/
Thread.sleep(2000);
Util.record(driver, deviceId);
/**
* 点击 筛选 //SPAN[@id="J_sift"]
*/
Util.click(driver, "//SPAN[@id=\"J_sift\"]");
Util.record(driver, deviceId);
/**
* 点击 筛选项目
*/
Util.click(driver,
"//LI[1]/LABEL[1]/INPUT[1]");
Util.record(driver, deviceId);
/**
* 设定 “最高价”“最低价”
*/
driver.findElementByXPath("//DIV[3]/DIV[1]/INPUT[1]").sendKeys("2000");
driver.findElementByXPath("//DIV[2]/INPUT[1]").sendKeys("4000");
/**
*
点击“确定”
*/
Util.click(driver,
"//BUTTON[@id=\"J_siftSearchBtn\"]");
Util.record(driver, deviceId);
/**
* 点击 销量
//DIV[4]/DIV[1]/UL[1]/LI[2]
*
*/
Util.click(driver,
"//DIV[4]/DIV[1]/UL[1]/LI[2]");
Util.record(driver, deviceId);
/**
* 点击 价格排序:
//DIV[4]/DIV[1]/UL[1]/LI[3]
*/
Util.click(driver,
"//DIV[4]/DIV[1]/UL[1]/LI[3]");
Util.record(driver, deviceId);
/**
*
切大图://DIV[@id="tbh5v0"]/DIV[1]/DIV[4]/DIV[1]/DIV[1]/DIV[1]
*/
Util.click(driver,
"//DIV[@id=\"tbh5v0\"]/DIV[1]/DIV[4]/DIV[1]/DIV[1]/DIV[1]");
Util.record(driver, deviceId);
Util.click(driver,
"//DIV[@id=\"tbh5v0\"]/DIV[1]/DIV[4]/DIV[1]/DIV[1]/DIV[1]");
Util.record(driver, deviceId);
Util.click(driver,
"//DIV[@id=\"tbh5v0\"]/DIV[1]/DIV[4]/DIV[1]/DIV[1]/DIV[1]");
Util.record(driver, deviceId);
}
@After
public void
destroy() {
Init.destroy(deviceId);
//
driver.quit();
}
}
package
ct4taobaoh5.test;
import
java.util.List;
import
org.junit.runner.JUnitCore;
import
org.junit.runner.notification.Failure;
import ct4h5.Install;
import ct4h5.Uninstall;
import ct4h5.config.Const;
import
ct4h5.report.GenerateReport;
import
ct4h5.util.Util;
/**
* @author 东海陈光剑
2014年2月17日 下午8:58:02
*/
public class
TestRunner {
/**
* @param
args
* @throws Exception
*/
public
static void main(String[] args) throws Exception {
run();
}
/**
* @throws
Exception
*
*/
private static
void run() throws Exception {
long start =
System.currentTimeMillis();
runTestCases();
long end =
System.currentTimeMillis();
report(start, end);
}
private static
void report(long start, long end) {
System.out.println("Running Time:
" + (end -
start) / 1000 + " s"
+ "( " + (end - start) /
1000 / 60
+ " min
)");
System.out.println("Run timestamp:" +
Const.timestamp);
String runningSec
= (end - start) / 1000 + "";
String runningMin = (end - start) / 1000
/ 60 +
"";
// String startReportCmd = "start
http://10.73.72.122:88/report.html";
//
Util.excuCmd(startReportCmd);
GenerateReport.genReport(Const.timestamp, runningSec,
runningMin);
}
/**
* @throws Exception
*
*/
private static
void runTestCases() throws Exception {
List<String>
classList = Util
.getClassInPackage(Const.packageTaobaoH5Path);
for (String c : classList) {
if (c.endsWith("Test")) {
runClass(c);
}
}
}
public static
void runClass(String className) throws
Exception {
String fullClassName
= Const.packageTaobaoH5Path + "." + className;
Class<?>
c =
Class.forName(fullClassName);
long start =
System.currentTimeMillis();
for (Failure failure : JUnitCore.runClasses(c).getFailures())
{
System.out.println(failure.toString());
}
System.out.println(JUnitCore.runClasses(c).wasSuccessful());
long end =
System.currentTimeMillis();
System.out.println(fullClassName + "
| Running Time: " + (end -
start)
/ 1000 + " s" + "( " + (end -
start) / 1000 / 60 + " min
)");
}
/**
* 多线程执行安装android-server.apk
*/
private static
void install() {
for (String e : Util.getDeviceList()) {
(new
Thread(new
Install(e))).start();
}
}
/**
*
多线程执行安装android-server.apk
*/
private static
void uninstall() {
for (String e : Util.getDeviceList()) {
(new
Thread(new
Uninstall(e))).start();
}
}
}
基础应用类:
package ct4h5.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.android.AndroidDriver;
import org.openqa.selenium.remote.ScreenshotException;
import sun.misc.BASE64Decoder;
import com.taobao.sword.android.elements.IAndroidActivity;
import ct4h5.config.Const;
import ct4h5.dao.InsertDB;
import ct4h5.report.GenerateReport;
/**
* @author 东海陈光剑 2014年2月22日 上午12:16:10
*/
public class Util {
public static List<String> getDeviceList() {
// TODO Auto-generated method stub
Process process = null;
String strBuff = "";
String t = "";
String command = "adb devices";
try {
process = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(
process.getInputStream(), "utf-8"));
while ((t = br.readLine()) != null) {
strBuff += t + "\n";
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* List of devices attached
* \nCoolpad5890-a1a1314a\tdevice\nHC34WW907981\tdevice\n\n
*/
print(strBuff);
List<String> deviceList = new ArrayList<String>(5);
String regex = "[\\n](.*)[\\t]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(strBuff);
while (matcher.find()) {
String deviceId = strBuff.substring(matcher.start(), matcher.end());
deviceId = deviceId.replaceAll("\\s*", "");
deviceList.add(deviceId);
}
return deviceList;
}
public static void print(String buff) {
// TODO Auto-generated method stub
System.out.println(buff);
}
/***********
* 根据包名来获取此包下所有的类名及其实例
*
* @param packagePath
* @return
*/
public static List<String> getClassInPackage(String packagePath) {
List<String> classList = new ArrayList(5);
String packageName = packagePath;
String packageDirName = packageName.replace(".", "/");
Enumeration<URL> dirs = null;
try {
dirs = Thread.currentThread().getContextClassLoader()
.getResources(packageDirName);
// 迭代此 Enumeration
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
File file = new File(url.getFile());
// 把此目录下的所有文件列出
String[] classes = file.list();
// 循环此数组,并把.class去掉 ".class".length() = 6
for (String className : classes) {
className = className.substring(0, className.length() - 6);
classList.add(className);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return classList;
}
public static void record(AndroidDriver driver, String deviceId)
throws InterruptedException {
/**
* 考虑到页面加载的时间,线程延时2s
*/
Thread.sleep(2000);
printTitle(driver, deviceId);
// GenerateImage(driver, deviceId);
screenShot(driver, deviceId);
}
/**
* @param driver
* @param deviceId
*/
public static void printTitle(AndroidDriver driver, String deviceId) {
System.out.println(deviceId + " | " + driver.getTitle());
System.out.println(driver.getCurrentUrl());
}
public static void printTitle(AndroidDriver driver) {
System.out.println(driver.getTitle());
System.out.println(driver.getCurrentUrl());
}
/**
* @param driver
* @param xPath
* @throws InterruptedException
*/
public static void click(AndroidDriver driver, String xPath)
throws InterruptedException {
// int i = 0;
// /**
// * 最多等待5s
// */
// while (!driver.findElement(By.xpath(xPath)).isDisplayed() && i < 10)
// {
// Thread.sleep(500);
// i++;
// }
// driver.getTouch().down(x, y);
driver.findElement(By.xpath(xPath)).click();
// driver.wait();// 报错:java.lang.IllegalMonitorStateException
Thread.sleep(1000);
}
/**
* 截图
*
* @param driver
* @param imgName
*/
public void takeScreenShot(WebDriver driver, String imgName) {
File scrFile = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(scrFile, new File("c:\\Learning\\" + imgName));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 发生异常截图
*
* @param e
* @return
*/
public String extractScreenShot(WebDriverException e) {
Throwable cause = e.getCause();
if (cause instanceof ScreenshotException) {
return ((ScreenshotException) cause).getBase64EncodedScreenshot();
}
return null;
}
/**
* 将Base64转换成图片
*
* @param activity
* @param url
* @return
*/
/**
* >adb -s <deviceID> shell /system/bin/screencap -p /sdcard/screenshot.png
* >adb -s <deviceID> pull /sdcard/screenshot.png d:/screenshot.png 2990
* KB/s (382785 bytes in 0.125s)
*
* @param driver
* @param deviceId
* @return
*/
public static boolean GenerateImage(AndroidDriver driver, String deviceId) {// 对字节数组字符串进行Base64解码并生成图片
String url = driver.getCurrentUrl();
System.out.println("AndroidDriver 截图 | " + url);
String imgStr = driver.getScreenshotAs(OutputType.BASE64);
/**
* 这里记得加上"/"目录标示符
*/
File fp = new File(Const.photoSavePath);
if (!fp.isDirectory())
fp.mkdirs();
String imgPath = Const.photoSavePath + "/" + deviceId;
File f = new File(imgPath);
if (!f.isDirectory())
f.mkdirs();
if (!imgPath.endsWith("/"))
imgPath += "/";
String timeChamp = (new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"))
.format(new Date());
/**
* url(去除非法字符)+时间戳 命名图片
*/
String imgName = url.replaceAll("[\\/:*?\"<>|!#]", "") + "_"
+ timeChamp + "_driver.jpeg";
if (imgStr == null)
// 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] bytes = decoder.decodeBuffer(imgStr);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
f = new File(imgPath);
if (!f.isDirectory())
f.mkdirs();
if (!imgPath.endsWith("/"))
imgPath += "/";
String imgFullPathName = imgPath + imgName;
OutputStream out = new FileOutputStream(imgFullPathName);
out.write(bytes);
out.flush();
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// @SuppressWarnings("deprecation")
// public static boolean GenerateImage(AndroidDriver driver) {//
// 对字节数组字符串进行Base64解码并生成图片
//
// String url = driver.getCurrentUrl();
// System.out.println("截图 | " + url);
// String imgStr = driver.getScreenshotAs(OutputType.BASE64);
// String imgPath = Const.photoSavePath + "/";
// String timeChamp = (new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"))
// .format(new Date());
// /**
// * url(去除非法字符)+时间戳 命名图片
// */
// String imgName = url.replaceAll("[\\/:*?\"<>|]", "") + "-" + timeChamp
// + ".jpeg";
// if (imgStr == null)
// // 图像数据为空
// return false;
// BASE64Decoder decoder = new BASE64Decoder();
// try {
// // Base64解码
// byte[] bytes = decoder.decodeBuffer(imgStr);
// for (int i = 0; i < bytes.length; ++i) {
// if (bytes[i] < 0) {// 调整异常数据
// bytes[i] += 256;
// }
// }
// // 生成jpeg图片
// File f = new File(imgPath);
// if (!f.isDirectory())
// f.mkdir();
// if (!imgPath.endsWith("/"))
// imgPath += "/";
// String imgFullPathName = imgPath + imgName;
// OutputStream out = new FileOutputStream(imgFullPathName);
// out.write(bytes);
// out.flush();
// out.close();
// return true;
// } catch (Exception e) {
// return false;
// }
// }
@SuppressWarnings({ "restriction", "unused" })
public static boolean screenShot(AndroidDriver driver, String deviceId) {// 对字节数组字符串进行Base64解码并生成图片
/**
* 这里记得加上"/"目录标示符
*/
File fp = new File(Const.photoSavePath);
if (!fp.isDirectory())
fp.mkdirs();
String url = driver.getCurrentUrl();
System.out.println("adb screenShot 截图 | " + url);
// String imgStr = driver.getScreenshotAs(OutputType.BASE64);
String imgPath = Const.photoSavePath + "/" + deviceId;
File f = new File(imgPath);
if (!f.isDirectory())
f.mkdirs();
if (!imgPath.endsWith("/"))
imgPath += "/";
String timeChamp = (new SimpleDateFormat("yyyyMMddhhmmss"))
.format(new Date());
/**
* url(去除非法字符)+时间戳 命名图片
*/
String imgName = url.replaceAll("[\\/:*?\"<>|!#]", "") + "_"
+ timeChamp + ".jpeg";
String imgFullPathName = imgPath + imgName;
String imgSrcPath = Const.photoSrcPath + deviceId + "/" + imgName;
InsertDB.insert(Const.timestamp, url, imgName, deviceId, timeChamp);
//
// /**
// * 生成报告
// */
// StringBuffer reportUrl = GenerateReport.genReportUrl(driver,
// deviceId,
// imgSrcPath);
// Const.report.append(reportUrl + "</tr>" + "<tr><th scope=\"row\">"
// + deviceId + "</th>");
// StringBuffer reportImgSrc = GenerateReport.genReportImgSrc(driver,
// deviceId, imgSrcPath);
// Const.report.append(reportImgSrc + "</tr>" + "</table>");
/**
* >adb -s <deviceID> shell /system/bin/screencap -p
* /sdcard/screenshot.png >adb -s <deviceID> pull /sdcard/screenshot.png
* d:/screenshot.png
*/
String screencapCmd = "adb -s " + deviceId
+ " shell /system/bin/screencap -p /sdcard/screenshot.png";
String pullScreenShotCmd = "adb -s " + deviceId
+ " pull /sdcard/screenshot.png " + imgFullPathName;
String rmScreenShotCmd = "rm -f /sdcard/screenshot.png";
excuCmd(screencapCmd);
excuCmd(pullScreenShotCmd);
excuCmd(rmScreenShotCmd);
return true;
// Process process = null;
// try {
// process = Runtime.getRuntime().exec(screencapCmd);
// BufferedReader br = new BufferedReader(new InputStreamReader(
// process.getInputStream(), "utf-8"));
// String buff = "";
// String imgStr = "";
// while ((buff = br.readLine()) != null) {
// Util.print(buff);
// imgStr += buff;
// }
//
// if (imgStr == null) // 图像数据为空
// return false;
// BASE64Decoder decoder = new BASE64Decoder();
//
// // Base64解码
// byte[] bytes = decoder.decodeBuffer(imgStr);
// for (int i = 0; i < bytes.length; ++i) {
// if (bytes[i] < 0) {// 调整异常数据
// bytes[i] += 256;
// }
// }
// // 生成jpeg图片
// File f1 = new File(imgPath);
// if (!f1.isDirectory())
// f1.mkdir();
// if (!imgPath.endsWith("/"))
// imgPath += "/";
// OutputStream out = new FileOutputStream(imgFullPathName);
// out.write(bytes);
// out.flush();
// out.close();
// return true;
// } catch (Exception e) {
// e.printStackTrace();
// return false;
// }
}
public static void excuCmd(String cmd) {
System.out.println("$" + cmd);
Process process = null;
String buff = "";
try {
/**
* adb -s HC34WW907981 install
* D:/Android/test/taobao_android.sword.signed.apk
*/
process = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(
process.getInputStream(), "utf-8"));
while ((buff = br.readLine()) != null) {
Util.print(buff);
// if (buff.contains("INSTALL_FAILED_ALREADY_EXISTS")) {
// Util.print(devName + "已安装");
// }
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param e
*/
public static void install(String deviceId) {
String cmdInstall = "adb -s " + deviceId + " install -r "
+ Const.apkPath;
Util.excuCmd(cmdInstall);
}
}
Mobile webdriver android-server.apk配置:
package ct4h5;
import
ct4h5.config.Const;
import
ct4h5.util.Util;
/**
* @author 东海陈光剑
2014年2月22日 上午2:27:35
*/
public class
Init {
/**
* @param deviceId
*
*/
public static
void init(String deviceId)
{
String cmdUninstall =
"adb -s " +
deviceId
+ "
uninstall org.openqa.selenium.android.app";
String cmdInstall = "adb
-s " + deviceId + " install -r
"
+
Const.apkPath;
/**
* 启动WebDriver
*/
int port = 8080;
String
cmdStart = "adb -s
"
+ deviceId
+ " shell am start -a
android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity -e
debug true";
String cmdForward
= "adb -s " + deviceId + "
forward tcp:" + port
+ " tcp:" +
port;
Util.excuCmd(cmdUninstall);
Util.excuCmd(cmdInstall);
Util.excuCmd(cmdStart);
Util.excuCmd(cmdForward);
}
/**
* @param
deviceId
*
*/
public
static void forward(String deviceId)
{
int port = 8080;
String
cmdStart = "adb -s
"
+ deviceId
+ " shell am start -a
android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity -e
debug true";
String cmdForward
= "adb -s " + deviceId + "
forward tcp:" + port
+ " tcp:" +
port;
Util.excuCmd(cmdStart);
Util.excuCmd(cmdForward);
}
public static void
destroy(String deviceId) {
String
cmdUninstall = "adb -s
" + deviceId
+ " uninstall
org.openqa.selenium.android.app";
Util.excuCmd(cmdUninstall);
}
}
写数据库:
package ct4h5.dao;
import
java.sql.*;
import
org.testng.internal.remote.SlavePool;
public class
InsertDB {
public
static void main(String[] args) {
for (int
i = 0; i <
10; i++)
insert("2", "2",
"2", "2", "2");
}
public static boolean
insert(String timestamp, String url, String imgName,
String deviceId, String imgTimeChamp)
{
try {
Class.forName("com.mysql.jdbc.Driver"); //
加载MYSQL JDBC驱动程序
System.out.println("Success loading
Mysql Driver!");
} catch
(Exception e) {
System.out.print("Error loading Mysql
Driver!");
e.printStackTrace();
}
try {
Connection connect =
DriverManager.getConnection(
"jdbc:mysql://10.73.72.122:3306/test", "root",
"isword");
// 连接URL为 jdbc:mysql//服务器地址/数据库名
,后面的2个参数分别是登陆用户名和密码
System.out.println("Success connect
Mysql server!");
Statement stmt =
connect.createStatement();
// String insertCmd = "insert into
ct_pic values(" + "\‘" +
//
timestamp
// + "\‘" + "," + "\‘" + deviceId + "\‘" + "," +
"\‘"
// + imgName + "\‘" + "," + "\‘" + url + "\‘" +
")";
String
insertCmd = "INSERT INTO
ct_pic(run_stamp,device_id,img_name,url,img_timestamp)"
+ " VALUES
("
+ "‘"
+ timestamp
+ "‘,"
+ "‘"
+ deviceId
+ "‘,"
+ "‘"
+ imgName
+ "‘,"
+ "‘"
+ url
+ "‘,‘"
+ imgTimeChamp + "‘)";
System.out.println(insertCmd);
boolean rs =
stmt.execute(insertCmd);
return
rs;
//
while (rs.next()) {
//
System.out.println(rs.getString("img_name"));
//
}
} catch (Exception e) {
e.printStackTrace();
return
false;
}
}
}
// GRANT ALL ON *.* TO root@"%" IDENTIFIED
BY isword;
Android WebApp & NativeApp 适配测试自动化平台GoGo实现 东海陈光剑,码迷,mamicode.com
评论(0)