使用pytest+selenium+allure实现web页面自动化测试

测试文件

  • base 基本方法
  • data 测试数据
  • page web页面相关操作
  • image 测试截图
  • log 日志文件
  • report 测试报告文件
  • temp 临时文件
  • tool 文件读取,发邮件文件
  • TestCases 测试用例

在page下的__init__.py文件下配置

import os
import time
from selenium.webdriver.common.by import By# 项目路径
PROJECT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 图片路径
IMAGE_PATH = os.path.join(PROJECT_PATH, 'image')
# 测试数据路径
DATA_PATH = os.path.join(PROJECT_PATH, 'data')
# 日志路径
LOG_PATH = os.path.join(PROJECT_PATH, 'log')
# 测试报告
REPORT_PATH = os.path.join(PROJECT_PATH, 'report', 'html')
# 临时文件
TEMP_PATH = os.path.join(PROJECT_PATH, 'temp')
# 请求url
url = "http://cal.apple886.com/""""  邮件信息  """
email_host = "smtp.qq.com"  # SMTP服务器
email_sender = '2022204437@qq.com'  # 发件人
email_license = 'jxyvidactsaiicja'  # 授权码
email_receivers = ['2022204437@qq.com']  # 收件人(可以群发)""" 以下为测试数据配置文件 """
image_path = os.path.join(IMAGE_PATH, '%serror.png' % time.strftime("%Y%m%d%H%M%S"))"""  以下为测试数据配置文件   """
add_data = os.path.join(DATA_PATH, 'add.json')
multi_data = os.path.join(DATA_PATH, 'multi.json')
subtr_data = os.path.join(DATA_PATH, 'subtr.json')"""  以下为logger配置文件   """
log_filename = os.path.join(LOG_PATH, '%sdemo.log' % time.strftime("%Y%m%d%H%M%S"))
log_when = "midnight"
log_interval = 1
log_backupCount = 30
log_encoding = "utf-8"
log_filemode = "w"
log_format = "%(asctime)s -[%(name)s]- %(levelname)s---[%(filename)s [%(funcName)s:%(lineno)s]] - %(message)s"
log_datefmt = "%Y-%m-%d %H:%M:%S"""""   以下为计算机配置数据   """
computer_add = By.XPATH, '//*[@id="simpleAdd"]'
computer_subtr = By.XPATH, '//*[@id="simpleSubtr"]'
computer_multi = By.XPATH, '//*[@id="simpleMulti"]'
computer_divi = By.XPATH, '//*[@id="simpleDivi"]'
computer_clear = By.XPATH, '//*[@id="simpleClearAllBtn"]'
computer_equal = By.XPATH, '//*[@id="simpleEqual"]'
computer_value = By.XPATH, '//*[@id="resultIpt"]'

在base下创建一个webpage.py文件

from selenium.webdriver.support.wait import WebDriverWait
from web.counter.base.logger import GetLogger
from web.counter import pagelog = GetLogger().get_logger()class WebPage:def __init__(self, driver):log.info("初始化driver{}".format(driver))self.driver = driver# 查找元素def base_find_element(self, loc, timeout=30, poll_frequency=0.5):log.info("正在查找元素{}".format(loc))return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll_frequency).until(lambda x: x.find_element(*loc))# 点击def base_click(self, loc):log.info("点击元素{}".format(loc))self.base_find_element(loc).click()# 输入def base_input(self, loc, key):log.info("输入元素{}输入值为{}".format(loc,key))self.base_find_element(loc).clear()self.base_find_element(loc).send_keys(key)# 获取文本def base_get_test(self, loc):log.info("获取文本{}".format(loc))return self.base_find_element(loc).text# 获取属性值def base_get_value(self, loc):log.info("获取{}属性值".format(loc))return self.base_find_element(loc).get_attribute('value')# 截图def base_get_image(self):log.error("错误!!!错误!!!错误!!!")self.driver.get_screenshot_as_file(page.image_path)

在base下创建一个driver.py文件

from selenium import webdriver
from web.counter import pageclass GetDriver:driver = None@classmethoddef get_driver(cls):if cls.driver is None:cls.driver = webdriver.Edge()cls.driver.maximize_window()cls.driver.get(page.url)return cls.driver@classmethoddef quit_driver(cls):if cls.driver:cls.driver.quit()cls.driver = None

在base下创建一个logger.py文件

import logging.handlers
from web.counter import pageclass GetLogger:logger = None@classmethoddef get_logger(cls):if cls.logger is None:# 获取日志器cls.logger = logging.getLogger()# 获取日志器级别cls.logger.setLevel(logging.INFO)# 获取处理器 控制台sh = logging.StreamHandler()# 获取处理器 文件-以以时间分隔th = logging.handlers.TimedRotatingFileHandler(filename=page.log_filename,when=page.log_when,interval=page.log_interval,backupCount=page.log_backupCount,encoding=page.log_encoding)fm = logging.Formatter(page.log_format)sh.setFormatter(fm)th.setFormatter(fm)cls.logger.addHandler(th)cls.logger.addHandler(sh)return cls.logger

在page下创建一个add_page.py文件

from selenium.webdriver.common.by import Byfrom web.counter.base.webpage import WebPage
from web.counter import pageclass AddPage(WebPage):# 点击数字def page_click_num(self, num):for n in str(num):loc = By.XPATH, '//*[@id="simple{}"]'.format(n)self.base_click(loc)# 点击加号def page_click_add(self):self.base_click(page.computer_add)# 点击等于def page_click_equal(self):self.base_click(page.computer_equal)# 获取结果def page_get_value(self):return self.base_get_value(page.computer_value)# 清屏def page_click_clear(self):self.base_click(page.computer_clear)# 截图def page_get_image(self):self.base_get_image()# 组装加法def page_add(self, a, b):self.page_click_num(a)self.page_click_add()self.page_click_num(b)self.page_click_equal()

在TestCases 下创建一个test_add.py文件

from time import sleep
import pytest
from web.counter.page.add_page import AddPage
from web.counter.base.driver import GetDriver
from web.counter.tool.read_json import GetJson
from web.counter.base.logger import GetLogger
from web.counter import pagelog = GetLogger().loggerclass TestAdd:def setup_class(self):self.computer = AddPage(GetDriver().get_driver())def teardown_class(self):GetDriver().quit_driver()@pytest.mark.parametrize("a, b, result", GetJson().get_data(page.add_data))def test_add_computer(self, a, b, result):self.computer.page_click_clear()self.computer.page_add(a, b)try:assert self.computer.page_get_value() == str(result)except:log.error("错误")sleep(1)self.computer.page_get_image()raise

在tool下创建一个read_json.py文件

import jsonclass GetJson:data_lists = Nonedata_dic = None# 读取json文件@classmethoddef read_json(cls, json_path):with open(json_path, "r", encoding="utf-8") as f:return json.load(f)# 获取测试数据@classmethoddef get_data(cls, json_path):cls.data_dic = cls.read_json(json_path)cls.data_lists = list()for data in cls.data_dic.values():cls.data_lists.append((data.get("a"), data.get("b"), data.get("result")))return cls.data_lists

在tool下创建一个send_emails.py文件

import time
import zipfile
import os
from email.mime.application import MIMEApplication
from web.counter import page
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipartclass SendEmails:def __init__(self):self.mime = MIMEMultipart()self.allure_report = Noneself.report_path = page.REPORT_PATHself.temp_path = page.TEMP_PATHdef send_email(self):self.mime['Subject'] = '%sxxx测试报告' % time.strftime('%Y年%m月%d日 %H:%M:%S ')content = 'hello, this is email content.'textApart = MIMEText(content)zip_Apart = MIMEApplication(open(SendEmails().make_zip, 'rb').read())zip_Apart.add_header('Content-Disposition', 'attachment', filename='allure_report.zip')self.mime.attach(textApart)self.mime.attach(zip_Apart)try:server = smtplib.SMTP(page.email_host)server.login(page.email_sender, page.email_license)server.sendmail(page.email_sender, page.email_receivers, self.mime.as_string())print('发送成功')server.quit()except smtplib.SMTPException as e:print('error:', e)  # 打印错误# 打包目录为zip文件(实际未压缩)@propertydef make_zip(self):if not os.path.exists(self.temp_path):os.makedirs(self.temp_path)self.allure_report = os.path.join(self.temp_path, 'allure_report.zip')zip_file = zipfile.ZipFile(self.allure_report, 'w')for present, dirs, files in os.walk(self.report_path):"""present:现在的目录dirs:该目录下包含的子目录files:该目录下包含的文件"""for file in files:pathfile = os.path.join(present, file)relpath = os.path.relpath(pathfile, page.PROJECT_PATH)  # 相对路径# ZIP_STORED:实际上并未压缩。zip_file.write(pathfile, relpath, zipfile.ZIP_STORED)zip_file.close()return self.allure_reportif __name__ == '__main__':report = page.REPORT_PATHtemp = page.TEMP_PATHprint(report)print(temp)SendEmails().send_email()print(SendEmails().allure_report)print("压缩包创建完成")# import zmail
# from web.counter import page
#
#
# def send_report():
#     """发送报告"""
#
#     with open(page.REPORT_PATH, encoding='utf-8') as f:
#         content_html = f.read()
#     try:
#         mail = {
#             'from': '2022204437@qq.com',
#             'subject': '最新的测试报告邮件',
#             'content_html': content_html,
#             'attachments': [page.REPORT_PATH, ]
#         }
#         server = zmail.server(*page.EMAIL_INFO.values())
#         server.send_mail(page.ADDRESSEE, mail)
#         print("测试邮件发送成功!")
#     except Exception as e:
#         print("Error: 无法发送邮件,{}!", format(e))
#
#
# if __name__ == "__main__":
#     '''请先在config/conf.py文件设置QQ邮箱的账号和密码'''
#     send_report()

web自动化大体就是这样,然后测试数据可以自己写

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

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

相关文章

伪协议和反序列化 [ZJCTF 2019]NiZhuanSiWei

打开题目 代码审计 第一层绕过 if(isset($text)&&(file_get_contents($text,r)"welcome to the zjctf")){ echo "<br><h1>".file_get_contents($text,r)."</h1></br>"; 要求我们get传参的text内容必须为w…

案例109:基于微信小程序的高校寻物平台

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

[XR806开发板试用] XR806——基于FreeRTOS下部署竞技机器人先进模糊控制器

前言 很荣幸参与到由“极术社区和全志在线联合组织”举办的XR806开发板试用活动。本人热衷于各种的开发板的开发&#xff0c;同时更愿意将其实现到具体项目中。秉承以上原则&#xff0c;发现大家的重心都放在开发中的环境构建过程&#xff0c;缺少了不少实际应用场景的运用&am…

数据仓库-数据治理小厂实践

一、简介 数据治理贯穿数仓中数据的整个生命周期&#xff0c;从数据的产生、加载、清洗、计算&#xff0c;再到数据展示、应用&#xff0c;每个阶段都需要对数据进行治理&#xff0c;像有些比较大的企业都是有自己的数据治理平台或者会开发一些便捷的平台&#xff0c;对于没有平…

鸿蒙-HarmonyOS之初见

鸿蒙初识&#xff0c;此事能成&#xff01;&#xff01; 自己安装工具、配置环境并运行成功&#xff0c;流程记录。 一、首先官网下载开发工具 官网地址&#xff1a;https://developer.huawei.com/consumer/cn/ 当前最新的版本3.1 &#xff0c;windows和Mac&#xff0c;Mac又…

js中的Array.from()和Array.of()方法的用法详情

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续…

VScode安装C/C++编译器步骤

一、安装C/C插件 二、安装 MinGW-w64 工具链 使用国内源 git clone https://gitee.com/cuihongxi/ubuntu2-mac.git 下载后进入到VScode文件夹下&#xff0c;点击msys2-x86_64-20231026.exe进行安装 完成后&#xff0c;确保选中“立即运行 MSYS2”框&#xff0c;然后选择“完…

stable diffusion工作原理

目录 序言stable diffusion能做什么扩散模型正向扩散逆向扩散 如何训练逆向扩散 Stable Diffusion模型潜在扩散模型变分自动编码器图像分辨率图像放大为什么潜在空间可能存在&#xff1f;在潜在空间中的逆向扩散什么是 VAE 文件&#xff1f; 条件化(conditioning)文本条件化&am…

深信服技术认证“SCSA-S”划重点:命令执行漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…

Python算法例21 交错正负数

1. 问题描述 给出一个含有正整数和负整数的数组&#xff0c;将其重新排列成一个正负数交错的数组。 2. 问题示例 给出数组[-1&#xff0c;-2&#xff0c;-3&#xff0c;4&#xff0c;5&#xff0c;6]&#xff0c;重新排序之后&#xff0c;变成[-1&#xff0c;5&#xff0c;-…

docker 部署kafka

随笔记录 目录 1. 安装zookeeper 2. 安装Kafka 2.1 拉取kafka image 2.2 查询本地docker images 2.3 查看本地 容器&#xff08;docker container&#xff09; 2.3.1 查看本地已启动的 docker container 2.3.2 查看所有容器的列表&#xff0c;包括已停止的容器。 2.4 …

个人财务工具、密钥管理平台、在线会计软件、稍后阅读方案 | 开源专题 No.51

gethomepage/homepage Stars: 10.1k License: GPL-3.0 这个项目是一个现代化、完全静态的、快速且安全的应用程序仪表盘&#xff0c;具有超过 100 种服务和多语言翻译的集成。 快速&#xff1a;网站在构建时以静态方式生成&#xff0c;加载时间飞快。安全&#xff1a;所有对后…

五分钟学完DBSCAN算法

基础概念 邻1个核心思想&#xff1a;基于密度&#xff0c;依据密度的连通性分析增长聚类 2个算法参数&#xff1a;邻域半径R和最少点数目minpoints 这两个算法参数实际可以刻画什么叫密集——当邻域半径R内的点的个数大于最少点数目minpoints时&#xff0c;就是密集。 3种点的…

油猴脚本教程案例【长按元素】- 哔哩哔哩一键三连

文章目录 1. 元数据2. 编写函数2.1 关键函数2.2 完整代码 3. 验证和调试3.1 效果演示 4. 可能遇到的问题和解决方法5. 结语 1. 元数据 在编写油猴脚本时&#xff0c;首先需要设置一些元数据&#xff0c;包括脚本的名称、命名空间、版本、描述等信息。以下是本脚本的元数据部分…

.NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式

之前写过使用自定义返回类的方式来统一接口数据返回格式&#xff0c;.Net Core webapi RestFul 统一接口数据返回格式-CSDN博客 但是这存在一个问题&#xff0c;不是所有接口会按照定义的数据格式返回&#xff0c;除非每个接口都返回我们自定义的类&#xff0c;这种实现起来不…

106 uni-app 小程序之巨坑 not found path,not found methods v-for渲染出现报错

1.Component is not found in path 你是否像我一样&#xff0c;检查了无数遍&#xff0c;引入路径检查千万遍&#xff0c;就是没写错&#xff0c;小程序后台就是给你报错&#xff0c; 不用慌&#xff0c;心里默念&#xff1a;我不能砸电脑&#xff0c;我不能砸电脑&#xff0…

主流数据库体系结构

MySQL 我们通常所说的 MySQL 数据库服务器由一个实例&#xff08;instance&#xff09;以及一个数据库&#xff08;database&#xff09;组成。实例包括一组后台进程/线程和许多内存结构&#xff0c;用于管理数据库&#xff1b;数据库由一组磁盘文件组成&#xff0c;用于存储数…

基于FPGA的简易BPSK和QPSK

1、框图 2、顶层 3、m_generator M序列的生成&#xff0c;输出速率为500Kbps 4、S2P是串并转换模块 将1bit的m序列转换到50M时钟下的2bit M序列数据&#xff08;就有4个象限&#xff09;&#xff1b; 5、my_pll是生成256M的时钟作为载波&#xff0c;因为sin和cos信号的…

论文阅读<MULTISCALE DOMAIN ADAPTIVE YOLO FOR CROSS-DOMAIN OBJECT DETECTION>

论文链接&#xff1a;https://arxiv.org/pdf/2106.01483v2.pdfhttps://arxiv.org/pdf/2106.01483v2.pdf 代码链接&#xff1a;GitHub - Mazin-Hnewa/MS-DAYOLO: Multiscale Domain Adaptive YOLO for Cross-Domain Object DetectionMultiscale Domain Adaptive YOLO for Cross…

Postgresql源码(118)elog/ereport报错跳转功能分析

1 日志接口 elog.c完成PG中日志的生产、记录工作&#xff0c;对外常用接口如下&#xff1a; 1.1 最常用的ereport和elog ereport(ERROR,(errcode(ERRCODE_UNDEFINED_TABLE),errmsg("relation \"%s\" does not exist",relation->relname)));elog(ERRO…