目录结构

依然使用了常见的po 模式

  • 目录结构

    • config

      • config.ini 修改目标路由与相关配置
    • elements
      • 抽象页面空间元素
    • method
      • 抽象页面方法
    • TestCase
      • 测试用例
    • utils
      • Assert 自定义断言
      • chromedriver 浏览器驱动 需匹配版本 非linux 环境无视
      • Driver 初始化driver
      • graphical 图片相对定位
      • log 日志
      • seleniumBase api封装
      • seleniumOpt opt定义

初始化Driver

根据判断运行环境 选择不同的chrome driver 或者使用 ChromeDriverManager 自动下载

class Driver:@classmethoddef driver(cls):try:# select local or docker# if platform == "Darwin":# url = Config().get_conf("dockerHub", "url")# driver = webdriver.Remote(url, desired_capabilities=capabilities(),#                           options=options())# # else:if platform.system() == "Linux":executable_path = os.path.join(os.path.dirname(__file__), "chromedriver")driver = webdriver.Chrome(executable_path=executable_path, options=options())else:executable_path = ChromeDriverManager().install()driver = webdriver.Chrome(executable_path=executable_path, options=options())driver.implicitly_wait(20)log.info(f"driver:{driver.name}")return driverexcept BaseException as e:log.error(e)raise e

自定义driveroptions 配置

def options():"""浏览器设置:return:"""_options = ChromeOptions()# # 设置chrome为手机界面# mobileEmulation = Config().get_conf("seleniumOpt", "mobileEmulation")# if mobileEmulation == 'true':#     mobile_emulation = {"deviceName": "Galaxy S5"}#     _options.add_experimental_option("mobileEmulation", mobile_emulation)if platform.system() == 'Darwin':passelse:_options.add_argument('--headless')_options.add_argument('--no-sandbox')_options.add_argument('--disable-gpu')_options.add_argument('--disable-dev-shm-usage')return _options

Base类

封装常用API 把driver 实例化传入
查找元素尽量使用显示等待 expected_conditions
使用了Faker 可随意生成测试数据
查找元素失败 使用allure 上传截图

class SeleniumBaseConfig:faker = Faker(locale="zh_CN")Assert = Assertlog = get_log()def __init__(self, driver: webdriver):""":param driver: 驱动"""self.driver = driverdef find_element(self, locator: tuple, timeout=5):"""find_element:param locator: (xpath,xxx)(id,xxx):param timeout: timeout:return:"""try:element = WebDriverWait(self.driver, timeout).until(EC.presence_of_element_located(locator))self.log.info(f"[{self.find_element.__name__}]  locator: {locator} element: {str(element)}")return elementexcept WebDriverException as e:self.log.error(e)allure.attach(self.get_png(), "异常截图", allure.attachment_type.PNG)allure.attach("未找到: {}, 详细信息如下: {}".format(locator, e))raise e

自定Assert

很常规 没什么可说的

class Assert:@staticmethoddef assert_unequal(exp, res):try:log.info("ASSERT UNEQUAL: EXPECT IS [{}] RESULT IS [{}]".format(exp, res))assert exp != resreturn Trueexcept AssertionError as e:log.error("ASSERT UNEQUAL ERROR: EXPECT IS [{}] RESULT IS [{}]".format(exp, res))raise e

关于页面元素

根据op 依旧对页面抽象成类 并继承SeleniumBaseConfig
元素类1一对1配套

class RegisterMethod(SeleniumBaseConfig):def __init__(self, driver):super().__init__(driver)def register(self, mobile: str):"""注册:param mobile:return:"""self.send_keys(RegisterLogin.INPUT_NUMBER, mobile)self.click(RegisterLogin.NEXT_STEP_BUTTON)time.sleep(1)

对应元素类

class Register:# ================== 公共 ================# 下一步NEXT_STEP_BUTTON = ("xpath", "//button")# 返回RETURN = ('xpath', '//p[@class="return-prev-step"]')# input 错误信息INPUT_ERROR_INFO = ("xpath", '//p[@class="default-input-error"]')# ================== home界面 ================CREATE_BUTTON = ("xpath", "//div[text()='创建']")  # 创建buttonJOIN_BUTTON = ("xpath", "//div[text()='加入']")  # 创建buttonINPUT_TEAM_NAME = ("xpath", '//input[@placeholder="请输入团队名称"]')  # 输入团队名称INPUT_YOUR_NAME = ("xpath", '//input[@placeholder="请输入你的姓名"]')  # 输入个人名称

测试用例

@pytest.mark.P3@allure.title("创建新团队:姓名输入汉字、英文、数字字符")@pytest.mark.flaky(reruns=1, reruns_delay=2)def test_create_team_username(self):"""姓名输入汉字、英文、数字字符1.register2.create team3.create_team_username"""pics = []self.driver.register(self.mobile)exp = "true"res = self.driver.check_button_disabled()self.driver.allure_report(self.test_create_team_username, pics, exp, res)self.driver.Assert.assert_equal(exp, res)

Config 配置

一般配置host 等数据 使用ConfigParser读取写入
config.ini

[loginParam]
username = username
password = 123456[domain]
cm = xx
class Config:def get_conf(self, title, value):"""read .ini:param title::param value::return:"""log.info("{} : {}:{}".format(self.get_conf.__name__, title, value))return self.config.get(title, value)def set_conf(self, title, value, text):"""change .ini:param title::param value::param text::return:"""log.info("{} : {}:{}:{}".format(self.set_conf.__name__, title, value, text))self.config.set(title, value, text)with open(self.config_path, 'w+') as f:return self.config.write(f)

main 启动

使用sys.argv 获取命令行自定义参数

if len(sys.argv) > 3:runCase = sys.argv[1]  # P1 P2 P3 ALL  指定运行的用例等级if runCase != "ALL":case_path = f"-m={runCase}"xml = sys.argv[2] # 报告路径if xml:xml_report_path = xmlBUILD_NUMBER = sys.argv[3]args = ["-s", "-v", "-n=auto", case_path, '--alluredir', xml_report_path, '--clean-alluredir']pytest.main(args=args)

图片相对定位 获得坐标

场景

canvas 页面 无元素可定位

使用

先截取想要点击的位置图片 保存到本地
find_me 传入driver 对象
通过 center_xcenter_y 属性方法 获得相对坐标

class GraphicalLocator():def __init__(self, img_path):self.locator = img_path# x, y position in pixels counting from left, top cornerself.x = Noneself.y = Noneself.img = cv2.imread(img_path)self.height = self.img.shape[0]self.width = self.img.shape[1]self.threshold = None@propertydef center_x(self):return self.x + int(self.width / 2) if self.x and self.width else None@propertydef center_y(self): return self.y + int(self.height / 2) if self.y and self.height else Nonedef find_me(self, drv):  # Clear last found coordinatesself.x = self.y = None# Get current screenshot of a web pagescr = drv.get_screenshot_as_png()# Convert img to BytesIOscr = Image.open(BytesIO(scr))# Convert to format accepted by OpenCVscr = numpy.asarray(scr, dtype=numpy.float32).astype(numpy.uint8)# Convert image from BGR to RGB formatscr = cv2.cvtColor(scr, cv2.COLOR_BGR2RGB)# Image matching works only on gray images# (color conversion from RGB/BGR to GRAY scale)img_match = cv2.minMaxLoc(cv2.matchTemplate(cv2.cvtColor(scr, cv2.COLOR_RGB2GRAY),cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY),cv2.TM_CCOEFF_NORMED))# Calculate position of found elementself.x = img_match[3][0]self.y = img_match[3][1]# From full screenshot crop part that matches template imagescr_crop = scr[self.y:(self.y + self.height),self.x:(self.x + self.width)]# Calculate colors histogram of both template# and matching images and compare themscr_hist = cv2.calcHist([scr_crop], [0, 1, 2], None,[8, 8, 8], [0, 256, 0, 256, 0, 256])img_hist = cv2.calcHist([self.img], [0, 1, 2], None,[8, 8, 8], [0, 256, 0, 256, 0, 256])comp_hist = cv2.compareHist(img_hist, scr_hist,cv2.HISTCMP_CORREL)# Save treshold matches of: graphical image and image histogramself.threshold = {'shape': round(img_match[1], 2), 'histogram': round(comp_hist, 2)}# Return image with blue rectangle around matchreturn cv2.rectangle(scr, (self.x, self.y),(self.x + self.width, self.y + self.height),(0, 0, 255), 2)

pytest

pytest 有很多好用的功能、比如失败重跑、多进程并行用例、fixture 测试
用例参数化等等
详见 gitHUB-SeleniumUIAuto 中的 readme

使用selenium + pytest + allure做WBE UI自动化相关推荐

  1. python图片比对、自动化测试_基于python+appium通过图片对比来做的UI自动化

    1.python + appium +图片对比实现UI自动化: 背景: 当手机需要适配不同的语言时,测试过程中易出现因为语言不熟悉,导致UIbug被遗漏(例如setting中的描述性文字显示不完整等等 ...

  2. 【Selenium+Pytest+allure报告生成自动化测试框架】附带项目源码和项目部署文档

    目录 前言 [文章末尾给大家留下了大量的福利] 测试框架简介 首先管理时间 添加配置文件 conf.py config.ini 读取配置文件 记录操作日志 简单理解POM模型 简单学习元素定位 管理页 ...

  3. Python + Selenium实现web端的UI自动化

    我的第一个Python自动化用例 环境准备 安装好Python 下载最新Python 命令行下查看是否安装成功: Python自带运行环境: IDLE是Python自带的集成开发环境,在开始菜单中搜索 ...

  4. python自动化框架pytest接口关联串联_python(pytest)+allure+jenkins 实现接口自动化的思路...

    ABZ理论 前言 身为著名的创业者+投资人,LinkedIn和Paypal的联合创始人Reid Hoffman有一个令我印象深刻的ABZ理论,他认为,你在任何时刻,手中都需要有三个计划:A计划.B计划 ...

  5. 用 Pytest+Appium+Allure 做 UI 自动化测试的那些事儿

    本文首发于 TesterHome 社区, 文末有福利 !链接 https://testerhome.com/topics/19327 前言 做 UI 自动化测试有段时间了,在 TesterHome 社 ...

  6. 基于Selenium与Pytest框架的Web UI自动化测试系统的设计与实现

    摘要 随着互联网的高速发展,软件技术日新月异,产品更新换代的加快等,始终都离不开一个最核心的要素就是保证产品的质量,测试人员则在其中担任着不可或缺的角色.测试人员的主要工作职责就是通过各种测试手段去发 ...

  7. 软件测试知识点和面试题--UI自动化篇

    主流自动化测试框架介绍 软件测试的自动化一般可以分为3层 * 代码层的单元测试 * 接口层的集成测试 * UI 层的测试 1)代码层自动化 代码层的自动化一般指针对代码进行的单元测试,比较常用的单元测 ...

  8. 网易 UI 自动化工具 Airtest 浅用记录

    一 使用目的 该工具主要是面向游戏UI测试基于图像识别,如游戏框架unity,Cocos-js以及网易内部的游戏框架 同时也支持原生Android App 的基于元素识别的UI自动化测试. 本文主要使 ...

  9. 面试中有关UI自动化的那些事 ~

    面试官过程中UI自动化必问的几个问题总结: 一.有做过UI自动化吗?怎么做的?这个问题在面试中问UI自动化相关技能的时候常常被问到,那该如何去回答呢? 接下来我就UI自动化相关的一些面试的问题做一个解 ...

  10. 深圳软件测试培训:Pytest+Appium+Allure 做 UI 自动化的那些事

    深圳软件测试培训:Pytest+Appium+Allure 做 UI 自动化的那些事 文本主要介绍下 Pytest+Allure+Appium 记录一些过程和经历. 法主要用了啥: Python3 A ...

最新文章

  1. bootstrap的php写在哪里,bootstrap用什么编辑器写
  2. 【运筹学】匈牙利法 ( 匈牙利法示例 2 | 第一步 : 变换系数矩阵 | 第二步 : 试指派 | 行列打√ | 直线覆盖 | 第二轮试指派 )
  3. leetcode day5 -- Reorder List Linked List Cycle II
  4. python画图视频_如何在视频文件的第一帧上画图,然后继续显示整个视频
  5. 重磅 | 20+技术大咖齐聚 阿里云数据库创新上云峰会进入一周倒计时
  6. Apache配置同一IP使用多域名对应多个网站
  7. 刘志明 | 知识图谱及金融相关
  8. springCloud 微服务框架搭建入门
  9. linux/bsd四大防火墙我们选择谁
  10. 算法分析:Oracle 11g 中基于哈希算法对唯一值数(NDV)的估算
  11. ssm+安卓APP校园学生疫情防范监控系统毕业设计源码281444
  12. java 抓取网页_Java抓取网页数据
  13. 泛娱乐出海走出水土不服,元宇宙社交诞生新机会!
  14. Protel 99se 快捷键
  15. 计算机软件如何助力科研,研究生必备科研绘图软件,助力科学研究
  16. 【Java项目】社区论坛项目
  17. 电力自动化系统为何需要卫星同步时钟装置?
  18. 高中英语语法(002)-否定
  19. 基础算法:斐波那契函数学习
  20. 中国A类IP地址小调查以及IPv6展望

热门文章

  1. python打包exe反编译源码_python的exe反编译
  2. 闭环控制 matlab仿真,反馈闭环控制系统Simulink仿真(带电流补偿的电压内环,直流调速)...
  3. 安卓库-图表库: MPChartView
  4. FishC笔记—14 讲 字符串:各种奇葩的内置方法
  5. xxnet 360浏览器设置
  6. pe安装linux 12.04,乌班图系统Ubuntu 12.04安装教程(图文详解)
  7. Web前端-html页面-网易注册表单,美化及时验证效果
  8. python微信语音转发方法_最全的微信语音转发方法,最简单的方式大家已经帮你选出来了...
  9. php转换ofd文件格式,一种OFD格式文档支持脚本的方法与流程
  10. 适配ofd签章SES_CertList