新手区 2015 年 3 月 新秀群作业-- Appium+Python+PO 设计模式 入门笔记

JennyHui · 2015年03月20日 · 最后由 81—1 回复于 2020年11月23日 · 7474 次阅读
本帖已被设为精华帖!

什么是 PageObject?

  • 属于 selenium 的一种设计模式,套用在 appium 身上了(实践表明,合适,因为 selenium 和 appium"本是同根生")
  • 个人对于 PO 的理解就是,页面元素 - 页面业务操作步骤的方法 - 测试用例(我知道抽象,大家自行谷哥了解下)

下图是我的代码结构:
Data:测试数据。后期准备把代码中会所有测试数据都整合到 excel 或者 xml 内,Data 文件夹就是这个用处
PO:所有 Page。以 Base 页面为基础(看下图分析,来理解 PO)
Public:一些公共的方法,比如测试报告脚本,封装好的
Result:测试结果,包括测试报告和截图
TestCase:测试用例都放这儿
run_case:测试套件,利用 HTMLTestRunner.py,输出测试报告到/Result 下

Base 内重新封装的是基础的 webdriver 方法和一些你自己测试用例有需要的公用方法,PO 内的其他 Page 都是继承自 Base
appium 与 selenium 的唯一不同就是对 driver 的设置上

在这里 driver 的调用,我感觉自己还没写好,我的需求是只在 Base 内定义好 driver,指定好端口,所有测试用例共用一个 driver,直接在测试用例内调用,我调试过了,自己 python 水平也是一般,没改出来,后期我再改善一下这个。

直接在 Page 内封装整个业务流程的方法,测试用例中代码量会少很多。(当然写在测试用例中也是可以的)
简单说明下:

  • 场景:登录业务
  • Page 内:a.输入用户名 b.输入密码 c.点击登录按钮;A.登录方法(包含 abc)
  • 测试用例内: 1.直接调用 Page 的 A;2.顺序调用 Page 的 abc 这两种方式各有各的利弊,各取所需吧

测试用例我用的是 unittest
我这个 demo 没有写断言,没有打 log,测试数据也没有放到外部文件。这些都是后期要改善的

关于报告的输出

通过测试套件去驱动 HTMLTestRunner 生成测试报告,并且加入了截图功能(这些都是参考 selenium 大神 Ray 的,请参照他的 coding:https://coding.net/u/tsbc/p/PySelenium_PO/git

总结

demo(https://github.com/JennyHui/appiumDemo/tree/master/pythonDemo%20v1.0
整体看来框架的搭建是很简单的,但也算是五脏俱全吧(好吧,还差几个,我知道啦)。个人觉得对于框架怎么搭,用哪种设计模式,用哪种工具,选择性还是很多的。跟 web 类似的啊,关键字,PO,RF......各取所需吧各位,而且,不同的设计模式下,代码结构如何,也是看各人选择的。

下一阶段学习,就像我写的完善 driver 调用,打 log,加断言,测试数据移至 excel,有些人页面元素也想放到 config 内,这一点大家可以根据项目来权衡。

如果我可以,你也可以,因为我是菜鸟。请在一个礼拜之内搞定你的代码结构哦

共收到 58 条回复 时间 点赞

实在不会总结嗷嗷嗷

赞赞赞!!!

看到这个帖子感觉很情切,我也是 python 出身,同样也用 webdriver 在移动端和 web 端做了几个自动化的项目,分享下我们的做法和思路,希望能抛砖引玉。
1,我们是采取的数据和脚本分离的形式来控制业务的逻辑和次序的,目前来看这样其实很好,首先脚本调用的是外部 xls 里面的数据,即使没有代码经验的人,也可以通过 xls 表格来进行自动化的业务参数配置。
2,对象库的管理,同样会放在 xls 里面,通过动态调用来实现,这样在脚本内就不会存在有大量的元素信息,一来维护不便,二来方便我们阅读。
3,我们还有点不同的是,我们将需要导入的包,都放在了一个 import.py 的文件里,所有脚本统一导入这个.py 文件,这样节省了很多不必要的代码量。
4,我们对脚本的逻辑控制,业务参数控制均抽离出来,放在 xls 里,类似于 UI 层的控制,脚本直接调用不必每次在脚本内修改代码,造成不必要的问题和维护。

参考下我们的模式希望有所共鸣,欢迎大家指正。

受教了,又学了一个很不错的设计模式!

学习了,回头有空把 ui 的自动化测试做起来

赞一个,一直在用 Page Object model

移动时代,改名为 screen object

#3 楼 @seasoncool2011 页面元素,定位方法,测试数据 都放在 xls 内是伐~我研究过这个~属于关键字驱动的~很赞!! 设计好 excel 表一切万事大吉!!! 赞赞赞~因为我自己自动化项目经验不多~想先把 PO 实践好再来整关键字~ps 第三点建议不错~我收了~么么哒 👏

app 路径放在哪里,如何取包安装?

目录结构很受教!多谢分享!

请教一个问题。web 页面的元素是怎么获取的呢,据我所知 uiautomator 是无法获得 webview 内的具体信息的,还望分享。

这个问题已经困扰了我好几天,但似乎在别人看来都不是问题!?

我眼前的这层窗户纸希望能有人看到,并帮我捅破,谢谢了,泪奔中~~~

#11 楼 @sunflower 我今天刚好也在折腾这个。webview 切换进去后,我手机版本连着 uiautomator 看不到 webview 下的信息,所以我用抓包的方式去找。虽然我手机代理有点问题吧。(也可以用浏览器去开这个 web 去定位出页面元素)
可以参考下这个帖子:http://testerhome.com/topics/2303

#12 楼 @jennyhui 谢谢回复。但不知你说的” 用抓包的方式去找 “和” 用浏览器去开这个 web 去定位出页面元素 “具体怎么操作呢?我已经看了http://testerhome.com/topics/2303adb这个帖子,关键是用 shell uiautomator dump 的方式大多数时候都 dump 不到 webview 里的信息(不论是纯 web 还是 hybrid app),不知你遇到这个问题没,希望进一步探讨。

#13 楼 @sunflower 是啊我也刚发现还是不行我刚在群里问了【只要到 webview 界面下,chrome inspect 可以自动获取】~估计还是得用浏览器去打开,然后查看 html 元素~~~看一下这个帖子http://testerhome.com/topics/1719

#14 楼 @jennyhui 这种 remote debugging 的方式我也尝试过,但 inspect 后出来一个空白页面。怀疑是我安装的插件不对,从https://developer.chrome.com/devtools/docs/remote-debugging应该能得到一些信息,但这个网址一直打不开,不知道是不是需要 *** 才能代开啊。。。

#15 楼 @sunflower 哦哦哦厉害我还在看话说你 webview 是国内得页面吗 如果是应该不用啊~webview 也是够纠结的~~~

#16 楼 @jennyhui 是啊,手机里就打开了一个 baidu 的首页。。。能否帮我看一下你那https://developer.chrome.com/devtools/docs/remote-debugging能打开吗?没用过 *** 工具啊

#17 楼 @sunflower 啊 我试一下 我是菜鸟呢 我还没有用用过 remote 调试的方式 抓取信息过 咳咳 我先看下

#17 楼 @sunflower https://developer.chrome.com/devtools/docs/remote-debugging 这个网站我 *** 可以开启来 我刚才脚本试了个 demo 还报错呢(selenium.common.exceptions.WebDriverException: Message: unknown error: cannot parse capability: chromeOptions
from unknown error: unrecognized chrome option: mobileEmulation )容我在研究一下 咳咳

#19 楼 @jennyhui 这个网站里面可能有新的 chrome adb plugin,你把这个 plugin 添加到你的 chrome 浏览器里然后在地址栏输入 chrome://inspect,应该就可以用了。

#20 楼 @sunflower 不用安装什么插件啊!~我谷歌直接开 chrome://inspect 就可以了 ~ 手机记得设计开启 USB 调试 ~~ 真的可以啊哈哈 好开心解决了 不过就是画面不出来不知道哪个元素对哪一个 = = 我再折腾一下 感觉离终点越来越近了

#21 楼 @jennyhui 我怎么这个坎坷呢😟 ,不过这个证明这个方法确实是好用的,你用的 chrome 版本和手机版本是多少啊 我找找差异

#22 楼 @sunflower 手机是安卓 5.0 的 chrome 是 41 的

你为啥这么牛。 模板 jenny 大神。

请教一下这个 demo 可以直接运行吗..

能不能更详细点讲解,我这边是在 eclipse(安装了 python 插件) 建立一个自己的 python project, 然后按照你的 project 结构导入代码文件,但是在执行时 Traceback (most recent call last):
File "/Users/fangcheng/Desktop/EclipseWorkSpace/AppiumWeb/run_case.py", line 25, in
test_case = Creatsuite()
File "/Users/fangcheng/Desktop/EclipseWorkSpace/AppiumWeb/run_case.py", line 16, in Creatsuite
discover = unittest.defaultTestLoader.discover(case_path, pattern='Test_*.py', top_level_dir=None)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/loader.py", line 190, in discover
import(start_dir)
ValueError: Empty module name

我运行示例代码也出现了如楼上所述的问题,还请楼主详细讲解一下。

#26 楼 @xxfcxx
#27 楼 @ellaw
目测是你路径写错了 检查一下

#28 楼 @jennyhui demo 的网址不能用了啊?能请各位有 demo 的提供一下吗

#30 楼 @jennyhui 非常感谢,等着好好研究下

感谢分享!

#30 楼 @jennyhui 你 qq 多少,加你问下具体问题

好屌,嗷嗷嗷

不错的设计模式

@halo_lan 必须的,我最佩服的厦门女测开一枚,没有之一!

@very 拿下妹子

@halo_lan 哈哈,拿不下

请问,这个在 testcase 里面,创建多个 testcase 时,是不是需要每个 testcase 里面都要创建一个 seesion

#39 楼 @lework 不是。appium 启动只开一个 session。测试集内的是按照你 testcase 顺序跑的。

#34 楼 @very 认识? 😪

@jennyhui 必须认识啊。。。

#42 楼 @very 你是谁呢?

看了以后 很有感触 这是我的目标啊

#45 楼 @louqqson008 嗯。如果你觉得项目合适,可以用这种方式。不过我觉得 PO 不是最优方案。你可以了解下关键字。

@jennyhui 谢谢你的建议,目前遇到无法识别 toast,并且获得 toast 的 TEXT,而无法继续进行 android 自动化,可否给点建议,目前我的想法是获得 toast 提示的 TEXT 和我预期知道会得到的提示 TEXT 进行比较来验证用例,现在无法获得就进行不下去了

#47 楼 @louqqson008 appium 暂不支持哦~robotium 可以~appium 未来应该会支持~

请教一下,所有测试用例共用一个 driver,在 page 页面中如何实现对该 driver 的调用及继承 Appium 已经封装好的 Android 方法呢(避免重新定义方法)?

妹子加个 qq 呗

#49 楼 @laiyuncong8404
可以把 driver 的实例化封装在一个类方法内~(这是其中的一个方法而已)
不过如果后期希望做到不同设备不同 driver 跑同一份测试脚本(或者其他并发策略)就要另外对 driver 做其他处理(论坛内有不少帖子实现了并发的功能了)

#BasePage

    //初始化driver
    public AndroidDriver SetDriver() throws MalformedURLException {
        try{
            driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), this.SetCa());

        }catch (MalformedURLException e){
            e.printStackTrace();
        }
        return driver;
    }
#DashPage

    /**
     * 业务封装
     */

    //搜索 - 收藏
    public void Search(String recipe,Class name) throws IOException, InvalidFormatException {
        LoggerControler log = this.MyLogger(name);
        AndroidDriver driver = super.SetDriver();
        this.ClickSearchBox();
        this.InputRecipe(recipe);
        log.info("本次搜索的食材是:"+recipe);
        driver.sendKeyEvent(66);
        this.ClickCollectionItem();
        //this.ClickFavorite();
        log.info("收藏的菜谱名为:"+this.GetRecipeName());
        super.captureScreen("Search_"+recipe);
        Assert.assertTrue(GetRecipeName().contains(recipe));
        log.info("该Case测试通过");
    }

感谢楼主分享,对于比你还新手的我来说,你的文章既是一份学习资料,也是一种鼓励。

@jennyhui
新手求指教,这句的作用是啥?
def init(self,appium_driver):
self.driver = appium_driver

kaige201314 [该话题已被删除] 中提及了此贴 07月22日 16:54

@jennyhui 请问 page object 这个 driver 怎么定义的呢,我现在用 PO 模式写,当 import 登录文件,调用登录函数方法时,老报:没有 driver

初学,求带带

miaoyan 回复

解决没 我也一直遇到这个问题

python3.6 不支持这样的语法了吗?初学者不懂

print(testunit)

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册