├── .idea
├── misc.xml
├── modules.xml
├── test.iml
└── workspace.xml
├── README.md
├── __pycache__
└── aa.cpython-36.pyc
├── allure_report.png
├── autotestFrame.png
├── framework
├── app
│ ├── __pycache__
│ │ └── appcommon.cpython-36.pyc
│ └── appcommon.py
├── base
│ ├── __pycache__
│ │ ├── appium_init.cpython-36.pyc
│ │ ├── selenium_action.cpython-36.pyc
│ │ └── selenium_init.cpython-36.pyc
│ ├── appium_init.py
│ ├── selenium_action.py
│ └── selenium_init.py
├── driver
│ ├── IEDriverServer.exe
│ ├── IEDriverServer_64.exe
│ ├── chromedriver.exe
│ └── geckodriver.exe
├── utils
│ ├── __pycache__
│ │ └── string_utils.cpython-36.pyc
│ └── string_utils.py
└── web
│ ├── __pycache__
│ └── webcommon.cpython-36.pyc
│ └── webcommon.py
├── requirements.txt
└── script
├── __init__.py
├── __pycache__
├── __init__.cpython-36.pyc
├── test_demo_api.cpython-36-pytest-5.4.1.pyc
├── test_demo_app.cpython-36-pytest-5.4.1.pyc
├── test_demo_h5.cpython-36-pytest-5.4.1.pyc
└── test_demo_web.cpython-36-pytest-5.4.1.pyc
├── report
└── xml
│ ├── 08bb2300-56d7-4510-a64c-f2f384ef4784-result.json
│ ├── 11191ab5-ac1d-4300-bdc4-7ede2330c1b7-attachment.txt
│ ├── 12180a99-1c2e-4d18-a2f5-f1fc9d7917d2-attachment.txt
│ ├── 1809dc95-dc9f-4923-9d34-499d78b156d1-result.json
│ ├── 193a0159-d9c6-4211-b62a-e97fbf5462bf-container.json
│ ├── 224c67c6-b374-43e3-801b-c772c5d6aa98-attachment.txt
│ ├── 2d6d43c4-b20e-4348-9a81-ff5ab4c15150-attachment.txt
│ ├── 383d029b-537b-42de-8a35-04f5db05f2de-result.json
│ ├── 3b271c01-846b-4734-b134-4fe09fbe3c36-container.json
│ ├── 45e1c77f-d981-4af7-953c-ebd0018a382a-attachment.txt
│ ├── 48b71512-7f42-47f3-9145-8f362a685764-result.json
│ ├── 550c69d6-e1fa-43d8-80b3-96dd00b296ee-attachment.txt
│ ├── 6c662ecd-9c65-438f-9e75-2a98e8f30d6d-container.json
│ ├── 733fc1eb-bb59-4416-8e6c-56b4000ac9ba-result.json
│ ├── 82f33b13-6f42-4e97-bdad-ce4257e2ee57-attachment.txt
│ ├── 927c3d0e-b4d5-4f2c-9408-8968464960d3-result.json
│ ├── 94e714c6-1b3b-4a4f-a82f-d942dd136bd4-attachment.txt
│ ├── d38dfa88-1e35-4991-a77e-82ea22f4e0d4-container.json
│ ├── d8dbc44f-7c13-44d7-913b-be44a67a88b1-result.json
│ ├── e6a7fe07-7239-4f9d-99e2-2f4af32ddc23-result.json
│ ├── eef9e64c-7950-4109-ab2c-d6e0f7049a3a-attachment.txt
│ ├── fb2d4685-8bb1-4d6c-8272-addc7c1b36bf-attachment.txt
│ ├── fd3c4538-bcff-4a3b-830a-fabc5e4ab066-attachment.txt
│ └── fd432725-474f-4a3a-b2fa-1f2949e7dc98-attachment.txt
├── test_demo_api.py
├── test_demo_app.py
├── test_demo_h5.py
└── test_demo_web.py
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/test.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/workspace.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 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
140 |
141 |
142 |
143 | C:\Users\Administrator\PycharmProjects\pyTestAutomation
144 | C:\Users\Administrator\PycharmProjects\pyTestAutomation\script\web
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | true
179 | DEFINITION_ORDER
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 | 1588585535209
378 |
379 |
380 | 1588585535209
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **设计思想**
2 |
3 | - 通过requests, BeautifulSoup实现API自动化,保证后端API主要功能及业务流程
4 |
5 | - 通过selenium实现web UI自动化,appium+stf实现android UI自动化,保证前端页面操作功能及业务流程
6 |
7 | - 通过pytest对测试脚本进行管理,allure report 实现报告输出
8 |
9 | - 通过jenkins实现脚本CI,tomcat实现测试报告线上化
10 |
11 | - 使用python作为脚本语言
12 |
13 | **设计框架(autotestFrame.png)**
14 |
15 | 
16 |
17 | **说明**
18 |
19 | - pytest:测试用例管理
20 |
21 | - allure:测试报告
22 |
23 | **代码结构**
24 |
25 | ├─framework 测试框架
26 |
27 | │ ├─base - 自动化测试基础类
28 |
29 | │ ├─web - web端driver管理基础类
30 |
31 | │ ├─driver - web脚本执行基础类
32 |
33 | │ ├─app - app脚本执行基础类
34 |
35 | ├─utils 测试工具类(文件处理等)
36 |
37 | ├─page 测试页面对象类
38 |
39 | ├─script 业务、功能脚本
40 |
41 |
42 | **脚本执行后,通过allure生成测试报告(allure_report.png)**
43 |
44 | 
45 |
46 | **项目部署**
47 | https://blog.csdn.net/jinwu18/article/details/106343588
48 |
--------------------------------------------------------------------------------
/__pycache__/aa.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/__pycache__/aa.cpython-36.pyc
--------------------------------------------------------------------------------
/allure_report.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/allure_report.png
--------------------------------------------------------------------------------
/autotestFrame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/autotestFrame.png
--------------------------------------------------------------------------------
/framework/app/__pycache__/appcommon.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/app/__pycache__/appcommon.cpython-36.pyc
--------------------------------------------------------------------------------
/framework/app/appcommon.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-24
3 | # @Author : 爱吃苹果的鱼
4 |
5 | from appium.webdriver.common.touch_action import TouchAction
6 | from selenium.webdriver.support.ui import WebDriverWait
7 | from selenium.webdriver.support import expected_conditions as EC
8 | import time
9 | from logger import logger
10 |
11 |
12 | class AppCommon:
13 |
14 | def __init__(self, driver):
15 | self.driver = driver
16 |
17 | def toast_chk(self, toast):
18 | try:
19 | WebDriverWait(self.driver, 5).until(lambda x: x.find_element_by_xpath('找到了toast"' + toast + '"'))
20 | logger.info('找到了toast"' + toast + '"')
21 | return True
22 | except:
23 | logger.info('找不到"' + toast + '"')
24 | return False
25 |
26 | def device_x_get(self):
27 | return self.driver.get_window_size()['width']
28 |
29 | def device_y_get(self):
30 | return self.driver.get_window_size()['height']
31 |
32 | def tap_click(self, x, y):
33 | act = TouchAction(self.driver)
34 | act.tap(x=x, y=y).perform()
35 |
36 | def swipe_left(self, swipe_times=1):
37 | logger.info("向左滑动" + str(swipe_times) + "次")
38 | size = self.driver.get_window_size()
39 | width = size["width"]
40 | height = size["height"]
41 | for i in range(0, swipe_times):
42 | self.driver.swipe(width*0.8, height*0.5, width*0.2, height*0.5, duration=800)
43 | # time.sleep(1)
44 |
45 | def swipe_right(self, swipe_times=1):
46 | logger.info("向右滑动" + str(swipe_times) + "次")
47 | size = self.driver.get_window_size()
48 | width = size["width"]
49 | height = size["height"]
50 | for i in range(0, swipe_times):
51 | self.driver.swipe(width*0.2, height*0.5, width*0.8, height*0.5)
52 | time.sleep(1)
53 |
54 | def swipe_up(self, swipe_times=1):
55 | logger.info("向上滑动" + str(swipe_times) + "次")
56 | size = self.driver.get_window_size()
57 | width = size["width"]
58 | height = size["height"]
59 | for i in range(0, swipe_times):
60 | self.driver.swipe(width*0.5, height*0.8, width*0.5, height*0.2)
61 | time.sleep(1)
62 |
63 | def swipe_down(self, swipe_times=1):
64 | logger.info("向下滑动" + str(swipe_times) + "次")
65 | size = self.driver.get_window_size()
66 | width = size["width"]
67 | height = size["height"]
68 | for i in range(0, swipe_times):
69 | self.driver.swipe(width*0.5, height*0.2, width*0.5, height*0.8)
70 | time.sleep(1)
71 |
--------------------------------------------------------------------------------
/framework/base/__pycache__/appium_init.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/base/__pycache__/appium_init.cpython-36.pyc
--------------------------------------------------------------------------------
/framework/base/__pycache__/selenium_action.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/base/__pycache__/selenium_action.cpython-36.pyc
--------------------------------------------------------------------------------
/framework/base/__pycache__/selenium_init.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/base/__pycache__/selenium_init.cpython-36.pyc
--------------------------------------------------------------------------------
/framework/base/appium_init.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | from appium import webdriver
6 |
7 |
8 | class AppiumInit:
9 |
10 | def __init__(self, platformVersion, platformName, deviceName, appPackage, appActivity, appiumPort):
11 | self.platformVersion = platformVersion
12 | self.platformName = platformName
13 | self.deviceName = deviceName
14 | self.appPackage = appPackage
15 | self.appActivity = appActivity
16 | self.appiumPort = appiumPort
17 |
18 | def setup(self):
19 | capabilities = {"platformVersion": self.platformVersion,
20 | "platformName": self.platformName,
21 | "deviceName": self.deviceName,
22 | "appPackage": self.appPackage,
23 | "appActivity": self.appActivity,
24 | "autoLaunch": True,
25 | "autoGrantPermissions": True,
26 | "newCommandTimeout": 120,
27 | "deviceReadyTimeout": 120,
28 | "noReset": True,
29 | }
30 | return webdriver.Remote("http://127.0.0.1:" + self.appiumPort + "/wd/hub", capabilities)
31 |
--------------------------------------------------------------------------------
/framework/base/selenium_action.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | import time
6 | from logger import logger
7 | from selenium.webdriver.support.ui import WebDriverWait
8 | from selenium.webdriver.support import expected_conditions as ec
9 | from selenium.webdriver.common.keys import Keys
10 |
11 |
12 | class SeleniumActionAPI:
13 | def __init__(self, driver):
14 | self.driver = driver
15 |
16 | def to_url(self, url):
17 | self.driver.get(url)
18 |
19 | def iframe_switch_to_default(self):
20 | self.driver.driver.switch_to.default_content()
21 |
22 | def iframe_switch(self, iframe_id_or_name):
23 | self.driver.switch_to.frame(iframe_id_or_name)
24 |
25 | def ele_list_get_by_id(self, ele_id):
26 | return self.driver.find_elements_by_id(ele_id)
27 |
28 | def ele_list_get_by_name(self, name):
29 | return self.driver.find_elements_by_name(name)
30 |
31 | def ele_list_get_by_xpath(self, xpath):
32 | return self.driver.find_elements_by_xpath(xpath)
33 |
34 | def ele_list_get_by_css_selector(self, css_selector):
35 | return self.driver.find_elements_by_css_selector(css_selector)
36 |
37 | def ele_list_get_by_class_name(self, class_name):
38 | return self.driver.find_elements_by_class_name(class_name)
39 |
40 | def ele_list_get_by_link_text(self, link_text):
41 | return self.driver.find_elements_by_link_text(link_text)
42 |
43 | def ele_list_get_by_partial_link_text(self, partial_link_text):
44 | return self.driver.find_elements_by_partial_link_text(partial_link_text)
45 |
46 | def ele_list_get_by_accessibility_id(self, accessibility_id):
47 | return self.driver.find_elements_by_accessibility_id(accessibility_id)
48 |
49 | def ele_list_get_by__android_uiautomator(self, uia_string):
50 | return self.driver.find_elements_by_android_uiautomator(uia_string)
51 |
52 | def ele_list_get_by_andriod_viewtag(self, viewtag):
53 | return self.driver.find_elements_by_android_viewtag(viewtag)
54 |
55 | def ele_list_get_by_custom(self, selector):
56 | return self.driver.find_elements_by_custom(selector)
57 |
58 | def ele_list_get_by_tag_name(self, tag_name):
59 | return self.driver.find_elements_by_tag_name(tag_name)
60 |
61 | def ele_display_chk(self, locator):
62 | WebDriverWait(self.driver, 5, 0.5).until(ec.presence_of_element_located(locator))
63 |
64 | def ele_get_by_id(self, ele_id):
65 | return self.driver.find_element_by_id(ele_id)
66 |
67 | def ele_get_by_name(self, name):
68 | return self.driver.find_element_by_name(name)
69 |
70 | def ele_get_by_xpath(self, xpath):
71 | return self.driver.find_element_by_xpath(xpath)
72 |
73 | def ele_get_by_css_selector(self, css_selector):
74 | return self.driver.find_element_by_css_selector(css_selector)
75 |
76 | def ele_get_by_class_name(self, class_name):
77 | return self.driver.find_element_by_class_name(class_name)
78 |
79 | def ele_get_by_link_text(self, link_text):
80 | return self.driver.find_element_by_link_text(link_text)
81 |
82 | def ele_get_by_partial_link_text(self, partial_link_text):
83 | return self.driver.find_element_by_partial_link_text(partial_link_text)
84 |
85 | def ele_get_by_accessibility_id(self, accessibility_id):
86 | return self.driver.find_element_by_accessibility_id(accessibility_id)
87 |
88 | def ele_get_by__android_uiautomator(self, uia_string):
89 | return self.driver.find_element_by_android_uiautomator(uia_string)
90 |
91 | def ele_get_by_andriod_viewtag(self, viewtag):
92 | return self.driver.find_element_by_android_viewtag(viewtag)
93 |
94 | def ele_get_by_custom(self, selector):
95 | return self.driver.find_element_by_custom(selector)
96 |
97 | def ele_get_by_tag_name(self, tag_name):
98 | return self.driver.find_element_by_tag_name(tag_name)
99 |
100 | def ele_click_by_id(self, ele_id):
101 | ele_text = self.driver.find_element_by_id(ele_id).text
102 | self.driver.find_element_by_id(ele_id).click()
103 | logger.info("点击'" + ele_text + "'")
104 |
105 | def ele_click_by_name(self, name):
106 | ele_text = self.driver.find_element_by_name(name).text
107 | self.driver.find_element_by_name(name).click()
108 | logger.info("点击'" + ele_text + "'")
109 |
110 | def ele_click_by_xpath(self, xpath):
111 | ele_text = self.driver.find_element_by_xpath(xpath).text
112 | self.driver.find_element_by_xpath(xpath).click()
113 | logger.info("点击'" + ele_text + "'")
114 |
115 | def ele_click_by_css_selector(self, css_selector):
116 | ele_text = self.driver.find_element_by_css_selector(css_selector).text
117 | self.driver.find_element_by_css_selector(css_selector).click()
118 | logger.info("点击'" + ele_text + "'")
119 |
120 | def ele_click_by_class_name(self, class_name):
121 | ele_text = self.driver.find_element_by_class_name(class_name).text
122 | self.driver.find_element_by_class_name(class_name).click()
123 | logger.info("点击'" + ele_text + "'")
124 |
125 | def ele_click_by_link_text(self, link_text):
126 | ele_text = self.driver.find_element_by_link_text(link_text).text
127 | self.driver.find_element_by_link_text(link_text).click()
128 | logger.info("点击'" + ele_text + "'")
129 |
130 | def ele_click_by_partial_link_text(self, partial_link_text):
131 | ele_text = self.driver.find_element_by_partial_link_text(partial_link_text).text
132 | self.driver.find_element_by_partial_link_text(partial_link_text).click()
133 | logger.info("点击'" + ele_text + "'")
134 |
135 | def ele_click_by_accessibility_id(self, accessibility_id):
136 | ele_text = self.driver.find_element_by_accessibility_id(accessibility_id).text
137 | self.driver.find_element_by_accessibility_id(accessibility_id).click()
138 | logger.info("点击'" + ele_text + "'")
139 |
140 | def ele_click_by__android_uiautomator(self, uia_string):
141 | ele_text = self.driver.find_element_by_android_uiautomator(uia_string).text
142 | self.driver.find_element_by_android_uiautomator(uia_string).click()
143 | logger.info("点击'" + ele_text + "'")
144 |
145 | def ele_click_by_andriod_viewtag(self, viewtag):
146 | ele_text = self.driver.find_element_by_android_viewtag(viewtag).text
147 | self.driver.find_element_by_android_viewtag(viewtag).click()
148 | logger.info("点击'" + ele_text + "'")
149 |
150 | def ele_click_by_custom(self, selector):
151 | ele_text = self.driver.find_element_by_custom(selector).text
152 | self.driver.find_element_by_custom(selector).click()
153 | logger.info("点击'" + ele_text + "'")
154 |
155 | def ele_click_by_tag_name(self, tag_name):
156 | ele_text = self.driver.find_elements_by_tag_name(tag_name).text
157 | self.driver.find_elements_by_tag_name(tag_name).click()
158 | logger.info("点击'" + ele_text + "'")
159 |
160 | def alert_text_get(self):
161 | logger.info("Alert text='" + self.driver.switch_to_alert().text + "'")
162 | return self.driver.switch_to_alert().text
163 |
164 | def alert_accept(self):
165 | logger.info("Accept alert")
166 | self.driver.switch_to_alert().accept()
167 |
168 | def alert_dismiss(self):
169 | logger.info("Dismiss alert")
170 | self.driver.switch_to_alert().dismiss()
171 |
172 | @staticmethod
173 | def ele_press_enter(ele):
174 | logger.info("点击回车按钮")
175 | ele.send_keys(Keys.ENTER)
176 |
177 | @staticmethod
178 | def ele_send_keys(ele, text):
179 | logger.info("文本框传值'" + text + "'")
180 | ele.send_keys(text)
181 |
182 | @staticmethod
183 | def ele_clear(ele):
184 | logger.info("清空文本框")
185 | ele.clear()
186 |
--------------------------------------------------------------------------------
/framework/base/selenium_init.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | from selenium import webdriver
6 | import sys, os
7 |
8 |
9 | class SeleniumInit:
10 | driver_path = 'C:/Users/Administrator/PycharmProjects/pyTestAutomation/framework/driver/chromedriver.exe'
11 |
12 | def setup(self, browser_type='web'):
13 | if browser_type == 'web':
14 | return webdriver.Chrome(executable_path=self.driver_path)
15 | elif browser_type == 'h5':
16 | emulation = {'deviceName': 'iPhone 5'}
17 | options = webdriver.ChromeOptions()
18 | options.add_experimental_option('mobileEmulation', emulation)
19 | return webdriver.Chrome(executable_path=self.driver_path, options=options)
20 | elif browser_type == 'headless':
21 | chrome_options = webdriver.ChromeOptions()
22 | chrome_options.add_argument('--headless')
23 | return webdriver.Chrome(executable_path=self.driver_path, options=chrome_options)
24 | else:
25 | return '类型不是web/h5,请确认参数是否有误'
26 |
--------------------------------------------------------------------------------
/framework/driver/IEDriverServer.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/driver/IEDriverServer.exe
--------------------------------------------------------------------------------
/framework/driver/IEDriverServer_64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/driver/IEDriverServer_64.exe
--------------------------------------------------------------------------------
/framework/driver/chromedriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/driver/chromedriver.exe
--------------------------------------------------------------------------------
/framework/driver/geckodriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/driver/geckodriver.exe
--------------------------------------------------------------------------------
/framework/utils/__pycache__/string_utils.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/utils/__pycache__/string_utils.cpython-36.pyc
--------------------------------------------------------------------------------
/framework/utils/string_utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | import random
6 |
7 |
8 | class StringUtils:
9 |
10 | @staticmethod
11 | def name_get():
12 | fst = '赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜' # 姓
13 | name = '永祥荣玉明树近伯晓正福佩中泽润智礼振岐跃良啸志英林江山春秋夏冬国凤龙呈' \
14 | '风雷发强刚贵才亮阳宝唐杰海磊蕾风岩炎申珏超宇岳枫锋田光克文永祥荣玉明树近' \
15 | '伯晓正福佩中泽润智礼振岐跃良啸志英' #名字
16 | if random.randint(0, 1) == 0: # 随机生成2个字在名字/单个字在名字
17 | return random.choice(fst) + random.choice(name)
18 | else:
19 | return random.choice(fst) + random.choice(name) + random.choice(name) # 拼接返回
20 |
21 | @staticmethod
22 | def phone_get():
23 | second = [3, 4, 5, 7, 8][random.randint(0, 4)] # 第二位数字
24 | third = {
25 | 3: random.randint(0, 9),
26 | 4: [5, 7, 9][random.randint(0, 2)],
27 | 5: [i for i in range(10) if i != 4][random.randint(0, 8)],
28 | 7: [i for i in range(10) if i not in [4, 9]][random.randint(0, 7)],
29 | 8: random.randint(0, 9),
30 | }[second] # 第三位数字
31 | suffix = random.randint(9999999, 100000000) # 最后八位数字
32 | return "1{}{}{}".format(second, third, suffix) # 拼接返回
33 |
--------------------------------------------------------------------------------
/framework/web/__pycache__/webcommon.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/web/__pycache__/webcommon.cpython-36.pyc
--------------------------------------------------------------------------------
/framework/web/webcommon.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/framework/web/webcommon.py
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | selenium==3.141.0
2 | pytest==5.4.1
3 | allure_python_commons==2.8.15
4 | logger==1.4
5 | Appium_Python_Client==1.0.1
6 | beautifulsoup4==4.9.1
7 |
--------------------------------------------------------------------------------
/script/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | import os
6 | import sys
7 |
8 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 表示上一级目录
9 | sys.path.insert(0, BASE_DIR+"/framework/base")
10 | sys.path.insert(1, BASE_DIR+"/framework/api")
11 | sys.path.insert(2, BASE_DIR+"/framework/app")
12 | sys.path.insert(4, BASE_DIR+"/framework/driver")
13 | sys.path.insert(5, BASE_DIR+"/framework/web")
14 | sys.path.insert(6, BASE_DIR+"/framework/utils")
15 |
--------------------------------------------------------------------------------
/script/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/script/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/script/__pycache__/test_demo_api.cpython-36-pytest-5.4.1.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/script/__pycache__/test_demo_api.cpython-36-pytest-5.4.1.pyc
--------------------------------------------------------------------------------
/script/__pycache__/test_demo_app.cpython-36-pytest-5.4.1.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/script/__pycache__/test_demo_app.cpython-36-pytest-5.4.1.pyc
--------------------------------------------------------------------------------
/script/__pycache__/test_demo_h5.cpython-36-pytest-5.4.1.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/script/__pycache__/test_demo_h5.cpython-36-pytest-5.4.1.pyc
--------------------------------------------------------------------------------
/script/__pycache__/test_demo_web.cpython-36-pytest-5.4.1.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinwu18/web-app-h5-api-pyTestAutomation/88742b0023fb1cf58c0d6f254e2b5a6060dde51c/script/__pycache__/test_demo_web.cpython-36-pytest-5.4.1.pyc
--------------------------------------------------------------------------------
/script/report/xml/08bb2300-56d7-4510-a64c-f2f384ef4784-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_h5_demo", "status": "passed", "attachments": [{"name": "log", "source": "45e1c77f-d981-4af7-953c-ebd0018a382a-attachment.txt", "type": "text/plain"}, {"name": "stdout", "source": "fb2d4685-8bb1-4d6c-8272-addc7c1b36bf-attachment.txt", "type": "text/plain"}], "start": 1590248927277, "stop": 1590248935353, "uuid": "0a13495f-e95d-413e-baf2-8880a8151526", "historyId": "ee433606d4a1197d1d16a80502656b09", "testCaseId": "129d1b0ced1ceec61c19f952f5004d3a", "fullName": "test_demo_h5.TestH5Demo#test_h5_demo", "labels": [{"name": "story", "value": "test_story_of_h5_demo"}, {"name": "feature", "value": "feature_h5_demo"}, {"name": "suite", "value": "test_demo_h5"}, {"name": "subSuite", "value": "TestH5Demo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "17960-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_h5"}]}
--------------------------------------------------------------------------------
/script/report/xml/11191ab5-ac1d-4300-bdc4-7ede2330c1b7-attachment.txt:
--------------------------------------------------------------------------------
1 | [32mINFO [0m root:selenium_action.py:179 文本框传值'selenium'
2 | [32mINFO [0m root:selenium_action.py:103 点击''
--------------------------------------------------------------------------------
/script/report/xml/12180a99-1c2e-4d18-a2f5-f1fc9d7917d2-attachment.txt:
--------------------------------------------------------------------------------
1 | [32mINFO [0m root:selenium_action.py:179 文本框传值'selenium'
2 | [32mINFO [0m root:selenium_action.py:103 点击''
--------------------------------------------------------------------------------
/script/report/xml/1809dc95-dc9f-4923-9d34-499d78b156d1-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_app_demo", "status": "failed", "statusDetails": {"message": "AssertionError: assert False", "trace": "self = \n\n @allure.story('test_story_of_app_demo')\n def test_app_demo(self):\n result = False\n> assert result\nE assert False\n\ntest_demo_app.py:19: AssertionError"}, "start": 1590248925922, "stop": 1590248925923, "uuid": "7305e0a7-a382-4441-833b-fca7d9ba8c38", "historyId": "1aa923a3228d4d4bd0e3330dc8a53e5a", "testCaseId": "9a1359f6c2e272da6e5c3f524a83e841", "fullName": "test_demo_app.TestAppDemo#test_app_demo", "labels": [{"name": "story", "value": "test_story_of_app_demo"}, {"name": "feature", "value": "feature_app_demo"}, {"name": "suite", "value": "test_demo_app"}, {"name": "subSuite", "value": "TestAppDemo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "17960-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_app"}]}
--------------------------------------------------------------------------------
/script/report/xml/193a0159-d9c6-4211-b62a-e97fbf5462bf-container.json:
--------------------------------------------------------------------------------
1 | {"uuid": "c130815f-edcb-4b93-8bcd-786cb680f0fc", "children": ["467e039e-eb4f-4f6d-b07e-511dcd51d2bd"], "befores": [{"name": "setup", "status": "passed", "start": 1590414385091, "stop": 1590414391085}], "start": 1590414385091, "stop": 1590414494009}
--------------------------------------------------------------------------------
/script/report/xml/224c67c6-b374-43e3-801b-c772c5d6aa98-attachment.txt:
--------------------------------------------------------------------------------
1 | [25/May/2020 21:48:07] INFO - 文本框传值'selenium'
2 | [25/May/2020 21:48:07] INFO - 点击''
3 |
--------------------------------------------------------------------------------
/script/report/xml/2d6d43c4-b20e-4348-9a81-ff5ab4c15150-attachment.txt:
--------------------------------------------------------------------------------
1 | [32mINFO [0m root:selenium_action.py:179 文本框传值'selenium'
2 | [32mINFO [0m root:selenium_action.py:174 点击回车按钮
--------------------------------------------------------------------------------
/script/report/xml/383d029b-537b-42de-8a35-04f5db05f2de-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_web_demo", "status": "passed", "attachments": [{"name": "log", "source": "12180a99-1c2e-4d18-a2f5-f1fc9d7917d2-attachment.txt", "type": "text/plain"}, {"name": "stdout", "source": "eef9e64c-7950-4109-ab2c-d6e0f7049a3a-attachment.txt", "type": "text/plain"}], "start": 1590414553917, "stop": 1590414559181, "uuid": "556c1a33-6ed5-46d1-bf68-d1876c118c41", "historyId": "efd368a57b32c86d7b1e1a28fdffebf9", "testCaseId": "967c6246631340560f91070705b83592", "fullName": "test_demo_web.TestDemo#test_web_demo", "labels": [{"name": "feature", "value": "feature_web_demo"}, {"name": "story", "value": "test_story_of_web_demo"}, {"name": "tag", "value": "web"}, {"name": "suite", "value": "test_demo_web"}, {"name": "subSuite", "value": "TestDemo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "41648-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_web"}]}
--------------------------------------------------------------------------------
/script/report/xml/3b271c01-846b-4734-b134-4fe09fbe3c36-container.json:
--------------------------------------------------------------------------------
1 | {"uuid": "822017a3-cd8e-4882-a362-a87293f2a620", "children": ["4db0d029-26d9-49b2-99fd-7dc679d44db5"], "befores": [{"name": "setup", "status": "passed", "start": 1590414525686, "stop": 1590414532470}], "start": 1590414525686, "stop": 1590414548643}
--------------------------------------------------------------------------------
/script/report/xml/45e1c77f-d981-4af7-953c-ebd0018a382a-attachment.txt:
--------------------------------------------------------------------------------
1 | [32mINFO [0m root:selenium_action.py:179 文本框传值'selenium'
2 | [32mINFO [0m root:selenium_action.py:174 点击回车按钮
--------------------------------------------------------------------------------
/script/report/xml/48b71512-7f42-47f3-9145-8f362a685764-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_h5_demo", "status": "passed", "attachments": [{"name": "log", "source": "2d6d43c4-b20e-4348-9a81-ff5ab4c15150-attachment.txt", "type": "text/plain"}, {"name": "stdout", "source": "82f33b13-6f42-4e97-bdad-ce4257e2ee57-attachment.txt", "type": "text/plain"}], "start": 1590414532471, "stop": 1590414545563, "uuid": "4db0d029-26d9-49b2-99fd-7dc679d44db5", "historyId": "ee433606d4a1197d1d16a80502656b09", "testCaseId": "129d1b0ced1ceec61c19f952f5004d3a", "fullName": "test_demo_h5.TestH5Demo#test_h5_demo", "labels": [{"name": "feature", "value": "feature_h5_demo"}, {"name": "story", "value": "test_story_of_h5_demo"}, {"name": "tag", "value": "h5"}, {"name": "suite", "value": "test_demo_h5"}, {"name": "subSuite", "value": "TestH5Demo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "41648-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_h5"}]}
--------------------------------------------------------------------------------
/script/report/xml/550c69d6-e1fa-43d8-80b3-96dd00b296ee-attachment.txt:
--------------------------------------------------------------------------------
1 | [32mINFO [0m root:selenium_action.py:179 文本框传值'selenium'
2 | [32mINFO [0m root:selenium_action.py:103 点击''
--------------------------------------------------------------------------------
/script/report/xml/6c662ecd-9c65-438f-9e75-2a98e8f30d6d-container.json:
--------------------------------------------------------------------------------
1 | {"uuid": "73121bde-6ed6-4989-9663-0bd6920d69fb", "children": ["6c9e7f9f-61dd-45db-9277-02385cd2262e"], "befores": [{"name": "setup", "status": "passed", "start": 1590414494035, "stop": 1590414513673}], "start": 1590414494035, "stop": 1590414525674}
--------------------------------------------------------------------------------
/script/report/xml/733fc1eb-bb59-4416-8e6c-56b4000ac9ba-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_app_demo", "status": "failed", "statusDetails": {"message": "AssertionError: assert False", "trace": "self = , setup = None\n\n @pytest.mark.app\n @allure.story('test_story_of_app_demo')\n def test_app_demo(self, setup):\n self.app.tap_click(int(959*self.app.device_x_get()/1080), int(1670*self.app.device_y_get()/1794))\n # time.sleep(5)\n # self.appium.ele_click_by_id('com.android.contacts:id/left_button')\n time.sleep(2)\n edit_boxes = self.appium.ele_list_get_by_class_name(\"android.widget.EditText\")\n self.appium.ele_send_keys(edit_boxes[0], self.util.name_get())\n self.appium.ele_send_keys(edit_boxes[1], self.util.phone_get())\n self.appium.ele_click_by_id('menu_save')\n result = self.app.toast_chk('联系人已保存')\n> assert result\nE assert False\n\ntest_demo_app.py:38: AssertionError"}, "attachments": [{"name": "log", "source": "fd3c4538-bcff-4a3b-830a-fabc5e4ab066-attachment.txt", "type": "text/plain"}, {"name": "stdout", "source": "94e714c6-1b3b-4a4f-a82f-d942dd136bd4-attachment.txt", "type": "text/plain"}], "start": 1590414513674, "stop": 1590414524867, "uuid": "6c9e7f9f-61dd-45db-9277-02385cd2262e", "historyId": "1aa923a3228d4d4bd0e3330dc8a53e5a", "testCaseId": "9a1359f6c2e272da6e5c3f524a83e841", "fullName": "test_demo_app.TestAppDemo#test_app_demo", "labels": [{"name": "story", "value": "test_story_of_app_demo"}, {"name": "feature", "value": "feature_app_demo"}, {"name": "tag", "value": "app"}, {"name": "suite", "value": "test_demo_app"}, {"name": "subSuite", "value": "TestAppDemo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "41648-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_app"}]}
--------------------------------------------------------------------------------
/script/report/xml/82f33b13-6f42-4e97-bdad-ce4257e2ee57-attachment.txt:
--------------------------------------------------------------------------------
1 | [25/May/2020 21:49:00] INFO - 文本框传值'selenium'
2 | [25/May/2020 21:49:00] INFO - 点击回车按钮
3 |
--------------------------------------------------------------------------------
/script/report/xml/927c3d0e-b4d5-4f2c-9408-8968464960d3-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_api_demo", "status": "failed", "statusDetails": {"message": "AssertionError: assert False", "trace": "self = , setup = None\n\n @pytest.mark.api\n @allure.story('test_story_of_api_demo')\n def test_api_demo(self, setup):\n self.webAct.to_url(\"http://www.baidu.com\") # 打开百度网页(无头模式)\n self.webAct.ele_send_keys(self.webAct.ele_get_by_id('kw'), 'selenium') # 搜索框输入'selenium'\n self.webAct.ele_click_by_id('su') # 百度一下\n time.sleep(3)\n bs = BeautifulSoup(self.driver.page_source, 'html.parser')\n result = False\n for item in bs.select(\"div[class = 'result c-container']\"):\n if 'selenium' in str(item.h3.a.get_text()).lower():\n result = True\n else:\n print(str(item.h3.a.get_text()).lower() + ':不包含selenium')\n result = False\n> assert result\nE assert False\n\ntest_demo_api.py:37: AssertionError"}, "attachments": [{"name": "log", "source": "550c69d6-e1fa-43d8-80b3-96dd00b296ee-attachment.txt", "type": "text/plain"}, {"name": "stdout", "source": "224c67c6-b374-43e3-801b-c772c5d6aa98-attachment.txt", "type": "text/plain"}], "start": 1590414391132, "stop": 1590414490857, "uuid": "467e039e-eb4f-4f6d-b07e-511dcd51d2bd", "historyId": "babf81610a1ee70c813a18818952ff06", "testCaseId": "e7cc79faeabba21c017566f2089e909b", "fullName": "test_demo_api.TestApiDemo#test_api_demo", "labels": [{"name": "story", "value": "test_story_of_api_demo"}, {"name": "feature", "value": "feature_api_demo"}, {"name": "tag", "value": "api"}, {"name": "suite", "value": "test_demo_api"}, {"name": "subSuite", "value": "TestApiDemo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "41648-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_api"}]}
--------------------------------------------------------------------------------
/script/report/xml/94e714c6-1b3b-4a4f-a82f-d942dd136bd4-attachment.txt:
--------------------------------------------------------------------------------
1 | [25/May/2020 21:48:36] INFO - 文本框传值'吕岩'
2 | [25/May/2020 21:48:37] INFO - 文本框传值'18334485634'
3 | [25/May/2020 21:48:39] INFO - 点击''
4 | [25/May/2020 21:48:44] INFO - 找不到"联系人已保存"
5 |
--------------------------------------------------------------------------------
/script/report/xml/d38dfa88-1e35-4991-a77e-82ea22f4e0d4-container.json:
--------------------------------------------------------------------------------
1 | {"uuid": "cf89a226-b31c-4df3-8152-c677d884195d", "children": ["556c1a33-6ed5-46d1-bf68-d1876c118c41"], "befores": [{"name": "setup", "status": "passed", "start": 1590414548654, "stop": 1590414553916}], "start": 1590414548654, "stop": 1590414562263}
--------------------------------------------------------------------------------
/script/report/xml/d8dbc44f-7c13-44d7-913b-be44a67a88b1-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_web_demo", "status": "passed", "attachments": [{"name": "log", "source": "11191ab5-ac1d-4300-bdc4-7ede2330c1b7-attachment.txt", "type": "text/plain"}, {"name": "stdout", "source": "fd432725-474f-4a3a-b2fa-1f2949e7dc98-attachment.txt", "type": "text/plain"}], "start": 1590248938423, "stop": 1590248942905, "uuid": "72a169db-e29a-4f0e-819d-c0a595507fba", "historyId": "efd368a57b32c86d7b1e1a28fdffebf9", "testCaseId": "967c6246631340560f91070705b83592", "fullName": "test_demo_web.TestDemo#test_web_demo", "labels": [{"name": "feature", "value": "feature_web_demo"}, {"name": "story", "value": "test_story_of_web_demo"}, {"name": "suite", "value": "test_demo_web"}, {"name": "subSuite", "value": "TestDemo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "17960-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "test_demo_web"}]}
--------------------------------------------------------------------------------
/script/report/xml/e6a7fe07-7239-4f9d-99e2-2f4af32ddc23-result.json:
--------------------------------------------------------------------------------
1 | {"name": "test_web_demo", "status": "broken", "statusDetails": {"message": "selenium.common.exceptions.WebDriverException: Message: 'chromedriver.exe' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home", "trace": "self = \n\n def start(self):\n \"\"\"\n Starts the Service.\n \n :Exceptions:\n - WebDriverException : Raised either when it can't start the service\n or when it can't connect to the service\n \"\"\"\n try:\n cmd = [self.path]\n cmd.extend(self.command_line_args())\n self.process = subprocess.Popen(cmd, env=self.env,\n close_fds=platform.system() != 'Windows',\n stdout=self.log_file,\n stderr=self.log_file,\n> stdin=PIPE)\n\nd:\\python\\python3\\lib\\site-packages\\selenium\\webdriver\\common\\service.py:76: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = \nargs = ['C:\\\\Users\\\\Administrator\\\\PycharmProjects\\\\pyTestAutomation\\\\chromedriver.exe', '--port=61984']\nbufsize = -1, executable = None, stdin = -1, stdout = -3, stderr = -3\npreexec_fn = None, close_fds = False, shell = False, cwd = None\nenv = environ({'ALLUSERSPROFILE': 'C:\\\\ProgramData', 'ANDROID_HOME': 'D:\\\\Android\\\\android-sdk', 'APPDATA': 'C:\\\\Users\\\\Admi...ble-features=NetworkServiceInProcess', 'PYTEST_CURRENT_TEST': 'web/test_demo_web.py::TestDemo::test_web_demo (setup)'})\nuniversal_newlines = False, startupinfo = None, creationflags = 0\nrestore_signals = True, start_new_session = False, pass_fds = ()\n\n def __init__(self, args, bufsize=-1, executable=None,\n stdin=None, stdout=None, stderr=None,\n preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,\n shell=False, cwd=None, env=None, universal_newlines=False,\n startupinfo=None, creationflags=0,\n restore_signals=True, start_new_session=False,\n pass_fds=(), *, encoding=None, errors=None):\n \"\"\"Create new Popen instance.\"\"\"\n _cleanup()\n # Held while anything is calling waitpid before returncode has been\n # updated to prevent clobbering returncode if wait() or poll() are\n # called from multiple threads at once. After acquiring the lock,\n # code must re-check self.returncode to see if another thread just\n # finished a waitpid() call.\n self._waitpid_lock = threading.Lock()\n \n self._input = None\n self._communication_started = False\n if bufsize is None:\n bufsize = -1 # Restore default\n if not isinstance(bufsize, int):\n raise TypeError(\"bufsize must be an integer\")\n \n if _mswindows:\n if preexec_fn is not None:\n raise ValueError(\"preexec_fn is not supported on Windows \"\n \"platforms\")\n any_stdio_set = (stdin is not None or stdout is not None or\n stderr is not None)\n if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:\n if any_stdio_set:\n close_fds = False\n else:\n close_fds = True\n elif close_fds and any_stdio_set:\n raise ValueError(\n \"close_fds is not supported on Windows platforms\"\n \" if you redirect stdin/stdout/stderr\")\n else:\n # POSIX\n if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:\n close_fds = True\n if pass_fds and not close_fds:\n warnings.warn(\"pass_fds overriding close_fds.\", RuntimeWarning)\n close_fds = True\n if startupinfo is not None:\n raise ValueError(\"startupinfo is only supported on Windows \"\n \"platforms\")\n if creationflags != 0:\n raise ValueError(\"creationflags is only supported on Windows \"\n \"platforms\")\n \n self.args = args\n self.stdin = None\n self.stdout = None\n self.stderr = None\n self.pid = None\n self.returncode = None\n self.universal_newlines = universal_newlines\n self.encoding = encoding\n self.errors = errors\n \n # Input and output objects. The general principle is like\n # this:\n #\n # Parent Child\n # ------ -----\n # p2cwrite ---stdin---> p2cread\n # c2pread <--stdout--- c2pwrite\n # errread <--stderr--- errwrite\n #\n # On POSIX, the child objects are file descriptors. On\n # Windows, these are Windows file handles. The parent objects\n # are file descriptors on both platforms. The parent objects\n # are -1 when not using PIPEs. The child objects are -1\n # when not redirecting.\n \n (p2cread, p2cwrite,\n c2pread, c2pwrite,\n errread, errwrite) = self._get_handles(stdin, stdout, stderr)\n \n # We wrap OS handles *before* launching the child, otherwise a\n # quickly terminating child could make our fds unwrappable\n # (see #8458).\n \n if _mswindows:\n if p2cwrite != -1:\n p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)\n if c2pread != -1:\n c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)\n if errread != -1:\n errread = msvcrt.open_osfhandle(errread.Detach(), 0)\n \n text_mode = encoding or errors or universal_newlines\n \n self._closed_child_pipe_fds = False\n \n try:\n if p2cwrite != -1:\n self.stdin = io.open(p2cwrite, 'wb', bufsize)\n if text_mode:\n self.stdin = io.TextIOWrapper(self.stdin, write_through=True,\n line_buffering=(bufsize == 1),\n encoding=encoding, errors=errors)\n if c2pread != -1:\n self.stdout = io.open(c2pread, 'rb', bufsize)\n if text_mode:\n self.stdout = io.TextIOWrapper(self.stdout,\n encoding=encoding, errors=errors)\n if errread != -1:\n self.stderr = io.open(errread, 'rb', bufsize)\n if text_mode:\n self.stderr = io.TextIOWrapper(self.stderr,\n encoding=encoding, errors=errors)\n \n self._execute_child(args, executable, preexec_fn, close_fds,\n pass_fds, cwd, env,\n startupinfo, creationflags, shell,\n p2cread, p2cwrite,\n c2pread, c2pwrite,\n errread, errwrite,\n> restore_signals, start_new_session)\n\nd:\\python\\python3\\lib\\subprocess.py:709: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = \nargs = 'C:\\\\Users\\\\Administrator\\\\PycharmProjects\\\\pyTestAutomation\\\\chromedriver.exe --port=61984'\nexecutable = None, preexec_fn = None, close_fds = False, pass_fds = ()\ncwd = None\nenv = environ({'ALLUSERSPROFILE': 'C:\\\\ProgramData', 'ANDROID_HOME': 'D:\\\\Android\\\\android-sdk', 'APPDATA': 'C:\\\\Users\\\\Admi...ble-features=NetworkServiceInProcess', 'PYTEST_CURRENT_TEST': 'web/test_demo_web.py::TestDemo::test_web_demo (setup)'})\nstartupinfo = , creationflags = 0\nshell = False, p2cread = Handle(272), p2cwrite = 5, c2pread = -1\nc2pwrite = Handle(280), errread = -1, errwrite = Handle(268)\nunused_restore_signals = True, unused_start_new_session = False\n\n def _execute_child(self, args, executable, preexec_fn, close_fds,\n pass_fds, cwd, env,\n startupinfo, creationflags, shell,\n p2cread, p2cwrite,\n c2pread, c2pwrite,\n errread, errwrite,\n unused_restore_signals, unused_start_new_session):\n \"\"\"Execute program (MS Windows version)\"\"\"\n \n assert not pass_fds, \"pass_fds not supported on Windows.\"\n \n if not isinstance(args, str):\n args = list2cmdline(args)\n \n # Process startup details\n if startupinfo is None:\n startupinfo = STARTUPINFO()\n if -1 not in (p2cread, c2pwrite, errwrite):\n startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES\n startupinfo.hStdInput = p2cread\n startupinfo.hStdOutput = c2pwrite\n startupinfo.hStdError = errwrite\n \n if shell:\n startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW\n startupinfo.wShowWindow = _winapi.SW_HIDE\n comspec = os.environ.get(\"COMSPEC\", \"cmd.exe\")\n args = '{} /c \"{}\"'.format (comspec, args)\n \n # Start the process\n try:\n hp, ht, pid, tid = _winapi.CreateProcess(executable, args,\n # no special security\n None, None,\n int(not close_fds),\n creationflags,\n env,\n os.fspath(cwd) if cwd is not None else None,\n> startupinfo)\nE FileNotFoundError: [WinError 2] 系统找不到指定的文件。\n\nd:\\python\\python3\\lib\\subprocess.py:997: FileNotFoundError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \n\n def setup(self):\n print(os.path.abspath('..').replace('script', 'framework' + os.sep + 'driver') + os.sep + 'chromedriver.exe')\n driver_path = os.path.abspath('..').replace('script',\n 'framework' + os.sep + 'driver') + os.sep + 'chromedriver.exe'\n> self.driver = webdriver.Chrome(executable_path=driver_path)\n\nweb\\test_demo_web.py:14: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nd:\\python\\python3\\lib\\site-packages\\selenium\\webdriver\\chrome\\webdriver.py:73: in __init__\n self.service.start()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = \n\n def start(self):\n \"\"\"\n Starts the Service.\n \n :Exceptions:\n - WebDriverException : Raised either when it can't start the service\n or when it can't connect to the service\n \"\"\"\n try:\n cmd = [self.path]\n cmd.extend(self.command_line_args())\n self.process = subprocess.Popen(cmd, env=self.env,\n close_fds=platform.system() != 'Windows',\n stdout=self.log_file,\n stderr=self.log_file,\n stdin=PIPE)\n except TypeError:\n raise\n except OSError as err:\n if err.errno == errno.ENOENT:\n raise WebDriverException(\n \"'%s' executable needs to be in PATH. %s\" % (\n> os.path.basename(self.path), self.start_error_message)\nE selenium.common.exceptions.WebDriverException: Message: 'chromedriver.exe' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home\n\nd:\\python\\python3\\lib\\site-packages\\selenium\\webdriver\\common\\service.py:83: WebDriverException"}, "start": 1590149485732, "stop": 1590149485732, "uuid": "ae836c61-106a-4e15-a2eb-b7bce26ed05a", "historyId": "ce289128d26247906904e9a4eb0e664a", "testCaseId": "372abe7c1a955bb401bda065764254db", "fullName": "web.test_demo_web.TestDemo#test_web_demo", "labels": [{"name": "story", "value": "test_story_of_web_demo"}, {"name": "feature", "value": "feature_web_demo"}, {"name": "parentSuite", "value": "web"}, {"name": "suite", "value": "test_demo_web"}, {"name": "subSuite", "value": "TestDemo"}, {"name": "host", "value": "我的PC-爱吃苹果的鱼"}, {"name": "thread", "value": "22836-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "web.test_demo_web"}]}
--------------------------------------------------------------------------------
/script/report/xml/eef9e64c-7950-4109-ab2c-d6e0f7049a3a-attachment.txt:
--------------------------------------------------------------------------------
1 | [25/May/2020 21:49:15] INFO - 文本框传值'selenium'
2 | [25/May/2020 21:49:15] INFO - 点击''
3 |
--------------------------------------------------------------------------------
/script/report/xml/fb2d4685-8bb1-4d6c-8272-addc7c1b36bf-attachment.txt:
--------------------------------------------------------------------------------
1 | [23/May/2020 23:48:49] INFO - 文本框传值'selenium'
2 | [23/May/2020 23:48:49] INFO - 点击回车按钮
3 |
--------------------------------------------------------------------------------
/script/report/xml/fd3c4538-bcff-4a3b-830a-fabc5e4ab066-attachment.txt:
--------------------------------------------------------------------------------
1 | [32mINFO [0m root:selenium_action.py:179 文本框传值'吕岩'
2 | [32mINFO [0m root:selenium_action.py:179 文本框传值'18334485634'
3 | [32mINFO [0m root:selenium_action.py:103 点击''
4 | [32mINFO [0m root:appcommon.py:23 找不到"联系人已保存"
--------------------------------------------------------------------------------
/script/report/xml/fd432725-474f-4a3a-b2fa-1f2949e7dc98-attachment.txt:
--------------------------------------------------------------------------------
1 | [23/May/2020 23:48:59] INFO - 文本框传值'selenium'
2 | [23/May/2020 23:48:59] INFO - 点击''
3 |
--------------------------------------------------------------------------------
/script/test_demo_api.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | from framework.base import selenium_init
6 | from framework.base import selenium_action
7 | import allure
8 | import pytest
9 | import time
10 | from bs4 import BeautifulSoup
11 |
12 |
13 | @allure.feature('feature_api_demo')
14 | class TestApiDemo:
15 |
16 | @pytest.fixture(scope='function')
17 | def setup(self):
18 | self.webInit = selenium_init.SeleniumInit()
19 | self.driver = self.webInit.setup('headless')
20 | self.webAct = selenium_action.SeleniumActionAPI(self.driver)
21 |
22 | @pytest.mark.api
23 | @allure.story('test_story_of_api_demo')
24 | def test_api_demo(self, setup):
25 | self.webAct.to_url("http://www.baidu.com") # 打开百度网页(无头模式)
26 | self.webAct.ele_send_keys(self.webAct.ele_get_by_id('kw'), 'selenium') # 搜索框输入'selenium'
27 | self.webAct.ele_click_by_id('su') # 百度一下
28 | time.sleep(3)
29 | bs = BeautifulSoup(self.driver.page_source, 'html.parser')
30 | result = False
31 | for item in bs.select("div[class = 'result c-container']"):
32 | if 'selenium' in str(item.h3.a.get_text()).lower():
33 | result = True
34 | else:
35 | print(str(item.h3.a.get_text()).lower() + ':不包含selenium')
36 | result = False
37 | assert result
38 |
39 | def teardown(self):
40 | self.driver.quit()
--------------------------------------------------------------------------------
/script/test_demo_app.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | import pytest
6 | import allure
7 | from framework.base import appium_init
8 | from framework.app.appcommon import AppCommon
9 | from framework.base.selenium_action import SeleniumActionAPI
10 | from framework.utils.string_utils import StringUtils
11 | import time
12 |
13 |
14 | @allure.feature('feature_app_demo')
15 | class TestAppDemo:
16 |
17 | @pytest.fixture(scope='function')
18 | def setup(self):
19 | self.appInit = appium_init.AppiumInit('7.1.1', 'android', '192.168.174.101:5555', 'com.android.contacts',
20 | 'com.android.contacts.activities.PeopleActivity', '4723')
21 | self.driver = self.appInit.setup()
22 | self.app = AppCommon(self.driver)
23 | self.appium = SeleniumActionAPI(self.driver)
24 | self.util = StringUtils()
25 |
26 | @pytest.mark.app
27 | @allure.story('test_story_of_app_demo')
28 | def test_app_demo(self, setup):
29 | self.app.tap_click(int(959*self.app.device_x_get()/1080), int(1670*self.app.device_y_get()/1794))
30 | # time.sleep(5)
31 | # self.appium.ele_click_by_id('com.android.contacts:id/left_button')
32 | time.sleep(2)
33 | edit_boxes = self.appium.ele_list_get_by_class_name("android.widget.EditText")
34 | self.appium.ele_send_keys(edit_boxes[0], self.util.name_get())
35 | self.appium.ele_send_keys(edit_boxes[1], self.util.phone_get())
36 | self.appium.ele_click_by_id('menu_save')
37 | result = self.app.toast_chk('联系人已保存')
38 | assert result
39 |
40 | def teardown(self):
41 | self.driver.quit()
42 |
43 |
--------------------------------------------------------------------------------
/script/test_demo_h5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | import time
6 | from framework.base import selenium_init
7 | from framework.base import selenium_action
8 | import allure
9 | import pytest
10 |
11 |
12 | @allure.feature('feature_h5_demo')
13 | class TestH5Demo:
14 |
15 | @pytest.fixture(scope='function')
16 | def setup(self):
17 | self.h5Init = selenium_init.SeleniumInit()
18 | self.driver = self.h5Init.setup('h5')
19 | self.webAct = selenium_action.SeleniumActionAPI(self.driver)
20 |
21 | @pytest.mark.h5
22 | @allure.story('test_story_of_h5_demo')
23 | def test_h5_demo(self, setup):
24 | self.webAct.to_url("http://www.baidu.com")
25 | self.webAct.ele_send_keys(self.webAct.ele_get_by_id('index-kw'), 'selenium') # 传入搜索关键字
26 | self.webAct.ele_press_enter(self.webAct.ele_get_by_id('index-kw'))
27 | time.sleep(3)
28 | result_list = self.webAct.ele_list_get_by_xpath("//div[@class='c-result-content']//span[@class='c-title-text']")
29 | result = False
30 | for i in range(len(result_list)):
31 | if 'selenium' in str(result_list[i].text).lower():
32 | result = True
33 | else:
34 | print(result_list[i].text + ':不包含selenium')
35 | result = False
36 | assert result
37 |
38 | def teardown(self):
39 | self.driver.quit()
40 |
--------------------------------------------------------------------------------
/script/test_demo_web.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2020-05-23
3 | # @Author : 爱吃苹果的鱼
4 |
5 | from framework.base import selenium_init
6 | from framework.base import selenium_action
7 | import allure
8 | import time
9 | import pytest
10 |
11 |
12 | @allure.feature('feature_web_demo')
13 | class TestDemo:
14 |
15 | @pytest.fixture(scope='function')
16 | def setup(self):
17 | self.webInit = selenium_init.SeleniumInit()
18 | self.driver = self.webInit.setup('web')
19 | self.webAct = selenium_action.SeleniumActionAPI(self.driver)
20 |
21 | @pytest.mark.web
22 | @allure.story('test_story_of_web_demo')
23 | def test_web_demo(self, setup):
24 | self.webAct.to_url("http://www.baidu.com")
25 | self.webAct.ele_send_keys(self.webAct.ele_get_by_id('kw'), 'selenium') # 传入搜索关键字
26 | self.webAct.ele_click_by_id('su') # 点击百度一下按钮
27 | time.sleep(3)
28 | result_list = self.webAct.ele_list_get_by_xpath("//div[@class='result c-container ']/h3/a")
29 | result = False
30 | for i in range(len(result_list)):
31 | if 'selenium' in str(result_list[i].text).lower():
32 | result = True
33 | else:
34 | print(result_list[i].text + ':不包含selenium')
35 | result = False
36 | assert result
37 |
38 | def teardown(self):
39 | self.driver.quit()
40 |
--------------------------------------------------------------------------------