Python学习笔记17:进阶篇(六)代码测试

代码测试

代码测试是软件开发过程中的关键环节,旨在确保代码质量、功能正确性以及性能符合预期。

在开发过程中,进行代码测试有很多好处:

  1. 提高软件质量:通过发现并修复错误,测试有助于提升软件的功能性、可靠性和稳定性,减少用户遇到的问题。
  2. 降低维护成本:及早发现错误可以减少后期修复的复杂度和成本,因为错误在系统更复杂时更难追踪和修正。
  3. 加速开发流程:自动化测试能够快速反馈代码变更的效果,使得开发者能迅速定位问题,加快迭代速度。
  4. 增强信心:全面的测试套件为开发团队和利益相关者提供了部署代码的信心,知道改动不太可能引入新的错误。
  5. 促进可维护性和可扩展性:编写可测试的代码往往意味着更好的模块化和解耦,这有利于未来的维护和功能扩展。
  6. 文档作用:测试用例本身也起到了文档的作用,展示了代码应该如何被使用,以及预期的行为是什么。
  7. 便于重构:有了坚实的测试基础,开发者可以更加大胆地进行代码重构,优化结构而不必过分担心引入新bug。
  8. 提升团队协作:共同的测试标准和实践促进了团队成员之间的沟通和理解,确保了项目的一致性和质量标准。

作为python学习者,我们更加需要学习代码的测试知识,因为python是自动化测试的首选语言。

测试工具

unittest

unittest是Python标准库中的一个模块,提供了编写和运行测试的强大工具。

  1. 测试用例:每个测试用例通常对应一个函数,使用test_前缀命名。
  2. 断言方法:如assertEqual()、assertTrue()等,用于比较实际结果与预期结果。
  3. 测试套件:使用unittest.TestSuite来组织多个测试用例。
  4. 测试运行器:使用unittest.TextTestRunner来执行测试。

if name == ‘main’:

插个小知识,以免后面看不懂。

在Python程序中,if name == ‘main’: 是一个常见的条件语句,其作用在于判断当前文件是否作为主程序直接被执行。如果文件是被直接执行,那么这个条件下的代码块将会被执行;反之,如果文件是被导入到其他模块中,则该代码块不会执行。这样的设计允许模块既可以作为独立的程序运行,又可以在其他程序中被引用而不会执行主程序的代码。

为什么需要这个判断?

  1. 避免重复执行:当一个模块被其他模块导入时,如果模块中有全局执行的代码(比如打印语句、初始化操作等),如果不加此判断,这些代码就会被执行。这对于只想使用该模块中定义的函数或类的其他模块来说,可能会产生意料之外的结果或副作用。

  2. 便于组织代码:将程序的入口点统一放在这一块,使得代码结构更加清晰。特别是对于包含多个函数和类的大型模块,这种方式有助于区分哪些代码是用来测试或演示模块功能的,哪些是模块的核心功能定义。

def hello(name):
    print(f"Hello, {name}!")

if __name__ == '__main__':
    hello("World")

在这个例子中,hello函数定义了一个简单的打招呼功能。当直接运行这个脚本时,因为__name__变量的值为’main’,所以会执行下面的代码块,打印出"Hello, World!"。但如果这个模块被其他脚本导入,hello函数可以被正常使用,但打招呼的那行代码不会执行,除非导入模块的脚本也显式调用了hello函数。

测试示例

测试函数

import unittest
from operator import add


class TestAddFunction(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(1, 2), 3)
        self.assertEqual(add(-1, 1), 0)
        self.assertEqual(add(0, 0), 0)

if __name__ == '__main__':
    unittest.main()

这段代码中,我们使用了断言assertEqual来测试我们add函数的正确性。
在这里插入图片描述
以上是代码测试通过的示例,假如有错误的结果又会是怎么样的呢?我们还是以add函数示例。

import unittest
from operator import add


class TestAddFunction(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(1, 2), 3)
        self.assertEqual(add(-1, 1), 2)
        self.assertEqual(add(0, 0), 0)


if __name__ == '__main__':
    unittest.main()

我们修改第二个断言中的函数预期值,并点击执行。
在这里插入图片描述
最终运行框中提示了第二个断言的错误,预期是0但是我们给的值是2,这是一个不能通过的测试。

能够正常通过的测试有了,不能通过的测试也有了。遇到不能通过的测试怎么呢?

首先,你应该检查你的输入参数,如果你能保证你的输入参数没有问题那么说明你的函数还有问题存在,需要修复。这个时候需要我们修改的是函数本身的逻辑,而不是测试的代码。通过debug的方式找到影响正确输出的代码进行修改即可。

测试类

先准备需要测试目标类。

class BankAccount:
    def __init__(self):
        self.balance = 0

    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self.balance += amount
        else:
            raise ValueError("存款金额必须大于0")

    def withdraw(self, amount):
        """取款"""
        if 0 < amount <= self.balance:
            self.balance -= amount
        else:
            raise ValueError("取款金额必须大于0且不超过账户余额")

    def get_balance(self):
        """查询余额"""
        return self.balance

编写一个测试实施类,对测试目标类进行测试。

import unittest
from bank_account import BankAccount


class TestBankAccount(unittest.TestCase):
    def setUp(self):
        """每个测试方法执行前的准备工作"""
        self.account = BankAccount()

    def test_initial_balance(self):
        """测试初始余额是否为0"""
        self.assertEqual(self.account.get_balance(), 0)

    def test_deposit(self):
        """测试存款功能"""
        self.account.deposit(100)
        self.assertEqual(self.account.get_balance(), 100)

    def test_withdraw(self):
        """测试取款功能"""
        self.account.deposit(800)
        self.account.withdraw(600)
        self.assertEqual(self.account.get_balance(), 200)

    def test_negative_deposit(self):
        """测试尝试存入负数时是否抛出异常"""
        with self.assertRaises(ValueError):
            self.account.deposit(-50)

    def test_overdraft_withdraw(self):
        """测试尝试超限取款时是否抛出异常"""
        self.account.deposit(100)
        with self.assertRaises(ValueError):
            self.account.withdraw(900)


if __name__ == '__main__':
    unittest.main()

在这里插入图片描述
这就是简单对类进行测试。

断言

断言方法是测试用例的核心,用于比较实际结果与预期结果,从而判断测试是否通过。以下是一些常用的断言方法及其用途:

assertEqual(a, b):检查a和b是否相等。
assertTrue(x):检查x是否为True。
assertFalse(x):检查x是否为False。
assertIn(item, list):检查item是否在list中。
assertNotIn(item, list):检查item是否不在list中。
assertIsNone(x):检查x是否为None。
assertIsNotNone(x):检查x是否不为None。
assertAlmostEqual(a,b):检查浮点数a和b是否足够接近(默认容差为7个十进制位)。
assertRaises(exc, callable, *args,**kwargs):检查在调用callable(*args, **kwargs)时是否抛出exc异常。

测试套件和测试运行器

测试套件就是将多个测试用例组合在一起,一次性执行。在需要组织和管理大量测试时会很有帮助。
测试运行器则是负责执行测试套件并收集测试结果。最常用的运行器是unittest.TextTestRunner,它会打印测试结果到控制台。

import unittest

# 假设有两个测试类
class TestAddition(unittest.TestCase):
    def test_add(self):
        self.assertEqual(1 + 1, 2)

class TestSubtraction(unittest.TestCase):
    def test_subtract(self):
        self.assertEqual(3 - 1, 2)

# 创建测试套件
suite = unittest.TestSuite()

# 将测试用例添加到套件中
suite.addTest(TestAddition('test_add'))
suite.addTest(TestSubtraction('test_subtract'))

# 运行测试套件
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

如代码示例,将多个测试用例组合到一起,一次执行,全部测试。

在这里插入图片描述

结尾

测试内容基本就这里结束了,没办法写的很深入,一个是本人水平问题,一个代码这东西,总归要是要结合到项目里面自己实战,发现问题到解决问题,这样才能有收获,才能有进步,才能有收获。当然初学时的练习也不要忘了!

作业

除了已经示例过的断言,增加两三个其他的断言进行使用,测试套件和测试运行器也别忘了用上。

  1. 自定义函数,并编写测试用例。
  2. 自定义类,编写测试用例。

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

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

相关文章

黑马程序员-瑞吉外卖-前六章

黑马程序员瑞吉外卖 文章目录 1、开发环境搭建1.1 数据库环境1.2 maven项目搭建1.2.1 新建项目1.2.2 整合MyBatisPlus1.2.3 整合Druid1.2.4 配置文件application.yml1.2.5 尝试启动项目1.2.6 将前端静态页面引入到项目中 2、 后台系统登录功能2.1 需求分析2.2 代码开发2.2.1 创…

解析网页数据并且处理网页正则表达式与re模块

目录 一、解析网页数据的技术 1&#xff0e;正则表达式 2&#xff0e;XPath 3&#xff0e;Beautiful Soup 4&#xff0e;JSONPath 二、正则表达式的语法 1&#xff0e;元字符 2&#xff0e;预定义字符集 三、 re 模块的使用 1&#xff0e;创建 Pattern 对象 2&#…

libreoffice报: error while loading shared libraries: libcups.so.2: cannot

切换到cd /opt/libreoffice7.1/programlibreoffice查看版本的时候报:/opt/libreoffice7.1/program/soffice.bin: error while loading shared libraries: libcups.so.2: cannot open shared object file: No such file or directory ./soffice --version解决办法&#xff1a; …

MySQL之复制(六)

复制 复制拓扑 拥有备库的主-主结构 另外一种相关的配置是为每个主库增加一个备库&#xff0c;如图所示。这种配置的优点是增加了冗余&#xff0c;对于不同地理位置的复制拓扑&#xff0c;能够消除站点单点失效的问题。你也可以像平常一样&#xff0c;将读查询分配到备库上。…

深入JVM:详解JIT即时编译器

文章目录 深入JVM&#xff1a;详解JIT即时编译器一、序言二、基础概念1、何为JIT即时编译2、热点代码 三、HotSpot内置的即时编译器1、C1编译器2、C2编译器3、分层编译3.1 协作流程 四、常见JIT优化技术1、方法内联2、逃逸分析&#xff08;1&#xff09;同步锁消除&#xff08;…

从零开始学习Linux(10)----动静态库

目录 1.制作静态库 1.编写源代码 2.编译 3.打包库 4.使用库 2.制作动态库 1.编译 2.打包库 3.总结 3.理解动态库加载 1.站在系统角度理解 2.谈谈编址&#xff0c;可执行程序 1.制作静态库 1.编写源代码 假设你编写了两个源代码文件mymath.c和myprintf.c以及它们对应…

vuex的actions返回结果类型是promise及actions方法互相调用

this.$store.dispatch(‘logout’)返回的结果是Promise类型的 调用成功的情况下&#xff0c;返回状态为fulfilled&#xff0c;值为undefined。 所以可以直接进行.then操作&#xff1a; this.$store.dispatch(logout).then((result) > {console.log(result); });因为 Vuex …

正则表达式;grep、sed、awk、soft、uniq、tr 详解

正则表达式 概念 正则表达式&#xff08;Regular Expression&#xff0c;常简写为regex、regexp或RE&#xff09;是一种强大的文本处理工具&#xff0c;它使用一种特殊的字符序列来帮助用户检查一个字符串是否与某种模式匹配。 标准正则表达式 首先安装正则表达式pcre库 创…

草莓不是莓,西瓜才是莓——解读 Kubernetes 中被驱逐的 Pod

每天都有成千上万的 Pod 从节点中被驱逐。它们无家可归、困惑不已&#xff0c;不得不放弃之前的生活方式。其中一些甚至变成无节点状态。 在 Kubernetes 中 Pod 被驱逐意味着什么&#xff1f;我们常常能看到 Pod 因为资源不足被终止。但为什么会发生这种情况呢&#xff1f; 驱…

ChatGPT API技术教程OpenAI APIKey在线对接-Chat Completion对象

表示模型根据提供的输入返回的聊天完成响应。 {"id": "chatcmpl-123","object": "chat.completion","created": 1677652288,"model": "gpt-3.5-turbo-0125","system_fingerprint": "fp…

ElementUI组件库,分页组件靠右显示

ElementUI组件库&#xff0c;分页组件靠右显示 分页组件 &#xff0c;el-pagination组件默认靠左显示&#xff0c;靠右显示的话只需给layout添加一个“->”属性值即可, 看图

AMEYA360代理品牌江苏润石:RS8661/2/4系列高压精密低噪声运算放大器

继RS8651/2/4系列高压精密低噪声运算放大器成功推向市场&#xff0c;润石科技再次成功量产RS8661/2/4系列高压精密低噪声运算放大器。 RS8661/2/4系列产品将工作电压提升到最高36V(18V)、失调电压进一步优化到5μV、在工业现场数据采集、各种仪器仪表测量设备\分析设备上有着广…

IDEA services模块无法启动springboot服务(添加了springboot但是为空白)

https://blog.csdn.net/m0_54042402/article/details/117918995 https://blog.csdn.net/qq_46550964/article/details/122235235 Alt8 显示services模块 发现有springboot启动模块&#xff0c;点一下springboot之后&#xff0c;这个模块就消失了 会自动在.idea文件夹下的work…

选专业填志愿,家庭经济条件是必须考虑因素

对比过去&#xff0c;大部分家庭的物质条件已经好很多了&#xff0c;但也有一部分家庭条件较为困难&#xff0c;对于家庭条件较为困难的高考学生而言&#xff0c;高考志愿填报需要考虑的因素更多&#xff0c;因为自己就读的专业&#xff0c;绝对不能是自己的家庭无法负担的专业…

数值分析笔记(三)函数逼近

最佳平方逼近 函数逼近是使用一种简单易算的函数来近似表示一个复杂函数。 该问题可转化为求解线性方程组 G n C F n ​ G_{n}CF_{n}​ Gn​CFn​​ 其中&#xff0c;系数 C ( c 0 , c 1 , ⋯ , c n ) T , F n ( ( f , φ 0 ) , ( f , φ 1 ) , ⋯ , ( f , φ n ) ) T C(c…

Java网络编程之UDP通信与TCP通信交互代码实现

​import java.net.InetAddress; import java.io.IOException; class Main {public static void main(String[] args) {try { InetAddress localAddress InetAddress.getLocalHost(); //获得本地主机 InetAddress remoteAddress InetAddress.getByName("www.itcast.cn&qu…

非强化学习的对齐方法

在文章《LLM对齐“3H原则”》和《深入理解RLHF技术》中&#xff0c;我们介绍了大语言模型与人类对齐的“3H原则”&#xff0c;以及基于人类反馈的强化学习方法&#xff08;RLHF&#xff09;&#xff0c;本文将继续介绍另外一种非强化学习的对齐方法&#xff1a;直接偏好优化&am…

【Java】解决Java报错:IllegalMonitorStateException in Synchronization

文章目录 引言一、IllegalMonitorStateException的定义与概述1. 什么是IllegalMonitorStateException&#xff1f;2. IllegalMonitorStateException的常见触发场景3. 示例代码 二、解决方案1. 确保在同步代码块或方法中调用wait()、notify()和notifyAll()2. 使用同步方法3. 使用…

鸿蒙开发系统基础能力:【@ohos.inputMethod (输入法框架)】

输入法框架 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import inputMethod from ohos.inputMethod;inputMethod8 常量值。 系统能力&#xff1a;以下各项对应的系统能力均为Sy…

NetSuite Account Merge 科目合并功能分析

最近项目中&#xff0c;客户有提到过能否将不用的Account与新建的Account进行合并&#xff0c;即我们所说的Merge功能&#xff5e;可以&#xff0c;但是该功能有使用的限制&#xff0c;比如最直接的一点需要注意&#xff0c;不同类型的Account是不可以使用Merge功能的&#xff…