python单元测试框架(继承、unittest参数化、断言、测试报告)

一、继承

继承能解决什么问题?

unittest每个模块都要用到前提条件以及清理,如果有上百个模块,我们要改域名和浏览器,就会工作量很大特别麻烦,这时我们可以用继承的思想只用改一次

我们可以将前提和清理提出来单独放到一个文件里,具体代码如下

from selenium import webdriver
import unittestclass Init(unittest.TestCase):@classmethoddef setUpClass(cls) -> None:cls.driver=webdriver.Chrome()cls.driver.maximize_window()cls.driver.get('http://www.baidu.com')cls.driver.implicitly_wait(30)@classmethoddef tearDownClass(cls) -> None:cls.driver.quit()

然后我们写测试用例的时候可以继承它,具体代码如下

from selenium import webdriver
import unittestfrom 单元测试框架.test.init import Init
class BaiduTest(Init):def test_baidu_title(self):'''百度测试:验证百度首页的title'''# assert self.driver.title=='百度一下,你就知道'self.assertEqual(self.driver.title,'百度一下,你就知道')def test_baidu_url(self):'''百度测试:验证百度首页的url'''assert self.driver.current_url=='https://www.baidu.com/'def test_baidu_video(self):'''百度测试:验证点击视频后跳转到视频的页面'''nowhandler=self.driver.current_window_handleself.driver.find_element_by_link_text('视频').click()allhandlers=self.driver.window_handlesfor handler in allhandlers:if handler!=nowhandler:self.driver.switch_to.window(handler)self.assertTrue(self.driver.current_url,'https://haokan.baidu.com/?sfrom=baidu-top')self.driver.close()self.driver.switch_to.window(nowhandler)def test_baidu_map(self):'''百度测试:验证点击地图后跳转到地图的页面'''nowhandler=self.driver.current_window_handleself.driver.find_element_by_link_text('地图').click()allhandlers=self.driver.window_handlesfor handler in allhandlers:if handler!=nowhandler:self.driver.switch_to.window(handler)self.assertTrue(self.driver.current_url.startswith('https://map.baidu'))self.driver.close()self.driver.switch_to.window(nowhandler)if __name__ == '__main__':unittest.main()
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036

二、参数化

在unittest测试框架中,参数化使用的库为:parameterized 安装方式为:pip3 install parameterized

参数化:

我们把相同的测试步骤,应用于不同的测试场景,那么我们就可以使用参数化了

可以解决的问题是可以使用少量的测试代码,来覆盖更多的测试场景

例如:我们测一下sina邮箱的登录模块,代码如下:

from selenium import webdriver
import unittest
import time as t
class BaiduTest(unittest.TestCase):def setUp(self) -> None: #前提self.driver=webdriver.Chrome()self.driver.get('https://mail.sina.com.cn/')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None: #清理self.driver.quit()def test_sina_null(self):'''sina邮箱验证:登录账户为空'''self.driver.find_element_by_class_name('loginBtn').click()divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,'请输入邮箱名')def test_sina_email_format(self):'''sina邮箱验证:登录邮箱格式不正确'''self.driver.find_element_by_id('freename').send_keys('qwert')self.driver.find_element_by_class_name('loginBtn').click()divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,'您输入的邮箱名格式不正确')def test_sina_username_error(self):'''sina邮箱验证:登录账户不匹配'''self.driver.find_element_by_id('freename').send_keys('asdf@sina.com')self.driver.find_element_by_id('freepassword').send_keys('asdfg')self.driver.find_element_by_class_name('loginBtn').click()t.sleep(3)divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,'登录名或密码错误')if __name__ == '__main__':unittest.main()

由于登录模块主要是⽤户名和密码的input表单的验证以及错误信息的验证,我们可以把用户名、密码、错误信息的验证参数化,具体实现的代码如下:

 from selenium import  webdriver
import  unittest
import  time as t
from parameterized import  parameterized,param
class BaiduTest(unittest.TestCase):def setUp(self) -> None: #前提self.driver=webdriver.Chrome()self.driver.get('https://mail.sina.com.cn/')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None: #清理self.driver.quit()@parameterized.expand([param('','','请输入邮箱名'),param('wertasd', 'asdf', '您输入的邮箱名格式不正确'),param('wertasd@sina.cn', 'asdf', '登录名或密码错误')])def test_sina_login(self,username,password,result):self.driver.find_element_by_id('freename').send_keys(username)t.sleep(3)self.driver.find_element_by_id('freepassword').send_keys(password)t.sleep(3)self.driver.find_element_by_class_name('loginBtn').click()t.sleep(3)divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,result)

三、断言

assertEqual

assertEqual()是验证两个值相等,值的是数据类型与内容也是相等的,⻅案例代码:

from selenium import webdriver
import unittest
class BaiduTest(unittest.TestCase):def setUp(self) -> None:self.driver=webdriver.Chrome()self.driver.get('http://www.baidu.com')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None:self.driver.quit()def test_baidu_title(self):'''百度测试:验证百度首页的title'''# assert self.driver.title=='百度一下,你就知道'self.assertEqual(self.driver.title,'百度一下,你就知道')

assertTrue

返回的是bool类型,也就是对被测试的对象进⾏验证,如果返回的是boolean类型并且是true,那么结果验证通过,那么⽅法assertFlase()验证的是被测试对象返回的内容是false,⻅案例代码:

from selenium import webdriver
import unittest
import time as t
class BaiduTest(unittest.TestCase):def setUp(self) -> None: #前提self.driver=webdriver.Chrome()self.driver.get('https://mail.sina.com.cn/')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None: #清理self.driver.quit()def test_sina_isLogin(self):'''sina邮箱验证,判断自动登录是否勾选'''isLogin=self.driver.find_element_by_id('store1')self.assertTrue(isLogin.is_selected())

assertIn

assertIn()值的是⼀个值是否包含在另外⼀个值⾥⾯,在这⾥特别的强调⼀下,在assertIn()的⽅法⾥⾯,有两个参数,那么值的包含其实就是第⼆个实际参数包含第⼀个实际参数。与之相反的⽅法是assergNotIn(),⻅案例代码:

import unittest
from selenium import webdriver
class UiTest(unittest.TestCase):
def setUp(self) -> None:
self.driver=webdriver.Chrome()
self.driver.maximize_window()
self.driver.get('http://www.baidu.com')
self.driver.implicitly_wait(30)
def tearDown(self) -> None:
self.driver.quit()
def test_baidu_title_001(self):
self.assertIn('百度',self.driver.title)
def test_baidu_title_002(self):
self.assertIn('百度⼀下,你就知道',self.driver.title)
if __name__ == '__main__':
unittest.main()

四、测试报告

在unittest的框架中,⽣成测试报告需要使⽤到HTMLTestRunner

import unittest
import os
from 单元测试框架.HTMLTestRunner import HTMLTestRunner #从HTMLTestRunner模块调用HTMLTestRunner类def getTests():'''加载所有的测试模块'''suite=unittest.TestLoader().discover(#找到被执行模块的路径start_dir=os.path.dirname(__file__),#加载路径下所有以test_开头的测试模块的文件pattern='test_*.py' #正则表达式)return suitedef runSuite():unittest.TextTestRunner().run(getTests())def base_dir():return os.path.dirname(os.path.dirname(__file__))#获取当前目录的上级目录def run():fp=open(os.path.join(base_dir(),'report','report.html'),'wb')#拼接report.html的路径 wb 二进制的方式写入runner=HTMLTestRunner(stream=fp,  #流 执行一个写入一个title='UI自动化测试报告',description='' )runner.run(getTests())if __name__ == '__main__':run()

怎么解决每次生成的测试报告不覆盖之前的测试报告,同时被保留:

解决方法:引入时间库获取时间戳

代码如下:

import time
import unittest
import os
from HTMLTestRunner import HTMLTestRunnerdef getTests():'''加载所有的测试模块'''suite=unittest.TestLoader().discover(#找到被执行模块的路径start_dir=os.path.dirname(__file__),#加载路径下所有以test_开头的测试模块的文件pattern='test_*.py' #正则表达式)return suitedef getNowTime():return time.strftime('%y-%m-%d %H-%M-%S',time.localtime(time.time()))def base_dir():return os.path.dirname(os.path.dirname(__file__))def run():fp=open(os.path.join(base_dir(),'report',getNowTime()+'report.html'),'wb')runner=HTMLTestRunner(stream=fp,title='UI自动化测试报告',description='')runner.run(getTests())if __name__ == '__main__':run()

这样每次执行的都会生成一个测试报告:

END今天的分享就到此结束了,点赞关注不迷路~

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

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

相关文章

ubuntu20.04 安装cudnn

中文地址是.cn:cuDNN 历史版本 | NVIDIA 开发者 英文地址是.com:cuDNN 历史版本 | NVIDIA 开发者 1、下载cudnn:cudnn-local-repo-ubuntu2004-8.8.1.3_1.0-1_amd64.deb 解压并安装:sudo dpkg -i cudnn-local-repo-ubuntu2004-8.8…

pytorch与cudatoolkit,cudnn对应关系及安装相应的版本

文章目录 一.cuda安装二、nvidia 驱动和cuda runtime 版本对应关系三、安装cudatoolkit,cudnn对应版本四、cuda11.2版本的对应安装的pytorch版本及安装五、相关参考 一.cuda安装 1.确定当前平台cuda可以安装的版本 安装好显卡驱动后,使用nvidia-smi命令可以查看这个…

P1903 [国家集训队] 数颜色 / 维护队列

带修改的莫队 带修改的莫队就是在基础莫队的基础上增加了一维属性,之前只需要维护l,r现在还需要维护一下时间t,排序还是先按照左端点块儿号排序,然后右端点块儿号排序,最后按时间排序。其它的都是差不多的。 #include…

计算机基础知识44

overflow溢出属性 visible:默认值,内容不会被修剪,会呈现在元素框之外。hidden:内容会被修剪,并且其余内容是不可见的。scroll:内容会被修剪,但是浏览器会显示滚动条以便查看其余的内容。auto: …

BEV-YOLO 论文学习

1. 解决了什么问题? 出于安全和导航的目的,自驾感知系统需要全面而迅速地理解周围的环境。目前主流的研究方向有两个:第一种传感器融合方案整合激光雷达、相机和毫米波雷达,和第二种纯视觉方案。传感器融合方案的感知表现鲁棒&am…

Qt 继承QAbstractTableModel实现自定义TableModel

1.简介 QAbstractTableModel为将数据表示为二维项数组的模型提供了一个标准接口。它不直接使用,但必须进行子类化。 由于该模型提供了比QAbstractItemModel更专业的接口,因此它不适合与树视图一起使用,尽管它可以用于向QListView提供数据。…

ElasticSearch离线安装

1. 上传和解压软件 将elasticsearch-7.11.2-linux-x86_64.tar.gz和kibana-7.11.2-linux-x86_64.tar.gz 上传到/data/es目录 解压文件 tar -zxvf elasticsearch-7.11.2-linux-x86_64.tar.gz tar -zxvf kibana-7.11.2-linux-x86_64.tar.gz 2. 创建es用户 因为安全问题&#xff…

7.判断素数----不知道哪里错了

#include<stdio.h>void fun(int n) { int i;for(i2;i<n;i){if(n%i0)break;}if(in)printf("%d是素数\n",n);elseprintf("%d不是素数",n); }int main(){int n;scanf("d",&n);fun(n);return 0;}

Direct3D地形绘制基础

高度图 用高度图来描述地形中的丘陵和山谷,高度图其实就是一个数组,该数组每个元素都指定了地形方格中某一个特定顶点的高度值。通常将高度图视为一个矩阵,这样高度图中的元素就与地形栅格中的顶点一一对应。 高度图被保存在磁盘中,通常为其每个元素元素只分配一个字节存…

工程(十四)——ubuntu20.04 PL-VINS

博主创建了一个科研互助群Q&#xff1a;772356582&#xff0c;欢迎大家加入讨论。这是一个科研互助群&#xff0c;主要围绕机器人&#xff0c;无人驾驶&#xff0c;无人机方面的感知定位&#xff0c;决策规划&#xff0c;以及论文发表经验&#xff0c;以方便大家很好很快的科研…

mac电脑系统清理软件CleanMyMac X2024破解版下载

基本上&#xff0c;不管是win版还是Mac版的电脑&#xff0c;其装机必备就是一款电脑系统清理软件&#xff0c;就比如Mac&#xff0c;目前在市面上&#xff0c;电脑系统清理软件是非常多的。 对于不熟悉系统的用户来说&#xff0c;使用一些小众工具&#xff0c;往往很多用户都不…

Yolov8目标识别与实例分割——算法原理详细解析

前言 YOLO是一种基于图像全局信息进行预测并且它是一种端到端的目标检测系统&#xff0c;最初的YOLO模型由Joseph Redmon和Ali Farhadi于2015年提出&#xff0c;并随后进行了多次改进和迭代&#xff0c;产生了一系列不同版本的YOLO模型&#xff0c;如YOLOv2、YOLOv3、YOLOv4&a…

深度学习连接

全连接批量归一化 目的是&#xff1a;通过归一化&#xff0c;让所有的 x i x_i xi​具有一样的分布&#xff0c;学习率是一个值&#xff0c;每个参数 w i w_i wi​梯度的值大致相当实现是&#xff1a;实际上是在全连接中增加了两个节点 γ \gamma γ, β \beta β

常见React Hooks 钩子函数用法

一、useState useState()用于为函数组件引入状态&#xff08;state&#xff09;。纯函数不能有状态&#xff0c;所以把状态放在钩子里面。 import React, { useState } from react import ./Button.cssexport function UseStateWithoutFunc() {const [name, setName] useStat…

reduxjs/toolkit的使用

用法&#xff1a; 下载包进行安装&#xff0c;store主入口&#xff0c;hooks简化store(复制粘贴进去即可)&#xff0c;slice相当于store中的模块化&#xff0c;最后在页面根入口导入store&#xff0c;并使用即可 1、安装 npm install reduxjs/toolkit react-redux -D2、目录结…

Window 11中安装Rust编译环境和集成开发环境

https://blog.csdn.net/weixin_43882409/article/details/87616268是我参考的一篇文章。 下载 先到https://www.rust-lang.org/learn/get-started&#xff0c;下载64-Bit&#xff08;64位&#xff09;的rustup-init.exe文件。 使用其他方式进行安装的网址https://forge.rust…

STM32F103C8T6第二天:按键点灯轮询法和中断法、RCC、电动车报警器(振动传感器、继电器、喇叭、433M无线接收发射模块)

1. 点亮LED灯详解&#xff08;307.11&#xff09; 标号一样的导线在物理上是连接在一起的。 将 PB8 或 PB9 拉低&#xff0c;就可以实现将对应的 LED 灯点亮。常用的GPIO HAL库函数&#xff1a; void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);//I/…

【深度学习】pytorch——神经网络工具箱nn

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 深度学习专栏链接&#xff1a; http://t.csdnimg.cn/dscW7 pytorch——神经网络工具箱nn 简介nn.Modulenn.Module实现全连接层nn.Module实现多层感知机 常用神经网络层图像相关层卷积层&#xff08;Conv&#xff…

高压放大器能够在哪里使用呢

高压放大器是一种重要的电子设备&#xff0c;可以在许多不同的领域和应用中使用。下面西安安泰将详细介绍高压放大器的应用。 医学影像&#xff1a;高压放大器在医学影像领域具有广泛的应用。医学影像设备&#xff08;如X射线机、CT扫描仪等&#xff09;需要高压来产生足够的能…

VUE3 TypeError: defineConfig is not a function

VUE3 TypeError: defineConfig is not a function 1. 问题2. 原因3. 解决 1. 问题 在运行npm run serve时&#xff0c;出现报错&#xff1a; 2. 原因 原因&#xff1a;由于用vue-cli直接创建了vue 3的项目&#xff0c;而里面的生态并非都是最新版&#xff0c;vue.config.js…