利用PO思想从0搭建app测试框架【demo】

实现思路:(以企业微信的通过手动输入添加成员为例)

PO思想六大原则(官网:https://martinfowler.com/bliki/PageObject.html):

(引用自:https://www.cnblogs.com/zxycb/p/13756662.html):

1. 公共的方法代表页面的服务

2. 不要暴露页面细节

3. 不要把断言和操作细节混用

4. 方法可以return到新打开的页面

5. 不要封装页面所有元素(用到哪些封装哪些)

6. 相同的行为会产生不同的结果,可以封装不同的方法

具体分析

原则一:要封装页面中的功能或服务,比如点击页面元素,可以进入到新的页面,则可为这个服务封装方法"进入新页面"

原则二:封装细节,对外只提供方法名(或者接口)

原则三:封装的操作细节中不要使用断言,把断言放到单独的模块中,比如:testcase

原则四:点击一个按钮会开启新的页面,可以用return方法链式跳转,比如return MainPage()表示跳转到主页

原则五:只为页面中重要的元素进行PO设计,舍弃不重要的内容;用到哪些再封装哪些

原则六:一个动作可能产生不同结果,比如点击按钮后,可能成功,也可能失败,为两种结果封装两个方法:click_success和click_error

1、梳理需要实现自动化的测试用例。

根据策略将需要实现的用例梳理出来,找其中一个先实现。

有时间可以建模,可以清晰页面的跳转关系(熟练了就没有必要输出了),类似如下这种

利用PO思想从0搭建app测试框架【demo】

2、构造PO模型

创建包结构:base、page、testcase

利用PO思想从0搭建app测试框架【demo】

根据用例涉及到的页面,创建页面相关的类和方法,具体的实现内容可以先跳过。

例如:base中的app.py

查看代码
class App:
    def start(self):
        """启动app"""
        return self  # 由于启动后要跳转到首页,所以这里返回self,便于调用into_main_page方法

    def stop(self):
        """停止app"""
        pass

    def restart(self):
        """重启app"""
        pass

    def into_main_page(self):
        """进入首页"""
        return MainPage()

例如:page中的main_page.py

查看代码
class MainPage:
    def goto_address_list(self):
        """跳转到通讯录页面"""
        return AddressListPage()

就这样用到那个就创建哪个页面类,链式的就把所有的都创建了,创建后的目录:

利用PO思想从0搭建app测试框架【demo】

3、编写测试用例

根据业务逻辑编写、链式调用、做结果校验,简单的调通,先把架子打起来,不用写细节

例如:testcase中的test_add_member.py

查看代码
class TestAddMember:
    def setup(self):
        self.app = App()
        self.main = self.app.start().into_main_page()

    def teardown(self):
        self.app.stop()

    def test_add_member_manual(self):
        """测试手动添输入加用例"""
        result = self.main.goto_address_list() \
            .goto_add_member_list() \
            .goto_add_member_manual() \
            .save() \
            .get_add_member_result()
        # todo 当前返回的是True,待完善后重新写断言
        assert result

 

4、填充各方法中的具体实现

  • 启动app
  • driver实例的传递
  • 补充细节操作

 

5、优化用例

  • 封装样板代码,提取页面元素
  • driver的复用:考虑每个class设置一次;每个case结束关闭app然后再次启动(这样不用每个case操作后都要返回到首页,缺点是重复启动浪费时间)

思路就是:让driver默认值为None首次肯定为None则首次一定会初始化;后面case执行时如果服务挂掉也会重新初始化;然后case之间只是关闭app,driver并不为None,就可以复用driver。

  • 初始化的desire_capability数据可以考虑放到配置文件中或者数据库,便于维护、管理。

 

6、并发执行

思路:当有多台机器时,执行pytest时需要配置appium client与server之间的端口,指定设备uuid

  • desire_capability中添加udid,并动态获取,指定设备;链接的端口改为动态获取
    • udid = os.getenv("uuid")
      port = os.getenv("port")
    • "uuid": udid,
    • self.driver = webdriver.Remote(f"http://localhost:{port}/wd/hub", desire_cap)
  • 另外开启一个cmd窗口,再启动server并指定端口:appium –session-override –p 4725 (端口号默认是4723,自己也可以指定一个端口)
  • 执行时指定参数:
    • mac系统:udid="127.0.0.1:7555" port=4723 pytest test_add_member.py
    • windows:set udid="127.0.0.1:7555",回车后再输入 set port="4723",回车后再输入 pytest test_add_member.py

利用PO思想从0搭建app测试框架【demo】

7、继续下一条用例输出

 

demo地址:https://gitee.com/fengyudeleishui/autotest/tree/master/homework/task_app

 

 

 

 

 

z

上一篇:JUC练习3——lock实现精准唤醒demo


下一篇:Mybatis源码学习(二)简单Demo的运行原理