Python + UnitTest 软件测试流程总结

以测试用户登录流程为例:

TestCase:

TestCase 主要用来编写测试用例,这里结合 断言(assertEqual 和 assertIn) 进行判断,避免了手动书写判断。

# tools.py
# 登录验证方法
def login(username, password):
    if username == 'admin' and password == '123456':
        return '登录成功'
    else:
        return '登录失败'
# TestCase.py
# 导入 unittest
import unittest
from tools import login


class TestLogin(unittest.TestCase):
    def test_username_password_ok(self):
        self.assertEqual('登录成功', login('admin', '123456'))

    def test_username_error(self):
        self.assertEqual('登录失败', login('root', '123456'))

    def test_password_error(self):
        self.assertEqual('登录失败', login('admin', '123123'))

    def test_username_password_error(self):
        # self.assertEqual('登录失败', login('root', '123123'))
        self.assertIn('失败', login('aaa', '123123')) # 结果中包含“失败”即可

TestSuite:

TestSuite 用来管理多个 TestCase 文件,使用 unittest.TestSuite() 实例化套件对象,再使用套件对象添加用例方法。

假如创建多个 TestCase 文件:

# testCase1.py
# 导包
import unittest

# 自定义测试类,继承 unittest 类中 testCase 类
class testDemo1(unittest.TestCase):
    # 测试方法(用例代码)
    def method1(self):
        print('测试方法1-1')

    def method2(self):
        print('测试方法1-2')
# testCase2.py
# 导包
import unittest

# 自定义测试类,继承 unittest 类中 testCase 类
class testDemo2(unittest.TestCase):
    # 测试方法(用例代码)
    def method1(self):
        print('测试方法2-1')

    def method2(self):
        print('测试方法2-2')

TestRunner:

用来执行对象。

# TestSuite_Runner.py
# TestSuite用来管理多个TestCase文件
# 1.导包
import unittest
# 2.实例化(创建对象)套件对象
from testCase1 import testDemo1
from testCase2 import testDemo2
from TestCase import TestLogin

suite = unittest.TestSuite()
# 3.使用套件对象添加用例方法
# 方法一:套件对象.addTest(测试类名('方法名'))
suite.addTest(testDemo1('method1'))
suite.addTest(testDemo1('method2'))
suite.addTest(testDemo2('method1'))
suite.addTest(testDemo2('method2'))

# 方法二:将一个测试类中的所有方法进行添加
# 套件对象.addTest(unittest.makeSuite(测试类名))
suite.addTest(unittest.makeSuite(testDemo1))
suite.addTest(unittest.makeSuite(testDemo2))
suite.addTest(unittest.makeSuite(TestLogin))

# 4.实例化运行对象
runner = unittest.TextTestRunner()

# 5.使用运行对象去执行套件对象
# 运行对象.run(套件对象)
runner.run(suite)

TestLoader:

用于多个 TestCase 中有多个 Method 时,写法较简便

# TestLoader.py
# 1.导包
import unittest

# 2.实例化加载对象并添加用例
# unittest.TestLoader().discover('用例所在的路径', '用例的代码文件名')
suite = unittest.TestLoader().discover('./case', '*.py')
# suite = unittest.defaultTestLoader().discover('./case', '*.py') 两种写法

# 将3.4.合并
unittest.TextTestRunner().run(suite)

TestFixture:

在执行每个测试方法的前后会出现一些重复操作,可以使用 TestFixture 进行书写。

# TestFixture.py
import unittest

class TestLogin(unittest.TestCase):
    # 1.打开浏览器(整个测试过程中就打开一次浏览器) 类级别
    @classmethod
    def setUpClass(cls) -> None:
        print('打开浏览器')

    # 2.输入网址(每个测试方法都需要一次) 方法级别
    def setUp(self):
        # 每个测试方法执行之前都会调用的方法
        print('输入网址')

    # 3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
    def test_1(self):
        print('输入正确信息,点击登录1')

    def test_2(self):
        print('输入错误信息,点击登录2')

    # 4.关闭当前页面(每个测试方法都需要一次) 方法级别
    def tearDown(self):
        # 每个测试方法执行之后都会调用的方法
        print('关闭当前页面')

    # 5.关闭浏览器(整个测试过程中就关闭一次浏览器) 类级别
    @classmethod
    def tearDownClass(cls) -> None:
        print('关闭浏览器')

Skip:

不想执行某个测试用例时,可以进行直接跳过(skip)或者条件触发(skipIf)跳过。

# skip.py
# 导包
import unittest

version = 30

# 自定义测试类
class testDemo(unittest.TestCase):
    # 测试方法
    @unittest.skip('直接跳过')
    def test_method1(self):
        print('测试方法111')

    @unittest.skipIf(version >= 30, '版本高跳过测试')
    def test_method2(self):
        print('测试方法222')

    def test_method3(self):
        print('测试方法333')
# 执行用例(方法)

Parameterized:

在实际开发中,测试用例的数据不能写死,这时用到json文件的读取,之后利用 parameterized 对读取函数进行调用。

首先执行 pip install parameterized 下载;

之后在模块中导入 from parameterized import parameterized

# 导入unittest/parameterized
import json
import unittest
from parameterized import parameterized
from tools import login


# 组织测试数据
def build_data():
    with open('data.json', encoding='utf-8') as f:
        result = json.load(f)
        data = []
        for info in result:
            data.append((info.get('username'), info.get('password'), info.get('expect')))
    return data

# 定义测试类
class TestLogin(unittest.TestCase):
    # 书写测试方法(用到的测试数据使用变量代替)
    @parameterized.expand(build_data())
    def test_login(self, username, password, expect):
        self.assertEqual(expect, login(username, password))

 这里的 data.json:

[
  {
    "desc": "正确用户名密码",
    "username": "admin",
    "password": "123456",
    "expect":"登录成功"
  },
  {
    "desc": "错误用户名",
    "username": "root",
    "password": "123456",
    "expect":"登录失败"
  },
  {
    "desc": "错误密码",
    "username": "admin",
    "password": "123123",
    "expect":"登录失败"
  }
]

在此过程中会生成测试报告,在终端中执行代码后,按照以下步骤可以进行查看:

 

 

运行html文件即可,效果如图:

这样生成的测试报告相对简陋,可以使用第三方库生成,在当前目录中放入顶部的两个文件。

接下来书写以下代码:

# 利用第三方生成测试报告
# 中文版
# 1.获取第三方的 测试运行类模块,将其放在代码的目录中
# 2.导包 unittest
import unittest
from HTMLTestRunnerCN import HTMLTestReportCN

# 3.使用 套件对象,加载对象 去添加用例方法
suite = unittest.defaultTestLoader.discover('.', 'pa*login.py')
# 4.实例化 第三方的运行对象
file = 'report_cn.html'
with open(file, 'wb') as f:
    # 运行对象(第二个参数是:是否详细 1/2,第三个参数是报告标题,第三个参数是python/pycharm版本)
    runner = HTMLTestReportCN(f, 2, '测试报告中文版', 'python 3.6.7')
    # 5.运行 套件对象
    runner.run(suite)

# --------------------上下两端代码不要一起执行------------------------

# 1.获取第三方的 测试运行类模块,将其放在代码的目录中
# 2.导包 unittest
import unittest
# 英文版
from HTMLTestRunner import HTMLTestRunner

# 3.使用 套件对象,加载对象 去添加用例方法
suite = unittest.defaultTestLoader.discover('.', 'pa*login.py')
# 4.实例化 第三方的运行对象
file = 'report.html'
with open(file, 'wb') as f:
    # 运行对象
    runner = HTMLTestRunner(f, 1, '测试报告', 'python 3.6.8')
    # 5.运行 套件对象
    runner.run(suite)

效果如下: 

 

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

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

相关文章

Vue入门教学——编写第一个页面

以Vue2.0为例子。 1、创建一个Vue项目 创建过程:Vue-cli(脚手架)的创建_vue脚手架创建项目命令-CSDN博客【注】项目名不能有大写字母。创建完毕后,使用VSCode打开项目文件夹(其他编辑器也行)。 2、运行项…

浅析高校用电问题及智慧电力监管平台的构建

安科瑞 崔丽洁 摘 要:介绍了当前高校用电存在的问题,进行了原因分析,由此提出建立高校用电智慧监管平台。对高校用电智慧监管平台的构架进行设计,运用物联网技术,实现各回路实时自主控制,并细化管理权限&a…

50代码审计-PHP无框架项目SQL注入挖掘

代码设计分为有框架和无框架 挖掘技巧:随机挖掘,定点挖掘,批量挖掘(用工具帮助扫描探针,推荐工具:fortify,seay系统)。 1.教学计划: ---审计项目漏洞 Demo->审计思…

打印流详解

概述 作用:打印流可以实现方便、高效的打印数据到文件中去。 高效体现在用到了缓冲流: public PrintStream(OutputStream out, boolean autoFlush, Charset charset) {super(out);this.autoFlush autoFlush;this.charOut new OutputStreamWriter(thi…

ObjectMapper - 实现复杂类型对象反序列化(天坑!)

目录 一、复杂类型反序列化 1.1、背景 1.2、问题解决 一、复杂类型反序列化 1.1、背景 a)例如有 AppResult 对象,如下: Data public class AppResult {private Integer code;private String msg;private Object data;} b)App…

建设银行余额生成器,工商农业邮政招商中国模版,易语言画板+编辑框实现截图

今天闲着没事干用易语言画板快照命令开发了一个虚拟余额生成器,当然我加了水印,模版上面都加了水印的,仅仅提供娱乐的效果,做不了啥事,然后软件主要就是画板上面加入了固定的模版图,图片的话你可以自己网上…

【React入门实战】实现Todo代办

文章目录 效果功能-状态管理相关接口定义相关方法定义 UIinput输入框:回车添加todo标题列表列表项Main 总体代码 非常简单入门的react-todo练习,代码写的很小白。 效果 技术栈:react-typeScript 数据分为代办Todo和已办完Done,可…

西门子S7-1200PLC混合通信编程(ModbusTcp和UDP通信)

S7-1200PLC的MODBUS-TCP通信 西门子PLC ModbusTcp通信访问网关后从站(SCL语言轮询状态机)-CSDN博客文章浏览阅读305次。西门子PLC的ModbusTcp通信在专栏已有很多文章介绍,所不同的是每个项目的通信需求都略有不同,今天我们以访问网关后的三个从站数据来举例,给出轮询的推荐…

WPS的JS宏基础(一)

基础知识 1、简单的第一个宏 //注意function只能全部用小写 function demo(){alert("你好!") }2、录制宏生成工资条 function 使用录制宏自动生成代码以JS宏为例()//使用相对引用 {Selection.Copy(undefined);ActiveCell.Offset(5, 0).Range("A1:M4").I…

Java进击框架:Spring-数据存取(七)

Java进击框架:Spring-数据存取(七) 前言事务管理声明式事务管理 DAO支持JDBC的数据访问使用JdbcTemplate控制数据库连接JDBC批处理操作封装 SQL 语句中的参数 使用R2DBC进行数据访问对象关系映射(ORM)数据访问HibernateJPA XML模式 前言 参考…

【免费送书】写博客模板

【点我-这里送书】 本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的…

如何优化负载均衡?一文讲懂

当web应用程序增长到单服务器无法承受的地步,企业就面临着优化负载均衡的需求。简而言之,企业需要实现流量重定向,就需要从业务可靠性的需求出发,寻找一套可行的负载均衡方案,那么常用的负载均衡方案有哪些&#xff1f…

UnoCSS框架常用语法

文章目录 🍉vscode 开发插件🍉设置边框颜色🍉设置宽、高、背景色、外边距🍉设置flex🍉设置元素在滚动时固定在指定区域内🍉vscode 开发插件 vscode 开发建议安装 UnoCSS插件 🍉设置边框颜色 border-[color]: 设置边框的颜色,[color]可以是预设的颜色名称(如…

什么是 eCPM?它与 CPM 有何不同?

目录 eCPM 什么是 eCPM?它与 CPM 有何不同? 如何计算 eCPM? 该指标的主要优势有哪些? eCPM 底价 eCPM 达到多少比较合适? eCPM 每千人有效成本 (eCPM) 是指发行商(App 开发者)在 App 中每…

境电商为什么要做独立站?API一键对接秒上架瞬间拥有全平台几十亿商品和用户!

境电商为什么要做独立站?它的优势又有哪一些? 如果说我们的企业是做b two b的跨境电商,那今天这个内容一定要仔细,API一键对接秒上架瞬间拥有全平台几十亿商品和用户! 第一呢,独立站它就是我们自己做的一个…

Linux入门(二)

Linux入门(二) 1:创建文件 1.1 touch命令 使用touch命令在文件不存在时,会创建文件。同时不支持在创建文件时,写入一些内容,该文件的大小是0kb. touch test.txt 注意,无法创建多级目录文件 …

redisson中的分布式锁

文章目录 redisson中的分布式锁可重入锁(Reentrant Lock) redisson中的分布式锁 ​ Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供…

力扣每日一题 ---- 2906. 构造乘积矩阵

这题很简单(一下就能想到是前缀和的提米),但是在处理12345上面需要仔细一点,本来我最开始想到的时候全部累乘在除掉当前数,但是这样就没有把12345考虑进去,如果他本身是12345的话,那么除他以外的乘积并不一定是0&#…

ubuntu22.04桌面版系统无法识别USB摄像头

虚拟机连接电脑摄像头连接失败(驱动程序错误) 本文为转载:版权归远作者所有,之所以转载是为了避免被原作者删除 巴黎铁塔下的女孩 你尽管努力,剩下的交给时间 虚拟机调用电脑的摄像头,正常情况下只需点击…

鲁大师10月新机性能/流畅/久用榜:骁龙8 Gen3一鸣惊人,双十一“6系”处理器成井喷状态

刚刚过去的10月份手机圈可谓是热闹纷呈,要数量有数量,要新品有新品,要旗舰有旗舰,要走量也有走量。10月份的大部分光芒,毫无疑问都将被骁龙8 Gen3以及重夺骁龙旗舰首发的小米 14系列身上。 骁龙8 Gen3毫无疑问,代表着骁龙旗舰处理器的又一个巅峰,从目前鲁大师后台抓取到的数据…