[Python]unittest-单元测试

目录

unittest的大致构成:

Test Fixture

Test Case-测试用例

Test Suite-测试套件

Test Runner

批量执行脚本

makeSuite()

TestLoader

discover()

用例的执行顺序

忽略用例执行

skip

skipIf

skipUnless

断言

HTML测试报告

错误截图


unittest是python中的单元测试框架

大致作用:

  • 提供用例的组织与执行-组织大量的测试用例
  • 提供丰富的比较方法-断言
  • 提供丰富的日志-总执行时间,失败用例数,成功用例数

unittest的大致构成:

Test Fixture

对一个测试用例环境搭建销毁,就是一个Test Fixture(设备,固定之物).通过覆盖setUp()和tearDown()方法来实现

setUp()是测试环境的搭建,比如获取待测浏览器的驱动,或者如果测试中需要访问的数据库,可以在setUp()中建立数据库的连接来进行初始化.

tearDown()进行测试环境的销毁,关闭浏览器,关闭数据库等操作

Test Case-测试用例

一个TestCase的实例就是一个测试用例,测试用例就是一个完整的测试流程,包括测试环境的搭建(setUp),实现测试代码的过程,测试环境的销毁,还原(tearDown())

一个测试用例就是一个完整的测试单元

Test Suite-测试套件

将多个测试用例集合在一起

Test Runner

测试的执行,unittest框架中,通过TextTestRunner类提供的run方法执行testCase或testSuite

感受单元测试

from selenium import webdriver
import unittest
import time
from selenium.webdriver.common.by import By


class Baidu2(unittest.TestCase):
    def setUp(self):  # 测试环境的构建
        print("-----setUp-----呜啦啦")
        self.driver = webdriver.Edge()
        self.driver.implicitly_wait(30)
        self.url = "https://www.baidu.com/"
        self.driver.maximize_window()
        time.sleep(3)

    def tearDown(self):  # 测试环境的销毁
        print("-----tearDown-----")
        self.driver.quit()

    def test_baidu(self):  # 脚本1
        driver = self.driver
        url = self.url
        driver.get(url)
        driver.find_element(By.ID, "kw").send_keys("我的世界")
        driver.find_element(By.ID, "su").submit()
        time.sleep(2)
        print(driver.title)
        # self.assertNotEqual(driver.title, "百度一下_百度搜索", msg="不相等")
        # self.assertTrue("beautiful"=="beauty", msg="Not Equal!")
        time.sleep(2)

    def test_findB(self):  # 脚本2
        driver = self.driver
        url = self.url
        driver.get(url)
        driver.find_element(By.ID, "kw").send_keys("B站")
        driver.find_element(By.ID, "su").submit()
        driver.find_element(By.LINK_TEXT, "哔哩哔哩(b站) - 哔哩哔哩 (゜-゜)つロ 干杯~-bi...").click()
        time.sleep(2)
        print(driver.title)
        time.sleep(2)

    if __name__ == "__main__":
        # unittest提供的全局main()方法,能够使一个单元测试模块轻松的变成可直接运行的测试脚本
        # 在main方法中搜索包含在此模块下的,以test命名的测试方法,并执行他们
        unittest.main()

在Baidu2这个类中,

  • setUp + test_baidu + tearDown -> 第1个Test Case
  • setUp + test_findB + tearDown -> 第2个Test Case

尝试将代码跑一下,可以发现.在每次执行被测试代码时,setUp与tearDown都会对应的执行一遍.

批量执行脚本

我们把一个web的每个功能模块都分成一个单元测试,那该怎么将每个模块的单元测试一起执行呢.

就要用到我们上面所提到的Test Suite(测试套件),其是一个集合,集合里装载着Test Case(测试用例)

使用测试套件的大致流程为:

  1. 创建一个测试套件 suite = unittest,TestSuite() #创建一个实例
  2. 把多个测试用例放入测试套件中 suite.addTest() #添加测试方法
  3. 执行测试套件 TextTestRunner的run方法启动suite

其中步骤2的addTest一次只能添加一个测试方法

下面介绍批量执行脚本的三种方式

makeSuite()

由unittest框架中提供的makeSuite()方法,能够把测试用例类内的所有测试用例组成一个TestSuite(测试套件),在使用此方法的时候只要把测试类名传入即可.

def createSuite1():  # makeSuite
    suite1 = unittest.TestSuite()  # 创建一个测试套件
    # 将MyUnitTest01中的Baidu1类中所有的test方法集合成Suite
    # 再将集合成的Suite通过addTest方法添加到我们所创建的Suite实例suite1中
    suite1.addTest(unittest.makeSuite(case.MyUnitTest01.Baidu1))  
    suite1.addTest(unittest.makeSuite(case.MyUnitTest02.Baidu2))
    return suite1
    
if __name__ == "__main__":
    suite = createSuite0()
    # verbosity表示测试结果的信息复杂度,有0,1,2三个级别,复杂度随级别递增
    runner = unittest.TextTestRunner(verbosity=2)  # 创建TextTestRunner实例
    runner.run(suite)

TestLoader

使用TestLoader,测试加载器将测试用例批量的加载到测试套件中

需要用到TestLoader的实例方法:loadTestsFromCase

def createSuite2():
    # 使用TestLoader加载器的实例方法,加载Baidu1类中的测试方法以suite类型返回
    a = unittest.TestLoader().loadTestsFromTestCase(case.MyUnitTest01.Baidu1)
    b = unittest.TestLoader().loadTestsFromTestCase(case.MyUnitTest02.Baidu2)
    # 将加载好的两个suite整合一下
    thesuite = unittest.TestSuite([a, b])
    return thesuite

discover()

上面的两种方式都要提前把类给导入

使用discover就不用添加类了,可以直接根据路径来匹配相应的文件

def createSuite3():
    # 根据所给出的路径,找到匹配正则表达式的文件中的test方法,并将找到的所有test方法以suite的形式返回
    # top_leve_dir一般设置None,默认值即可
    discover = unittest.defaultTestLoader.discover('./case', pattern='MyUnit*.py', top_level_dir=None)
    print(discover)
    return discover

用例的执行顺序

在unittest框架中默认加载测试用例的顺序是根据ASCII码的顺序

在一个模块中,命为TestA的方法会比TestB的方法优先执行.

而在suite中,会根据addTest()添加的顺序来执行

        suite1中含有:

  •                 testB
  •                 testA

        suite2中含有:

  •                 test9
  •                 test2

------------------------------

suite.addTest(suite2)

suite.addTest(suite1)

------------------------------

则最终的执行顺序为:

test2->test9->testA->testB

忽略用例执行

在unittest中想要把test方法进行跳过,可以使用unittest提供的skip标签

这里介绍三个标签:

  1. skip([原因])-无条件跳过标签
  2. skipIf([条件,原因])-有条件跳过标签
  3. skipUnless([条件,原因])-有条件跳过标签

skip

@unittest.skip("暂时跳过此方法")
def test_hao(self):
    driver = self.driver
    url = self.url
    driver.get(url)
    driver.find_element(By.LINK_TEXT, "hao123").click()
    time.sleep(2)

skipIf

比skip多了一个参数,布尔值.

如果为true,则跳过

@unittest.skipIf(2 < 1, "满足条件")
def test_hao(self):
    driver = self.driver
    url = self.url
    driver.get(url)
    driver.find_element(By.LINK_TEXT, "hao123").click()
    time.sleep(2)

skipUnless

与skipIf差不多,但与其相反

如果为false,则跳过

这里就不举例介绍啦~

断言

unittest框架的目的是对代码进行测试,查看结果是否符合我们的预期.

断言就起到了前面后半句的作用,查看结果是否符合我们的期望.

unittest中:

  • 如果某一个case的断言不符合预期测试就会立即停止当前正在执行的case并生成错误信息(并不会影响其他case执行),
  • 如果断言通过则继续执行下一个case

在unittest的单元测试库中提供了许多断言的方法,下面是一些常用的方法.

序 号

断言方法

断言描述

1

assertEqual(arg1, arg2, msg=None)

验证arg1=arg2,不等则fail

2

assertNotEqual(arg1, arg2, msg=None)

验证arg1 != arg2, 相等则fail

3

assertTrue(expr, msg=None)

验证expr是true,如果为false,则fail

4

assertFalse(expr,msg=None)

验证expr是false,如果为true,则fail

5

assertIs(arg1, arg2, msg=None)

验证arg1、arg2是同一个对象,不是则fail

6

assertIsNot(arg1, arg2, msg=None)

验证arg1、arg2不是同一个对象,是则fail

7

assertIsNone(expr, msg=None)

验证expr是None,不是则fail

8

assertIsNotNone(expr, msg=None)

验证expr不是None,是则fail

9

assertIn(arg1, arg2, msg=None)

验证arg1是arg2的子串,不是则fail

10

assertNotIn(arg1, arg2, msg=None)

断言描述验证arg1不是arg2的子串,是则fail

11

assertIsInstance(obj, cls, msg=None)

验证obj是cls的实例,不是则fail

12

assertNotIsInstance(obj, cls,msg=None)

验证obj不是cls的实例,是则fail

msg是自己定义给断言如果发生错误显示的信息

HTML测试报告

下载HTMLTestRunner.py,并将其扔到python的lib当中

import unittest
import HTMLTestRunner
import time
import os,sys
if __name__ == "__main__":
    curpath = sys.path[0]  # 获取当前的根目录
    print(curpath)
    # 取当前时间
    now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))
    # 查看是否有文件夹/resultreport,如果没有则创建
    if not os.path.exists(curpath + '/resultreport'):
        os.makedirs(curpath + '/resultreport')
    # 创建报告文件的名称:  根目录+resultreport(报告文件夹)+时间+html格式文件
    filename = curpath + '/resultreport/' + now + 'resultreport.html'
    # 写入创建的html文件中
    # 打开文件,模式为二进制写wb,文件变量名为fp
    with open(filename, 'wb') as fp:
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u'测试报告',description=u'用例执行情况',verbosity=2)
        suite = createSuite1()
        # verbosity表示测试结果的信息复杂度,有0,1,2三个级别,复杂度随级别递增
        runner.run(suite)

 

错误截图

在断言没通过的时候,我们可以设置自动截图来查看当时的web情况如何,这样就能方便我们对测试用例的观察

def savescreenshot(driver, file_name):
    if not os.path.exists('./image'):
        os.makedirs('./image')
    cur = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
    # 截图保存
    driver.get_screenshot_as_file('./image/'+cur+'-'+file_name)
    time.sleep(1)
def test_baidu(self):
    driver = self.driver
    url = self.url
    driver.get(url)
    driver.find_element(By.ID, "kw").send_keys("蜡笔小新")
    driver.find_element(By.ID, "su").submit()
    time.sleep(2)
    try:
        self.assertEquals("haha", "wowo")
    except:
        savescreenshot(driver, 'wow.png')
    time.sleep(2)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《红蓝攻防对抗实战》八.利用OpenSSL对反弹shell流量进行加密

前文推荐&#xff1a; 《红蓝攻防对抗实战》一. 隧道穿透技术详解《红蓝攻防对抗实战》二.内网探测协议出网之TCP/UDP协议探测出网《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网《红蓝攻防对抗实战》四.内网探测协议出网之ICMP协议探测出网《红蓝攻防对抗…

【C++深入浅出】模版初识

目录 一. 前言 二. 泛型编程 三. 函数模版 3.1 函数模版的概念 3.2 函数模版的格式 3.3 函数模版的原理 3.4 函数模板的实例化 3.5 模板参数的匹配原则 四. 类模版 4.1 类模版的定义 4.2 类模版的实例化 一. 前言 本期我们要介绍的是C的又一大重要功能----模版。通…

单例模式详解【2023年最新】

一、单例模式概念 单例模式是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。它的目的是限制一个类只能创建一个对象&#xff0c;以确保在整个应用程序中只有一个共享的实例。 单例模式通常用于以下情况&#xff1a;…

git stash的使用方法

git stash的使用方法 应用场景 当我们在开发一个新功能的时候&#xff0c;或者开发到一半&#xff0c;然后就收到了线上master 出现了bug&#xff0c;当分支开发已经进行了或者进行到一半了&#xff0c;这时怎么办呢&#xff1f; 这时解决方案有两种&#xff1a;一种是先先将当…

数据分析和互联网医院小程序:提高医疗决策的准确性和效率

互联网医院小程序已经在医疗领域取得了显著的进展&#xff0c;为患者和医疗从业者提供了更便捷和高效的医疗服务。随着数据分析技术的快速发展&#xff0c;互联网医院小程序能够利用大数据来提高医疗决策的准确性和效率。本文将探讨数据分析在互联网医院小程序中的应用&#xf…

在HTML当中引入Vue控件,以element-ui为例

前情&#xff1a;需要实现一个同时满足按天、按周、按月选择的时间选择器&#xff0c;但是以HTML为基础写的都不太满足我的要求&#xff0c;要么只能按天选择&#xff0c;要么就是想选择久远的时间得点很久&#xff0c;除非自己写捷径&#xff0c;所以就看上了element-ui的这个…

泰州市旅游景点门票预订管理系统 vue+uniapp微信小程序

本文从管理员、用户的功能要求出发&#xff0c;泰州市旅游景点管理小程序中的功能模块主要是实现用户、景点类型、景区信息、门票预定。经过认真细致的研究&#xff0c;精心准备和规划&#xff0c;最后测试成功&#xff0c;系统可以正常使用。分析功能调整与泰州市旅游景点管理…

ubuntu 下的 使用anaconda 环境运行python 项目

pycharm部署django项目到云服务器的详细流程_编程网 anaconda 安装环境 Ubuntu安装Anaconda详细步骤&#xff08;Ubuntu22.04.1&#xff0c;Anaconda3-2023.03&#xff09;-CSDN博客 ubuntu下Anaconda安装与使用教程_ubuntu 运行anaconda_fakerth的博客-CSDN博客 Anaconda教…

吴恩达《机器学习》1-2:什么是机器学习?

一、什么是机器学习&#xff1f; Arthur Samuel&#xff08;1959&#xff09;&#xff1a; 他定义机器学习为&#xff0c;在进行特定编程的情况下&#xff0c;给予计算机学习能力的领域。 Tom Mitchell&#xff08;1998&#xff09;&#xff1a; 他定义的机器学习是&#xff0c…

微服务框架Consul--新手入门

Consul Consul 是由 HashiCorp 开发的一款软件工具&#xff0c;提供了一组功能&#xff0c;用于服务发现、配置管理和网络基础设施自动化。它旨在帮助组织管理现代分布式和微服务架构系统的复杂性。以下是Consul的一些关键方面和功能&#xff1a; 服务发现&#xff1a;Consul …

【ChatGPT 01】ChatGPT基础科普

1. 从图灵测试到ChatGPT 1950年&#xff0c;艾伦•图灵(Alan Turing)发表论文**《计算机器与智能》&#xff08; Computing Machinery and Intelligence&#xff09;&#xff0c;提出并尝试回答“机器能否思考”这一关键问题。在论文中&#xff0c;图灵提出了“模仿游戏”&…

Go语言用Resty库编写的音频爬虫代码

目录 一、Go语言与Resty库简介 二、音频爬虫的实现 1、确定抓取目标 2、使用Resty发送HTTP请求 3、解析响应数据 4、下载音频文件 5、并发下载音频文件 三、注意事项 总结 随着互联网的飞速发展&#xff0c;网络爬虫逐渐成为数据获取和分析的重要工具。在音频领域&…

队列概念|循环队列的实现

前言 今天我们将学习循环队列实现&#xff0c;我们首先介绍队列的概念和结构&#xff0c;之后一步步讲解循环队列由来与实现。 一、队列的概念与结构 1、队列的概念 队列&#xff1a; 只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表。队列是…

Leetcode—274.H指数【中等】

2023每日刷题&#xff08;十三&#xff09; Leetcode—274.H指数 算法思想 参考自灵茶山艾府 实现代码 int minValue(int a, int b) {return a < b ? a : b; }int hIndex(int* citations, int citationsSize){int cnt[5001] {0};int i;for(i 0; i < citationsSize; …

android开发使用OkHttp自带的WebSocket实现IM功能

一、背景 android app开发经常会有IM需求&#xff0c;很多新手不晓得如何入手&#xff0c;难点在于通讯不中断。其实android发展到今天&#xff0c;很多技术都很完善&#xff0c;有很多类似框架可以实现。例如有&#xff1a;okhttp自带的websocket框架、easysocket等等。本文主…

14 结构性模式-适配器模式

1 适配器模式介绍 适配器模式(adapter pattern )的原始定义是&#xff1a;将类的接口转换为客户期望的另一个接口&#xff0c;适配器可以让不兼容的两个类一起协同工作。 2 适配器模式原理 3 适配器模式应用实例 /*** SD卡接口**/ public interface SDCard {//读取SD卡Strin…

JavaEE-cookie和session

本部分内容包括 cookie基本概念&#xff0c;sendcookies和getcookies代码&#xff1b; session基本概念&#xff0c;session实现登陆界面&#xff1b; 上述过程中涉及的代码如下&#xff1a; 1 import javax.servlet.ServletException; import javax.servlet.annotation.WebSe…

spring-代理模式

代理模式 一、概念1.静态代理2.动态代理 一、概念 ①介绍 二十三种设计模式中的一种&#xff0c;属于结构型模式。它的作用就是通过提供一个代理类&#xff0c;让我们在调用目标 方法的时候&#xff0c;不再是直接对目标方法进行调用&#xff0c;而是通过代理类间接调用。让不…

搞定蓝牙-第六篇(HID

搞定蓝牙-第六篇&#xff08;HID&#xff09; ble与HIDHOGPGAPP与HID ESP32程序分析 ble与HID HOGP 我们发现&#xff0c;电脑连接了蓝牙键盘就可以直接使用了&#xff0c;不需要配置任何东西&#xff0c;那么&#xff0c;这两者是怎么通讯的呢。我们使用的电脑windows系统内…

离线语音通断器开发-稳定之后顺应新需求

使用云知声的US516p6方案开发了一系列的离线语音通断器&#xff0c;目前已经取得了不小的收获&#xff0c;有1路的&#xff0c;3路的&#xff0c;4路的&#xff0c;唛头和扬声器包括唛头线材也在不断的更新打磨中找到了效果特别好的供应商。 离线语音通断器&#xff0c;家用控…