当前位置: 首页 > news >正文

Appium+python自动化(三十二)- PageObject+unittest

kyb_login.py
代码实现
# coding=utf-8
from appium import webdriver
import yaml
from selenium.common.exceptions import NoSuchElementException
import logging
import logging.configCON_LOG='../log/log.conf'
logging.config.fileConfig(CON_LOG)
logging=logging.getLogger()stream=open('../yaml/desired_caps.yaml','r')
data=yaml.load(stream)desired_caps={}
desired_caps['platformName']=data['platformName']desired_caps['platformVersion']=data['platformVersion']
desired_caps['deviceName']=data['deviceName']desired_caps['app']=data['app']
desired_caps['noReset']=data['noReset']desired_caps['unicodeKeyboard']=data['unicodeKeyboard']
desired_caps['resetKeyboard']=data['resetKeyboard']desired_caps['appPackage']=data['appPackage']
desired_caps['appActivity']=data['appActivity']driver = webdriver.Remote('http://'+str(data['ip'])+':'+str(data['port'])+'/wd/hub', desired_caps)def check_updateBtn():logging.info("check_updateBtn")try:element = driver.find_element_by_id('android:id/button2')except NoSuchElementException:logging.info('update element is not found!')else:element.click()def check_skipBtn():logging.info("check_skipBtn")try:element = driver.find_element_by_id('com.tal.kaoyan:id/tv_skip')except NoSuchElementException:logging.info('skipBtn element is not found!')else:element.click()check_updateBtn()
check_skipBtn()logging.info('start login...')driver.find_element_by_id('com.tal.kaoyan:id/login_email_edittext').send_keys('自学网2018')
driver.find_element_by_id('com.tal.kaoyan:id/login_password_edittext').send_keys('zxw2018')
driver.find_element_by_id('com.tal.kaoyan:id/login_login_btn').click()
logging.info('login finished')
案例分析

上面的脚本看似都比较完善,有了log采集,参数配置、启动时页面元素自动检测。但是也存在一些不足之处:

  • 公共模块和业务模块混合在一起显得代码冗余等
  • 测试场景单一(如果要实现如下测试场景该怎么办?)
  • 元素定位属性和代码混杂在一起

以上这些都是需要优化的地方。

重构优化思路
将一些公共的内容(如:check_updateBtn,check_skipBtn,capability)抽离出来。
元素定位方法和元素属性值与业务代码分离
登录功能模块封装为一个独立的模块
使用unittest进行用例综合管理
Page Object
Page Object是Selenium自动化测试项目开发实践的最佳设计模式之一,通过对界面元素的封装减少冗余代码,同时在后期维护中,若元素定位发生变化,只需要调整页面元素封装的代码,提高测试用例的可维护性。

脚本实现
封装App启动配置信息
desired_caps.py

# coding=utf-8
from appium import webdriver
import yaml
import logging
import logging.configCON_LOG='../log/log.conf'
logging.config.fileConfig(CON_LOG)
logging=logging.getLogger()def appium_desired():file = open('../yaml/desired_caps.yaml', 'r')data = yaml.load(file)desired_caps={}desired_caps['platformName']=data['platformName']desired_caps['platformVersion']=data['platformVersion']desired_caps['deviceName']=data['deviceName']desired_caps['app']=data['app']desired_caps['appPackage']=data['appPackage']desired_caps['appActivity']=data['appActivity']desired_caps['noReset']=data['noReset']desired_caps['unicodeKeyboard']=data['unicodeKeyboard']desired_caps['resetKeyboard']=data['resetKeyboard']logging.info('start app...')driver=webdriver.Remote('http://'+str(data['ip'])+':'+str(data['port'])+'/wd/hub',desired_caps)driver.implicitly_wait(8)return driverif __name__ == '__main__':appium_desired()

记得在原来的yaml配置表desired_caps.yaml补充如下内容:

unicodeKeyboard: True 

resetKeyboard: True

封装基类: 
baseView.py
代码实现
# coding=utf-8
class BaseView(object):def __init__(self,driver):self.driver=driverdef find_element(self,*loc):return self.driver.find_element(*loc)
封装通用公共类
common_fun.py
代码实现
# coding=utf-8from page_object.baseView import BaseView
from page_object.desired_caps import appium_desired
from selenium.common.exceptions import NoSuchElementException
import logging
from selenium.webdriver.common.by import Byclass Common(BaseView):cancelBtn=(By.ID,'android:id/button2')skipBtn=(By.ID,'com.tal.kaoyan:id/tv_skip')def check_cancelBtn(self):logging.info('==========check_cancelBtn=========')try:cancelBtn = self.driver.find_element(*self.cancelBtn)except NoSuchElementException:logging.info('no cancelBtn')else:cancelBtn.click()def check_skipBtn(self):logging.info('=========check skipBtn=============')try:skipBtn = self.driver.find_element(*self.skipBtn)except NoSuchElementException:logging.info('no skipBtn')else:skipBtn.click()if __name__ == '__main__':driver=appium_desired()com=Common(driver)com.check_cancelBtn()com.check_skipBtn()
封装登录操作 
loginView.py
代码实现
# coding=utf-8
import logging
from page_object.common_fun import Common
from page_object.desired_caps import appium_desired
from selenium.webdriver.common.by import Byclass LoginView(Common):username_type=(By.ID,'com.tal.kaoyan:id/login_email_edittext')password_type=(By.ID,'com.tal.kaoyan:id/login_password_edittext')loginBtn=(By.ID,'com.tal.kaoyan:id/login_login_btn')def login_action(self,username,password):self.check_cancelBtn()self.check_skipBtn()logging.info('============login_action==============')logging.info('username is:%s' %username)self.driver.find_element(*self.username_type).send_keys(username)logging.info('password is:%s'%password)self.driver.find_element(*self.password_type).send_keys(password)logging.info('click loginBtn')self.driver.find_element(*self.loginBtn).click()logging.info('login finished!')if __name__ == '__main__':driver=appium_desired()l=LoginView(driver)l.login_action('程序员的世界你不懂','干')

unittest用例封装

测试场景

使用如下账号进行分别登录测试

1.封装用例启动结束时的配置: 
myunit.py
代码实现
# coding=utf-8import unittest
from page_object.desired_caps import appium_desired
import logging
from time import sleepclass StartEnd(unittest.TestCase):def setUp(self):logging.info('=====setUp====')self.driver=appium_desired()def tearDown(self):logging.info('====tearDown====')sleep(5)self.driver.close_app()

2.用例封装 
test_login.py
代码实现
# coding=utf-8from unittest.myunit import StartEnd
from page_object.loginView import LoginView
import unittest
import loggingclass TestLogin(StartEnd):def test_login_bjhg2019(self):logging.info('======程序员的世界你不懂=====')l=LoginView(self.driver)l.login_action('程序员的世界你不懂','干')def test_login_bjhg2018(self):logging.info('======程序员的世界你不懂=====')l=LoginView(self.driver)l.login_action('程序员的世界你不懂','测试一下看看')def test_login_error(self):logging.info('======test_login_error=====')l = LoginView(self.driver)l.login_action('88888', '222464564')if __name__ == '__main__':unittest.main()

相关文章:

  • 树莓派超全系列教程文档--(66)rpicam-apps可用选项介绍之视频选项
  • 区块链大讲堂 | 分布式隐私计算友好的零知识证明协议
  • 举出一个异步接口测试的例子
  • 解锁数据潜能——亮数据Web数据集,精准、全面、即时
  • 阿里云获取DASHSCOPE_API_KEY教程,以及配置DASHSCOPE_API_KEY环境变量
  • 【设计模式精讲 Day 12】代理模式(Proxy Pattern)
  • 单片机测ntc热敏电阻的几种方法(软件)
  • 【C++】第十二节——详解list(上)—(list的介绍和使用、模拟实现)
  • 在Neo4j中高效处理字符串数组:完整指南与实践
  • vue | vue-macros 插件升级以及配置
  • Flink SQL解析工具类实现:从SQL到数据血缘的完整解析
  • 6.23 deque | 优先队列_堆排序 | 博弈论
  • Python 数据分析与可视化 Day 5 - 数据可视化入门(Matplotlib Seaborn)
  • 基于springboot+uniapp的“川味游”app的设计与实现7000字论文
  • go channel用法
  • 微算法科技(NASDAQ:MLGO)研发可信共识算法TCA,解决区块链微服务中的数据一致性与安全挑战
  • 拼团系统多层限流架构详解
  • 针对我的简历模拟面试
  • 采集MFC软件的数据方法记录
  • Flutter开发中记录一个非常好用的图片缓存清理的插件
  • 沈阳网站开发公司电话/seo百科大全
  • 怎么用百度网盘做网站/上海关键词优化外包
  • 现在网站开发都什么技术/东莞网络营销推广公司
  • 网站建设说明书/关键词歌曲歌词
  • 网站策划的最终体现/百度代运营公司
  • 住房和城乡建设部干部学院网站/免费制作网站的软件