├── .DS_Store
├── .idea
├── compiler.xml
├── iOSMonkey.iml
├── libraries
│ ├── Maven__aopalliance_aopalliance_1_0.xml
│ ├── Maven__cglib_cglib_3_2_6.xml
│ ├── Maven__com_alibaba_fastjson_1_2_31.xml
│ ├── Maven__com_aventstack_extentreports_3_1_5.xml
│ ├── Maven__com_beust_jcommander_1_72.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_0.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_9_6.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_8_8.xml
│ ├── Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_csv_2_8_8.xml
│ ├── Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_yaml_2_9_6.xml
│ ├── Maven__com_google_code_findbugs_jsr305_1_3_9.xml
│ ├── Maven__com_google_code_gson_gson_2_8_4.xml
│ ├── Maven__com_google_errorprone_error_prone_annotations_2_1_3.xml
│ ├── Maven__com_google_guava_guava_23_6_jre.xml
│ ├── Maven__com_google_inject_guice_4_1_0.xml
│ ├── Maven__com_google_j2objc_j2objc_annotations_1_1.xml
│ ├── Maven__com_relevantcodes_extentreports_2_41_2.xml
│ ├── Maven__com_squareup_okhttp3_okhttp_3_9_1.xml
│ ├── Maven__com_squareup_okio_okio_1_13_0.xml
│ ├── Maven__commons_beanutils_commons_beanutils_1_9_2.xml
│ ├── Maven__commons_codec_commons_codec_1_10.xml
│ ├── Maven__commons_collections_commons_collections_3_2_1.xml
│ ├── Maven__commons_digester_commons_digester_1_8_1.xml
│ ├── Maven__commons_io_commons_io_2_6.xml
│ ├── Maven__commons_lang_commons_lang_2_4.xml
│ ├── Maven__commons_logging_commons_logging_1_2.xml
│ ├── Maven__commons_validator_commons_validator_1_6.xml
│ ├── Maven__io_appium_java_client_6_0_0.xml
│ ├── Maven__io_rest_assured_json_path_3_1_1.xml
│ ├── Maven__io_rest_assured_rest_assured_3_1_1.xml
│ ├── Maven__io_rest_assured_rest_assured_common_3_1_1.xml
│ ├── Maven__io_rest_assured_xml_path_3_1_1.xml
│ ├── Maven__javax_activation_activation_1_1.xml
│ ├── Maven__javax_inject_javax_inject_1.xml
│ ├── Maven__javax_mail_mail_1_4.xml
│ ├── Maven__javax_websocket_javax_websocket_api_1_1.xml
│ ├── Maven__javax_xml_bind_jaxb_api_2_2_12.xml
│ ├── Maven__junit_junit_4_12.xml
│ ├── Maven__log4j_log4j_1_2_17.xml
│ ├── Maven__net_bytebuddy_byte_buddy_1_8_3.xml
│ ├── Maven__net_iharder_base64_2_3_8.xml
│ ├── Maven__org_apache_ant_ant_1_9_6.xml
│ ├── Maven__org_apache_ant_ant_launcher_1_9_6.xml
│ ├── Maven__org_apache_commons_commons_exec_1_3.xml
│ ├── Maven__org_apache_commons_commons_lang3_3_7.xml
│ ├── Maven__org_apache_httpcomponents_httpclient_4_5_5.xml
│ ├── Maven__org_apache_httpcomponents_httpcore_4_4_6.xml
│ ├── Maven__org_apache_httpcomponents_httpmime_4_5_2.xml
│ ├── Maven__org_apache_velocity_velocity_1_7.xml
│ ├── Maven__org_aspectj_aspectjweaver_1_9_1.xml
│ ├── Maven__org_ccil_cowan_tagsoup_tagsoup_1_2_1.xml
│ ├── Maven__org_checkerframework_checker_compat_qual_2_0_0.xml
│ ├── Maven__org_codehaus_groovy_groovy_2_4_12.xml
│ ├── Maven__org_codehaus_groovy_groovy_json_2_4_12.xml
│ ├── Maven__org_codehaus_groovy_groovy_xml_2_4_12.xml
│ ├── Maven__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml
│ ├── Maven__org_freemarker_freemarker_2_3_23.xml
│ ├── Maven__org_glassfish_grizzly_grizzly_framework_2_3_3.xml
│ ├── Maven__org_glassfish_grizzly_grizzly_http_2_3_3.xml
│ ├── Maven__org_glassfish_grizzly_grizzly_http_server_2_3_3.xml
│ ├── Maven__org_glassfish_grizzly_grizzly_rcm_2_3_3.xml
│ ├── Maven__org_glassfish_tyrus_tyrus_client_1_13_1.xml
│ ├── Maven__org_glassfish_tyrus_tyrus_container_grizzly_1_2_1.xml
│ ├── Maven__org_glassfish_tyrus_tyrus_core_1_13_1.xml
│ ├── Maven__org_glassfish_tyrus_tyrus_spi_1_13_1.xml
│ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml
│ ├── Maven__org_hamcrest_hamcrest_library_1_3.xml
│ ├── Maven__org_jsoup_jsoup_1_9_2.xml
│ ├── Maven__org_mongodb_bson_3_3_0.xml
│ ├── Maven__org_mongodb_mongodb_driver_3_3_0.xml
│ ├── Maven__org_mongodb_mongodb_driver_core_3_3_0.xml
│ ├── Maven__org_openpnp_opencv_3_2_0_1.xml
│ ├── Maven__org_ow2_asm_asm_6_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_api_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_chrome_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_edge_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_firefox_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_ie_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_java_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_opera_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_remote_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_safari_driver_3_12_0.xml
│ ├── Maven__org_seleniumhq_selenium_selenium_support_3_12_0.xml
│ ├── Maven__org_springframework_spring_aop_5_0_5_RELEASE.xml
│ ├── Maven__org_springframework_spring_beans_5_0_5_RELEASE.xml
│ ├── Maven__org_springframework_spring_context_5_0_5_RELEASE.xml
│ ├── Maven__org_springframework_spring_core_5_0_5_RELEASE.xml
│ ├── Maven__org_springframework_spring_expression_5_0_5_RELEASE.xml
│ ├── Maven__org_springframework_spring_jcl_5_0_5_RELEASE.xml
│ ├── Maven__org_testng_testng_7_0_0_beta1.xml
│ ├── Maven__org_uncommons_reportng_1_1_5.xml
│ ├── Maven__org_xerial_sqlite_jdbc_3_8_11_1.xml
│ └── Maven__org_yaml_snakeyaml_1_21.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── META-INF
└── MANIFEST.MF
├── README.md
├── config
├── .DS_Store
└── config.yaml
├── iOSMonkey.gif
├── logs
└── iOSMonkey.log
├── pom.xml
├── src
└── main
│ ├── java
│ ├── Driver
│ │ └── DriverServer.java
│ ├── Event
│ │ ├── CaseEvent.java
│ │ ├── FunctionEvent.java
│ │ ├── MonkeyBackEvent.java
│ │ ├── MonkeyDaemon.java
│ │ ├── MonkeyEvent.java
│ │ ├── MonkeyHomeKeyEvent.java
│ │ ├── MonkeySpecialEvent.java
│ │ ├── MonkeySubmitEvent.java
│ │ ├── MonkeySwipeEvent.java
│ │ ├── MonkeyTapEvent.java
│ │ └── MonkeyXpathEvent.java
│ ├── MathRandom.java
│ ├── Monkey.java
│ ├── ScreenShots
│ │ ├── ModifyPic.java
│ │ └── Screenshot.java
│ ├── Test.java
│ └── Untils
│ │ ├── FileUntils.java
│ │ ├── GetPerformance.java
│ │ ├── MailConfig.java
│ │ ├── MyLogger.java
│ │ ├── SearchCrash.java
│ │ └── SendMail.java
│ └── resources
│ └── log4j.properties
├── testcase
├── .DS_Store
└── testcase.yaml
├── 性能文件.png
└── 执行流程.png
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xinxi1990/iOSMonkey/b92486fee0257b677e59ff7c8a1deca427568e76/.DS_Store
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/iOSMonkey.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__cglib_cglib_3_2_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_alibaba_fastjson_1_2_31.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_aventstack_extentreports_3_1_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_beust_jcommander_1_72.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_9_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_8_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_csv_2_8_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_yaml_2_9_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_code_gson_gson_2_8_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_errorprone_error_prone_annotations_2_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_guava_guava_23_6_jre.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_inject_guice_4_1_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_j2objc_j2objc_annotations_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_relevantcodes_extentreports_2_41_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_squareup_okhttp3_okhttp_3_9_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_squareup_okio_okio_1_13_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_beanutils_commons_beanutils_1_9_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_codec_commons_codec_1_10.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_collections_commons_collections_3_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_digester_commons_digester_1_8_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_io_commons_io_2_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_lang_commons_lang_2_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_validator_commons_validator_1_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_appium_java_client_6_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_rest_assured_json_path_3_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_rest_assured_rest_assured_3_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_rest_assured_rest_assured_common_3_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_rest_assured_xml_path_3_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_activation_activation_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_inject_javax_inject_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_mail_mail_1_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_websocket_javax_websocket_api_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_xml_bind_jaxb_api_2_2_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__junit_junit_4_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__log4j_log4j_1_2_17.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_8_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_iharder_base64_2_3_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_ant_ant_1_9_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_ant_ant_launcher_1_9_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_commons_commons_exec_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_7.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_httpcomponents_httpmime_4_5_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_velocity_velocity_1_7.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_aspectj_aspectjweaver_1_9_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_ccil_cowan_tagsoup_tagsoup_1_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_checkerframework_checker_compat_qual_2_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_groovy_groovy_2_4_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_groovy_groovy_json_2_4_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_groovy_groovy_xml_2_4_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_freemarker_freemarker_2_3_23.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_grizzly_grizzly_framework_2_3_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_grizzly_grizzly_http_2_3_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_grizzly_grizzly_http_server_2_3_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_grizzly_grizzly_rcm_2_3_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_tyrus_tyrus_client_1_13_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_tyrus_tyrus_container_grizzly_1_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_tyrus_tyrus_core_1_13_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_tyrus_tyrus_spi_1_13_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_library_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_jsoup_jsoup_1_9_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mongodb_bson_3_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mongodb_mongodb_driver_3_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mongodb_mongodb_driver_core_3_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_openpnp_opencv_3_2_0_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_ow2_asm_asm_6_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_api_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_chrome_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_edge_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_firefox_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_ie_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_java_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_opera_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_remote_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_safari_driver_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_seleniumhq_selenium_selenium_support_3_12_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_aop_5_0_5_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_beans_5_0_5_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_context_5_0_5_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_core_5_0_5_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_expression_5_0_5_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_jcl_5_0_5_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_testng_testng_7_0_0_beta1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_uncommons_reportng_1_1_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_xerial_sqlite_jdbc_3_8_11_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_yaml_snakeyaml_1_21.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: Monkey
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 简介
2 | 使用Appium框架二次开发iOS端Monkey测试工具
3 |
4 | 目前支持功能:
5 |
6 | 1.基于随机事件:点击、滑动、输入、xpath定位、返回、重启app等事件,根据随机概率随机触发
7 |
8 | 2.支持多设备并发,替换appium端口和wda端口即可
9 |
10 | 3.支持testcase,需要在yaml文件中配置测试用例
11 |
12 | 4.支持步骤截图并生成gif图片
13 |
14 | 5.支持log打印
15 |
16 | 6.支持appium server自启动
17 |
18 | 7.支持守护线程
19 |
20 | 8.支持崩溃查询并且邮件发送
21 |
22 | 9.支持生成性能文件
23 |
24 | # 项目打包
25 | ```aidl
26 | 根目录下: mvn install
27 | 在target目录下生成jar包
28 | ```
29 |
30 | # 运行命令
31 | ```shell
32 | cd /target 目录下
33 |
34 | 参数说明:
35 | -f: config文件配置地址
36 |
37 | config文件中配置数据:
38 |
39 | UDID: "606EC265-1ED8-454D-AF80-BEB78A417B55" #设备udid
40 | BUNDLEID: "com.iOS.Demo" #app的bundle id
41 | TIMING: "1" #运行时间,单位分钟
42 | PORT: "3460" #appium端口
43 | PROXYPORT: "5680" #WDA端口
44 | NeedScreenshot: "true" #是否截图, true是截图
45 | ScreenshotFolder: "~/iOSMonkey" #截图目录
46 | VERBOSE: "true" # 打印日志
47 | TRACEPATH: "~/iOSMonkey" # 性能文件路径
48 | AppiumLogFolder: "~/iOSMonkey" # appiumlog文件路径
49 | TestCase: "/Users/xinxi/Desktop/iOSMonkey/testcase.yaml" # 测试用例文件,可选项
50 |
51 | java -jar iOSMonkey-1.0.jar -f ~/config.yaml
52 |
53 | 在APP setCapability 添加 wdaLocalPort 8101 8102
54 | 默认的webDriverAgent监听的端口是8000,不冲突就可以并发了
55 | ```
56 |
57 | # 生成运行步骤gif图
58 |
59 | 安装ffmpeg brew install ffmpeg
60 |
61 | 
62 |
63 | # config配置文件
64 | 在代码中config目录下config.yaml
65 |
66 | # 测试app
67 | 在代码中app目录下有测试app,可以根据配置config.yaml运行
68 |
69 | # 如何生产性能文件
70 | 参考: https://appiumpro.com/editions/12
71 |
72 |
73 | # 相关问题
74 |
75 | 1.iOS9.0版本不能xcuitest,需要iOS9.3
76 |
77 | 2.查看模拟崩溃日志路径
78 | ~/Library/Logs/DiagnosticReports
79 |
80 |
81 |
--------------------------------------------------------------------------------
/config/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xinxi1990/iOSMonkey/b92486fee0257b677e59ff7c8a1deca427568e76/config/.DS_Store
--------------------------------------------------------------------------------
/config/config.yaml:
--------------------------------------------------------------------------------
1 | UDID: "DDAC13B0-786D-4DC7-A920-4BEAF56CD616"
2 | BUNDLEID: "com.iOS.Demo"
3 | TIMING: "1"
4 | PORT: "3460"
5 | PROXYPORT: "5680"
6 | NeedScreenshot: "true"
7 | ScreenshotFolder: "/Users/xinxi/Desktop/iOSMonkey/pic"
8 | VERBOSE: "true"
9 | TRACEPATH: "/Users/xinxi/Desktop/iOSMonkey"
10 | AppiumLogFolder: "/Users/xinxi/Desktop/iOSMonkey"
11 | TestCase: "/Users/xinxi/Desktop/iOSMonkey/testcase.yaml"
--------------------------------------------------------------------------------
/iOSMonkey.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xinxi1990/iOSMonkey/b92486fee0257b677e59ff7c8a1deca427568e76/iOSMonkey.gif
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | iOSMonkey
8 | iOSMonkey
9 | 1.0
10 |
11 |
12 |
13 | maven-assembly-plugin
14 |
15 | false
16 |
17 | jar-with-dependencies
18 |
19 |
20 |
21 | Monkey
22 |
23 |
24 |
25 |
26 |
27 | make-assembly
28 | package
29 |
30 | assembly
31 |
32 |
33 |
34 |
35 |
36 | org.apache.maven.plugins
37 | maven-compiler-plugin
38 |
39 | 8
40 | 8
41 |
42 |
43 |
44 | org.apache.maven.plugins
45 | maven-surefire-plugin
46 |
47 |
48 |
49 |
50 |
51 | 2.4
52 |
53 |
54 |
55 |
56 |
57 | io.appium
58 | java-client
59 | 6.0.0
60 |
61 |
62 | org.seleniumhq.selenium
63 | selenium-java
64 | 3.12.0
65 |
66 |
67 | org.testng
68 | testng
69 | 6.14.3
70 | test
71 |
72 |
73 | net.iharder
74 | base64
75 | 2.3.8
76 |
77 |
78 | log4j
79 | log4j
80 | 1.2.17
81 | test
82 |
83 |
84 | junit
85 | junit
86 | 4.12
87 | test
88 |
89 |
90 | org.yaml
91 | snakeyaml
92 | 1.21
93 |
94 |
95 | log4j
96 | log4j
97 | 1.2.17
98 | compile
99 |
100 |
101 | org.uncommons
102 | reportng
103 | 1.1.5
104 | test
105 |
106 |
107 | com.google.inject
108 | guice
109 | 4.1.0
110 |
111 |
112 | com.aventstack
113 | extentreports
114 | 3.1.5
115 | provided
116 |
117 |
118 | com.relevantcodes
119 | extentreports
120 | 2.41.2
121 |
122 |
123 | org.apache.velocity
124 | velocity
125 | 1.7
126 |
127 |
128 | com.alibaba
129 | fastjson
130 | 1.2.31
131 | compile
132 |
133 |
134 | io.rest-assured
135 | rest-assured
136 | 3.1.1
137 | compile
138 |
139 |
140 | javax.mail
141 | mail
142 | 1.4
143 |
144 |
145 | com.fasterxml.jackson.dataformat
146 | jackson-dataformat-yaml
147 | 2.9.6
148 |
149 |
150 | com.fasterxml.jackson.dataformat
151 | jackson-dataformat-csv
152 | 2.8.8
153 |
154 |
155 | org.testng
156 | testng
157 | 7.0.0-beta1
158 | compile
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/src/main/java/Driver/DriverServer.java:
--------------------------------------------------------------------------------
1 | package Driver;
2 |
3 | import java.io.*;
4 | import java.net.URL;
5 |
6 | import static Untils.FileUntils.timeDate;
7 | import static Untils.MyLogger.log_info;
8 |
9 | import io.appium.java_client.android.AndroidDriver;
10 | import io.appium.java_client.ios.IOSDriver;
11 | import io.appium.java_client.remote.IOSMobileCapabilityType;
12 | import io.appium.java_client.remote.MobileCapabilityType;
13 | import org.openqa.selenium.remote.DesiredCapabilities;
14 |
15 | /**
16 | * @author xinxi
17 | * 创建appium driver
18 | */
19 |
20 | public class DriverServer {
21 |
22 | public static IOSDriver iosDriver;
23 | public static AndroidDriver androidDriver;
24 | private static String rootPath = System.getProperty("user.dir");
25 | private static String AppiumLog = "/" +timeDate() +"_appium.log";
26 | private static long AppiumWaitTime = 20 * 1000; // Appium Server启动时间
27 | private static int AppiumPort = 4723;
28 | private static String AppiumHost = "127.0.0.1";
29 | private static int GlobleWaitTime = 30 * 1000; // 设置全局隐示等待
30 | private static String udid;
31 | private static int appiumPort;
32 | private static int wdaPORT;
33 |
34 | public DriverServer(String UDID,int AppiumPort,int WDAPORT) {
35 | udid = UDID;
36 | appiumPort = AppiumPort;
37 | wdaPORT = WDAPORT;
38 | }
39 |
40 |
41 |
42 |
43 | /**
44 | * 组装Appium的capabilities
45 | * return: driver实例
46 | */
47 | public IOSDriver baseDriver(String BUNDLEID) throws IOException, InterruptedException {
48 | DesiredCapabilities caps=new DesiredCapabilities();
49 | caps.setCapability("platformName", "ios");
50 | caps.setCapability("automationName", "xcuitest");
51 | caps.setCapability("deviceName", "iPhone");
52 | caps.setCapability("udid", udid);
53 | caps.setCapability("app", BUNDLEID);
54 | //caps.setCapability("newCommandTimeout", 1800);
55 | //caps.setCapability("wdaConnectionTimeout", 1800*1000);
56 | caps.setCapability("wdaLocalPort", Integer.parseInt(String.valueOf(wdaPORT)));
57 | iosDriver = new IOSDriver(new URL(String.format("http://127.0.0.1:%s/wd/hub", appiumPort)),caps);
58 | log_info(String.format("capabilities配置:%s", iosDriver.getCapabilities()));
59 | log_info("app启动!");
60 | return iosDriver;
61 | }
62 |
63 |
64 | /**
65 | * 组装iOS的capabilities
66 | * return: driver实例
67 | */
68 | public IOSDriver IOSBaseDriver() throws IOException, InterruptedException {
69 | DesiredCapabilities capabilities = new DesiredCapabilities();
70 | String url = "http://"+ AppiumHost +":" + appiumPort + "/wd/hub";
71 | log_info("appium Remote URL:" + url);
72 | capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
73 | capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "XCUITest");
74 | capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone sim");
75 | //capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "11.2");
76 | capabilities.setCapability(MobileCapabilityType.UDID, udid);
77 | capabilities.setCapability(MobileCapabilityType.APP, "com.luojilab.LuoJiFM-IOS");
78 | capabilities.setCapability(MobileCapabilityType.NO_RESET, true);
79 | capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1800);
80 | capabilities.setCapability(IOSMobileCapabilityType.WDA_CONNECTION_TIMEOUT, 1800*1000);
81 | capabilities.setCapability(IOSMobileCapabilityType.WDA_LOCAL_PORT,Integer.parseInt(String.valueOf(wdaPORT)));
82 | capabilities.setCapability(IOSMobileCapabilityType.AUTO_ACCEPT_ALERTS,true);
83 | //capabilities.setCapability(IOSMobileCapabilityType.START_IWDP, true);
84 | //capabilities.setCapability("autoWebview", true);
85 | //capabilities.setCapability("xcodeOrgId", "7Q6C9D7LVN");
86 | // capabilities.setCapability("xcodeSigningId", "iPhone Developer");
87 | iosDriver = new IOSDriver(new URL(url),capabilities);
88 | log_info(String.format("capabilities配置:%s", iosDriver.getCapabilities()));
89 | log_info("app启动!");
90 | return iosDriver;
91 | }
92 |
93 | /**
94 | * 组装Android的capabilities
95 | * return: driver实例
96 | */
97 | public AndroidDriver AndroidBaseDriver() throws IOException, InterruptedException {
98 | DesiredCapabilities caps=new DesiredCapabilities();
99 | DesiredCapabilities capabilities = new DesiredCapabilities();
100 | capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
101 | capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, udid);
102 | capabilities.setCapability(MobileCapabilityType.UDID, udid);
103 | capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1800);
104 | capabilities.setCapability("appPackage", "com.luojilab.player");
105 | //Android 7要用 uiautomator2
106 | //if(getSDKVersion(udid) > 23){
107 | // capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator2");
108 | // log.info("Using uiautomator2");
109 | //}
110 | String url = "http://"+ AppiumHost +":" + appiumPort + "/wd/hub";
111 | androidDriver = new AndroidDriver(new URL(url),caps);
112 | log_info("appium URL:" + url);
113 | log_info(String.format("capabilities配置:%s", iosDriver.getCapabilities()));
114 | log_info("app启动!");
115 | return androidDriver;
116 | }
117 |
118 |
119 |
120 | /**
121 | * 启动appium server
122 | */
123 | public void startAppiumServer(String AppiumLogFolder) throws IOException, InterruptedException {
124 | String startCmd = String.format("appium -a %s -p %s --log %s --relaxed-security",AppiumHost,appiumPort,AppiumLogFolder + AppiumLog);
125 | log_info("appium运行命令:" + startCmd);
126 | Runtime.getRuntime().exec(startCmd);
127 | Thread.sleep(AppiumWaitTime);
128 | }
129 |
130 |
131 |
132 | /**
133 | * 启动前杀死appium server进程
134 | */
135 | public void killAppiumServer() throws IOException{
136 | String serachCmd = String.format("lsof -i:%s", appiumPort);
137 | Process p = Runtime.getRuntime().exec(serachCmd);
138 | InputStream is = p.getInputStream();
139 | BufferedReader reader = new BufferedReader(new InputStreamReader(is));
140 | String line ;
141 | while ((line = reader.readLine()) != null) {
142 | if (line.contains(String.valueOf("TCP"))){
143 | String[] tt=line.split("\\s+");
144 | String killCmd = String.format("kill -9 %s", tt[1]);
145 | log_info(String.format("kill AppiumServer命令:%s", killCmd));
146 | Runtime.getRuntime().exec(killCmd);
147 | break;
148 | }
149 | }
150 | is.close();
151 | reader.close();
152 | p.destroy();
153 | }
154 |
155 | /**
156 | * 启动前杀死WDA server进程
157 | */
158 | public void killWDAServer() throws IOException{
159 | String serachCmd = String.format("lsof -i:%s", wdaPORT);
160 | Process p = Runtime.getRuntime().exec(serachCmd);
161 | InputStream is = p.getInputStream();
162 | BufferedReader reader = new BufferedReader(new InputStreamReader(is));
163 | String line ;
164 | while ((line = reader.readLine()) != null) {
165 | if (line.contains(String.valueOf("TCP"))){
166 | String[] tt=line.split("\\s+");
167 | String killCmd = String.format("kill -9 %s", tt[1]);
168 | log_info(String.format("kill WDAServer命令:%s", killCmd));
169 | Runtime.getRuntime().exec(killCmd);
170 | break;
171 | }
172 | }
173 | is.close();
174 | reader.close();
175 | p.destroy();
176 | }
177 |
178 |
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/java/Event/CaseEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 |
4 | import Driver.DriverServer;
5 | import io.appium.java_client.ios.IOSDriver;
6 | import io.appium.java_client.ios.IOSElement;
7 |
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.List;
12 | import java.util.Map;
13 | import static Untils.FileUntils.readYaml;
14 | import static Untils.MyLogger.log_info;
15 |
16 | /**
17 | * @author xinxi
18 | * 根据步骤生成自动化case
19 | */
20 |
21 |
22 | public class CaseEvent {
23 |
24 | private static String TestCase = "testcase";
25 | private static String CaseName = "casename";
26 | private static String Steps = "steps";
27 | private static String When = "when";
28 | private static String By = "by";
29 | private static String Action = "action";
30 | private static String SleepTime = "sleeptime";
31 | private static String SendValue;
32 | private static String Method;
33 | private static String ElementValue;
34 | private static List ElementList;
35 | private static IOSDriver iosDriver;
36 | private static IOSElement iosElement;
37 | private static DriverServer driverServer;
38 | public static String projectPath = System.getProperty("user.dir");
39 |
40 | public CaseEvent(IOSDriver Driver) {
41 | this.iosDriver = Driver;
42 | }
43 |
44 | public static void main(String[] args) throws InterruptedException, IOException {
45 | driverServer = new DriverServer("606EC265-1ED8-454D-AF80-BEB78A417B55",4723,8001);
46 | driverServer.killWDAServer();
47 | driverServer.killAppiumServer();
48 | driverServer.startAppiumServer("./");
49 | iosDriver = driverServer.baseDriver("com.iOS.Demo");
50 | }
51 |
52 |
53 | public void generateCase(String casePath) throws InterruptedException {
54 | log_info("测试用例文件路径:" + casePath);
55 | Map caseYaml = readYaml(casePath);
56 | generateRule(caseYaml);
57 | }
58 |
59 |
60 | /**
61 | * 递归解析Case.yaml文件
62 | * @param caseYaml
63 | * @throws InterruptedException
64 | */
65 | private void generateRule(Map caseYaml) throws InterruptedException {
66 | for (Object key : caseYaml.keySet()) {
67 | Object value = caseYaml.get(key);
68 | if (key.toString().startsWith(TestCase)){
69 | log_info("测试用例:" + key);
70 | generateRule((Map) value);
71 | }else if (key.toString().startsWith(CaseName)){
72 | log_info("用例名字:" + value);
73 | }else if (key.toString().startsWith(Steps)){
74 | log_info("用例步骤:" + value);
75 | for (Object action : (ArrayList) (value)) {
76 | acitonGenerate((Map) action);
77 | }
78 | }
79 | }
80 | }
81 |
82 |
83 | /**
84 | * 映射appium操作元素的动作
85 | * @param actionMap
86 | * @throws InterruptedException
87 | */
88 | private void acitonGenerate(Map actionMap) throws InterruptedException {
89 | for (Object key : actionMap.keySet()) {
90 | Object value = actionMap.get(key);
91 | if (key.toString().startsWith(When)){
92 | if (!value.toString().equals("")){
93 | Method = value.toString().split(";")[0];
94 | ElementValue = value.toString().split(";")[1];
95 | log_info("检查【" + ElementValue + "】是否存在");
96 | if (Method.equals("name")){
97 | ElementList = iosDriver.findElements(org.openqa.selenium.By.name(ElementValue));
98 | if (ElementList.size() > 0){
99 | log_info(ElementValue + "存在");
100 | continue;
101 | }else {
102 | log_info(ElementValue + "不存在,剩余步骤不执行");
103 | break;
104 | }
105 | }else if (Method.equals("xpath")){
106 | ElementList = iosDriver.findElements(org.openqa.selenium.By.xpath(ElementValue));
107 | if (ElementList.size() > 0){
108 | log_info(ElementValue + "存在");
109 | continue;
110 | }else {
111 | log_info(ElementValue + "不存在,剩余步骤不执行");
112 | break;
113 | }
114 | }
115 | }else {
116 | log_info("没有待检查元素");
117 | }
118 |
119 | }else if (key.toString().startsWith(By)){
120 | Method = value.toString().split(";")[0];
121 | ElementValue = value.toString().split(";")[1];
122 | log_info("定位元素方法:" + Method);
123 | log_info("定位元素值:" + ElementValue);
124 | if (Method.equals("name")){
125 | iosElement = (IOSElement) iosDriver.findElement(org.openqa.selenium.By.name(ElementValue));
126 | }else if (Method.equals("xpath")){
127 | iosElement = (IOSElement) iosDriver.findElement(org.openqa.selenium.By.xpath(ElementValue));
128 | }
129 | }else if (key.toString().startsWith(Action)){
130 | log_info("事件动作:" + value);
131 | if (value.toString().startsWith("click")){
132 | iosElement.click();
133 | }else if (value.toString().startsWith("sendKeys")){
134 | SendValue = value.toString().split(";")[1];
135 | iosElement.clear();
136 | iosElement.sendKeys(SendValue);
137 | log_info("输入内容:" + SendValue);
138 | }
139 | }else if (key.toString().startsWith(SleepTime)){
140 | Thread.sleep(Long.parseLong(String.valueOf(value)));
141 | log_info("等待时间:" + value);
142 | }
143 | }
144 |
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/Event/FunctionEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.AppiumDriver;
4 | import io.appium.java_client.TouchAction;
5 | import io.appium.java_client.pagefactory.AppiumFieldDecorator;
6 | import io.appium.java_client.touch.WaitOptions;
7 | import io.appium.java_client.touch.offset.PointOption;
8 | import org.openqa.selenium.By;
9 | import org.openqa.selenium.Dimension;
10 | import org.openqa.selenium.JavascriptExecutor;
11 | import org.openqa.selenium.support.PageFactory;
12 | import org.testng.Assert;
13 | import org.testng.log4testng.Logger;
14 | import java.time.Duration;
15 | import java.util.HashMap;
16 | import static Untils.MyLogger.log_info;
17 |
18 |
19 | /**
20 | * @author xinxi
21 | * appium基本操作封装类
22 | */
23 |
24 | public abstract class FunctionEvent {
25 |
26 | public final AppiumDriver> driver;
27 | public String PageSource;
28 | public Logger logger;
29 | public Boolean is_exist;
30 | private Dimension dimension;
31 | private TouchAction touchAction;
32 | private long sleepTime = 300;
33 | private int MaxScroll = 10;
34 | private int MaxBack = 10;
35 |
36 | public FunctionEvent(AppiumDriver> driver) {
37 | this.driver = driver;
38 | PageFactory.initElements(new AppiumFieldDecorator(driver), this);
39 | touchAction = new TouchAction(this.driver);
40 | }
41 |
42 |
43 | /**
44 | * 查询元素是否存在
45 | * return: bool
46 | */
47 | public Boolean findElementsBy(By by) throws InterruptedException {
48 | sleep(1);
49 | is_exist = false;
50 | if (driver.findElements(by).size() > 0){
51 | log_info(String.format("查询到元素:%s",by));
52 | is_exist = true;
53 | }else {
54 | is_exist = false;
55 | }
56 | return is_exist;
57 | }
58 |
59 |
60 | /**
61 | * 页面是否包含某个文案
62 | * return:bool
63 | */
64 | public Boolean findElements(String text) throws InterruptedException {
65 | this.sleep(1);
66 | is_exist = false;
67 | PageSource = this.driver.getPageSource();
68 | if (PageSource.contains(text)){
69 | is_exist = true;
70 |
71 | }else {
72 | is_exist = false;
73 | }
74 | return is_exist;
75 | }
76 |
77 |
78 | /**
79 | * 断言页面包含某个的元素
80 | */
81 | public void assertContain(String text) throws InterruptedException {
82 | this.sleep(2);
83 | PageSource = this.driver.getPageSource();
84 | if (PageSource.contains(text)){
85 | Assert.assertTrue(true);
86 | }else {
87 | Assert.assertFalse(true);
88 | }
89 | }
90 |
91 |
92 | /**
93 | * 断言页面不包含某个的元素
94 | */
95 | public void assertNotContain(String text){
96 | PageSource = this.driver.getPageSource();
97 | if (!PageSource.contains(text)){
98 | Assert.assertTrue(true);
99 | }else {
100 | Assert.assertFalse(true);
101 | }
102 |
103 | }
104 |
105 | /**
106 | * 断言页面包含element
107 | * by:元素
108 | */
109 | public void assertContainBy(By by){
110 |
111 | if (driver.findElements(by).size() > 0){
112 | Assert.assertTrue(true);
113 | }else {
114 | Assert.assertFalse(true);
115 | }
116 |
117 | }
118 |
119 |
120 | /**
121 | * 断言页面不包含element
122 | * by:元素
123 | */
124 | public void assertNotContainBy(By by){
125 |
126 | if (!(driver.findElements(by).size() > 0)){
127 | Assert.assertTrue(true);
128 | }else {
129 | Assert.assertFalse(true);
130 | }
131 | }
132 |
133 |
134 | /**
135 | * 等待
136 | */
137 | public void sleep(int time) throws InterruptedException {
138 | Thread.sleep(1000 * time);
139 | }
140 |
141 | /**
142 | * 获取屏幕尺寸
143 | */
144 | private Dimension getWindowSize(){
145 | dimension = driver.manage().window().getSize();
146 | return dimension;
147 | }
148 |
149 |
150 | /**
151 | * 向上滚动
152 | * @ looper 次数
153 | */
154 | public void scrollUp(int loop) throws InterruptedException {
155 | for (int i = 0; i < loop ; i++) {
156 | touchAction = new TouchAction(this.driver);
157 | touchAction.press(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.3)));
158 | touchAction.waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)));
159 | touchAction.moveTo(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.8)));
160 | touchAction.release();
161 | touchAction.perform();
162 | log_info("向上滑动!");
163 | Thread.sleep(sleepTime);
164 | }
165 | }
166 |
167 | /**
168 | * 向上滚动
169 | * @ looper 次数
170 | */
171 | public void scrollDown(int loop) throws InterruptedException {
172 | for (int i = 0; i < loop ; i++) {
173 | touchAction = new TouchAction(this.driver);
174 | touchAction.press(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.8)));
175 | touchAction.waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)));
176 | touchAction.moveTo(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.3)));
177 | touchAction.release();
178 | touchAction.perform();
179 | log_info("向下滑动!");
180 | Thread.sleep(sleepTime);
181 | }
182 | }
183 |
184 |
185 |
186 | /**
187 | * 向下滚动到某个元素
188 | */
189 | public void scrollDown(String value) throws InterruptedException {
190 | sleep(1);
191 | JavascriptExecutor js = (JavascriptExecutor) driver;
192 | HashMap scrollObject = new HashMap();
193 | scrollObject.put("direction", "down");
194 | scrollObject.put("name", value);
195 | js.executeScript("mobile: scroll", scrollObject);
196 | log_info(String.format("向下滑动到元素:%s", value));
197 | }
198 |
199 |
200 |
201 | /**
202 | * 向上滚动到某个元素
203 | */
204 | public void scrollUp(String value){
205 | JavascriptExecutor js = (JavascriptExecutor) driver;
206 | HashMap scrollObject = new HashMap();
207 | scrollObject.put("direction", "up");
208 | scrollObject.put("name", value);
209 | js.executeScript("mobile: scroll", scrollObject);
210 | log_info(String.format("向上滑动到元素:%s", value));
211 | }
212 |
213 |
214 | /**
215 | * 向下滚动到某个元素
216 | */
217 | public void scrollDownElement(String value) throws InterruptedException {
218 | while (MaxScroll > 0 ){
219 | if (findElements(value)){
220 | break;
221 | }else {
222 | scrollDown(1);
223 | MaxScroll --;
224 | }
225 | }
226 | }
227 |
228 |
229 | /**
230 | * 返回键
231 | */
232 | public void goBack(){
233 | driver.navigate().back();
234 | }
235 |
236 | /**
237 | * 循环返回到某个位置
238 | */
239 | public void loopBack(By by) throws InterruptedException {
240 | while (MaxBack > 0){
241 | if (findElementsBy(by)){
242 | break;
243 | }else {
244 | goBack();
245 | MaxBack --;
246 | }
247 | }
248 | }
249 |
250 |
251 | /**
252 | * 点击引导蒙层
253 | */
254 | public void tapGurid(int tapCount){
255 |
256 |
257 | }
258 |
259 | }
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeyBackEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.ios.IOSDriver;
4 | import static Untils.MyLogger.log_info;
5 |
6 |
7 | /**
8 | * @author xinxi
9 | * Monkey返回事件
10 | */
11 |
12 |
13 | public class MonkeyBackEvent extends MonkeyEvent {
14 | private IOSDriver driver;
15 |
16 | public MonkeyBackEvent(IOSDriver driver) {
17 | super(MonkeyEvent.EVENT_TYPE_BACK);
18 | this.driver = driver;
19 | }
20 |
21 |
22 | public int injectEvent() throws Exception {
23 | try {
24 | driver.navigate().back();
25 | log_info("sending Back Event Over!");;
26 | return MonkeyEvent.INJECT_SUCCESS;
27 | }catch (Exception E){
28 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
29 | return INJECT_FAIL;
30 | }
31 | }
32 |
33 | }
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeyDaemon.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.ios.IOSDriver;
4 | import java.io.BufferedReader;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 | import java.util.Timer;
8 | import java.util.TimerTask;
9 |
10 | import static Untils.MyLogger.log_info;
11 |
12 | public class MonkeyDaemon extends TimerTask {
13 |
14 | public static int loopTime = 60 * 1000; // 每隔5s执行一次
15 | private static String UDID;
16 | private static String BUNDLEID;
17 |
18 |
19 | public MonkeyDaemon(String UDID, String BUNDLEID) {
20 | this.UDID = UDID;
21 | this.BUNDLEID = BUNDLEID;
22 | }
23 |
24 | @Override
25 | public void run() {
26 | if (UDID.contains("-")) {
27 | log_info("模拟器检查app运行状态!");
28 | String runcmd = "xcrun simctl spawn booted log stream --level=debug";
29 | Process pp = null;
30 | try {
31 | pp = Runtime.getRuntime().exec(runcmd);
32 | } catch (IOException e) {
33 | e.printStackTrace();
34 | }
35 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pp.getInputStream()));
36 | String line;
37 | int lineCount = 0;
38 | String runstring = "";
39 | try {
40 | while ((line = bufferedReader.readLine()) != null) {
41 | lineCount++;
42 | if (lineCount < 100) {
43 | runstring += line + "\n";
44 | } else {
45 | break;
46 | }
47 | }
48 | } catch (IOException e) {
49 | e.printStackTrace();
50 | } finally {
51 | //System.out.println("===" + runstring + "===");
52 | if (runstring.contains("LuoJiFMIOS")) {
53 | log_info("模拟器app运行中!");
54 | } else {
55 | log_info("模拟器app不在运行中!");
56 | try {
57 | Runtime.getRuntime().exec("xcrun simctl launch booted " + BUNDLEID);
58 | log_info("====非测试APP,重新呼起测试APP====");
59 | } catch (IOException e) {
60 | e.printStackTrace();
61 | }
62 | }
63 | }
64 | } else {
65 | log_info("真机检查app运行状态!");
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeyEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | /**
4 | * abstract class for monkey event
5 | */
6 | public abstract class MonkeyEvent {
7 | protected int eventType;
8 | public static final int EVENT_TYPE_TAP = 0;
9 | public static final int EVENT_TYPE_SWIPE = 1;
10 | public static final int EVENT_TYPE_LAUNCH = 2;
11 | public static final int EVENT_TYPE_BACK = 3;
12 | public static final int EVENT_TYPE_SUBMIT = 4;
13 | public static final int EVENT_TYPE_CONTENT = 5;
14 | public static final int EVENT_TYPE_HOMEKEY = 6;
15 |
16 |
17 |
18 | public static final int INJECT_SUCCESS = 1;
19 | public static final int INJECT_FAIL = 0;
20 |
21 |
22 | public MonkeyEvent(int type) {
23 | eventType = type;
24 | }
25 |
26 | /**
27 | * @return event type
28 | */
29 | public int getEventType() {
30 | return eventType;
31 | }
32 |
33 | /**
34 | * @return true if it is safe to throttle after this event, and false otherwise.
35 | */
36 | public boolean isThrottlable() {
37 | return true;
38 | }
39 |
40 |
41 | /**
42 | * @return INJECT_SUCCESS if it goes through, and INJECT_FAIL if it fails
43 | * in the case of exceptions, return its corresponding error code
44 | */
45 | public abstract int injectEvent() throws Exception;
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeyHomeKeyEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import static Untils.MyLogger.log_info;
4 | import io.appium.java_client.ios.IOSDriver;
5 |
6 |
7 | /**
8 | * @author xinxi
9 | * Monkey重新启动app事件类
10 | */
11 |
12 |
13 | public class MonkeyHomeKeyEvent extends MonkeyEvent{
14 | private String UDID, BUNDLEID;
15 | public static IOSDriver iosDriver;
16 |
17 | public MonkeyHomeKeyEvent(IOSDriver driver) {
18 | super(MonkeyEvent.EVENT_TYPE_HOMEKEY);
19 | this.iosDriver = driver;
20 | }
21 |
22 | public int injectEvent() throws Exception {
23 | log_info("sending HOMEKEY Event.");
24 | iosDriver.closeApp();
25 | iosDriver.launchApp();
26 | return MonkeyEvent.INJECT_SUCCESS;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeySpecialEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.ios.IOSDriver;
4 | import org.openqa.selenium.By;
5 | import java.util.ArrayList;
6 | import static Untils.MyLogger.log_info;
7 |
8 | public class MonkeySpecialEvent {
9 |
10 | public static IOSDriver iosDriver;
11 | private ArrayList arrayList;
12 | private By closeLogin = By.id("medal popview dismiss");
13 | private By sure = By.name("确定");
14 | private By freeSee = By.name("随便看看");
15 | private By cancel = By.name("取消");
16 |
17 | public MonkeySpecialEvent(IOSDriver driver) {
18 | iosDriver = driver;
19 | arrayList = new ArrayList();
20 | arrayList.add(closeLogin);
21 | arrayList.add(sure);
22 | arrayList.add(sure);
23 | arrayList.add(freeSee);
24 | arrayList.add(cancel);
25 | }
26 |
27 |
28 | /**
29 | * 关闭弹框
30 | */
31 | public void closeAlert() throws Exception {
32 | try {
33 | for (Object by : arrayList) {
34 | if (iosDriver.findElements((By) by).size() > 0) {
35 | iosDriver.findElement((By) by).click();
36 | log_info("关闭弹框");
37 | }
38 | }
39 | }
40 | catch(Exception E){
41 | log_info(this.getClass().getName() + "-" + "closeAlert:" + E);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeySubmitEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.TouchAction;
4 | import io.appium.java_client.ios.IOSDriver;
5 | import io.appium.java_client.touch.offset.PointOption;
6 | import static Untils.MyLogger.log_info;
7 |
8 |
9 |
10 | /**
11 | * @author xinxi
12 | * Monkey输入事件类
13 | */
14 |
15 | public class MonkeySubmitEvent extends MonkeyEvent {
16 | private IOSDriver driver;
17 | private int x, y;
18 |
19 | public MonkeySubmitEvent(IOSDriver driver, int x, int y) {
20 | super(MonkeyEvent.EVENT_TYPE_SUBMIT);
21 | this.x = x;
22 | this.y = y;
23 | this.driver = driver;
24 | }
25 |
26 | public int injectEvent() throws Exception {
27 | try {
28 | log_info("sending Submit Event : Tap->(" + x + ", " + y + ")");
29 | TouchAction touchAction = new TouchAction(driver);
30 | touchAction.tap(PointOption.point(x, y)).perform();
31 | log_info("sending Tap Event Over!");
32 | return MonkeyEvent.INJECT_SUCCESS;
33 | }catch (Exception E){
34 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
35 | return INJECT_FAIL;
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeySwipeEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.TouchAction;
4 | import io.appium.java_client.ios.IOSDriver;
5 | import io.appium.java_client.touch.WaitOptions;
6 | import io.appium.java_client.touch.offset.PointOption;
7 | import org.openqa.selenium.Dimension;
8 | import java.time.Duration;
9 | import static Untils.MyLogger.log_info;
10 |
11 |
12 | /**
13 | * @author xinxi
14 | * Monkey滑动类
15 | */
16 |
17 | public class MonkeySwipeEvent extends MonkeyEvent {
18 | private Dimension dimension;
19 | private TouchAction touchAction;
20 | private long sleepTime = 300;
21 | private IOSDriver driver;
22 | private int MaxScroll = 1;
23 |
24 |
25 | public MonkeySwipeEvent(IOSDriver driver) {
26 | super(MonkeyEvent.EVENT_TYPE_SWIPE);
27 | this.driver = driver;
28 | }
29 |
30 | @Override
31 | public int injectEvent() throws Exception {
32 | return 0;
33 | }
34 |
35 | /**
36 | * 向上滚动事件
37 | */
38 | public int injectEvent_scrollUp() throws Exception {
39 | try {
40 | log_info("sending scrollUp Event!");
41 | this.scrollUp(MaxScroll);
42 | log_info("sending scrollUp Over!");
43 | return MonkeyEvent.INJECT_SUCCESS;
44 | }catch (Exception E){
45 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
46 | return INJECT_FAIL;
47 | }
48 | }
49 |
50 |
51 | /**
52 | * 向下滚动事件
53 | */
54 | public int injectEvent_scrollDown() throws Exception {
55 | try {
56 | log_info("sending scrollDown Event!");
57 | this.scrollDown(MaxScroll);
58 | log_info("sending scrollDown Over!");
59 | return MonkeyEvent.INJECT_SUCCESS;
60 | }catch (Exception E){
61 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
62 | return INJECT_FAIL;
63 | }
64 | }
65 |
66 |
67 | /**
68 | * 获取屏幕尺寸
69 | */
70 | private Dimension getWindowSize(){
71 | dimension = driver.manage().window().getSize();
72 | return dimension;
73 | }
74 |
75 | /**
76 | * 向上滚动
77 | * @ looper 次数
78 | */
79 | public void scrollUp(int loop) throws InterruptedException {
80 | for (int i = 0; i < loop ; i++) {
81 | touchAction = new TouchAction(this.driver);
82 | touchAction.press(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.3)));
83 | touchAction.waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)));
84 | touchAction.moveTo(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.8)));
85 | touchAction.release();
86 | touchAction.perform();
87 | log_info("向上滑动!");
88 | Thread.sleep(sleepTime);
89 | }
90 | }
91 |
92 |
93 |
94 |
95 | /**
96 | * 向上滚动
97 | * @ looper 次数
98 | */
99 | public void scrollDown(int loop) throws InterruptedException {
100 | for (int i = 0; i < loop ; i++) {
101 | touchAction = new TouchAction(this.driver);
102 | touchAction.press(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.8)));
103 | touchAction.waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)));
104 | touchAction.moveTo(PointOption.point((int) (getWindowSize().width * 0.5),(int) (getWindowSize().height * 0.3)));
105 | touchAction.release();
106 | touchAction.perform();
107 | log_info("向下滑动!");
108 | Thread.sleep(sleepTime);
109 | }
110 | }
111 |
112 |
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeyTapEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 | import io.appium.java_client.TouchAction;
4 | import io.appium.java_client.ios.IOSDriver;
5 | import io.appium.java_client.touch.offset.PointOption;
6 | import static Untils.MyLogger.log_info;
7 |
8 |
9 | /**
10 | * @author xinxi
11 | * Monkey点击事件类
12 | */
13 |
14 | public class MonkeyTapEvent extends MonkeyEvent{
15 | private int x, y;
16 | private IOSDriver driver;
17 |
18 | public MonkeyTapEvent(IOSDriver driver, int x, int y) {
19 | super(MonkeyEvent.EVENT_TYPE_TAP);
20 | this.x = x;
21 | this.y = y;
22 | this.driver = driver;
23 | }
24 |
25 | public int injectEvent() throws Exception {
26 | try {
27 | log_info("sending Tap Event : Tap->(" + x + ", " + y + ")");
28 | TouchAction touchAction = new TouchAction(driver);
29 | touchAction.tap(PointOption.point(x, y)).perform();
30 | log_info("sending Tap Event Over!");
31 | return MonkeyEvent.INJECT_SUCCESS;
32 | }catch (Exception E){
33 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
34 | return INJECT_FAIL;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/Event/MonkeyXpathEvent.java:
--------------------------------------------------------------------------------
1 | package Event;
2 |
3 |
4 | import io.appium.java_client.ios.IOSDriver;
5 | import io.appium.java_client.ios.IOSElement;
6 | import org.openqa.selenium.By;
7 | import java.util.List;
8 | import java.util.Random;
9 | import static Untils.MyLogger.log_info;
10 |
11 | /**
12 | * @author xinxi
13 | * Monkey Xpath点击事件类
14 | */
15 |
16 |
17 | public class MonkeyXpathEvent extends MonkeyEvent {
18 |
19 | private IOSDriver driver;
20 | private By xpath1= By.xpath("//*[contains(name(), 'Text') and" +
21 | " @name!='' and string-length(@label)<10]");
22 | private By xpath2= By.xpath("//*[contains(name(), 'Image') and @name!='']");
23 |
24 | public MonkeyXpathEvent(IOSDriver driver) {
25 | super(MonkeyEvent.EVENT_TYPE_CONTENT);
26 | this.driver = driver;
27 | }
28 |
29 |
30 | /**
31 | 随机点击文本控件
32 | */
33 | public int injectEvent_Text() throws Exception {
34 | try {
35 | log_info("sending injectEvent Text!");
36 | Random ra = new Random();
37 | List ellist1 = driver.findElements(xpath1);
38 | if (ellist1.size() > 0 ){
39 | int randomEl1 = ra.nextInt(ellist1.size() + 1);
40 | IOSElement iosElement = (IOSElement) ellist1.get(randomEl1);
41 | iosElement.click();
42 | log_info(String.format(this.getClass().getName() + "-" + "injectEvent_Text click %s!", randomEl1));
43 | return MonkeyEvent.INJECT_SUCCESS;
44 | }else {
45 | log_info(this.getClass().getName() + "-" + "injectEvent_Text miss!");
46 | return MonkeyEvent.INJECT_FAIL;
47 | }
48 | }catch (Exception E){
49 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
50 | return MonkeyEvent.INJECT_FAIL;
51 | }
52 | }
53 |
54 |
55 | /**
56 | 随机点击图标控件
57 | */
58 | public int injectEvent_Image() throws Exception {
59 | try {
60 | log_info("sending injectEvent Image!");
61 | Random ra = new Random();
62 | List ellist1 = driver.findElements(xpath2);
63 | if (ellist1.size() > 0 ){
64 | int randomEl1 = ra.nextInt(ellist1.size() + 1);
65 | IOSElement iosElement = (IOSElement) ellist1.get(randomEl1);
66 | iosElement.click();
67 | log_info(String.format(this.getClass().getName() + "-" + "injectEvent_Image click %s!", randomEl1));
68 | return MonkeyEvent.INJECT_SUCCESS;
69 | }else {
70 | log_info(this.getClass().getName() + "-" + "injectEvent_Image miss!");
71 | return MonkeyEvent.INJECT_FAIL;
72 | }
73 | }catch (Exception E){
74 | log_info(this.getClass().getName() + "-" + "injectEvent异常:" + E);
75 | return MonkeyEvent.INJECT_FAIL;
76 | }
77 | }
78 |
79 |
80 | @Override
81 | public int injectEvent() throws Exception {
82 | return 0;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/MathRandom.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @author xinxi
3 | * 随机数类
4 | */
5 |
6 |
7 | public class MathRandom {
8 |
9 | /**
10 | * 0出现的概率为%40
11 | */
12 | public static double EVENT_TYPE_TAP = 0.55;
13 | /**
14 | * 1出现的概率为%30
15 | */
16 | public static double EVENT_TYPE_SWIPE = 0.20;
17 | /**
18 | * 2出现的概率为%10
19 | */
20 | public static double EVENT_TYPE_BACK = 0.15;
21 |
22 | public static double EVENT_TYPE_SUBMIT = 0.05;
23 |
24 | public static double EVENT_TYPE_CONTENT = 0.00;
25 |
26 | public static double EVENT_TYPE_SPECIAL_POINT = 0.04;
27 |
28 | public static double EVENT_TYPE_HOMEKEY = 0.01;
29 |
30 |
31 |
32 |
33 | public int PercentageRandom() {
34 | double randomNumber;
35 | randomNumber = Math.random();
36 | if (randomNumber >= 0 && randomNumber <= EVENT_TYPE_TAP) {
37 | return 0;
38 | } else if (randomNumber >= EVENT_TYPE_TAP / 100 && randomNumber <= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE) {
39 | return 1;
40 | } else if (randomNumber >= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE
41 | && randomNumber <= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK) {
42 | return 2;
43 | } else if (randomNumber >= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK
44 | && randomNumber <= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT) {
45 | return 3;
46 | } else if (randomNumber >= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT
47 | && randomNumber <= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT
48 | + EVENT_TYPE_CONTENT) {
49 | return 4;
50 | }else if (randomNumber >= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT + EVENT_TYPE_CONTENT
51 | && randomNumber <= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT
52 | + EVENT_TYPE_CONTENT + EVENT_TYPE_SPECIAL_POINT) {
53 | return 5;
54 | }else if (randomNumber >= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT + EVENT_TYPE_CONTENT
55 | + EVENT_TYPE_SPECIAL_POINT
56 | && randomNumber <= EVENT_TYPE_TAP + EVENT_TYPE_SWIPE + EVENT_TYPE_BACK + EVENT_TYPE_SUBMIT
57 | + EVENT_TYPE_CONTENT + EVENT_TYPE_SPECIAL_POINT + EVENT_TYPE_HOMEKEY) {
58 | return 6;
59 | }
60 | return -1;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/Monkey.java:
--------------------------------------------------------------------------------
1 | import Driver.DriverServer;
2 | import Event.*;
3 | import Untils.GetPerformance;
4 | import io.appium.java_client.ios.IOSDriver;
5 | import org.apache.commons.io.FileUtils;
6 | import org.apache.log4j.Level;
7 | import org.openqa.selenium.Dimension;
8 | import ScreenShots.Screenshot;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.text.DecimalFormat;
12 | import java.text.NumberFormat;
13 | import java.util.*;
14 | import static Event.MonkeyDaemon.loopTime;
15 | import static Untils.FileUntils.createGif;
16 | import static Untils.FileUntils.readYaml;
17 | import static Untils.MyLogger.initLogger;
18 | import static Untils.MyLogger.log_info;
19 | import static Untils.SearchCrash.*;
20 |
21 |
22 | public class Monkey {
23 |
24 | public static IOSDriver iosDriver;
25 | private int width,height, submitX_mim,
26 | submitX_max, submitY_mim,
27 | submitY_max, contentX_min,
28 | contentX_max, contentY_mim,
29 | contentY_max, special_point_x,
30 | special_point_y;
31 | private static boolean needhelp = false;
32 | private static String ConfigPath;
33 | private static String UDID;
34 | private static String BUNDLEID;
35 | private static String NeedScreenshot;
36 | private static String PORT;
37 | private static String PROXYPORT;
38 | private static String VERBOSE;
39 | private static String TRACEPATH;
40 | private static String ScreenshotFolder;
41 | private static String AppiumLogFolder;
42 | private static String TestCase;
43 | private static String Need = "true";
44 | private static Dimension dimension;
45 | private boolean is_running = true;
46 | private int eventcount = 0;
47 | private static String TIMING;
48 | private DriverServer driverServer;
49 | private static long EventWaitTime = 100;
50 | private static int ScreentCount = 0;
51 | private static boolean NEEDHELP = false;
52 |
53 |
54 |
55 | public static void main(String[] args) throws Exception {
56 | executeParameter(args);
57 | }
58 |
59 |
60 | /**
61 | * 执行参数
62 | * @param args
63 | * @throws Exception
64 | */
65 | private static void executeParameter(String[] args) {
66 | int optSetting = 0;
67 |
68 | for (; optSetting < args.length; optSetting++) {
69 | for (; optSetting < args.length; optSetting++) {
70 | if ("-f".equals(args[optSetting])) {
71 | ConfigPath = args[++optSetting];
72 | } else if ("-h".equals(args[optSetting])) {
73 | NEEDHELP = true;
74 | System.out.println("-f:配置文件");
75 | break;
76 | }
77 | }
78 | }
79 | if (!needhelp) {
80 | Map configMap = readYaml(ConfigPath);
81 | UDID = (String) configMap.get("UDID");
82 | BUNDLEID = (String) configMap.get("BUNDLEID");
83 | TIMING = (String) configMap.get("TIMING");
84 | PORT = (String) configMap.get("PORT");
85 | PROXYPORT = (String) configMap.get("PROXYPORT");
86 | VERBOSE = (String) configMap.get("VERBOSE");
87 | NeedScreenshot = (String) configMap.get("NeedScreenshot");
88 | ScreenshotFolder = (String) configMap.get("ScreenshotFolder");
89 | VERBOSE = (String) configMap.get("VERBOSE");
90 | TRACEPATH = (String) configMap.get("TRACEPATH");
91 | AppiumLogFolder = (String) configMap.get("AppiumLogFolder");
92 | TestCase = (String) configMap.get("TestCase");
93 |
94 | try {
95 | log_info(
96 | "\n" + "测试设备:" + UDID +
97 | "\n" + "测试App:" + BUNDLEID +
98 | "\n" + "Appium端口:" + PORT +
99 | "\n" + "WDA端口:" + PROXYPORT +
100 | "\n" + "是否需要截图:" + NeedScreenshot +
101 | "\n" + "是否需要打印log:" + VERBOSE);
102 | if (VERBOSE.equals(Need)){
103 | initLogger().setLevel(Level.ALL);
104 | }else {
105 | initLogger().setLevel(Level.WARN);
106 | }
107 | org.testng.Assert.assertTrue((!UDID.equals(null)) && (!BUNDLEID.equals(null)));
108 | } catch (Exception e) {
109 | log_info("请确认参数配置,需要帮助请输入 java -jar iosMonkey.jar -h\n"
110 | + "ERROR信息"+ e.toString());
111 | }
112 | try {
113 | new Monkey().run();
114 | } catch (Exception e) {
115 | e.printStackTrace();
116 | }
117 | }
118 | }
119 |
120 |
121 | /**
122 | * 运行monkey主方法
123 | * @throws Exception
124 | */
125 | public void run() throws Exception {
126 | log_info("查询是否有缓存崩溃文件!");
127 | backup();
128 | driverServer = new DriverServer(UDID,Integer.parseInt(PORT),Integer.parseInt(PROXYPORT));
129 | driverServer.killWDAServer();
130 | driverServer.killAppiumServer();
131 | driverServer.startAppiumServer(AppiumLogFolder);
132 | iosDriver = driverServer.baseDriver(BUNDLEID);
133 | Screenshot SC = new Screenshot(UDID,ScreenshotFolder);
134 | log_info("本次设定的运行时长【" + TIMING + "】分钟");
135 | long startTime = System.currentTimeMillis();
136 | Map coordinateMap = calculateCoordinate(iosDriver);
137 |
138 | if (!TestCase.equals("")){
139 | log_info("用例文件地址:" + TestCase);
140 | new CaseEvent(iosDriver).generateCase(TestCase); //生成case
141 | }else {
142 | log_info("未配置测试用例,进行Monkey测试!");
143 | }
144 |
145 | if (NeedScreenshot.equals(Need)) {
146 | File outputPath = new File(Screenshot.ScreenshotFolder);
147 | if (outputPath.exists()){
148 | FileUtils.deleteQuietly(new File(String.valueOf(outputPath)));
149 | log_info(String.format("删除%s",outputPath));
150 | FileUtils.forceMkdir(outputPath);
151 | log_info(String.format("创建%s",outputPath));
152 | }else {
153 | FileUtils.forceMkdir(outputPath);
154 | log_info(String.format("创建%s",outputPath));
155 | }
156 | }
157 |
158 | Timer timer = new Timer();
159 | //延迟0秒,并且每过5s执行一次
160 | timer.schedule(new MonkeyDaemon(UDID,BUNDLEID), 0, loopTime);
161 |
162 | GetPerformance getPerformance= new GetPerformance();
163 | HashMap args = getPerformance.startTrace(iosDriver,TRACEPATH);
164 | try {
165 | while (is_running) {
166 | new MonkeySpecialEvent(iosDriver).closeAlert();
167 | switch (new MathRandom().PercentageRandom()) {
168 | case 0: {
169 | int x = (int) Math.ceil(Math.random() * (width - 1));
170 | int y = (int) Math.ceil(Math.random() * (height - 1));
171 | if (NeedScreenshot.equals(Need)) {
172 | SC.screenshot(ScreentCount,new Double(x).intValue(), new Double(y).intValue());
173 | ScreentCount ++;
174 | }
175 | new MonkeyTapEvent(iosDriver, x, y).injectEvent();
176 | eventcount = eventcount+1;
177 | log_info("---EVENT执行了:"+eventcount+"次---");
178 | break;
179 | }
180 | case 1: {
181 | new MonkeySwipeEvent(iosDriver).injectEvent_scrollDown();
182 | eventcount = eventcount+1;
183 | log_info("---EVENT执行了:"+eventcount+"次---");
184 | break;
185 | }
186 | case 2: {
187 | new MonkeyBackEvent(iosDriver).injectEvent();
188 | eventcount = eventcount+1;
189 | log_info("---EVENT执行了:"+eventcount+"次---");
190 | break;
191 | }
192 | case 3: {
193 | int x = randomSubmitCoordinate(coordinateMap)[0];
194 | int y = randomSubmitCoordinate(coordinateMap)[1];
195 | if (NeedScreenshot.equals(Need)){
196 | SC.screenshot(ScreentCount,x ,y);
197 | ScreentCount ++;
198 | }
199 | new MonkeySubmitEvent(iosDriver, x, y).injectEvent();
200 | eventcount = eventcount+1;
201 | log_info("---EVENT执行了:"+eventcount+"次---");
202 | break;
203 | }
204 | case 4: {
205 | new MonkeyXpathEvent(iosDriver).injectEvent_Text();
206 | eventcount = eventcount+1;
207 | log_info("---EVENT执行了:"+eventcount+"次---");
208 | break;
209 | }
210 | case 5: {
211 | new MonkeyHomeKeyEvent(iosDriver).injectEvent();
212 | eventcount = eventcount+1;
213 | log_info("---EVENT执行了:"+eventcount+"次---");
214 | break;
215 | }
216 | }
217 |
218 | long endTime = System.currentTimeMillis();
219 | if((endTime - startTime) > (Integer.parseInt(TIMING) * 60 * 1000)) {
220 | log_info("已运行" + (endTime - startTime)/60/1000 + "分钟,任务即将结束");
221 |
222 | // 发送邮件
223 | log_info("退出守护线程!");
224 | is_running = false;
225 | timer.cancel();
226 | }else {
227 | Thread.sleep(EventWaitTime);
228 | long runTime = (endTime - startTime) / 1000;
229 | String p = getRunProgress(Integer.parseInt(TIMING) * 60, (int)runTime);
230 | System.out.println(String.format("当前运行进度:%s",p));
231 | }
232 | }
233 | getPerformance.endTrace(iosDriver,args);
234 | }catch (Exception E){
235 | log_info(this.getClass().getName() + "-" + "Run异常:" + E);
236 | }
237 |
238 | if (NeedScreenshot.equals(Need)){
239 | createGif(Screenshot.ScreenshotFolder); //生成gif
240 | }
241 | teardown();
242 | }
243 |
244 |
245 |
246 | public void teardown() throws IOException {
247 | ArrayList crashList = searchCrashPath();
248 | log_info("搜索是否有崩溃日志");
249 | int crashSize = crashList.size();;
250 | if (crashList.size() !=0 ){
251 | String [] strings = (String[]) crashList.toArray(new String[crashSize]);
252 | for (Object str:strings ) {
253 | System.out.println(str);
254 | }
255 | System.out.println(merageCrashResult);
256 | if (mergeFiles(strings,merageCrashResult)){
257 | }else {
258 | log_info("合并crash文件失败!");
259 | }
260 | }else {
261 | log_info("本次运行monkey未发生崩溃!");
262 | }
263 |
264 | }
265 |
266 |
267 | /**
268 | * 计算运行进度,保留一位小数
269 | */
270 | public static String getRunProgress(int totalTime, int currentTime){
271 | try {
272 | float Progress = (float) currentTime / (float)totalTime;
273 | DecimalFormat decimalFormat= new DecimalFormat(".0");
274 | String p= decimalFormat.format(Progress * 100);
275 | return p ;
276 | }catch (Exception e) {
277 | log_info(String.format("计算运行进度异常!%s", e));
278 | return "0";
279 | }
280 | }
281 |
282 |
283 |
284 | /**
285 | * 计算坐标
286 | */
287 | private Map calculateCoordinate(IOSDriver iosDriver) throws Exception {
288 | dimension = iosDriver.manage().window().getSize();
289 | width= dimension.width;
290 | height= dimension.height;
291 |
292 | NumberFormat numberFormat = NumberFormat.getInstance();
293 | numberFormat.setMaximumFractionDigits(2);
294 |
295 | submitX_max = width - 1;
296 | submitX_mim = width / 10;
297 | submitY_max = height - 1;
298 | submitY_mim = height / 10 * 9;
299 | contentX_max = width - width / 10;
300 | contentX_min = width / 10;
301 | contentY_max = height / 2 + height / 10;
302 | contentY_mim = height / 2 - height / 10;
303 | special_point_x = width / 2;
304 | special_point_y = (int) (height * 0.94);
305 |
306 | Map Coordinatemap = new HashMap();
307 | Coordinatemap.put("submitX_max",submitX_max);
308 | Coordinatemap.put("submitX_mim",submitX_mim);
309 | Coordinatemap.put("submitY_max",submitY_max);
310 | Coordinatemap.put("submitY_mim",submitY_mim);
311 | Coordinatemap.put("contentX_max",contentX_max);
312 | Coordinatemap.put("contentX_min",contentX_min);
313 | Coordinatemap.put("contentY_max",contentY_max);
314 | Coordinatemap.put("contentY_mim",contentY_mim);
315 | Coordinatemap.put("special_point_x",special_point_x);
316 | Coordinatemap.put("special_point_y",special_point_y);
317 | return Coordinatemap;
318 | }
319 |
320 | /**
321 | * 计算随机坐标
322 | */
323 | private int[] randomContentCoordinate(Map coordinateMap) throws Exception {
324 | Random random = new Random();
325 | contentX_max = (int) coordinateMap.get("contentX_max");
326 | contentX_min = (int) coordinateMap.get("contentX_min");
327 | contentY_max = (int) coordinateMap.get("contentY_max");
328 | contentY_mim = (int) coordinateMap.get("contentY_mim");
329 | int x = random.nextInt(contentX_max) % (contentX_max - contentX_min + 1) + contentX_min;
330 | int y = random.nextInt(contentY_max) % (contentY_max - contentY_mim + 1) + contentY_mim;
331 | int[] array = {x, y};
332 | return array;
333 | }
334 |
335 |
336 | /**
337 | * 计算随机坐标
338 | */
339 | private int[] randomSubmitCoordinate(Map coordinateMap) throws Exception {
340 | try {
341 | Random random = new Random();
342 | submitX_max = (int) coordinateMap.get("submitX_max");
343 | submitX_mim = (int) coordinateMap.get("submitX_mim");
344 | submitY_max = (int) coordinateMap.get("submitY_max");
345 | submitY_mim = (int) coordinateMap.get("submitY_mim");
346 | int x = random.nextInt(submitX_max) % (submitX_max - submitX_mim + 1) + submitX_mim;
347 | int y = random.nextInt(submitY_max) % (submitY_max - submitY_mim + 1) + submitY_mim;
348 | int[] array = {x, y};
349 | return array;
350 | }catch (Exception E){
351 | log_info(this.getClass().getName() + "-" + "计算随机坐标异常:" + E);
352 | int[] array = {0, 0};
353 | return array;
354 | }
355 | }
356 | }
357 |
--------------------------------------------------------------------------------
/src/main/java/ScreenShots/ModifyPic.java:
--------------------------------------------------------------------------------
1 | package ScreenShots;
2 |
3 | import javax.imageio.ImageIO;
4 | import java.awt.*;
5 | import java.awt.image.BufferedImage;
6 | import java.io.File;
7 | import java.io.IOException;
8 | import static Untils.MyLogger.log_info;
9 |
10 |
11 | public class ModifyPic {
12 | private Font font = new Font("", Font.PLAIN, 20);// 添加字体的属性设置
13 | private Graphics2D g = null;
14 | private int fontsize;
15 | private int x;
16 | private int y;
17 | private String imgSrcPath;
18 | private String imgDesPath;
19 | private String content;
20 | private String fontStyle;
21 | private Color color;
22 |
23 | /**
24 | * 导入本地图片到缓冲区
25 | */
26 | public BufferedImage loadImageLocal(String imgSrcPath) {
27 | try {
28 | this.imgSrcPath = imgSrcPath;
29 | return ImageIO.read(new File(this.imgSrcPath));
30 | } catch (IOException e) {
31 | log_info(e.getMessage());
32 | }
33 | return null;
34 | }
35 |
36 | /**
37 | * 生成新图片到本地
38 | */
39 | public void writeImageLocal(String imgDesPath, BufferedImage img) {
40 | if (imgDesPath != null && img != null) {
41 | try {
42 | this.imgDesPath = imgDesPath;
43 | File outputfile = new File(this.imgDesPath);
44 | ImageIO.write(img, "png", outputfile);
45 | } catch (IOException e) {
46 | log_info(e.getMessage());
47 | }
48 | }
49 | }
50 |
51 | /**
52 | * 设定文字的字体等
53 | */
54 | public void setFont(String fontStyle, int fontSize) {
55 | this.fontsize = fontSize;
56 | this.fontStyle = fontStyle;
57 | this.font = new Font(this.fontStyle, Font.PLAIN, this.fontsize);
58 | }
59 |
60 | /**
61 | * 设定文字在图片中的位置以及文字的颜色
62 | * @param x
63 | * @param y
64 | * @param color
65 | */
66 | public void setLocalColor(int x,int y,Color color){
67 | this.x = x;
68 | this.y = y;
69 | this.color=color;
70 | }
71 |
72 | /**
73 | * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
74 | */
75 | public BufferedImage modifyImage(BufferedImage img, String content) {
76 | try {
77 | int w = img.getWidth();
78 | int h = img.getHeight();
79 | g = img.createGraphics();
80 | //g.setBackground(Color.WHITE);
81 | g.setColor(this.color);
82 | if (this.font != null)
83 | g.setFont(this.font);
84 | // 验证输出位置的纵坐标和横坐标
85 | if (x >= h || y >= w) {
86 | this.x = h - this.fontsize + 2;
87 | this.y = w;
88 | }
89 | this.content=content;
90 | if (content != null) {
91 | g.drawString(this.content, this.x, this.y);
92 | }
93 | g.dispose();
94 | } catch (Exception e) {
95 | log_info(e.getMessage());
96 | }
97 | return img;
98 | }
99 |
100 |
101 | public ModifyPic(String imgSrcPath, String imgDesPath, String content,
102 | String fontStyle, int fontsize, int x, int y,Color color) {
103 | super();
104 | this.fontsize = fontsize;
105 | this.x = x;
106 | this.y = y;
107 | this.imgSrcPath = imgSrcPath;
108 | this.imgDesPath = imgDesPath;
109 | this.content = content;
110 | this.fontStyle = fontStyle;
111 | this.color=color;
112 | setFont(fontStyle, fontsize);
113 | writeImageLocal(imgDesPath, modifyImage(loadImageLocal(imgSrcPath), content));
114 | }
115 |
116 |
117 | public ModifyPic(String fontStyle, int fontsize, int x, int y,Color color) {
118 | super();
119 | this.fontsize = fontsize;
120 | this.x = x;
121 | this.y = y;
122 | this.fontStyle = fontStyle;
123 | this.color=color;
124 | setFont(fontStyle, fontsize);
125 | setLocalColor(x,y,color);
126 | }
127 |
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/java/ScreenShots/Screenshot.java:
--------------------------------------------------------------------------------
1 | package ScreenShots;
2 |
3 | import java.awt.*;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import static Untils.MyLogger.log_info;
7 |
8 |
9 | /**
10 | * @author xinxi
11 | * 截图
12 | */
13 |
14 | public class Screenshot {
15 |
16 | public static String projectPath = System.getProperty("user.dir");
17 | public static String ScreenshotFolder;
18 | public static String screenshotPath1 ;
19 | public static String screenshotPath2 ;
20 | public static String udid;
21 | private static int waitShot = 500;
22 |
23 | public Screenshot(String UDID,String Folder) {
24 | udid = UDID;
25 | ScreenshotFolder = String.format(Folder + "/", udid);
26 | File file = new File(ScreenshotFolder);
27 | if (! file.exists()){
28 | file.mkdir();
29 | log_info("创建保存图片文件夹:" + ScreenshotFolder);
30 | }
31 | }
32 |
33 | public void screenshot(int COUNT, int x, int y) throws InterruptedException {
34 | //File file = new File(projectPath);
35 | //String RootPath = file.getParent();
36 | //log_info("文件的上级目录为 : " + RootPath);
37 | screenshotPath1 = ScreenshotFolder + "iOSMonkey.png";
38 | screenshotPath2 = ScreenshotFolder + String.format("iOSMonkey%s.png",String.format("%03d", COUNT));
39 | String screenshotCmd = String.format("xcrun simctl io booted screenshot %s", screenshotPath1);
40 | log_info("截图命令:" + screenshotCmd);
41 |
42 | if (udid.contains("-")) {
43 | try {
44 | Process pp = Runtime.getRuntime().exec(screenshotCmd);
45 | pp.waitFor();
46 | } catch (IOException e) {
47 | e.printStackTrace();
48 | } catch (InterruptedException e) {
49 | e.printStackTrace();
50 | }
51 | } else {
52 | try {
53 | Runtime.getRuntime().exec("idevicescreenshot -u " + udid + " " + screenshotPath1);
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | }
57 | }
58 | Thread.sleep(waitShot);
59 | File file1 = new File(screenshotPath1);
60 | if (file1.exists() && file1.length() > 0) {
61 | new ModifyPic(screenshotPath1, screenshotPath2, "◯", "STYLE_ITALIC", 50, x, y, Color.RED);
62 | log_info("create ScreenShots : " + screenshotPath2);
63 | file1.delete();
64 | } else if (file1.exists() && file1.length() <= 0) {
65 | file1.delete();
66 | } else {
67 | log_info("截图失败,并没有找到截图文件!");
68 | }
69 |
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/Test.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 | import java.nio.Buffer;
3 | import java.sql.Time;
4 | import java.text.DecimalFormat;
5 |
6 | import static Untils.MyLogger.log_info;
7 |
8 | public class Test {
9 |
10 |
11 | public static void main(String[] args) throws InterruptedException, IOException {
12 |
13 | // while (true){
14 | // new Test().run("DDAC13B0-786D-4DC7-A920-4BEAF56CD616");
15 | // Thread.sleep(1000);
16 | // }
17 |
18 | //System.out.println(getRunProgress(3600,2000));
19 |
20 | long a = System.currentTimeMillis();
21 | System.out.println(a);
22 | Thread.sleep(2000);
23 | long b = System.currentTimeMillis();
24 | System.out.println(b);
25 | System.out.println(b-a);
26 |
27 |
28 |
29 |
30 | }
31 |
32 |
33 |
34 | public void run(String UDID) {
35 | if (UDID.contains("-")){
36 | log_info("模拟器检查app运行状态!");
37 | String runcmd = "xcrun simctl spawn booted log stream --level=debug";
38 | Process pp = null;
39 | try {
40 | pp = Runtime.getRuntime().exec(runcmd);
41 | } catch (IOException e) {
42 | e.printStackTrace();
43 | }
44 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pp.getInputStream()));
45 | String line;
46 | int lineCount = 0;
47 | String runstring = "";
48 | try {
49 | while ((line = bufferedReader.readLine()) != null) {
50 | lineCount++;
51 | if (lineCount < 5) {
52 | runstring += line + "\n";
53 | }else {
54 | break;
55 | }
56 | }
57 | } catch (IOException e) {
58 | e.printStackTrace();
59 | }finally {
60 | System.out.println(runstring);
61 | if (runstring.contains("LuoJiFMIOS")) {
62 | log_info("模拟器app运行中!");
63 | } else {
64 | log_info("模拟器app不在运行中!");
65 | log_info("====非测试APP,重新呼起测试APP====");
66 | //Runtime.getRuntime().exec("xcrun simctl launch booted " + BUNDLEID);
67 | }
68 | }
69 | }else {
70 | log_info("真机检查app运行状态!");
71 | }
72 | }
73 |
74 |
75 |
76 |
77 | /**
78 | * 计算运行进度,保留一位小数
79 | */
80 | public static String getRunProgress(int totalTime, int currentTime){
81 | try {
82 | float Progress = (float) currentTime / (float)totalTime;
83 | DecimalFormat decimalFormat= new DecimalFormat(".0");
84 | String p= decimalFormat.format(Progress * 100);
85 | return p ;
86 | }catch (Exception e) {
87 | log_info(String.format("计算运行进度异常!%s", e));
88 | return "0";
89 | }
90 | }
91 |
92 |
93 |
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/Untils/FileUntils.java:
--------------------------------------------------------------------------------
1 | package Untils;
2 |
3 | import org.yaml.snakeyaml.Yaml;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.text.SimpleDateFormat;
7 | import java.util.Calendar;
8 | import java.util.Date;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.regex.Matcher;
12 | import java.util.regex.Pattern;
13 | import static Untils.MyLogger.log_info;
14 |
15 |
16 | public class FileUntils {
17 |
18 |
19 | public static String timeDate(){
20 | Date now = new Date();
21 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
22 | String timestr = dateFormat.format(now);
23 | return timestr;
24 | }
25 |
26 | /**
27 | * 用当前日期生成唯一序列号
28 | * 格式:年+月+日+小时+分钟
29 | * 20150421113300
30 | * @return
31 | */
32 | public static String currentTime(){
33 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
34 | Calendar cal = Calendar.getInstance();
35 | String times = format.format(cal.getTime()).substring(0,19);
36 | Pattern pattern = Pattern.compile("[^0-9]");
37 | Matcher matcher = pattern.matcher(times);
38 | StringBuffer sbr = new StringBuffer();
39 | while (matcher.find()) {
40 | matcher.appendReplacement(sbr,"");
41 | }
42 | matcher.appendTail(sbr);
43 | //System.out.println(sbr.toString());
44 | return sbr.toString();
45 | }
46 |
47 | public static void sleep(double d) {
48 | try {
49 | d *= 1000;
50 | Thread.sleep((int)d);
51 | } catch (Exception e){}
52 | }
53 |
54 |
55 | /**
56 | * 读Yaml文件
57 | * param YamlName
58 | * return Map类型
59 | */
60 | public static Map readYaml(String yamlpath) {
61 |
62 | Map map = null;
63 | try{
64 | File dumpFile = new File(yamlpath);
65 | Yaml yaml = new Yaml();
66 | map = (Map) yaml.load((new FileInputStream(dumpFile)));
67 | }catch (Exception e){
68 | System.out.println(String.format("读取%s异常! + \n + %s", yamlpath,e));
69 | }
70 | return map;
71 | }
72 |
73 |
74 | /**
75 | * 读Yaml文件
76 | * param YamlName
77 | * return Map类型
78 | */
79 | public static List readYamlList(String yamlpath) {
80 |
81 | List list = null;
82 | try{
83 | File dumpFile = new File(yamlpath);
84 | Yaml yaml = new Yaml();
85 | list = yaml.load((new FileInputStream(dumpFile)));
86 | }catch (Exception e){
87 | System.out.println(String.format("读取%s异常! + \n + %s", yamlpath,e));
88 | }
89 | return list;
90 | }
91 |
92 |
93 | /**
94 | * 生成gif
95 | */
96 | public static void createGif(String folderPath){
97 | try {
98 | String pngPath = folderPath + "iOSMonkey%03d.png";
99 | String gifPath = folderPath + "iOSMonkey.gif";
100 | String cmd = "ffmpeg -f image2 -framerate 1 -i " + pngPath + " -y " + gifPath;
101 | log_info(String.format("合并gif命令:%s", cmd));
102 | Runtime.getRuntime().exec(cmd);
103 | log_info("生成gif地址:" + gifPath );
104 | }catch (Exception E){
105 | log_info("生成gif异常:" + E);
106 | }
107 | }
108 |
109 | public static void main(String[] args) {
110 | Map map = readYaml("./config/config.yaml");
111 | System.out.println(map);
112 | }
113 |
114 |
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/Untils/GetPerformance.java:
--------------------------------------------------------------------------------
1 | package Untils;
2 |
3 | import io.appium.java_client.ios.IOSDriver;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.util.Base64;
9 | import java.util.HashMap;
10 |
11 | /**
12 | * @author xinxi
13 | * 获取iOS性能日志
14 | */
15 |
16 | public class GetPerformance {
17 |
18 |
19 | private File traceZip;
20 |
21 | public HashMap startTrace(IOSDriver iosDriver,String tracePath){
22 | traceZip = new File(tracePath + "/trace.zip");
23 | HashMap args = new HashMap<>();
24 | args.put("timeout", 60000);
25 | args.put("pid", "current");
26 | args.put("profileName", "Time Profiler");
27 | iosDriver.executeScript("mobile: startPerfRecord", args);
28 | return args;
29 | }
30 |
31 |
32 | public void endTrace(IOSDriver iosDriver, HashMap args) throws IOException {
33 | args = new HashMap<>();
34 | args.put("profileName", "Time Profiler");
35 | String b64Zip = (String)iosDriver.executeScript("mobile: stopPerfRecord", args);
36 | byte[] bytesZip = Base64.getMimeDecoder().decode(b64Zip);
37 | FileOutputStream stream = new FileOutputStream(traceZip);
38 | stream.write(bytesZip);
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/Untils/MailConfig.java:
--------------------------------------------------------------------------------
1 | package Untils;
2 |
3 | public class MailConfig {
4 | // 设置服务器,用户名、口令以及邮箱的后缀
5 | protected static String mail_host = "smtp.exmail.qq.com";
6 | protected static String mail_user = "xxxx";
7 | protected static String mail_pwd = "xxxx";
8 | protected static String mail_postfix = "xxxxx";
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/Untils/MyLogger.java:
--------------------------------------------------------------------------------
1 | package Untils;
2 |
3 | import org.apache.log4j.Level;
4 | import org.apache.log4j.Logger;
5 |
6 | public class MyLogger {
7 |
8 | public static Logger logger;
9 |
10 | /**
11 | * 初始化logger
12 | */
13 | public static Logger initLogger(){
14 | logger = Logger.getLogger("iOSMonkey");
15 | return logger;
16 | }
17 |
18 | /**
19 | * info日志
20 | */
21 | public static void log_info(String text){
22 | initLogger().info(text);
23 | }
24 |
25 | /**
26 | * debug日志
27 | */
28 | public static void log_debug(String text){
29 | initLogger().info(text);
30 | }
31 |
32 | public static void main(String[] args) {
33 | initLogger().setLevel(Level.ALL);
34 | initLogger().info("test111");
35 |
36 | }
37 |
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/Untils/SearchCrash.java:
--------------------------------------------------------------------------------
1 | package Untils;
2 |
3 | import org.apache.http.util.TextUtils;
4 | import java.io.*;
5 | import java.nio.channels.FileChannel;
6 | import java.text.SimpleDateFormat;
7 | import java.util.ArrayList;
8 | import java.util.Date;
9 |
10 | import static Untils.MyLogger.log_info;
11 |
12 | /**
13 | * @author xinxi
14 | * 运行完monkey查询崩溃日志
15 | */
16 |
17 |
18 | public class SearchCrash {
19 |
20 | public static String startStr = "xxxxxxxx";
21 | public static String endStr = ".crash";
22 | public static String rootPath;
23 |
24 | static {
25 | try {
26 | rootPath = getRootPath() +"/Library/Logs/DiagnosticReports";
27 | } catch (IOException e) {
28 | e.printStackTrace();
29 | } catch (InterruptedException e) {
30 | e.printStackTrace();
31 | }
32 | }
33 |
34 | public static String backupPath;
35 |
36 | static {
37 | try {
38 | backupPath = getRootPath() + "/Library/Logs/DiagnosticReports/backups";
39 | } catch (IOException e) {
40 | e.printStackTrace();
41 | } catch (InterruptedException e) {
42 | e.printStackTrace();
43 | }
44 | }
45 |
46 | public static String merageCrashResult;
47 |
48 | static {
49 | try {
50 | merageCrashResult = String.format( getRootPath() + "/Library/Logs/DiagnosticReports/ios_crash_%s.log", getCurrentTime());
51 | } catch (IOException e) {
52 | e.printStackTrace();
53 | } catch (InterruptedException e) {
54 | e.printStackTrace();
55 | }
56 | }
57 |
58 | public static void main(String[] args) throws IOException, InterruptedException {
59 | //backup();
60 | // ArrayList arrayList = new ArrayList();
61 | // arrayList.add("/Users/xinxi/Library/Logs/DiagnosticReports/backups/LuoJiFMIOS_2018-11-15-143820_xinxideMacBook-Pro.crash");
62 | // arrayList.add("/Users/xinxi/Library/Logs/DiagnosticReports/backups/LuoJiFMIOS_2018-11-15-143839_xinxideMacBook-Pro.crash");
63 | // int size = arrayList.size();
64 | // String [] strings = (String[]) arrayList.toArray(new String[size]);
65 | // mergeFiles(strings,merageCrashResult);
66 |
67 | System.out.println(getRootPath());
68 |
69 | }
70 |
71 |
72 | /**
73 | * 查询模拟崩溃日志全路径
74 | */
75 | public static ArrayList searchCrashPath() throws IOException {
76 | ArrayList arrayList = new ArrayList();
77 | InputStreamReader stdISR = null;
78 | InputStreamReader errISR = null;
79 | String[] command = { "sh", "-c", "ls " + rootPath };
80 | Process process = null;
81 | try {
82 | process = Runtime.getRuntime().exec(command);
83 | process.waitFor();
84 | String line = null;
85 | stdISR = new InputStreamReader(process.getInputStream());
86 | BufferedReader stdBR = new BufferedReader(stdISR);
87 | while ((line = stdBR.readLine()) != null) {
88 | if (line.startsWith(startStr) && line.endsWith(endStr)){
89 | String fullPath = rootPath + "/" + line;
90 | arrayList.add(fullPath);
91 | }
92 | }
93 | } catch (IOException | InterruptedException e) {
94 | e.printStackTrace();
95 | }
96 | return arrayList;
97 | }
98 |
99 |
100 |
101 | /**
102 | * 查询模拟崩溃日志
103 | */
104 | public static ArrayList searchCrashLogs() throws IOException {
105 | ArrayList arrayList = new ArrayList();
106 | InputStreamReader stdISR = null;
107 | InputStreamReader errISR = null;
108 | String[] command = { "sh", "-c", "ls " + rootPath };
109 | Process process = null;
110 | try {
111 | process = Runtime.getRuntime().exec(command);
112 | process.waitFor();
113 | String line = null;
114 | stdISR = new InputStreamReader(process.getInputStream());
115 | BufferedReader stdBR = new BufferedReader(stdISR);
116 | while ((line = stdBR.readLine()) != null) {
117 | if (line.startsWith(startStr) && line.endsWith(endStr)){
118 | arrayList.add(line);
119 | }
120 | }
121 | } catch (IOException | InterruptedException e) {
122 | e.printStackTrace();
123 | }
124 | return arrayList;
125 | }
126 |
127 |
128 | /**
129 | * 备份崩溃日志
130 | */
131 | public static void backup() throws IOException {
132 | ArrayList arrayList = searchCrashLogs();
133 | Process process = null;
134 | if (arrayList.size() != 0){
135 | for (Object source:arrayList) {
136 | System.out.println(source);
137 | try {
138 | String sourcePath = rootPath + "/" + source;
139 | String destinationPath = backupPath+ "/" + source;
140 | String[] command = { "sh", "-c", String.format("mv %s %s",sourcePath,destinationPath)};
141 | Runtime.getRuntime().exec(command);
142 | log_info(String.format("从%s移动到%s",sourcePath,destinationPath));
143 | } catch (IOException e) {
144 | //moving file failed.
145 | e.printStackTrace();
146 | }
147 | }
148 | log_info("移动崩溃日志完成!");
149 | }else {
150 | log_info("未查询到崩溃日志!");
151 | }
152 | }
153 |
154 |
155 |
156 | /**
157 | * 获取电脑根目录地址
158 | * @throws IOException
159 | * @throws InterruptedException
160 | */
161 | public static String getRootPath() throws IOException, InterruptedException {
162 | InputStreamReader stdISR = null;
163 | InputStreamReader errISR = null;
164 | Process process = null;
165 | String rootName = null;
166 | String[] command = {"sh", "-c", "echo $HOME"};
167 | try {
168 | process = Runtime.getRuntime().exec(command);
169 | process.waitFor();
170 | String line = null;
171 | stdISR = new InputStreamReader(process.getInputStream());
172 | BufferedReader stdBR = new BufferedReader(stdISR);
173 | while ((line = stdBR.readLine()) != null) {
174 | rootName = line;
175 |
176 | }
177 | } catch (IOException | InterruptedException e) {
178 | e.printStackTrace();
179 | }
180 | return rootName;
181 |
182 |
183 |
184 | }
185 |
186 |
187 | /**
188 | * 文件合并
189 | * @param fpaths
190 | * @param resultPath
191 | * @return
192 | */
193 | public static boolean mergeFiles(String[] fpaths, String resultPath) {
194 | if (fpaths == null || fpaths.length < 1 || TextUtils.isEmpty(resultPath)) {
195 | return false;
196 | }
197 | if (fpaths.length == 1) {
198 | return new File(fpaths[0]).renameTo(new File(resultPath));
199 | }
200 | File[] files = new File[fpaths.length];
201 | for (int i = 0; i < fpaths.length; i ++) {
202 | files[i] = new File(fpaths[i]);
203 | if (TextUtils.isEmpty(fpaths[i]) || !files[i].exists() || !files[i].isFile()) {
204 | return false;
205 | }
206 | }
207 | File resultFile = new File(resultPath);
208 | try {
209 | FileChannel resultFileChannel = new FileOutputStream(resultFile, true).getChannel();
210 | for (int i = 0; i < fpaths.length; i ++) {
211 | FileChannel blk = new FileInputStream(files[i]).getChannel();
212 | resultFileChannel.transferFrom(blk, resultFileChannel.size(), blk.size());
213 | blk.close();
214 | }
215 | resultFileChannel.close();
216 | } catch (FileNotFoundException e) {
217 | e.printStackTrace();
218 | return false;
219 | } catch (IOException e) {
220 | e.printStackTrace();
221 | return false;
222 | }
223 | for (int i = 0; i < fpaths.length; i ++) {
224 | files[i].delete();
225 | }
226 | return true;
227 | }
228 |
229 | public static String getCurrentTime(){
230 | SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
231 | String CurrentTime = df.format(new Date());
232 | log_info("当前时间:" + CurrentTime);
233 | return CurrentTime;
234 | }
235 |
236 | }
237 |
--------------------------------------------------------------------------------
/src/main/java/Untils/SendMail.java:
--------------------------------------------------------------------------------
1 | package Untils;
2 |
3 |
4 | import javax.activation.DataHandler;
5 | import javax.activation.DataSource;
6 | import javax.activation.FileDataSource;
7 | import javax.mail.*;
8 | import javax.mail.internet.*;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.io.UnsupportedEncodingException;
12 | import java.text.SimpleDateFormat;
13 | import java.util.*;
14 | import static Untils.MyLogger.log_info;
15 |
16 | /**
17 | * @author xinxi
18 | * 发送测试报告
19 | */
20 |
21 | public class SendMail {
22 | public static Properties properties;
23 | public static String from;
24 | public static String username;
25 | public static String password;
26 | public static String host;
27 | public static Session session;
28 | public static String Subject;
29 | public static String Content = getCurrentTime() + "\n" + String.format("具体%s详见附件!", Subject) +
30 | "\n" + "如附件中文件格式丢失,请手动改成.html格式!";
31 | private static String mailist;
32 | private static String newPathName;
33 | private static String taskOver = "完成";
34 |
35 | public static void main(String [] args) throws IOException, InterruptedException {
36 |
37 |
38 | }
39 |
40 |
41 | /**
42 | * 拼接接收者地址
43 | * @param mailist
44 | * @return
45 | */
46 | public static InternetAddress[] Address(String mailist){
47 | //多个接收账号
48 | InternetAddress[] address=null;
49 | try {
50 | List list = new ArrayList();
51 | //不能使用string类型的类型,这样只能发送一个收件人
52 | String []median=mailist.split(",");
53 | //对输入的多个邮件进行逗号分割
54 | for(int i=0;i