2024年最全Appium PO模式UI自动化测试框架——设计与实践_po模式自动化框架,面试经历分享

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事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())


img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

43261)]
[外链图片转存中…(img-21TpkM8e-1715122143262)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值