Python —— UI自动化用例前置处理日志封装

1、UI自动化用例增加前置

1、fixture(夹具)的使用

前置顾名思义是在执行测试用例之前做的一些事情,在自动化测试时会碰到用例执行前需要做一些前置操作,以及用例执行后需要做一些后置操作,比如登录、退出等,通过pytest fixture可以很方便实现。那么根据上篇文章写的用例,写一个获取浏览器驱动的前置,如下:

@pytest.fixture()
def driver_fixture():driver = webdriver.Chrome()driver.maximize_window()yield drivertime.sleep(5)driver.quit()

将这个前置放在项目目录下的conftest.py文件中,可以实现数据共享,不需要import 导入 conftest.py,pytest用例就会自动查找。对 于一些公共的fixture我们可以将其存放到conftest.py进行管理。

针对上一篇文章,点击登录的操作也是很多用例都要遇到的,那么对这个操作也写一个夹具,如下:

import pytest
from selenium import webdriver
from d9_fixture前置后置处理及日志封装.pageobjects.home_page import HomePage
from d9_fixture前置后置处理及日志封装.pageobjects.login_page import LoginPage# 自定义的fixture函数 -- 可以共享使用了,会在每个测试函数运行时都会执行?scope='function'
# session代表的是会话,整个测试用例运行就是一次会话
@pytest.fixture()
def get_driver():print("这是前置")driver = webdriver.Chrome()driver.get("http://mall.banabann.com:3344/")driver.maximize_window()yield driverprint("这是后置")driver.quit()'''
此时,函数的返回值就是driver,因此前置返回就是driver,可以使用夹具替换掉其他文件中的实例化驱动语句
'''# 登录也是前置,因此,登录也可以作为夹具
@pytest.fixture()
def login(get_driver):# 点击首页的登录操作print("这是login的前置")homepage = HomePage(get_driver)homepage.click_login_link()# 在登陆页面进行登录操作loginpage = LoginPage(get_driver)loginpage.login("auto", "123456")yield get_driverprint("这是login的后置")

 注意点:login夹具中,调用了get_driver夹具,那么输出语句执行顺序是:

        1、get_driver的前置

        2、login的前置

        3、login的后置

        4、get_driver的后置

可以参考下图:

2、fixture的作用域

fixture默认的作用域是function(函数)级别的,每次执行测试函数时都会运行fixture前置/后置,如果 想要fixture在全部测试用例执行期间只运行一次,可以设置为session(会话)级别。举例如下:

@pytest.fixture(scope='session')
def driver_fixture():
driver = webdriver.Chrome()
driver.maximize_window()
yield driver
time.sleep(5)
driver.quit()

2、关于UI自动化用例执行期间,浏览器关闭打开的最优选择

 浏览器在执行期间的打开关闭有2种类型:

        1、执行所有用例,浏览器只打开/关闭一次(可以通过给夹具设定作用域为session实现)

        2、每次执行一条用例,都会有浏览器打开/关闭的操作

那么我们该选择哪一种呢?选择第2种,原因如下:

        1、UI自动化不稳定

        2、前面一个用例失败,导致后面用例接连失败

        3、最好每条用例都可以单独执行-打开/关闭浏览器-可以避免很多问题

2、loguru日志封装

1、日志的级别

        DEBUG 调试

        INFO 一般的提示信息

        WARN 警告

        ERROR 程序已经发生了错误

        CRITICAL ERROR 严重的错误

2、添加日志的写法

from loguru import loggerlogger.add(sink="my.log",encoding="utf8",level="INFO",rotation="1kB",retention=20)

3、实战

主要改动点:

1、在base_page.py中增加异常捕获代码

2、在base_page.py中二次封装点击、获取文本、输入文本的函数

3、给全部用例执行的轨迹增加日志信息

4、增加了login夹具

目录:

 run.py的文件内容:

import pytest
# -s,-v选项可以让pytest执行的日志更加的丰富
pytest.main(['-s','-v'])

conftest.py的内容:

import pytest
from selenium import webdriverfrom d9_fixture前置后置处理及日志封装.pageobjects.home_page import HomePage
from d9_fixture前置后置处理及日志封装.pageobjects.login_page import LoginPage# 自定义的fixture函数 -- 可以共享使用了,会在每个测试函数运行时都会执行?scope='function'
# session代表的是会话,整个测试用例运行就是一次会话
@pytest.fixture()
def get_driver():print("这是前置")driver = webdriver.Chrome()driver.get("http://mall.banbanban.com:3344/")driver.maximize_window()yield driverprint("这是后置")driver.quit()'''
此时,函数的返回值就是driver,因此前置返回就是driver,可以使用夹具替换掉其他文件中的实例化驱动语句
'''# 登录也是前置,因此,登录也可以作为夹具
@pytest.fixture()
def login(get_driver):# 点击首页的登录操作print("这是login的前置")homepage = HomePage(get_driver)homepage.click_login_link()# 在登陆页面进行登录操作loginpage = LoginPage(get_driver)loginpage.login("auto", "123456")yield get_driverprint("这是login的后置")

 base_page.py 文件的内容:

from d9_fixtur.pageobjects.home_page import HomePage
from d9_fixture.pageobjects.my_order_page import MyOrderPage
from d9_fixture.pageobjects.product_detail_page import ProductDetailPage
from d9_fixture.pageobjects.submit_order_page import SubmitOrderPagedef test_submit_order(login):# 登录,点击首页的登录链接home_page = HomePage(login)# 点击商品列表home_page.click_goods_list()# 搜索选择商品home_page.search_select_product("Mac")# 商品详情页product_detail_page = ProductDetailPage(login)product_name = product_detail_page.get_product_name()product_price = product_detail_page.get_product_price()product_detail_page.buy_now()# 提交订单submit_order_page = SubmitOrderPage(login)submit_order_page.submit_order()# 进入我的订单页面home_page.my_order()my_order_page = MyOrderPage(login)# 断言# 1、检查订单商品名称assert my_order_page.get_product_name() == product_name# 2、检查订单商品数量assert my_order_page.get_product_num() == '1'# 3、检查订单商品价格assert my_order_page.get_product_price() == product_price# 4、检查订单的状态assert my_order_page.get_order_status() == '待支付'

home_page.py文件的内容:

import time
from selenium.webdriver.common.by import By
from d9_fixtur.common.base_page import BasePageclass HomePage(BasePage):# 属性-登录链接login_link_locator = (By.LINK_TEXT,'登录')# 欢迎提示信息welcome_tips_locator = (By.XPATH,'//span[text()="欢迎来到我的世界"]')welcome_tips_text_locator = (By.XPATH,'//span[@class="text"]')# 用户名username_text_locator = (By.XPATH,'//a[@class="link-name"]')# 点击个人中心person_center_locator = (By.XPATH,"//span[text()='个人中心']")# 点击商品列表goods_list_locator = (By.LINK_TEXT,"商品列表")# 搜索框serach_input_locator = (By.XPATH,"//input[@class='search-input']")# 搜索按钮search_button_locator = (By.XPATH,"//input[@value = '搜索']")# 搜索第一个商品first_goods_locator = (By.XPATH,"//div[@class='goods-img']")# 我的订单定位my_order_button_locator = (By.XPATH,"//span[@data-route='order']")def click_login_link(self):time.sleep(5)self.click(self.login_link_locator)def is_display_welcome_tips(self):time.sleep(1)return self.wait_element_visible(self.welcome_tips_locator).is_displayed()def get_username_text(self):return self.get_text(self.username_text_locator)# 点击个人中心按钮def click_person_center(self):self.click(self.person_center_locator)# 点击商品列表def click_goods_list(self):self.click(self.goods_list_locator)# 进入我的订单页面def my_order(self):time.sleep(2)self.click(self.my_order_button_locator)# 搜索并选择对应的商品def search_select_product(self,goodname):time.sleep(1)self.input_text(self.serach_input_locator, goodname)self.click(self.search_button_locator)# 选择第一个商品time.sleep(1)self.click(self.first_goods_locator)

login.py文件的内容:

import time
from selenium.webdriver.common.by import By
from d9_fixture前置后置处理及日志封装.common.base_page import BasePageclass LoginPage(BasePage):# 属性->元素定位信息(元素定位方法+元素定位值)-元组类型phone_input_locator = (By.XPATH, '//input[@placeholder="请输入手机号/用户名"]')pwd_input_locator = (By.XPATH, '//input[@placeholder="请输入密码"]')login_button_locator = (By.CLASS_NAME, 'login-button')login_tips_locator = (By.XPATH,'//p[@class="el-message__content"]')# 用户名输入框错误提示文本user_input_error_tips_locator = (By.XPATH, '//div[contains(@class,"msg-error")]/following-sibling::div[1]')def login(self,phone,pwd):# 因为继承了 basepage类,所以克不用再写driver参数# self.wait_element_visible(self.driver,self.phone_input_locator).send_keys("17728373518")self.input_text(self.phone_input_locator, phone)self.input_text(self.pwd_input_locator, pwd)# 点击登录按钮time.sleep(3)self.click(self.login_button_locator)def get_login_tips(self):# 这里比较文本内容time.sleep(2)return self.get_text(self.login_tips_locator)def get_user_input_error_tips(self):return self.get_text(self.user_input_error_tips_locator)

my_order_page.py文件的内容:

from time import sleep
from selenium.webdriver.common.by import By
# 我的订单页面
from d9_fixture.common.base_page import BasePageclass MyOrderPage(BasePage):# 最新的一笔订单的商品名goods_name_locator = (By.XPATH,"//a[@class='name']")# 商品数量goods_num_locator = (By.XPATH,"//div[@class='goods-number']")# 商品付款总额pay_price_locator = (By.XPATH,"//td[@rowspan='1']/div/div/span")# 订单状态order_status_locator = (By.XPATH,"//div[@class='status']/div")def get_product_name(self):return self.get_text(self.goods_name_locator)def get_product_num(self):sleep(2)goods_num = self.get_text(self.goods_num_locator)return goods_num[1:]def get_product_price(self):product_amount = self.get_text(self.pay_price_locator)return product_amount[1:]def get_order_status(self):order_status = self.get_text(self.order_status_locator)return order_status.strip()

 product_detail_page.py文件的内容:

from selenium.webdriver.common.by import By# 商品详情页面
from d9_fixture.common.base_page import BasePageclass ProductDetailPage(BasePage):# 商品名product_name_locator = (By.XPATH, "//div[@class='name-box']/div[@class='name']")# 商品价格product_price_locator = (By.XPATH, '//div[@class="price"]')# 添加购物车button_addcart_locator = (By.CLASS_NAME, "add-cart")# 立即购买button_buynow_locator = (By.CLASS_NAME, "buy-now")# 收藏商品button_collect_locator = (By.CLASS_NAME, "collect")def add_cart(self):self.click(self.button_addcart_locator)def buy_now(self):self.click(self.button_buynow_locator)def get_product_name(self):return self.get_text(self.product_name_locator)def get_product_price(self):product_price = self.get_text(self.product_price_locator)# 将换行符号去掉product_price = product_price.replace('\n', '')# 去掉开头的'¥'  ‘¥0.01’return product_price[1:]

 submit_order_page.py文件的内容:

from selenium.webdriver.common.by import By
# 提交订单页面
from d9_fixture.common.base_page import BasePageclass SubmitOrderPage(BasePage):# 提交订单按钮button_submit_locator = (By.LINK_TEXT, "提交订单")def submit_order(self):self.click(self.button_submit_locator)

user_center_page.py文件的内容:

from time import sleep
from selenium.webdriver.common.by import By
from d9_fixture.common.base_page import BasePageclass PersonCenterPage(BasePage):take_delivery_goods_link_locaotr = (By.LINK_TEXT,"收货地址")add_new_address_locator = (By.LINK_TEXT,"新增收货地址")recipient_name_locator = (By.XPATH,"//div[text()='收件人:']/following-sibling::div/input")recipient_phone_locator = (By.XPATH,"//div[@class='item'][1]//input[@class='input']")recipient_province_locator = (By.XPATH,"//div[@prop='province']//i")click_prodropdown_icon_locator = (By.XPATH,"//div[@x-placement='bottom-start']//li[text()='陕西省']")recipient_city_locator = (By.XPATH,"//div[@prop='city']//i")click_citydropdown_icon_locator = (By.XPATH,"//div[@x-placement='bottom-start']//li[text()='延安市']")recipient_area_locator = (By.XPATH,"//div[@prop='area']//i")click_areadropdown_icon_locator = (By.XPATH,"//div[@x-placement='bottom-start']//li[text()='黄龙县']")detail_address_locator = (By.XPATH,"//div[text()='详细地址:']/parent::div/div[2]/input")submit_button_locator = (By.LINK_TEXT,"保存收件人信息")add_address_success_tips_locator = (By.CLASS_NAME,"el-message__content")# 将新增地址的所有操作都放在一个函数中def write_detail_address(self,name,phone,province,city,area,detail_address):# 点击收货地址self.click(self.take_delivery_goods_link_locaotr)# 点击新增地址按钮self.click(self.add_new_address_locator)# 填写姓名sleep(2)self.input_text(self.recipient_name_locator, name)# 填写电话号码self.input_text(self.recipient_phone_locator, phone)# 填写省份信息self.click(self.recipient_province_locator)sleep(1)self.click((By.XPATH,f"//div[@x-placement='bottom-start']//li[text()='{province}']"))# 填写城市信息self.click(self.recipient_city_locator)self.click((By.XPATH,f"//div[@x-placement='bottom-start']//li[text()='{city}']"))# 填写区域信息self.click(self.recipient_area_locator)self.click((By.XPATH,f"//div[@x-placement='bottom-start']//li[text()='{area}']"))# 填写详细地址self.input_text(self.detail_address_locator, detail_address)# 点击提交按钮self.click(self.submit_button_locator)# 是否添加地址成功,通过提示来进行断言def add_new_address_tips(self):return self.get_text(self.add_address_success_tips_locator)# 添加手机号码作为断言的函数def is_phone_displayed(self,phone_number):return self.wait_element_visible((By.XPATH,f"//div[text()='{phone_number}']")).is_displayed()

test_add_address.py文件的内容:

from selenium import webdriver
from d9_fixture.pageobjects.home_page import HomePage
from d9_fixture.pageobjects.login_page import LoginPage
from d9_fixture.pageobjects.user_center_page import PersonCenterPagedef test_is_add_address_success(login):home_page = HomePage(login)# 点击个人中心home_page.click_person_center()# 在个人中心页面添加地址user_page = PersonCenterPage(login)# 添加地址user_page.write_detail_address("富贵花","18867894326","","东北市","富贵区","城市花园1号楼1单元101室")assert  user_page.add_new_address_tips() == '添加地址成功'# 添加手机号码断言assert user_page.is_phone_displayed("18867894326")

test_login.py文件的内容:

from time import sleep
import pytest
from selenium import webdriver
from d9_fixture.pageobjects.home_page import HomePage
from d9_fixture.pageobjects.login_page import LoginPagedef test_login_success(get_driver):# 点击首页的登录操作homepage = HomePage(get_driver)homepage.click_login_link()# 在登陆页面进行登录操作loginpage = LoginPage(get_driver)loginpage.login("uto","123456")# 断言检测测试是否成功(通过预期结果和实际结果的比较)#  检查点:1、欢迎页,如果函数的返回值为True,那么断言之后返回是通过的assert homepage.is_display_welcome_tips()# assert loginpage.get_login_tips() == '账号或者密码不正确'assert homepage.get_username_text() == 'uto'# 对登录结果的断言
def test_login_uncorrect_username(get_driver):homepage = HomePage(get_driver)homepage.click_login_link()# 在登陆页面进行登录操作login_page = LoginPage(get_driver)login_page.login("lemon_auto1", "lemon123456")# 页面登录过程中的提示信息断言sleep(1)assert login_page.get_login_tips() == '账号或密码不正确'login_datas = [{'username':'','password':'123456','tips':'账号为4~16位字母、数字或下划线'},{'username':'11','password':'123456','tips':'账号为4~16位字母、数字或下划线'},{'username':'lem','password':'123456','tips':'账号为4~16位字母、数字或下划线'}]@pytest.mark.parametrize('datas',login_datas)
def test_login_fail(datas,get_driver):# 点击首页的登录链接home_page = HomePage(get_driver)home_page.click_login_link()# 在登录页面进行登录操作login_page = LoginPage(get_driver)login_page.login(datas['username'], datas['password'])# 用户名输入框的提示 - 断言assert login_page.get_user_input_error_tips()== datas['tips']

test_submit_order.py文件的内容:

from d9_fixture.pageobjects.home_page import HomePage
from d9_fixture.pageobjects.my_order_page import MyOrderPage
from d9_fixture.pageobjects.product_detail_page import ProductDetailPage
from d9_fixture.pageobjects.submit_order_page import SubmitOrderPagedef test_submit_order(login):# 登录,点击首页的登录链接home_page = HomePage(login)# 点击商品列表home_page.click_goods_list()# 搜索选择商品home_page.search_select_product("Mac")# 商品详情页product_detail_page = ProductDetailPage(login)product_name = product_detail_page.get_product_name()product_price = product_detail_page.get_product_price()product_detail_page.buy_now()# 提交订单submit_order_page = SubmitOrderPage(login)submit_order_page.submit_order()# 进入我的订单页面home_page.my_order()my_order_page = MyOrderPage(login)# 断言# 1、检查订单商品名称assert my_order_page.get_product_name() == product_name# 2、检查订单商品数量assert my_order_page.get_product_num() == '1'# 3、检查订单商品价格assert my_order_page.get_product_price() == product_price# 4、检查订单的状态assert my_order_page.get_order_status() == '待支付'

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/150693.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国两轮“技术派”绿源,为全球电动市场带来跨越式方案

历史越长的行业,遇到变革之时,需要经历的考验、做出的突破就越多。两轮电动车,这个非常本土化的赛道,就是如此。 中国是两轮电动车产销大国,自上世纪晚期开始,中国两轮电动车迅速发展,绿源等一…

Modbus转MQTT以太网网关MQT-802主要特点和典型应用

随着社会的快速发展,物联网已经潜移默化地深入工控行业的各个领域,其高效的资源整合和强大的数据采集能力,深受客户的喜爱。上海泗博为实现客户在云端平台接收处理世界万物的信息以及实现远程控制,精心打造一款全新物联网产品&…

工作小计-GPU硬编以及依赖库 nvcuvidnvidia-encode

工作小计-GPU编码以及依赖库 已经是第三篇关于编解码的记录了。项目中用到GPU编码很久了,因为yuv太大,所以编码显得很重要。这次遇到的问题是环境的搭建问题。需要把开发机上的环境放到docker中,以保证docker中同样可以进行GPU的编码。 1 定…

Python轮廓追踪【OpenCV形态学操作】

文章目录 概要代码运行结果 概要 一些理论知识 OpenCV形态学操作理论1 OpenCV形态学操作理论2 OpenCV轮廓操作|轮廓类似详解 代码 代码如下,可以直接运行 import cv2 as cv# 定义结构元素 kernel cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) # print kern…

小程序设计基本微信小程序的校园生活助手系统

项目介绍 通篇文章的撰写基础是实际的应用需要,然后在架构系统之前全面复习大学所修习的相关知识以及网络提供的技术应用教程,以校园生活助手系统的实际应用需要出发,架构系统来改善现校园生活助手系统工作流程繁琐等问题。不仅如此以操作者…

国产CAN总线收发芯片DP1042 兼容替换TJA1042

说明 1 简述 DP1042是一款应用于 CAN 协议控制器和物理总线之间的接口芯片,可应用于卡车、公交、小汽车、工业控制等领域,支持 5Mbps CAN FD 灵活数据速率,具有在总线与 CAN 协议控制器之间进行差分信号传输的能力,完全兼容“ISO…

Fabric.js 样式不更新怎么办?

本文简介 带尬猴,我嗨德育处主任 不知道你有没有遇到过在使用 Fabric.js 时无意中一些骚操作修改了元素的样式,但刷新画布却没更新元素样式? 如果你也遇到同样的问题的话,可以尝试使用本文的方法。 是否需要重新绘制 我先举个例…

最近面试遇到的高频面试题

大家好,我是 jonssonyan 互联网寒冬?金九银十真的不存在了么?虽说现在行情是差了一些,面试机会少了一些,但是大部分公司还是或多或少的招人,春招秋招都在进行。有人离职就有人入职。所以如果你还没约到面试…

npm改变npm缓存路径和改变环境变量

在安装nodejs时,系统会自动安装在系统盘C, 时间久了经常会遇到C盘爆满,有时候出现红色,此时才发现很多时候是因为npm 缓存保存在C盘导致的,下面就介绍下如何改变npm缓存路径。 1、首先找到安装nodejs的路径&#xff0c…

单元测试,集成测试,系统测试的区别是什么?

实际的测试工作当中,我们会从不同的角度对软件测试的活动进行分类,题主说的“单元测试,集成测试,系统测试”,是按照开发阶段进行测试活动的划分。这种划分完整的分类,其实是分为四种“单元测试,…

618京东到家APP-门详页反爬实战

一、背景与系统安全需求分析 1. 系统的重要性 上图所示是接口所属位置、对电商平台或在线商店而言,分类查商品都是很重要的,通过为用户提供清晰的商品分类,帮助他们快速找到所需产品,节省浏览时间,提升购物效率,是购物结算产生GMV的核心环节。那么电商平台为什么都很看重…

Kubernetes - 一键安装部署 K8S(附:Kubernetes Dashboard)

问题描述 不知道大伙是如何安装 K8s,特别还是集群的时候,我上一次安装搭建的时候,那个恶心到我了,真的是一步一个脚印走完整个搭建流程,爬了不少坑。 于是,才有了今天的文章,到底有没有可以一…