背景
UI 自动化测试,即通过自动化的伎俩来管制机器模仿人进行手工操作。随着 GrowingIO 业务的一直倒退,新需要的一直减少,回归测试的工作越来越重,现有测试的资源曾经不足以应答沉重的回归测试工作,亟需 UI 自动化来代替人手工进行回归测试,解放回归测试的人力去做更精准的测试。因而,引出下文在 GrowingIO 的Web UI 自动化的建设,本文次要就以下两个方面开展介绍:
1.框架搭建
2.集成品质平台
框架搭建
PageObject
家喻户晓,UI 自动化测试,是位于测试金字塔塔尖的地位,ROI 低。其痛点次要体现在:
1.测试用例保护老本高,页面元素定位形式或者布局有一些轻微的变动,之前写好的代码可能就有很大的改变;
2.代码冗余,复用性低,可读性不好。
针对以上痛点,同时也通过大量调研,决定应用 PageObject 设计模式,其核心思想为六大准则:
- 公共办法代表页面提供的服务
- 不要裸露页面细节
- 不要把断言和操作细节混用
- 办法能够 Return 到新的页面
- 不要把整页内容都放到 PageObject 中
- 雷同的行为产生不同的后果,能够封装不同后果
根据以上六大准则,并联合 GrowingIO 具体业务的状况,目录层级设计如下:
- BasePage 层:封装对网页的一些根底操作的办法,比方关上浏览器、查找元素、截屏等
- Component 层:继承 BasePage 层,封装了对页面中公共组件的操作方法,比方工夫组件
- Page 层:继承Component层,该层中的每个办法都对应以后页面的一个性能,办法里能够调用Component 层中的办法或调用 BasePage 层中封装的办法
- TestCase 层:调用业务 Page 层中封装的办法,编写业务 Case,并做断言
理论我的项目的目录分层如下:
├── basepage│ └── base_page.py├── component│ └── element_design.py├── conf│ ├── conf.py├── datas├── log│ └── all.log├── log.py├── page│ ├── home_page.py│ ├── login_page.py│ ├── main_page.py│├── pytest.ini├── report│ ├── requirements.txt├── run_all_cases.py├── testcase│ ├── conftest.py│ ├── testcase.py│└── util └── util.py
Selenium + Python
语言选择 Python,对于新人敌对且组内人员比拟相熟,能够迅速上手;
目前市场上的 Web UI 自动化测试计划百花齐放,基于底层技术的不同大体上分为以下几类:
1.WebDriver Protocol 类:
如 Selenium 3,WebdriverIO,Protractor,Nightwatchjs
2.Proxy JS 注入类:
如 Selenium RC,TestCafe,Cypress
3.DevTool Protocol 类:
如 Puppeteer, Playwright t
咱们抉择应用 Selenium 3,劣势如下:
- 开源、收费
- 多浏览器反对:Firefox、Chrome、IE、Opera、Edge
- 多平台反对:Linux、Windows、Mac
- 多语言反对:Java、Python、Ruby、C#、JavaScript、C++
- 对 Web 页面有良好的反对
- 简略(API 简略,API:在类外面封装好的办法,即裸露给他人的一个可用的接口)、灵便(用开发语言驱动)、足够稳固
最次要的是 Selenium 的 Grid 计划即分布式计划十分成熟,而所谓的分布式就是由一个 Hub 节点和若干个 Node 代理节点组成。Hub 用来治理各个代理节点的注册信息和状态信息,并且承受近程客户端代码的申请调用,而后把申请的命令转发给代理节点来执行,最初再汇总各个代理节点的执行后果返回给近程客户端。无论是与 Jenkins 集成,还是对用例执行工夫的要求,分布式执行才是 UI 自动化的最终态,这里应用 docker-compose 来创立 Hub 和 Node 节点
docker-compose.yml 文件内容如下:
version: '3'services: hub: container_name: selenium-hub image: selenium/hub restart: always ports: - 4445:4444 environment: HUB_HOST: hub health-timeout: 30 SE_NODE_SESSION_TIMEOUT: 30000 JAVA_OPTS: -Xmx1024m chrome: image: selenium/node-chrome-debug:3.141.59-20210311 container_name: chrome_test restart: always depends_on: - hub ports: - 4446:5900 volumes: - /etc/hosts:/etc/hosts - /dev/shm:/dev/shm environment: JAVA_OPTS: -Xmx512m HUB_HOST: hub NODE_MAX_SESSION: 5 NODE_MAX_INSTANCES: 5 firefox: image: selenium/node-firefox-debug:3.141.59-20210311 container_name: firefox_test restart: always ports: - 4447:5900 volumes: - /etc/hosts:/etc/hosts - /dev/shm:/dev/shm depends_on: - hub environment: - JAVA_OPTS=-Xmx512m - HUB_HOST=hub - NODE_MAX_SESSION=4 - NODE_MAX_INSTANCES=4
Grid 模式执行用例的流程图
Pytest
治理和组织测试用例的框架选用 Pytest 框架,其长处如下:
- 简略灵便,容易上手,文档丰盛
- 反对参数化,能够细粒度地管制要测试的测试用例
- 具备很多第三方插件,并且能够自定义扩大,比拟好用的如allure-pytest(完满测试报告)、pytest-rerunfailures(失败case反复执行)、pytest-xdist(多CPU散发)等
- 能够很好的和Jenkins联合
说到 Pytest 就不得不提其精华:Fixture,Fixture 与传统的测试框架的(Setup/Teardown)相比更加灵便:
- 有独立的命名,并通过申明它们从测试函数、模块、类或整个我的项目中的应用来激活
- 按模块化的形式实现,每个 Fixture 都能够相互调用
- Fixture 的作用范畴灵便可配置,能够scope参数,指定Fixture的作用域:函数(Function),模块(Module),类(Class),或整个我的项目(Session),执行程序为:Session > Module > Class > Function
本我的项目中大量应用了@pytest.fixtrue装璜器来装璜办法,被装璜的办法名作为一个参数传入测试方法中,能够应用这种形式来实现测试之前的初始化,也能够返回数据库给测试函数,尤其是跟conftest文件和yield搭配应用
conftest.py
import pytestfrom selenium import webdriverfrom selenium.webdriver import DesiredCapabilities@pytest.fixture(scope='session')def init_driver(): if browser == "chrome": driver = webdriver.Chrome() elif browser == 'firefox': driver = webdriver.Firefox() elif browser == 'safari': driver = webdriver.Safari() elif browser == 'remote': capabilities = DesiredCapabilities.CHROME driver = webdriver.Remote(command_executor='http://localhost:4445/wd/hub', desired_capabilities=capabilities) else: driver = '' print('浏览器类型暂不反对!!') driver_obj = OpBasePage(driver) yield init_driver.open_op_url().login_op_by_gui(username, password) # 敞开浏览器 driver_obj.close_browser()
test_dashboard.py
class TestDataBoard: @pytest.fixture() def board(self, init_driver): yield init_driver.jump_to_board_by_url() def test_board_sort(self, board): board.click_button_go_to_board_manage().check_board_sort()
从以上2个文件中能够看到,conftest.py 文件中办法名init_driver传入了,test_dashboard.py 文件中的board办法中,board办法被@pytest.fixtrue装璜器装璜后,又传入了test_board_sort测试方法,所以当运行测试方法test_board_sort时,程序执行程序为
Allure
Allure 是一款轻量级并且非常灵活的开源测试报告框架。 它反对绝大多数测试框架, 例如 TestNG、Pytest、JUint 等。它简略易用,易于与 Jenkins 集成,展现屡次测试用例的趋势状况。
Allure 装璜器:
测试用例中应用
import allureimport pytest@allure.feature("distribute-analysis")class TestDistributionAnalysis: @pytest.fixture() def distribution_analysis(self, init_driver): yield init_driver.jump_to_distribution_analysis_by_url() @allure.story("check distribute analysis") def test_analysis_success(self, distribution_analysis): with allure.step("create chart"): distribution_name, save_toast, distribute_detail_analysis = distribution_analysis.click_button_to_create_distribute_analysis().create_distribution_analysis() distribution_list_name, distribute_analysis = distribute_detail_analysis.click_crumb_to_distribution_analysis().get_first_distribution_chart_name() assert distribution_name == distribution_list_name, '新建散布剖析单图后未展现在列表页' with allure.step("delete chart"): distribute_analysis.delete_first_distribution_chart()
测试报告样例
嵌入截图的失败用例样例
至此,Web UI 自动化框架(PageObject + Selenium + Pytest + Allure)搭建实现,框架整体的执行流程如下:
集成品质平台
自动化框架搭建实现,但这仅仅是第一步,为了便于跟踪和验证自动化发现的问题,又将自动化框架与自研的品质平台进行集成,并与飞书和 Jira 买通,造成一个残缺可追踪的闭环流程,具体流程如下:
1.在品质平台的页面上,抉择测试环境地址和我的项目 ID,而后点击【启动 Web UI 测试】按钮,即在选定的测试环境和我的项目下,执行自动化用例
2.自动化用例执行实现,会发送飞书告诉,并且主动爬取每一条失败用例的数据,展现在品质平台上
3.测试人员查看,剔除掉非bug的用例,勾选残余数据,点击【提交 BUG 】按钮,即主动在 Jira 上,批量创立 sub-bug 并指派给对应的开发人员
4.当开发人员批改实现后,反复步骤1~3,直到测试用例全副通过
集成品质平台后的流程图
总结
本文次要介绍了 Web UI 自动化在 GrowingIO 的框架搭建和集成品质平台两大部分,整体的一个思路就是:首先,抉择适合的框架并落地,其次就是,自动化发现的问题,要及时跟踪和验证,让整个流程造成一个残缺的闭环。当然上文提到的 Web UI 自动化的搭建和集成品质平台的整个流程,肯定还存在诸多须要打磨的中央,心愿大家不吝赐教。