网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
然后根据事先整理好的业务操作流程与页面跳转关系(3.设计理念中提到的前置工作输出)进行功能的封装,这里推荐根据6大原则对相关操作进行实现,顺了之后就是熟练工了,大同小异的。如果日后出现了布局变更或者业务变更,统一在对应的po页面中进行修改即可。另外,一些业务逻辑的判断,(比如是否存在该用户,不存在新建,存在直接进入),也可以放在po中,但是需要谨慎,这里比较推荐的还是放在测试用例内,也方便大家根据不同的情况做断言。
最后在页面元素、业务操作齐全的状态下进行测试用例的实现,一般来说可以先使用冒烟测试的测试用例来进行简单的业务验证,当然直接使用系统测试的测试用例也是完全没问题的,之后只需要根据之前整理好的用例选单进行转化即可。至于用例的存放目录结构可以根据po页面维度来存放,也可以根据业务维度来进行存放,见仁见智。
5.3 具体实现
5.3.1 base部分
这边先定义一个BasePage类,用来实现一些公共方法与元素定位的实现(webdriver)
class BasePage:
def \_\_init\_\_(self, driver):
self.driver = driver
self.driver.implicitly_wait(10)
def by\_id(self, id):
return self.driver.find_element(By.ID, id)
def by\_xpath(self, xpath):
return self.driver.find_element(By.XPATH, xpath)
def by\_class\_name(self, class_name):
return self.driver.find_element(By.CLASS_NAME, class_name)
def by\_uiautomator(self, uiautomator):
return self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, uiautomator)
另外后续的一些触屏的操作、元素判断也可以按需放在这里面
def is\_element(self, element):
source = self.driver.page_source
if element in source:
return True
else:
return False
def drag(self, bx=0.50, bw=0.05, by=0.4, bz=0.9):
x = self.driver.get_window_size()['width']
y = self.driver.get_window_size()['height']
sx = x \* bx
ex = x \* bw
sy = y \* by
ey = y \* bz
return self.driver.swipe(sx, sy, ex, ey, 1000)
这里我定义了另一个driver_setup的方法,方便每次设备启动使用
def driver\_setup():
desired_caps = dict()
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '10'
desired_caps['deviceName'] = '你自己的设备名'
desired_caps['appPackage'] = '包名'
desired_caps['appActivity'] = '启动名'
desired_caps['noReset'] = True # 不重置session信息
desired_caps['fullReset'] = False # 效果类似与卸载APP 如果不想每次重新登录,设为False
return desired_caps
5.3.2 po部分
目录大致如上,这里值得注意的是,不要把APP里所有的页面都加入到自动化测试中,100%的自动化测试覆盖率会让你苦不堪言,也大可不必。将每次必须回归的重要流程与高重复业务流程、场景加入即可。
以下就是po中的创建顾客页面的实现方法了,直接继承BasePage类,这里有几个例子需要关注的是,性别选择可以封装成两个方法,尽量不用同一个;另一个如果是点击类事件(单结果事件),直接click就行,不用单独在封装完元素后再进行业务操作封装,备注这样的多结果事件则要在下面单独进行业务指定。
class CustomerCreatePage(BasePage):
"""
定义封装创建客户页面的各类操作
创建客
创建客户并开卡
"""
# 定义会员编号输入框
def customer\_number(self):
return self.by_id('com.tiffany.rta.debug:id/edt\_customer\_number')
# 定义姓名输入框
def customer\_name(self):
return self.by_id('com.tiffany.rta.debug:id/edt\_customer\_name')
# 定义手机输入框
def customer\_mobile(self):
return self.by_id('com.tiffany.rta.debug:id/edt\_customer\_mobile')
# 定义性别选择
def customer\_sex(self):
return self.by_id('com.tiffany.rta.debug:id/tv\_customer\_sex')
# 定义性别内选择项目-男
def customer\_sex\_item\_male(self):
return self.by_id('com.tiffany.rta.debug:id/tv\_customer\_boy').click()
# 定义性别内选择项目-女
def customer\_sex\_item\_female(self):
return self.by_id('com.tiffany.rta.debug:id/tv\_customer\_girl').click()
# 定义生日选择框
def customer\_birthday(self):
return self.by_id('com.tiffany.rta.debug:id/tv\_customer\_birthday')
# 定义备注输入框
def customer\_memo(self):
return self.by_id('com.tiffany.rta.debug:id/ed\_remark')
# 定义保存并开卡按钮
def save\_and\_register\_card\_button(self):
return self.by_id('com.tiffany.rta.debug:id/mb\_save\_open\_card').click()
接下来就是组合多个元素进行业务操作的定义
# 定义新建顾客操作
def do\_create\_customer(self):
self.customer_number().send_keys('00001')
self.customer_name().send_keys('自动化测试01')
self.customer_mobile().send_keys('13200000000')
self.customer_sex()
self.customer_sex_item_male()
self.save_button()
5.3.3 test_case部分
测试用例类继承unittest下的TestCase,初始化的时候将对应的用例业务流程加入到里面,另外在具体的测试用例中需要加对应的判断逻辑与操作步骤完整的添加在里面。使用try捕获异常的时候记得把对应的报错名也写上,一是方便定位问题,二是有可能会导致即使用例失败,测试报告上的结果也是pass。
class TestCustomerListPage(unittest.TestCase):
"""
定义客户列表界面的测试用例
创建客户
"""
# 初始化必要的设备信息与业务页面
def setUp(self):
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', driver_setup())
self.base_page = BasePage(driver=self.driver)
self.home_page = HomePage(driver=self.driver)
self.customer_list = CustomerListPage(driver=self.driver)
self.customer_detail = CustomerDetailPage(driver=self.driver)
self.customer_create = CustomerCreatePage(driver=self.driver)
# 测试用例1 -- 创建顾客
def test\_1\_create\_customer(self):
self.home_page.go_customer()
customer_name = '自动化测试01'
# 业务逻辑判断 -- 是否存在该新客
if self.base_page.is_element(customer_name):
self.customer_list.select_customer()
self.customer_detail.do_delete_customer()
self.home_page.go_index()
self.home_page.go_customer()
if self.base_page.is_element(customer_name):
self.customer_check.check_pass()
else:
self.customer_list.goto_create_customer()
self.customer_create.do_create_customer()
self.customer_detail.back_button()
else:
self.customer_list.goto_create_customer()
self.customer_create.do_create_customer()
self.customer_detail.back_button()
try:
self.assertTrue(self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,
'new UiSelector().text("自动化测试01")'))
except NoSuchElementException as e:
return e
sleep(5)
def tearDown(self):
self.driver.quit()
if __name__ == "\_\_main\_\_":
unittest.main()
5.3.4 run部分
具体的测试用例报告模板,大家可以自由选择,这边使用的是HTMLTestReportCN,启动的方式都是大同小异的,无非就是根据自己的测试场景进行定制就行。另外测试模板的组合和样式有兴趣的同学可以自己对报告脚本进行修改,打造更适合自己团队需求的测试报告。
# 两套测试报告模板路径,只用一个的可以就定义一个
report_path = os.path.join(os.getcwd() + '\\result')
result_path = os.path.join(report_path, 'report.html')
# 测试套件路径,根据需求修改
test_dir = os.path.join(os.getcwd() + '\\test\_case\\trade')
# 执行指定测试用例
def test\_suit():
suit = unittest.TestSuite()
suit.addTest(TestOrderResultPage('test\_1\_order\_result'))
suit.addTest(TestOrderResultPage('test\_2\_order\_result\_home\_page'))
return suit
# 执行测试用例集
dis = unittest.defaultTestLoader.discover(test_dir, pattern="test\*.py")
if __name__ == "\_\_main\_\_":
with open(result_path, 'wb') as fp:
runner = HTMLTestReportCN.HTMLTestRunner(stream=fp, title='自动化APP测试报告',
description='基于自动化APP测试框架产生的测试报告')
runner.run(test_suit())
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
43261)]
[外链图片转存中…(img-21TpkM8e-1715122143262)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!