|
@@ -1,13 +1,22 @@
|
|
package net.mooctest.www.android_auto_test.utils;
|
|
package net.mooctest.www.android_auto_test.utils;
|
|
|
|
|
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import com.google.gson.JsonObject;
|
|
import io.appium.java_client.AppiumDriver;
|
|
import io.appium.java_client.AppiumDriver;
|
|
|
|
+import io.appium.java_client.android.AndroidDriver;
|
|
|
|
+import io.appium.java_client.android.AndroidTouchAction;
|
|
import io.appium.java_client.android.nativekey.AndroidKey;
|
|
import io.appium.java_client.android.nativekey.AndroidKey;
|
|
|
|
+import io.appium.java_client.android.nativekey.KeyEvent;
|
|
|
|
+import io.appium.java_client.touch.WaitOptions;
|
|
|
|
+import io.appium.java_client.touch.offset.PointOption;
|
|
import net.mooctest.www.android_auto_test.Scripts.MergeScript;
|
|
import net.mooctest.www.android_auto_test.Scripts.MergeScript;
|
|
import net.mooctest.www.android_auto_test.models.WidgetInfo;
|
|
import net.mooctest.www.android_auto_test.models.WidgetInfo;
|
|
import net.mooctest.www.android_auto_test.models.WidgetInfoNode;
|
|
import net.mooctest.www.android_auto_test.models.WidgetInfoNode;
|
|
import org.openqa.selenium.WebElement;
|
|
import org.openqa.selenium.WebElement;
|
|
|
|
|
|
import java.io.*;
|
|
import java.io.*;
|
|
|
|
+import java.time.Duration;
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
|
|
|
public class widgetMergeTools {
|
|
public class widgetMergeTools {
|
|
@@ -357,6 +366,80 @@ public class widgetMergeTools {
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ public static void runOneWidget(WidgetInfo wInfo, AndroidDriver driver){
|
|
|
|
+ WebElement we;
|
|
|
|
+ //先定位
|
|
|
|
+ String id = wInfo.getId();
|
|
|
|
+ String text = wInfo.getText();
|
|
|
|
+ String className = wInfo.getClassName();
|
|
|
|
+ String desc = wInfo.getDesc();
|
|
|
|
+ String packageName = wInfo.getPackageName();
|
|
|
|
+ int index = wInfo.getIndex();
|
|
|
|
+ String using = "//" + className + "[";
|
|
|
|
+ if (!text.equals("") && text != null) {
|
|
|
|
+ using += "@text='" + text + "'";
|
|
|
|
+ }
|
|
|
|
+ if (!id.equals("") && id != null) {
|
|
|
|
+ if (using.contains("@")) {
|
|
|
|
+ using += " and ";
|
|
|
|
+ }
|
|
|
|
+ using += "@resource-id='" + id + "'";
|
|
|
|
+ }
|
|
|
|
+ if (!desc.equals("") && desc != null) {
|
|
|
|
+ if (using.contains("@")) {
|
|
|
|
+ using += " and ";
|
|
|
|
+ }
|
|
|
|
+ using += "@content-desc='" + desc + "'";
|
|
|
|
+ }
|
|
|
|
+ if (!packageName.equals("") && packageName != null) {
|
|
|
|
+ if (using.contains("@")) {
|
|
|
|
+ using += " and ";
|
|
|
|
+ }
|
|
|
|
+ using += "@package='" + packageName + "'";
|
|
|
|
+ }
|
|
|
|
+ if (index != -1) {
|
|
|
|
+ if (using.contains("@")) {
|
|
|
|
+ using += " and ";
|
|
|
|
+ }
|
|
|
|
+ using += "@index='" + index + "'";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ using += "]";
|
|
|
|
+ System.out.println(using);
|
|
|
|
+ try {
|
|
|
|
+ if (wInfo.getBehavior().equals("click")) {
|
|
|
|
+ try {
|
|
|
|
+ we = driver.findElementByXPath(using);
|
|
|
|
+ we.click();
|
|
|
|
+ }catch(Exception e){
|
|
|
|
+ try {
|
|
|
|
+ Thread.sleep(30000);
|
|
|
|
+ we = driver.findElementByXPath(using);
|
|
|
|
+ we.click();
|
|
|
|
+ }catch (Exception e2){
|
|
|
|
+ throw e2;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (wInfo.getBehavior().equals("sendKeys")) {
|
|
|
|
+ we = driver.findElementByXPath(using);
|
|
|
|
+ we.sendKeys(wInfo.getBehaviorArgs().get(0));
|
|
|
|
+ } else if (wInfo.getBehavior().equals("sendKeyEvent")) {
|
|
|
|
+ //(Integer.parseInt(wInfo.getBehaviorArgs().get(0))));
|
|
|
|
+ //TODO 有坑
|
|
|
|
+ driver.pressKey(new KeyEvent(AndroidKey.BACK));
|
|
|
|
+ } else if (wInfo.getBehavior().equals("swipe")) {
|
|
|
|
+ ArrayList<String> args = wInfo.getBehaviorArgs();
|
|
|
|
+ AndroidTouchAction touchAction = new AndroidTouchAction(driver);
|
|
|
|
+ touchAction.press(PointOption.point(Integer.parseInt(args.get(0)), Integer.parseInt(args.get(1))))
|
|
|
|
+ .waitAction(WaitOptions.waitOptions(Duration.ofMillis(Integer.parseInt(args.get(4)))))
|
|
|
|
+ .moveTo(PointOption.point(Integer.parseInt(args.get(2)), Integer.parseInt(args.get(3))))
|
|
|
|
+ .release().perform();
|
|
|
|
+ }
|
|
|
|
+ }catch(NoSuchElementException | InterruptedException ex){
|
|
|
|
+ System.out.println("未找到元素:"+using);
|
|
|
|
+ System.out.println("继续复现,但本条路径可能已经失败");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
//运行其中一条路径
|
|
//运行其中一条路径
|
|
public static void runOnePath(int maxSize, WidgetInfoNode node, AppiumDriver driver, MergeScript script){
|
|
public static void runOnePath(int maxSize, WidgetInfoNode node, AppiumDriver driver, MergeScript script){
|
|
WebElement we;
|
|
WebElement we;
|
|
@@ -366,7 +449,7 @@ public class widgetMergeTools {
|
|
path = getPath(0, maxSize, new Stack<WidgetInfoNode>(), node);
|
|
path = getPath(0, maxSize, new Stack<WidgetInfoNode>(), node);
|
|
path.pop();
|
|
path.pop();
|
|
while (!path.empty()) {
|
|
while (!path.empty()) {
|
|
- Thread.sleep(3000);
|
|
|
|
|
|
+ Thread.sleep(6000);
|
|
WidgetInfoNode wInfoNode= path.pop();
|
|
WidgetInfoNode wInfoNode= path.pop();
|
|
wInfoNode.setVisited(true);
|
|
wInfoNode.setVisited(true);
|
|
WidgetInfo wInfo = wInfoNode.getWidgetInfo();
|
|
WidgetInfo wInfo = wInfoNode.getWidgetInfo();
|
|
@@ -410,8 +493,18 @@ public class widgetMergeTools {
|
|
System.out.println(using);
|
|
System.out.println(using);
|
|
try {
|
|
try {
|
|
if (wInfo.getBehavior().equals("click")) {
|
|
if (wInfo.getBehavior().equals("click")) {
|
|
- we = driver.findElementByXPath(using);
|
|
|
|
- script.openExecuteClick(we);
|
|
|
|
|
|
+ try {
|
|
|
|
+ we = driver.findElementByXPath(using);
|
|
|
|
+ script.openExecuteClick(we);
|
|
|
|
+ }catch(Exception e){
|
|
|
|
+ try {
|
|
|
|
+ Thread.sleep(30000);
|
|
|
|
+ we = driver.findElementByXPath(using);
|
|
|
|
+ script.openExecuteClick(we);
|
|
|
|
+ }catch (Exception e2){
|
|
|
|
+ e2.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
} else if (wInfo.getBehavior().equals("sendKeys")) {
|
|
} else if (wInfo.getBehavior().equals("sendKeys")) {
|
|
we = driver.findElementByXPath(using);
|
|
we = driver.findElementByXPath(using);
|
|
script.openExecuteInput(wInfo.getBehaviorArgs().get(0),we);
|
|
script.openExecuteInput(wInfo.getBehaviorArgs().get(0),we);
|
|
@@ -433,7 +526,103 @@ public class widgetMergeTools {
|
|
System.out.println("复现失败");
|
|
System.out.println("复现失败");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ //resList2Json
|
|
|
|
+ public static void resList2Json(ArrayList<WidgetInfoNode> resList,String dirName){
|
|
|
|
+ String JsonName = "operationFlowJSON";
|
|
|
|
+ String acName = "ofActivity";
|
|
|
|
+ File JsonFile = new File(dirName+File.separator+JsonName+".json");
|
|
|
|
+ File acFile = new File(dirName+File.separator+acName+".json");
|
|
|
|
|
|
|
|
+ JSONObject object = new JSONObject();
|
|
|
|
+ JSONArray node = new JSONArray();
|
|
|
|
+ JSONArray links = new JSONArray();
|
|
|
|
+
|
|
|
|
+ JSONObject acObject = new JSONObject();
|
|
|
|
+ JSONArray acArray = new JSONArray();
|
|
|
|
+ HashSet<String> arraySet = new HashSet();
|
|
|
|
+ //写结点
|
|
|
|
+ for(int i = 0;i<resList.size();i++){
|
|
|
|
+ WidgetInfoNode wInfoNode = resList.get(i);
|
|
|
|
+ WidgetInfo wInfo = wInfoNode.getWidgetInfo();
|
|
|
|
+ JSONObject tempObject = new JSONObject();
|
|
|
|
+ String labelContains = "";
|
|
|
|
+ labelContains += "activity = " + wInfo.getActivity()+"\n";
|
|
|
|
+ labelContains += "index = " + wInfo.getIndex() + "\n";
|
|
|
|
+ labelContains += "id = " + wInfo.getId() + "\n";
|
|
|
|
+ labelContains += "text = " + wInfo.getText() + "\n";
|
|
|
|
+ labelContains += "className = " + wInfo.getClassName() + "\n";
|
|
|
|
+ labelContains += "desc = " + wInfo.getDesc() + "\n";
|
|
|
|
+ labelContains += "packageName = " + wInfo.getPackageName() + "\n";
|
|
|
|
+ labelContains += "behavior = " + wInfo.getBehavior() + "\n";
|
|
|
|
+ labelContains += "arg = " + wInfo.getBehaviorArgs() + "\n";
|
|
|
|
+ tempObject.put("name",labelContains);
|
|
|
|
+ tempObject.put("category",wInfo.getActivity());
|
|
|
|
+ arraySet.add(wInfo.getActivity());
|
|
|
|
+ tempObject.put("draggable",true);
|
|
|
|
+ node.add(tempObject);
|
|
|
|
+ }
|
|
|
|
+ //写边
|
|
|
|
+ for(int i = 0;i<resList.size();i++){
|
|
|
|
+ WidgetInfoNode wInfoNode = resList.get(i);
|
|
|
|
+ WidgetInfo wInfo = wInfoNode.getWidgetInfo();
|
|
|
|
+ ArrayList<WidgetInfoNode> nextList = wInfoNode.getNext();
|
|
|
|
+ for(int j = 0 ;j<nextList.size();j++){
|
|
|
|
+ JSONObject tempObject = new JSONObject();
|
|
|
|
+ WidgetInfoNode nextNode = nextList.get(j);
|
|
|
|
+ int thisIndex = i;
|
|
|
|
+ int nextIndex = resList.indexOf(nextNode);
|
|
|
|
+ JSONObject labelJson = new JSONObject();
|
|
|
|
+ String labelContains = "";
|
|
|
|
+ labelContains += wInfo.getBehavior()+"( ";
|
|
|
|
+ ArrayList<String> args = wInfo.getBehaviorArgs();
|
|
|
|
+ if(args == null) labelContains += ")";
|
|
|
|
+ else {
|
|
|
|
+ for (int k = 0; k < args.size(); k++) {
|
|
|
|
+ if (k == args.size() - 1) {
|
|
|
|
+ labelContains += args.get(k) + " )";
|
|
|
|
+ } else {
|
|
|
|
+ labelContains += args.get(k) + ", ";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ labelJson.put("show",true);
|
|
|
|
+ labelJson.put("formatter",labelContains);
|
|
|
|
+
|
|
|
|
+ tempObject.put("source",thisIndex);
|
|
|
|
+ tempObject.put("target",nextIndex);
|
|
|
|
+ tempObject.put("label",labelJson);
|
|
|
|
+ links.add(tempObject);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //结点
|
|
|
|
+ object.put("data",node);
|
|
|
|
+ object.put("line",links);
|
|
|
|
+ String jsonString = object.toJSONString();
|
|
|
|
+ //页面
|
|
|
|
+
|
|
|
|
+ Iterator iterator = arraySet.iterator();
|
|
|
|
+ while (iterator.hasNext()) {
|
|
|
|
+ JSONObject acTemp = new JSONObject();
|
|
|
|
+ acTemp.put("name",iterator.next());
|
|
|
|
+ acArray.add(acTemp);
|
|
|
|
+ }
|
|
|
|
+ acObject.put("categories",acArray);
|
|
|
|
+ String acString = acObject.toJSONString();
|
|
|
|
+ try {
|
|
|
|
+ BufferedWriter bw = new BufferedWriter(new FileWriter(JsonFile));
|
|
|
|
+ bw.write(jsonString);
|
|
|
|
+ bw.flush();
|
|
|
|
+ bw.close();
|
|
|
|
+ bw = new BufferedWriter(new FileWriter(acFile));
|
|
|
|
+ bw.write(acString);
|
|
|
|
+ bw.flush();
|
|
|
|
+ bw.close();
|
|
|
|
+ }catch(Exception e){
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
public static void resList2Pic(ArrayList<WidgetInfoNode> resList,String dirName) {
|
|
public static void resList2Pic(ArrayList<WidgetInfoNode> resList,String dirName) {
|
|
String dotName = "mergeWidgetInfo";
|
|
String dotName = "mergeWidgetInfo";
|
|
@@ -509,6 +698,97 @@ public class widgetMergeTools {
|
|
System.out.println("画图失败");
|
|
System.out.println("画图失败");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ public static void simpleResList2Pic(ArrayList<WidgetInfoNode> resList,String dirName) {
|
|
|
|
+ String dotName = "simpleMergeWidgetInfo";
|
|
|
|
+ File dotFile = new File(dirName+File.separator+dotName+".dot");
|
|
|
|
+ try {
|
|
|
|
+ BufferedWriter bw = new BufferedWriter(new FileWriter(dotFile));
|
|
|
|
+ Set<String> activityName = new HashSet<>();
|
|
|
|
+ for (int i = 0; i < resList.size();i++){
|
|
|
|
+ WidgetInfoNode wInfoNode = resList.get(i);
|
|
|
|
+ String activity = wInfoNode.getWidgetInfo().getActivity();
|
|
|
|
+ activityName.add(activity);
|
|
|
|
+ }
|
|
|
|
+ String []activityNames = activityName.toArray(new String[activityName.size()]);
|
|
|
|
+
|
|
|
|
+ //write start
|
|
|
|
+ bw.write("digraph g {\n");
|
|
|
|
+ bw.flush();
|
|
|
|
+ bw.write(" node [shape=box, style=filled, fillcolor=lightblue, fontname=\"simsun.ttc\", fontsize=14];\n" +
|
|
|
|
+ " edge [fontname=\"simsun.ttc\", fontsize=12];\n");
|
|
|
|
+ bw.flush();
|
|
|
|
+ //write subgraph
|
|
|
|
+ for(int i = 0;i<activityNames.length;i++){
|
|
|
|
+ String aName = activityNames[i];
|
|
|
|
+ String outputAName = aName.replaceAll("\\.","_");
|
|
|
|
+ bw.write(" subgraph cluster_"+outputAName+"{\n");
|
|
|
|
+ bw.write(" label = \""+outputAName+"\"\n");
|
|
|
|
+ bw.flush();
|
|
|
|
+ for (int j = 0; j < resList.size();j++){
|
|
|
|
+ WidgetInfoNode wInfoNode = resList.get(j);
|
|
|
|
+ WidgetInfo wInfo = wInfoNode.getWidgetInfo();
|
|
|
|
+ if(aName.equals(wInfo.getActivity())){
|
|
|
|
+ if(aName.equals("")){
|
|
|
|
+ bw.write(" " + j + "[label = \"" + "Start" + " \"];\n");
|
|
|
|
+ }else {
|
|
|
|
+ String labelContains = "";
|
|
|
|
+ if(!isStringEmpty(wInfo.getBehavior())) {
|
|
|
|
+ labelContains += "behavior = " + wInfo.getBehavior() + "\n";
|
|
|
|
+ }
|
|
|
|
+ if(!isStringEmpty(wInfo.getId())) {
|
|
|
|
+ labelContains += " id = " + wInfo.getId() + "\n";
|
|
|
|
+ }else if(!isStringEmpty(wInfo.getText())) {
|
|
|
|
+ labelContains += " text = " + wInfo.getText() + "\n";
|
|
|
|
+ labelContains += " className = " + wInfo.getClassName() + "\n";
|
|
|
|
+ }else if(!isStringEmpty(wInfo.getDesc())) {
|
|
|
|
+ labelContains += " desc = " + wInfo.getDesc() + "\n";
|
|
|
|
+ labelContains += " className = " + wInfo.getClassName() + "\n";
|
|
|
|
+ }else if(!isStringEmpty(wInfo.getPackageName())) {
|
|
|
|
+ labelContains += " packageName = " + wInfo.getPackageName() + "\n";
|
|
|
|
+ labelContains += " className = " + wInfo.getClassName() + "\n";
|
|
|
|
+ }else if(wInfo.getIndex()!=-1) {
|
|
|
|
+ labelContains += " index = " + wInfo.getIndex() + "\n";
|
|
|
|
+ labelContains += " className = " + wInfo.getClassName() + "\n";
|
|
|
|
+ }
|
|
|
|
+ bw.write(" " + j + "[label = \"" + labelContains + " \"];\n");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ bw.write(" }\n");
|
|
|
|
+ bw.flush();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //可添加的其他配置项
|
|
|
|
+
|
|
|
|
+ //write edge
|
|
|
|
+ for (int i = 0; i < resList.size();i++) {
|
|
|
|
+ WidgetInfoNode wInfoNode = resList.get(i);
|
|
|
|
+ ArrayList<WidgetInfoNode> nextList = wInfoNode.getNext();
|
|
|
|
+ for(int j = 0 ;j<nextList.size();j++){
|
|
|
|
+ WidgetInfoNode nextNode = nextList.get(j);
|
|
|
|
+ int nextIndex = resList.indexOf(nextNode);
|
|
|
|
+ bw.write(" "+i+"->"+nextIndex+";\n");
|
|
|
|
+ bw.flush();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bw.write("}\n");
|
|
|
|
+ bw.flush();
|
|
|
|
+ bw.close();
|
|
|
|
+
|
|
|
|
+ createDot(dirName,dotName);
|
|
|
|
+ }catch(Exception e){
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ System.out.println("画图失败");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ public static boolean isStringEmpty(String s){
|
|
|
|
+ if(s==null)return true;
|
|
|
|
+ if(s.equals("")) return true;
|
|
|
|
+ if(s.trim().equals("")) return true;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
public static void createDot(String dirName,String dotName){
|
|
public static void createDot(String dirName,String dotName){
|
|
Process p;
|
|
Process p;
|
|
File f =new File("");
|
|
File f =new File("");
|
|
@@ -536,9 +816,10 @@ public class widgetMergeTools {
|
|
}
|
|
}
|
|
return sb.toString();
|
|
return sb.toString();
|
|
}
|
|
}
|
|
|
|
+
|
|
public static void main(String []args){
|
|
public static void main(String []args){
|
|
- ArrayList<WidgetInfoNode> resList = widgetMergeTools.getResList("D:\\工作\\test");
|
|
|
|
- widgetMergeTools.resList2Pic(resList,"test");
|
|
|
|
|
|
+ ArrayList<WidgetInfoNode> resList = widgetMergeTools.getResList("D:\\myWorkSpace\\test");
|
|
|
|
+ widgetMergeTools.resList2Json(resList,"operationFlow");
|
|
// ArrayList<WidgetInfoNode> nodeList = widgetMergeTools.getAllPath(resList);
|
|
// ArrayList<WidgetInfoNode> nodeList = widgetMergeTools.getAllPath(resList);
|
|
// //nodeList.size()
|
|
// //nodeList.size()
|
|
// for(int i =0;i<1;i++){
|
|
// for(int i =0;i<1;i++){
|