16_Python编程从入门到实践_重构\测试

一,重构

你经常会遇到这样的情况:代码能够正确地运行,但可做进一步的改进——将代码划分为一系列完成具体工作的函数。这样的过程被称为重构 。重构让代码更清晰、更易于理解、更容易扩展。
在这里插入图片描述

二,测试函数

1)编写一个简单的代码程序:

在这里插入图片描述
在这里插入图片描述

2)单元测试和测试用例:

Python标准库中的模块unittest 提供了代码测试工具。
单元测试 用于核实函数的某个方面没有问题;
测试用例 是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。
全覆盖式测试 用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖

1,可通过的测试

创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测试就很简单了。要为函数编写测试用例,可先导入模块unittest 以及要测试的函数,再创建一个继承unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。
下面是一个只包含一个方法的测试用例,它检查函数get_formatted_name() 在给定名和姓时能否正确地工作:
在这里插入图片描述

2,不能通过的测试

测试未通过时结果是什么样的呢?我们来修改get_formatted_name() ,使其能够处理中间名,但这样做时,故意让这个函数无法正确地处理像JanisJoplin这样只有名和姓的姓名。
下面是函数get_formatted_name() 的新版本,它要求通过一个实参指定中间名:
在这里插入图片描述

3,测试位通过时怎么办

测试未通过时怎么办呢?如果你检查的条件没错,测试通过了意味着函数的行为是对的,而测试未通过意味着你编写的新代码有错。因此,测试未通过时,不要修改测试,而应修复导致测试不能通过的代码:检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。
在这个示例中,get_formatted_name() 以前只需要两个实参——名和姓,但现在它要求提供名、中间名和姓。新增的中间名参数是必不可少的,这导致get_formatted_name() 的行为不符合预期。就这里而言,最佳的选择是让中间名变为可选的。这样做后,使用类似于JanisJoplin的姓名进行测试时,测试就会通过了,同时这个函数还能接受中间名。下面来修改get_formatted_name() ,将中间名设置为可选的,然后再次运行这个测试用例。如果通了,我们接着确认这个函数能够妥善地处理中间名。
要将中间名设置为可选的,可在函数定义中将形参middle 移到形参列表末尾,并将其默认值指定为一个空字符串。我们还要添加一个if 测试,以便根据是否提供了中间名相应地创建姓名:
在这里插入图片描述

4,添加新测试

在这里插入图片描述

三,测试类

1)各种断言方法

Python在unittest.TestCase 类中提供了很多断言方法。前面说过,断言方法检查你认为应该满足的条件是否确实满足。如果该条件确实满足,你对程序行为的假设就得到了确认,你就可以确信其中没有错误。如果你认为应该满足的条件实际上并不满足,Python将引发异常。
表11-1描述了6个常用的断言方法。使用这些方法可核实返回的值等于或不等于预期的值、返回的值为True 或False 、返回的值在列表中或不在列表中。你只能在继承unittest.TestCase 的类中使用这些方法,下面来看看如何在测试类时使用其中的一个。

unittest Module中的断言方法:
方法                    	   用途
assertEqual(a, b)  	       核实a == b
assertNotEqual(a, b)       核实a != b
assertTrue(x) 			   核实x 为True
assertFalse(x)             核实x 为False
assertIn(item , list ) 	   核实 item 在 list 中
assertNotIn(item , list )  核实 item 不在 list 中
2)一个要测试的类

类的测试与函数的测试相似——你所做的大部分工作都是测试类中方法的行为,但存在一些不同之处,下面来编写一个类进行测试。来看一个帮助管理匿名调查的类:
在这里插入图片描述
为证明AnonymousSurvey 类能够正确地工作,我们来编写一个使用它的程序:
在这里插入图片描述
实际执行报错,代码跟书上一模一样,就是执行不了
在这里插入图片描述

3)测试AnonymousSurvey 类
4)方法setUp()
### 关于《Python编程:从入门实践》第十二章中的重构 #### 什么是重构重构是指对现有代码进行结构调整而不改变其外部行为的过程。通过重构可以使代码更加简洁、易读以及便于维护和扩展[^4]。 #### 示例说明 以下是一个基于《Python编程:从入门实践》书中提到的游戏开发案例 `MyGame` 的简单重构示例: 原始代码可能如下所示: ```python import sys import pygame from settings import Settings from ship import Ship class MyGame: """管理游戏资源和行为的类""" def __init__(self): """初始化游戏并创建游戏资源""" pygame.init() self.settings = Settings() self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height)) pygame.display.set_caption("MyGame 1.0") self.ship = Ship(self) def run_game(self): """"开始游戏的主循环""" while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() self.screen.fill(self.settings.bg_color) self.ship.blitme() # 让最近绘制的屏幕可见 pygame.display.flip() if __name__ == '__main__': ai = MyGame() ai.run_game() ``` 为了使代码更具模块化特性,可以对其进行重构,将事件处理逻辑分离成独立的方法。 经过重构后的代码结构如下: ```python import sys import pygame from settings import Settings from ship import Ship class MyGame: """管理游戏资源和行为的类""" def __init__(self): """初始化游戏并创建游戏资源""" pygame.init() self.settings = Settings() self.screen = pygame.display.set_mode( (self.settings.screen_width, self.settings.screen_height)) pygame.display.set_caption("MyGame 1.0") self.ship = Ship(self) def _check_events(self): """响应按键和鼠标事件""" for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() def _update_screen(self): """更新屏幕上的图像,并切换到新屏幕""" self.screen.fill(self.settings.bg_color) self.ship.blitme() # 让最近绘制的屏幕可见 pygame.display.flip() def run_game(self): """开始游戏的主循环""" while True: self._check_events() self._update_screen() if __name__ == '__main__': ai = MyGame() ai.run_game() ``` 在此过程中,我们将 `_check_events()` 和 `_update_screen()` 方法分别用于处理事件和更新屏幕显示,从而提高了代码的可读性和可维护性[^3]。 #### 解释 - **方法拆分**:原代码中所有的功能都被集中写在了 `run_game` 函数里,这使得该函数变得复杂难以阅读。通过将不同职责的功能提取至不同的辅助方法(如 `_check_events`, `_update_screen`),可以让每个方法专注于单一的任务。 - **命名约定**:以单下划线开头的方法名表示这些方法是内部使用的私有方法,在设计时应遵循这一惯例来增强代码语义表达力。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值