├── .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 | 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 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 174 | 175 | 176 | 177 | 178 | true 179 | DEFINITION_ORDER 180 | 181 | 182 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 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 | 266 | 267 | 268 | 269 | 270 | 290 | 291 | 292 | 312 | 313 | 314 | 334 | 335 | 336 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 1588585535209 378 | 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 | 414 | 415 | 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 | ![](https://github.com/jinwu18/web-app-h5-api-pyTestAutomation/blob/master/autotestFrame.png) 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 | ![](https://github.com/jinwu18/web-app-h5-api-pyTestAutomation/blob/master/allure_report.png) 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 | INFO  root:selenium_action.py:179 文本框传值'selenium' 2 | INFO  root:selenium_action.py:103 点击'' -------------------------------------------------------------------------------- /script/report/xml/12180a99-1c2e-4d18-a2f5-f1fc9d7917d2-attachment.txt: -------------------------------------------------------------------------------- 1 | INFO  root:selenium_action.py:179 文本框传值'selenium' 2 | INFO  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 | INFO  root:selenium_action.py:179 文本框传值'selenium' 2 | INFO  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 | INFO  root:selenium_action.py:179 文本框传值'selenium' 2 | INFO  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 | INFO  root:selenium_action.py:179 文本框传值'selenium' 2 | INFO  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 | INFO  root:selenium_action.py:179 文本框传值'吕岩' 2 | INFO  root:selenium_action.py:179 文本框传值'18334485634' 3 | INFO  root:selenium_action.py:103 点击'' 4 | INFO  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 | --------------------------------------------------------------------------------