python函数规则 python函数格式标准详解
Python 中的论文讨论unittest框架中,如何结合高效参数化.expand测试带有默认参数的函数。针对传统方法中需要为默认参数单独编写测试的痛点,提出了一种利用哨兵值(如无)和动态构建关键字参数kwargs的策略,从而将多个测试场景合并为一个参数化测试,提升测试代码的简洁性和可维护性。挑战:测试带有默认参数的Python函数
在Python中,函数经常会定义默认参数的函数,例如:def get_user(user_id,adults_only=False): quot;quot;quot;根据用户ID获取用户信息,可选地限制为成人用户。 :param user_id:userID :param Adult_only:布尔值,如果为True则只返回成人用户,默认为False。 quot;quot;quot;#实际实现未展示细节 if user_id == 1: return quot;nonequot; if Adult_only else quot;childquot; elif user_id == 2: return quot;adult"; if african_only else quot;adult"; return无登录后复制
当我们需要测试adults_only参数的不同值(True、False)以及其默认行为时,通常会遇到一些挑战。使用unittest配合parameterized.expand可以很好地处理参数化测试,但对于默认参数的测试,直接的参数化往往无法覆盖。
例如,一个典型的参数化测试可能如下:importunittestfromparameterizedimportparameterized#假设get_user函数已定义如上#为了方便测试,我们模拟一个子对象class MockChild: def __init__(self, id): self.id = idclass TestGetUser(unittest.TestCase): def setUp(self): self.child = MockChild(1) # 模拟一个ID为1的用户 @parameterized.expand([ (True, quot;nonequot;), (False, quot;childquot;) ]) def test_get_child_explicit_args(self,adults_only,expected): quot;quot;quot;测试显式传递adults_only参数的情况。
quot;quot;quot;actual = get_user(self.child.id,adults_only) self.assertEqual(expected,actual)登录后复制
然而,上述测试导致直接测试adults_only参数使用其默认值(即不传递该参数)的情况。为了覆盖这个场景,我们可能需要额外编写一个独立的测试方法:
立即学习“Python免费学习笔记(深入)”;def test_get_child_default_arg(self): quot;quot;quot;测试adults_only参数使用默认值的情况。quot;quot;quot;actual = get_user(self.child.id) # 不传递adults_only参数 self.assertEqual(quot;childquot;,,实际)登录后复制分离的测试方式虽然有效,但引入了代码重复,并且当测试次数增多时,会使测试套件变得冗长且不易维护。理想情况下,我们希望能够将所有相关测试场景(包括默认参数)合并到一个参数化测试中。解决方案:利用哨兵值与动态关键字参数
为了解决上述问题,我们可以采用一种策略问题:在parameterized.expand中引入一个“哨兵值”(sentinel) value),例如None,来表示我们希望测试函数使用其默认参数的情况。然后,在测试方法内部,根据这个提示兵值动态地构建提供给目标函数的关键字参数。
以下是具体的实现:import unittestfromparameterized importparameterized# 假设 get_user 函数和 MockChild 类已定义如上class TestGetUserUnified(unittest.TestCase): def setUp(self): self.child = MockChild(1) #模拟一个ID为1的用户@parameterized.expand([ (True, quot;nonequot;), # 显式提交adults_only=True (False, quot;childquot;), # 显式提交adults_only=False (None, quot;childquot;) # 使用None作为哨兵值,表示测试默认参数]) def test_get_child_unified(self,adults_only_param,预期): quot;quot;quot;统一测试get_user函数,包括adults_only参数的显式值和默认值。
”实际)#运行测试if __name__ == '__main__':unittest.main(argv=['first-arg-is-ignored'],exit=False)登录后复制
在这个统一的测试方法中:parameterized.expand的扩展:我们在列表参数中添加了一个元组(None,"child")。这里的None就是我们定义的哨兵值,它不代表adults_only参数的实际值,而是表示我们希望在这次测试中不提供adults_only 参数。动态构建 kwargs: 在 test_get_child_unified 方法内部,我们首先初始化一个空的字典 kwargs。条件判断:通过 if Adult_only_param is not None:判断当前确定的参数是否为哨兵值。如果不是 None,则说明我们应该显式将adults_only_param作为adults_only参数传入给 get_user 函数,从而将其添加到 kwargs 字典中。`kwargs解包:**调用get_user(user_id, kwargs)时,kwargs` 粘贴字典中的键值对解包为调用时的参数关键字。当adults_only_param 为 True 或 False 时,kwargs 会是 {"adults_only": True} 或 {"adults_only": False},函数被调用为 get_user(user_id,adults_only=True/False)。当adults_only_param 为 None时,kwargs 保持为空字典 {},函数被调用为get_user(user_id),此时adults_only参数将使用其默认值False。注意事项与总结哨兵值的选择:选定的哨兵值(如None)不会是目标函数参数的有效输入值。如果None本身就是adults_only参数的一个合法且有意义的输入,那么你需要选择另一个独特的对象作为哨兵值(例如,创建一个object()实例)。代码可行性:这种方法虽然合并了测试,但引入了额外的逻辑来处理哨兵值和动态参数。在某些情况下,如果默认参数的测试场景非常简单且数量有限,单独的测试方法可能会更引人注目。但是,对于参数组合复杂或需要间隔添加新测试的情况,这种方法能够显着减少代码重复。
适用性:此策略不仅适用于unittest和parameterized.expand,也可评估其他支持参数化测试的框架(如
通过采用这种结合提示兵值和动态关键字参数的策略,我们有效的补救函数默认参数的测试场景整合到参数化测试中,从而提高了测试代码的简洁性、可高效维护性和可扩展性,使得测试套件更加精炼和内容。
以上就是Python函数默认参数的统一测试策略的详细信息,更多请关注乐哥常识网其他相关文章!