app自动化框架配置文件
这是下厨房app自动化框架最基本的框架

具体环境部署参考其他博客
这里只做相关配置文件
一、config.ini配置文件相关参数以及操作config.ini文件方法

最基本的手机/模拟器配置config.ini文件如下:
[capabilities]
platformName= Android #指定移动平台
automationName= uiautomator2 #指定驱动
deviceName= 127.0.0.1:62001 #需要连接的虚拟机设备
noReset= True #每个会话要重置状态
forceAppLaunch= True #即使在后台运行,测试时也要重启应用
shouldTerminateApp= True #测试结束时要强制结束应用
;以上针对手机配置的
[app_number]
appPackage= com.xiachufang
appActivity= .home.HomeActivity
;以上针对app需要获取的
对于配置文件,有专门开一个config.py模块来操作config.ini文件,比如添加、读取
专门写一个Config类,里面有添加、修改方法、读取扇区方法
具体代码如下:
点击查看代码
import configparser
import os
CONFIG_PATH=os.path.dirname(os.path.abspath(__file__))
class Config:
"""操作config.ini文件的方法"""
#以下都是创建类实例时必须要做的初始化操作,所以要把他们放在init方法里
def __init__(self,filename):
# 传入一个文件(ini格式)
self.filename=filename
#创建自带的工具configparser(专门处理ini格式)来处理这个文件
self.cf=configparser.ConfigParser()
#因为这个工具改变原来的大小写optionxform,所以要用这个工具自带的方法来不改变大小写
self.cf.optionxform=str
#读取文件内容(要给文件路径)
self.cf.read(CONFIG_PATH,filename)
#接下来要写方法对config的增加、修改和读取
def add_config(self,section,option,value):
"""在config里面添加或修改东西,需要给扇区,选项,值 """
# set方法的作用是:在内存中修改配置(还没写到文件里)
#直接操作文件就像「用记事本手动改配置」,容易出错且麻烦;
#而 set 方法配合 configparser 就像「用专门的配置编辑工具」,会自动处理格式、保留原有内容、应对各种特殊情况,让代码更简洁、可靠
#所以先用set方法,然后再对配置文件进行添加和修改
self.cf.set(section,option,value)
#打开配置文件并写入
#这里使用join是因为两点:1.open第一个参数是一个完整的路径2.join会把路径和文件名拼接起来成一个参数
with open(join(CONFIG_PATH,self.filename),'w') as f:
#使用以上创建的工具的write方法来写入文件内容
self.cf.write(f)
#所有对config.ini的操作都是基于创建的工具来,在里面找方法来对ini文件进行操作
def read_config(self,section,option):
"""读取config文件内容,需要给哪个扇区,哪个选项,用get方法获取值并返回"""
return self.cf.get(section, option)
#为什么init里面有获取config内容的方法,却还需要单独写一个获取config内容的方法?
#__init__ 里的 self.cf.read(...) 是「加载整个配置文件到内存」,就像把一本字典书全部翻开摊在桌上。
#read_config(section, option) 是「从摊开的书中查找特定内容」,比如 "查一下第 3 章第 2 节写了什么
def read_section(self,section):
"""这个 read_section方法的作用是读取配置文件中某个区块(section)里的所有键值对
但是使用configparser(cf)工具会将所有内容读取成字符串,所以要将这些字符串转换成原本的类型"""
#先创建一个空字典,里面存放转换后的值
dct={}
#取出配置文件里面的扇区然后进行循环判断
for key,raw in self.cf.items(section):
try:
#如果将布尔值识别成字符串,使用getboolean能够把原本的布尔值转换成布尔值
dct[key]=self.cf.getboolean(section,key)
except valueError:
#如果上面转换布尔值转换失败就说明不是布尔值,就使用getint将原本的整数转换成整数
try:
dct[key]=self.cf.getint(section,key)
except valueError:
#如果整数转换就说明也不是整数,那么就使用原本的key=raw
dct[key]=raw
return dct
def read_capabilities(self,app_name):
"""将app_name和capabilities内容读取出来组装成完整的capabilities返回"""
#读取config文件里面的capabilities扇区内容
capa_dict=self.read_section('capabilities')
#读取config文件里面的app_name扇区内容
app_dict=self.read_section(app_name)
#将app_name的内容更新到capabilities内容里面
capa_dict.update(app_dict)
#返回完整的capabilities
return capa_dict
二、tools文件里面的工具(像打开APP)这种方法放在tools.py模块里面
打开APP,需要写一个类,里面有打开、滑动等方法(这些只写了打开)
具体代码如下:
点击查看代码
class OpenApp:
def __init__(self,capabilities):
"""打开app需要的前提准备——需要url、用配置信息建立远程连接"""
#appium获取的监控地址
self.appium_url='http://localhost:4723'
#建立远程连接(使用webdriver.Remote(url,options=传入应用的配置信息->配置信息指的就是capabilities,
#但是appium不认识字典格式)方法,UiAutomator2Options().load_capabilities(capabilities)方法是将字典capabilities能够转换成appium能够识别的格式)
self.driver=webdriver.Remote(self.appium_url,options=UiAutomator2Options().load_capabilities(capabilities))
def start(self):
return self.driver
#为什么不在init里面返回值
# init一般是赋值,不能返回值,返回的值永远是none
# 想要返回只能单独写一个方法
#因为 __init__ 是 Python 中特殊的「初始化方法」,它的职责是初始化对象的属性(比如给 self.driver 赋值),而不是「返回值」。
#即使你在 __init__ 里写 return self.driver,Python 也会忽略这个返回值(创建对象时,__init__ 始终返回 None)。
点击查看代码
"""基类页面-每个页面都要继承"""
class BasePage:
def __init__(self,driver):
#每个页面都需要驱动操作
self.driver=driver
四、base_case里面的BaseCase
主要是setup、tearDown方法,每个用例都需要执行
点击查看代码
class BaseCase(unittest.TestCase):
def setUp(self):
#需要使用config类里面读取capabilities方法读取配置信息
#将配置信息给OpenApp()的start方法来打开app
#1.创建config(需要给文件)
config=Config('config.ini')
#2.使用config里面的read_capabilities(需要给扇区)方法来读取配置文件内容
capabilities=config.read_capabilities('app_number')
#3.使用OpenApp(需要给配置文件内容)里面的start()方法来打开APP
self.driver=OpenApp(capabilities).start()
def tearDown(self):
self.driver.quit()

浙公网安备 33010602011771号