项目结构
代码语言:javascript复制├── data # 存放元素定位yaml文件
├── src # 源代码
│ ├── cases # 测试用例
│ ├── pages # 元素业务操作类
│ ├── tools # 常用工具
│ └── utils # 封装的类
├── .gitignore # 上传git时候忽略的文件
├── Jenkinsfile # jenkins运行流程
├── README.md # 项目说明
└── requirements.txt # python包管理
根据上述方式创建好文件之后,把我们之前写的元素操作放到utils
文件夹中去
yaml
文件放到data
文件夹中
另外UI测试的时候需要打开浏览器,把不同操作系统对应的driver放到tools
文件夹中
https://github.com/allure-framework/allure2/releases
后面需要在使用到allure
来生成报告,下载一份allure.zip解压后将它也放到tools
文件夹中
摆放之后的文件夹如下:
常量文件
随着项目变大,里面的文件也越来越多,所以需要一个变量快速的拿到我们想要的路径
在utils
文件夹中新增一个constant.py
文件
首先拿到当前项目根节点的绝对路径
使用os.path.abspath(__file__)
拿到当前文件夹的绝对路径
使用os.path.dirname(path)
拿到path
的上一层路径
使用三次就可以拿到根路径地址了:当前文件
→utils
→src
→uitest
BASE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
接下来就是根据根路径使用os.path.join()
方法进行路径拼接了
import os
BASE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
BASE_DATA_PATH = os.path.join(BASE_PATH, 'data')
SRC_PATH = os.path.join(BASE_PATH, 'src')
TOOL_PATH = os.path.join(SRC_PATH, 'tools')
ALLURE_TOOL_PATH = os.path.join(TOOL_PATH, 'allure-2.14.0/bin')
在测试过程中,需要有一些文件夹存放一些临时的文件
这些文件夹可以在运行的过程中判断是否存在,如果不存在则创建
代码语言:javascript复制LOG_PATH = os.path.join(BASE_PATH, 'log')
REPORT_PATH = os.path.join(BASE_PATH, 'report')
TEST_PIC = os.path.join(REPORT_PATH, 'test_pic')
for i in [LOG_PATH, REPORT_PATH, TEST_PIC]:
if not os.path.exists(i):
os.mkdir(i)
现在我们就可以通过constant.py
文件拿到项目中的路径了
打开浏览器
到这里我们就能使用绝对路径拿到driver
文件去打开浏览器了
设置desired_capabilities
desired_capabilities
可以设置的方式有三种
- none: 当html下载完成之后,不等待解析完成,selenium会直接返回
- eager: 要等待整个dom树加载完成,即DOMContentLoaded这个事件完成,仅对html的内容进行下载解析
- normal: 即正常情况下,selenium会等待整个界面加载完成(指对html和子资源的下载与解析,如JS文件,图片等,不包括ajax)
在进行UI自动化测试的时候经常会遇到一个奇怪的问题,也就是人工去操作没有问题,但是使用脚本操作的时候却提示没找到元素,或者脚本迟迟不进行下一步操作
这可能是因为某几个资源没有加载完成导致的。这时候我们可以将desired_capabilities
设置为eager
只要DOM加载完毕,元素基本上就可以找到和操作了
代码语言:javascript复制from selenium.webdriver import DesiredCapabilities
desired_capabilities = DesiredCapabilities.CHROME
desired_capabilities["pageLoadStrategy"] = "eager"
webdriver.Chrome(desired_capabilities=desired_capabilities)
确定当前操作系统
代码语言:javascript复制platform.system()
- Windows
- Linux
- Darwin
if platform.system() == "Windows":
driver_path = f'{TOOL_PATH}/driver/win/chromedriver'
elif platform.system() == "Linux":
driver_path = f'{TOOL_PATH}/driver/linux/chromedriver'
os.system(f"chmod -R 777 {driver_path}")
else:
driver_path = f'{TOOL_PATH}/driver/mac/chromedriver'
os.system(f"chmod -R 777 {driver_path}")
对没有图形化界面的Linux系统,需要使用无头浏览器运行
代码语言:javascript复制chrome_option = Options()
chrome_option.add_argument('--headless')
chrome_option.add_argument('--no-sandbox')
chrome_option.add_argument('--disable-gpu')
chrome_option.add_argument('--disable-dev-shm-usage')
运行H5
使用H5的方式运行,需要修改浏览器的mobileEmulation
配置
chrome_option = Options()
chrome_option.add_experimental_option('mobileEmulation', {'deviceName': deviceName})
chrome_option.add_experimental_option('w3c', False)
完整的打开浏览器操作
增加一些异常处理、兼容性处理
- HEADLESS:是否采用无头浏览器模式
- True:是
- False:否
打开浏览器后最大化
代码语言:javascript复制try:
self.driver.maximize_window()
except Exception as e:
print(f"浏览器最大化失败:{e}")
切换frame
代码语言:javascript复制def switch_frame(self, frame_locator):
self.driver.switch_to.default_content()
self.driver.switch_to.frame(frame_locator.element)
完整代码
代码语言:javascript复制def open(self, url, locator, frame_locator=None, driver='chrome', deviceName='iPhone X'):
"""
:param url: 打开的地址
:param locator: 确认打开成功的元素
:param frame_locator: 需要切换的frame
:param driver: 浏览器驱动
:param deviceName: h5测试设备型号
:return:
"""
driver = driver.lower()
if driver in ['chrome', 'ie', 'chrome-h5']:
try:
socket.setdefaulttimeout(50)
if not self.driver:
if 'chrome' in driver:
desired_capabilities = DesiredCapabilities.CHROME
desired_capabilities["pageLoadStrategy"] = "eager"
chrome_option = Options()
if HEADLESS == 'true':
chrome_option.add_argument('--headless')
if driver == 'chrome-h5':
chrome_option.add_experimental_option('mobileEmulation', {'deviceName': deviceName})
chrome_option.add_experimental_option('w3c', False)
if platform.system() == "Windows":
driver_path = f'{TOOL_PATH}/driver/win/chromedriver'
elif platform.system() == "Linux":
chrome_option.add_argument('--headless')
chrome_option.add_argument('--no-sandbox')
chrome_option.add_argument('--disable-gpu')
chrome_option.add_argument('--disable-dev-shm-usage')
driver_path = f'{TOOL_PATH}/driver/linux/chromedriver'
os.system(f"chmod -R 777 {driver_path}")
else:
driver_path = f'{TOOL_PATH}/driver/mac/chromedriver'
os.system(f"chmod -R 777 {driver_path}")
logger.info(f'使用的chromedriver为「{driver_path}」。请确认版本是否与当前浏览器版本一致')
self.driver = webdriver.Chrome(executable_path=f'{driver_path}',
chrome_options=chrome_option,
desired_capabilities=desired_capabilities)
elif driver == 'ie':
ie_options = DesiredCapabilities.INTERNETEXPLORER # 将忽略IE保护模式的参数设置为True
ie_options['ignoreProtectedModeSettings'] = True # 忽略浏览器缩放设置
ie_options['ignoreZoomSetting'] = True # 启动带有自定义设置的IE浏览器
self.driver = webdriver.Ie(capabilities=ie_options)
time.sleep(2)
self.driver.get(url)
time.sleep(5)
try:
self.driver.maximize_window()
except Exception as e:
print(f"浏览器最大化失败:{e}")
if frame_locator:
self.wait_element_visible(frame_locator)
self.switch_frame(frame_locator)
if locator:
self.wait_element_visible(locator)
except Exception as e:
raise Exception(f"打开浏览器进入{url}失败:{e}")
self.wait_for(10)
return self.driver
项目地址
新建了一个version_1
分支:
https://gitee.com/zx660644/uitest/tree/version_1/