├── Appium参考文档汇总及安装.pdf ├── Demo ├── README.md ├── demo.py ├── gitignore ├── idea │ └── vcs.xml ├── page │ ├── app.py │ ├── base_page.py │ ├── main_page.py │ └── search_page.py ├── search.yaml ├── test_api_demo.py ├── test_demo.py ├── test_demo_unit.py ├── test_ios.py ├── test_ios_real.py ├── test_ios_real_web.py ├── test_ios_real_web_sim.py ├── test_ios_real_webview.py ├── test_web.py ├── testcase.yaml └── testcase │ └── test_demo.py ├── README.md ├── 第一章 自动化测试理论.pdf ├── 第七章 测试框架封装改造.pdf ├── 第三章 App自动化测试框架Appium.pdf ├── 第九章 自动化测试平台.pdf ├── 第二章 App 结构解析.pdf ├── 第五章 iOS 自动化测试.pdf ├── 第八章 自动遍历回归测试.pdf ├── 第六章 基于 Page Object 模式的自动化测试用例实战.pdf ├── 第十章 移动自动化测试持续集成实战.pdf └── 第四章 Android 自动化测试.pdf /Appium参考文档汇总及安装.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/Appium参考文档汇总及安装.pdf -------------------------------------------------------------------------------- /Demo/README.md: -------------------------------------------------------------------------------- 1 | # Geek_AppAutomationTestingCode 2 | -------------------------------------------------------------------------------- /Demo/demo.py: -------------------------------------------------------------------------------- 1 | # This sample code uses the Appium python client 2 | # pip install Appium-Python-Client 3 | # Then you can paste this into a file and simply run with Python 4 | 5 | from appium import webdriver 6 | from appium.webdriver.common.touch_action import TouchAction 7 | 8 | caps = {} 9 | caps["platformName"] = "android" 10 | caps["deviceName"] = "seveniruby" 11 | caps["appPackage"] = "com.xueqiu.android" 12 | caps["appActivity"] = ".view.WelcomeActivityAlias" 13 | caps["autoGrantPermissions"] = "true" 14 | 15 | driver = webdriver.Remote("http://localhost:4723/wd/hub", caps) 16 | driver.implicitly_wait(10) 17 | 18 | el1 = driver.find_element_by_id("com.xueqiu.android:id/home_search") 19 | el1.click() 20 | 21 | TouchAction(driver).long_press().move_to().release().perform(); 22 | driver.swipe() 23 | el2 = driver.find_element_by_id("com.xueqiu.android:id/search_input_text") 24 | el2.send_keys("pdd") 25 | 26 | driver.quit() 27 | -------------------------------------------------------------------------------- /Demo/gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /venv/ 3 | -------------------------------------------------------------------------------- /Demo/idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Demo/page/app.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from appium import webdriver 4 | from selenium.webdriver.remote.webdriver import WebDriver 5 | from selenium.webdriver.support.wait import WebDriverWait 6 | 7 | from page.main_page import MainPage 8 | 9 | 10 | class App: 11 | 12 | driver:WebDriver=None 13 | @classmethod 14 | def start(cls): 15 | caps = {} 16 | caps["platformName"] = "android" 17 | caps["deviceName"] = "seveniruby" 18 | caps["appPackage"] = "com.xueqiu.android" 19 | caps["appActivity"] = ".view.WelcomeActivityAlias" 20 | caps["autoGrantPermissions"] = "true" 21 | #caps["udid"] = "emulator-5556" 22 | caps["chromedriverExecutable"]="/Users/seveniruby/projects/chromedriver/2.20/chromedriver" 23 | caps["showChromedriverLog"]=True 24 | 25 | cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps) 26 | cls.driver.implicitly_wait(10) 27 | 28 | # sleep(20) 29 | # if len(self.driver.find_elements_by_id("image_cancel")) >=1: 30 | # self.driver.find_element_by_id("image_cancel").click() 31 | # 32 | # 33 | 34 | 35 | 36 | # WebDriverWait(self.driver, 15).until( 37 | # expected_conditions.visibility_of_element_located((By.ID, "image_cancel")) 38 | # ) 39 | 40 | # def loaded(driver): 41 | # print(datetime.datetime.now()) 42 | # if len(cls.driver.find_elements_by_id("image_cancel")) >=1: 43 | # cls.driver.find_element_by_id("image_cancel").click() 44 | # return True 45 | # else: 46 | # return False 47 | # 48 | # try: 49 | # WebDriverWait(cls.driver, 20).until(loaded) 50 | # except: 51 | # print("no update") 52 | 53 | return MainPage(cls.driver) 54 | 55 | @classmethod 56 | def quit(cls): 57 | cls.driver.quit() -------------------------------------------------------------------------------- /Demo/page/base_page.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | from selenium.webdriver.remote.webdriver import WebDriver 3 | 4 | 5 | class BasePage: 6 | _black_list = [ 7 | (By.ID, "image_cancel"), 8 | (By.ID, "tips") 9 | ] 10 | 11 | def __init__(self, driver: WebDriver): 12 | self.driver = driver 13 | 14 | def find_element(self, locator): 15 | print(locator) 16 | try: 17 | return self.driver.find_element(*locator) 18 | except: 19 | self.handle_exception() 20 | # self.find_element(locator) 21 | return self.driver.find_element(*locator) 22 | 23 | def find_element_and_click(self, locator): 24 | print("click") 25 | try: 26 | #如果click也有异常,可以这样处理 27 | self.find_element(locator).click() 28 | except: 29 | self.handle_exception() 30 | self.find_element(locator).click() 31 | 32 | 33 | def handle_exception(self): 34 | print(":exception") 35 | self.driver.implicitly_wait(0) 36 | for locator in self._black_list: 37 | print(locator) 38 | elements=self.driver.find_elements(*locator) 39 | 40 | if len(elements)>=1: 41 | #todo: 不是所有的弹框处理都是要点击弹框,可根据业务需要自行封装 42 | elements[0].click() 43 | else: 44 | print("%s not found" % str(locator)) 45 | 46 | #todo: 私用page source会更快的定位 47 | 48 | # page_source=self.driver.page_source 49 | # if "image_cancel" in page_source: 50 | # self.driver.find_element(*locator).click() 51 | # elif "tips" in page_source: 52 | # pass 53 | 54 | 55 | self.driver.implicitly_wait(10) -------------------------------------------------------------------------------- /Demo/page/main_page.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | from selenium.webdriver.remote.webdriver import WebDriver 3 | 4 | from page.base_page import BasePage 5 | from page.search_page import SearchPage 6 | 7 | 8 | class MainPage(BasePage): 9 | _search_locator = (By.ID, "com.xueqiu.android:id/home_search") 10 | 11 | def to_search(self): 12 | #todo: too slow 13 | self.find_element_and_click(self._search_locator) 14 | return SearchPage(self.driver) -------------------------------------------------------------------------------- /Demo/page/search_page.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | from page.base_page import BasePage 3 | 4 | class SearchPage(BasePage): 5 | 6 | _input_locator=(By.ID, "com.xueqiu.android:id/search_input_text") 7 | _name_locator=(By.ID, "name") 8 | def search(self, keyword): 9 | self.find_element(self._input_locator).send_keys(keyword) 10 | self.find_element(self._name_locator).click() 11 | return self 12 | 13 | def get_current_price(self): 14 | return float(self.driver.find_element_by_id("current_price").text) 15 | 16 | 17 | -------------------------------------------------------------------------------- /Demo/search.yaml: -------------------------------------------------------------------------------- 1 | - [ xiaomi, 1 ] 2 | - [ pdd, 20 ] 3 | - [ alibaba, 100 ] 4 | - [ jd, 10] -------------------------------------------------------------------------------- /Demo/test_api_demo.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from time import sleep 3 | 4 | from appium import webdriver 5 | from appium.webdriver.common.touch_action import TouchAction 6 | from appium.webdriver.extensions.android.gsm import GsmCallActions 7 | from selenium.webdriver.common.by import By 8 | from selenium.webdriver.support import expected_conditions 9 | from selenium.webdriver.support.wait import WebDriverWait 10 | 11 | 12 | class TestApiDemo: 13 | def setup(self): 14 | caps = {} 15 | caps["platformName"] = "android" 16 | caps["deviceName"] = "seveniruby" 17 | caps["appPackage"] = "io.appium.android.apis" 18 | caps["appActivity"] = ".ApiDemos" 19 | caps["autoGrantPermissions"] = "true" 20 | 21 | self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps) 22 | self.driver.implicitly_wait(10) 23 | 24 | 25 | def test_toast(self): 26 | self.driver.find_element_by_accessibility_id("Views").click() 27 | self.driver.find_element_by_android_uiautomator( 28 | 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("Popup Menu").instance(0));' 29 | ).click() 30 | 31 | #self.driver.swipe() 32 | #self.driver.find_element_by_accessibility_id("Popup Menu").click() 33 | 34 | self.driver.find_element_by_accessibility_id("Make a Popup!").click() 35 | assert len(self.driver.find_elements_by_xpath('//*[@text="Edit"]')) == 1 36 | 37 | self.driver.find_element_by_xpath("//*[@text='Search']").click() 38 | 39 | assert "Clicked popup menu item Search XXX" in self.driver.find_element_by_xpath("//*[@class='android.widget.Toast']").text 40 | 41 | 42 | def test_gsm_call(self): 43 | self.driver.send_sms("15600534760", "Hello, From Seveniruby") 44 | self.driver.make_gsm_call("15600534760", GsmCallActions.CALL) 45 | 46 | def test_performance(self): 47 | print(self.driver.get_performance_data_types()) 48 | for p in self.driver.get_performance_data_types(): 49 | try: 50 | print(self.driver.get_performance_data("io.appium.android.apis", p, 5)) 51 | except: 52 | pass 53 | 54 | def teardown(self): 55 | self.driver.quit() 56 | -------------------------------------------------------------------------------- /Demo/test_demo.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from time import sleep 3 | 4 | import pytest 5 | import yaml 6 | from appium import webdriver 7 | from selenium.webdriver.common.by import By 8 | from selenium.webdriver.remote.webdriver import WebDriver 9 | from selenium.webdriver.support import expected_conditions 10 | from selenium.webdriver.support.wait import WebDriverWait 11 | from hamcrest import * 12 | 13 | from page.search_page import SearchPage 14 | 15 | 16 | class TestDemo: 17 | search_data=yaml.safe_load(open("search.yaml", "r")) 18 | print(search_data) 19 | 20 | def setup(self): 21 | caps = {} 22 | caps["platformName"] = "android" 23 | caps["deviceName"] = "seveniruby" 24 | caps["appPackage"] = "com.xueqiu.android" 25 | caps["appActivity"] = ".view.WelcomeActivityAlias" 26 | caps["autoGrantPermissions"] = "true" 27 | #caps["udid"] = "emulator-5556" 28 | caps["chromedriverExecutableDir"]="/Users/seveniruby/projects/chromedriver/2.20/" 29 | caps["showChromedriverLog"]=True 30 | 31 | self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps) 32 | self.driver.implicitly_wait(10) 33 | 34 | # sleep(20) 35 | # if len(self.driver.find_elements_by_id("image_cancel")) >=1: 36 | # self.driver.find_element_by_id("image_cancel").click() 37 | # 38 | # 39 | 40 | 41 | 42 | # WebDriverWait(self.driver, 15).until( 43 | # expected_conditions.visibility_of_element_located((By.ID, "image_cancel")) 44 | # ) 45 | 46 | def loaded(driver): 47 | print(datetime.datetime.now()) 48 | if len(self.driver.find_elements_by_id("image_cancel")) >=1: 49 | self.driver.find_element_by_id("image_cancel").click() 50 | return True 51 | else: 52 | return False 53 | 54 | try: 55 | WebDriverWait(self.driver, 20).until(loaded) 56 | except: 57 | print("no update") 58 | 59 | 60 | def test_demo(self): 61 | el1 = self.driver.find_element_by_id("com.xueqiu.android:id/home_search") 62 | el1.click() 63 | el2 = self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text") 64 | el2.send_keys("pdd") 65 | 66 | 67 | def test_xpath(self): 68 | self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name') ]").click() 69 | 70 | @pytest.mark.parametrize("keyword, expected_price", [ 71 | ("pdd", 20), 72 | ("alibaba", 100), 73 | ("jd", 10) 74 | ]) 75 | def test_search(self, keyword, expected_price): 76 | self.driver.find_element_by_id("com.xueqiu.android:id/home_search").click() 77 | self.driver.find_element_by_id("search_input_text").send_keys(keyword) 78 | self.driver.find_element_by_id("name").click() 79 | 80 | price=self.driver.find_element_by_id("current_price") 81 | 82 | assert float(price.text) > expected_price 83 | assert "price" in price.get_attribute("resource-id") 84 | assert_that(price.get_attribute("package"), equal_to("com.xueqiu.android")) 85 | 86 | 87 | @pytest.mark.parametrize("keyword, expected_price", search_data) 88 | def test_search_from_yaml(self, keyword, expected_price): 89 | self.driver.find_element_by_id("com.xueqiu.android:id/home_search").click() 90 | self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text").send_keys(keyword) 91 | self.driver.find_element_by_id("name").click() 92 | 93 | price=self.driver.find_element_by_id("current_price") 94 | 95 | assert float(price.text) > expected_price 96 | assert "price" in price.get_attribute("resource-id") 97 | assert_that(price.get_attribute("package"), equal_to("com.xueqiu.android")) 98 | 99 | def test_search_from_testcase(self): 100 | TestCase("testcase.yaml").run(self.driver) 101 | 102 | 103 | def test_webview(self): 104 | self.driver.find_element_by_xpath("//*[@text='交易']").click() 105 | for i in range(5): 106 | sleep(1) 107 | print(self.driver.contexts) 108 | 109 | self.driver.find_element_by_accessibility_id("A股开户").click() 110 | 111 | def test_webview_api_23(self): 112 | self.driver.find_element_by_xpath("//*[@text='交易']").click() 113 | for i in range(5): 114 | print(self.driver.contexts) 115 | 116 | self.driver.find_element_by_accessibility_id("A股开户").click() 117 | self.driver.switch_to.context(self.driver.contexts[1]) 118 | print(self.driver.current_context) 119 | WebDriverWait(self.driver, 20)\ 120 | .until(expected_conditions.visibility_of_element_located((By.ID, "phone-number"))) 121 | self.driver.find_element_by_id("phone-number").send_keys("15600534760") 122 | 123 | 124 | def test_search_po(self): 125 | 126 | search_page= SearchPage(self.driver) 127 | search_page.search("alibaba") 128 | 129 | assert search_page.get_current_price() > 10 130 | 131 | 132 | def teardown(self): 133 | sleep(200) 134 | self.driver.quit() 135 | 136 | 137 | class TestCase: 138 | def __init__(self, path): 139 | file=open(path, "r") 140 | self.steps=yaml.safe_load(file) 141 | 142 | 143 | def run(self, driver: WebDriver): 144 | for step in self.steps: 145 | element=None 146 | print(step) 147 | 148 | if isinstance(step, dict): 149 | if "id" in step.keys(): 150 | element=driver.find_element_by_id(step["id"]) 151 | elif "xpath" in step.keys(): 152 | element=driver.find_element_by_xpath(step["xpath"]) 153 | else: 154 | print(step.keys()) 155 | 156 | if "input" in step.keys(): 157 | element.send_keys(step["input"]) 158 | else: 159 | element.click() 160 | 161 | if "get" in step.keys(): 162 | text=element.get_attribute(step["get"]) 163 | print(text) 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /Demo/test_demo_unit.py: -------------------------------------------------------------------------------- 1 | 2 | from appium import webdriver 3 | from appium.webdriver.common.touch_action import TouchAction 4 | from unittest import TestCase 5 | 6 | class TestDemo(TestCase): 7 | def setUp(self): 8 | caps = {} 9 | caps["platformName"] = "android" 10 | caps["deviceName"] = "seveniruby" 11 | caps["appPackage"] = "com.xueqiu.android" 12 | caps["appActivity"] = ".view.WelcomeActivityAlias" 13 | caps["autoGrantPermissions"] = "true" 14 | caps['unicodeKeyboard']=True 15 | 16 | self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps) 17 | self.driver.implicitly_wait(10) 18 | 19 | def test_demo(self): 20 | el1 = self.driver.find_element_by_id("com.xueqiu.android:id/home_search") 21 | el1.click() 22 | el2 = self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text") 23 | el2.send_keys("pdd") 24 | 25 | def test_capabilities(self): 26 | el1 = self.driver.find_element_by_id("com.xueqiu.android:id/home_search") 27 | el1.click() 28 | el2 = self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text") 29 | el2.send_keys("阿里巴巴") 30 | 31 | 32 | def tearDown(self): 33 | pass 34 | #self.driver.quit() 35 | -------------------------------------------------------------------------------- /Demo/test_ios.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from appium import webdriver 4 | 5 | 6 | class TestIOS: 7 | 8 | def setup(self): 9 | caps = {} 10 | caps["platformName"] = "ios" 11 | caps[ 12 | "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphonesimulator/UICatalog.app" 13 | caps["automationName"] = "xcuitest" 14 | caps["deviceName"] = "iPhone X" 15 | caps["platformVersion"] = "11.0" 16 | 17 | self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps) 18 | 19 | def test_buttons(self): 20 | el1 = self.driver.find_element_by_accessibility_id("Buttons") 21 | el1.click() 22 | 23 | def teardown(self): 24 | sleep(20) 25 | self.driver.quit() 26 | -------------------------------------------------------------------------------- /Demo/test_ios_real.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from appium import webdriver 4 | 5 | 6 | class TestIOS: 7 | 8 | def setup(self): 9 | caps = {} 10 | caps["platformName"] = "ios" 11 | # caps[ 12 | # "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphonesimulator/UICatalog.app" 13 | caps["automationName"] = "xcuitest" 14 | # caps["deviceName"] = "iPhone X" 15 | # caps["platformVersion"] = "11.0" 16 | 17 | caps["deviceName"] = "seveniruby ipad" 18 | caps["udid"] = "9df22446af15919c494c85b4c1c8b00eaa3a5bd0" 19 | 20 | caps["xcodeOrgId"] = "96NJEQL7Y2" 21 | caps["xcodeSigningId"] = "iPhone Developer" 22 | caps[ 23 | "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphoneos/UICatalog.app" 24 | 25 | self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps) 26 | 27 | def test_buttons(self): 28 | el1 = self.driver.find_element_by_accessibility_id("Buttons") 29 | el1.click() 30 | 31 | def teardown(self): 32 | sleep(20) 33 | self.driver.quit() 34 | -------------------------------------------------------------------------------- /Demo/test_ios_real_web.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from appium import webdriver 4 | 5 | 6 | class TestIOS: 7 | 8 | def setup(self): 9 | caps = {} 10 | caps["platformName"] = "ios" 11 | # caps[ 12 | # "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphonesimulator/UICatalog.app" 13 | caps["automationName"] = "xcuitest" 14 | # caps["deviceName"] = "iPhone X" 15 | # caps["platformVersion"] = "11.0" 16 | 17 | caps["deviceName"] = "seveniruby ipad" 18 | caps["udid"] = "9df22446af15919c494c85b4c1c8b00eaa3a5bd0" 19 | caps["startIWDP"] = True 20 | caps["browserName"] = "Safari" 21 | # 22 | # caps["xcodeOrgId"] = "96NJEQL7Y2" 23 | # caps["xcodeSigningId"] = "iPhone Developer" 24 | # caps[ 25 | # "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphoneos/UICatalog.app" 26 | 27 | self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps) 28 | self.driver.implicitly_wait(10) 29 | def test_web_testerhome(self): 30 | self.driver.get("https://testerhome.com") 31 | print(self.driver.page_source) 32 | sleep(2) 33 | self.driver.save_screenshot("首页.png") 34 | self.driver.find_element_by_link_text("社团").click() 35 | sleep(2) 36 | self.driver.save_screenshot("社团.png") 37 | self.driver.find_element_by_link_text("霍格沃兹测试学院").click() 38 | sleep(2) 39 | self.driver.save_screenshot("学院.png") 40 | 41 | def teardown(self): 42 | # sleep(10) 43 | self.driver.quit() 44 | -------------------------------------------------------------------------------- /Demo/test_ios_real_web_sim.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from appium import webdriver 4 | 5 | 6 | class TestIOS: 7 | 8 | def setup(self): 9 | caps = {} 10 | caps["platformName"] = "ios" 11 | # caps[ 12 | # "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphonesimulator/UICatalog.app" 13 | caps["automationName"] = "xcuitest" 14 | caps["deviceName"] = "iPhone X" 15 | caps["platformVersion"] = "11.0" 16 | # 17 | # caps["deviceName"] = "seveniruby ipad" 18 | # caps["udid"] = "9df22446af15919c494c85b4c1c8b00eaa3a5bd0" 19 | # caps["startIWDP"] = True 20 | caps["browserName"] = "Safari" 21 | # 22 | # caps["xcodeOrgId"] = "96NJEQL7Y2" 23 | # caps["xcodeSigningId"] = "iPhone Developer" 24 | # caps[ 25 | # "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphoneos/UICatalog.app" 26 | 27 | self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps) 28 | self.driver.implicitly_wait(10) 29 | def test_web_testerhome(self): 30 | self.driver.get("https://testerhome.com") 31 | print(self.driver.page_source) 32 | sleep(2) 33 | self.driver.save_screenshot("首页.png") 34 | self.driver.find_element_by_partial_link_text("MTSC2019").click() 35 | sleep(2) 36 | self.driver.save_screenshot("MTSC2019.png") 37 | 38 | def teardown(self): 39 | # sleep(10) 40 | self.driver.quit() 41 | -------------------------------------------------------------------------------- /Demo/test_ios_real_webview.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from appium import webdriver 4 | 5 | 6 | class TestIOS: 7 | 8 | def setup(self): 9 | caps = {} 10 | caps["platformName"] = "ios" 11 | # caps[ 12 | # "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphonesimulator/UICatalog.app" 13 | caps["automationName"] = "xcuitest" 14 | # caps["deviceName"] = "iPhone X" 15 | # caps["platformVersion"] = "11.0" 16 | 17 | caps["deviceName"] = "seveniruby ipad" 18 | caps["udid"] = "9df22446af15919c494c85b4c1c8b00eaa3a5bd0" 19 | caps["startIWDP"] = True 20 | 21 | caps["xcodeOrgId"] = "96NJEQL7Y2" 22 | caps["xcodeSigningId"] = "iPhone Developer" 23 | caps[ 24 | "app"] = "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-dfavfehsvaabuqdpmxouzqphclvl/Build/Products/Debug-iphoneos/UICatalog.app" 25 | 26 | self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps) 27 | self.driver.implicitly_wait(10) 28 | 29 | def test_webview(self): 30 | self.driver.find_element_by_accessibility_id("Web View").click() 31 | for i in range(5): 32 | print(self.driver.contexts) 33 | sleep(1) 34 | 35 | self.driver.switch_to.context(self.driver.contexts[1]) 36 | print(self.driver.page_source) 37 | self.driver.save_screenshot("main.png") 38 | self.driver.find_element_by_link_text("Buy").click() 39 | sleep(10) 40 | self.driver.save_screenshot("buy.png") 41 | 42 | def teardown(self): 43 | # sleep(10) 44 | self.driver.quit() 45 | -------------------------------------------------------------------------------- /Demo/test_web.py: -------------------------------------------------------------------------------- 1 | from appium import webdriver 2 | from selenium.webdriver.common.by import By 3 | from selenium.webdriver.support import expected_conditions 4 | from selenium.webdriver.support.wait import WebDriverWait 5 | 6 | 7 | class TestWeb: 8 | 9 | def setup(self): 10 | caps={} 11 | caps["browserName"]="chrome" 12 | caps["deviceName"]="hogwarts" 13 | caps["platformName"]="android" 14 | caps["chromedriverExecutable"] = "/Users/seveniruby/projects/chromedriver/2.34/chromedriver" 15 | caps["showChromedriverLog"] = True 16 | # caps["noReset"]=True 17 | 18 | 19 | self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps) 20 | self.driver.implicitly_wait(10) 21 | 22 | def test_testerhome_search(self): 23 | self.driver.get("https://testerhome.com") 24 | self.driver.switch_to.context("NATIVE_APP") 25 | self.driver.find_element_by_id("com.android.chrome:id/button_secondary").click() 26 | self.driver.switch_to.context(self.driver.contexts[1]) 27 | print(self.driver.current_context) 28 | print(self.driver.page_source) 29 | # self.driver.find_element_by_link_text("Sign In").click() 30 | 31 | self.driver.find_element_by_css_selector("#mobile-search-form > input").send_keys("hogwarts") 32 | -------------------------------------------------------------------------------- /Demo/testcase.yaml: -------------------------------------------------------------------------------- 1 | - id: home_search 2 | get: text 3 | - id: search_input_text 4 | input: alibaba 5 | - id: name 6 | - id: current_price 7 | get: text -------------------------------------------------------------------------------- /Demo/testcase/test_demo.py: -------------------------------------------------------------------------------- 1 | from page.app import App 2 | 3 | class TestDemo: 4 | 5 | def setup(self): 6 | self.search_page=App.start().to_search() 7 | 8 | def test_search_po(self): 9 | self.search_page.search("alibaba") 10 | assert self.search_page.get_current_price() > 10 11 | 12 | def teardown(self): 13 | App.quit() 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Geek_AppAutomationTesting 2 | -------------------------------------------------------------------------------- /第一章 自动化测试理论.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第一章 自动化测试理论.pdf -------------------------------------------------------------------------------- /第七章 测试框架封装改造.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第七章 测试框架封装改造.pdf -------------------------------------------------------------------------------- /第三章 App自动化测试框架Appium.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第三章 App自动化测试框架Appium.pdf -------------------------------------------------------------------------------- /第九章 自动化测试平台.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第九章 自动化测试平台.pdf -------------------------------------------------------------------------------- /第二章 App 结构解析.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第二章 App 结构解析.pdf -------------------------------------------------------------------------------- /第五章 iOS 自动化测试.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第五章 iOS 自动化测试.pdf -------------------------------------------------------------------------------- /第八章 自动遍历回归测试.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第八章 自动遍历回归测试.pdf -------------------------------------------------------------------------------- /第六章 基于 Page Object 模式的自动化测试用例实战.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第六章 基于 Page Object 模式的自动化测试用例实战.pdf -------------------------------------------------------------------------------- /第十章 移动自动化测试持续集成实战.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第十章 移动自动化测试持续集成实战.pdf -------------------------------------------------------------------------------- /第四章 Android 自动化测试.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geektime-geekbang/Geek_AppAutomationTesting/f3b277444e2b6627a3e7adab71d350002445491e/第四章 Android 自动化测试.pdf --------------------------------------------------------------------------------