如何测试依赖于argparse的Python类?

2023-12-15

下面的粘贴包含来自三个单独的 Python 文件的相关片段。第一个是从命令行调用的脚本,它在给定某些参数的情况下实例化 CIPuller。发生的情况是脚本被调用,类似于:script.py ci(其他参数将被 argparse 吞掉)。

第二个是名为的子类的一部分Puller。第三个是子类的一部分Puller called CIPuller.

这非常有效,因为调用了正确的子类,并且任何使用错误的其他参数的用户都可以看到给定子类的正确参数,以及来自超类的通用参数。 (尽管我离线时意识到也许我应该使用argparse 子命令为了这。)

我一直在尝试为这些类编写测试。目前,我需要一个ArgumentParser实例化类,但在测试中我没有从命令行实例化事物,因此我的ArgumentParser是没用的。

我尝试创建一个ArgumentParser在测试工具中传递给CIPuller's测试代码中的构造函数,但如果我使用add_argument在那里,argparse 在调用时会抱怨双重(重复)参数,这是可以理解的add_argument in the CIPuller构造函数。

用参数测试这些类的合适设计是什么?

#!/usr/bin/env python                                                             

from ci_puller import CIPuller                                                    
import argparse                                                                   
import sys                                                                        

# Using sys.argv[1] for the argument here, as we don't want to pass that onto     
# the subclasses, which should receive a vanilla ArgumentParser                   
puller_type = sys.argv.pop(1)                                                     

parser = argparse.ArgumentParser(                                                 
    description='Throw data into Elasticsearch.'                                  
)                                                                                 

if puller_type == 'ci':                                                           
    puller = CIPuller(parser, 'single')                                         
else:                                                                             
    raise ValueError("First parameter must be a supported puller. Exiting.")      

puller.run()                                                                      


class Puller(object):                                                             

    def __init__(self, parser, insert_type):                                      
        self.add_arguments(parser)                                                
        self.args = parser.parse_args()                                           

        self.insert_type = insert_type                                            

    def add_arguments(self,parser):
        parser.add_argument(                                                      
            "-d", "--debug",                                                      
            help="print debug info to stdout",                                    
            action="store_true"                                                   
        )                                                                         

        parser.add_argument(                                                      
            "--dontsend",                                                         
            help="don't actually send anything to Elasticsearch",                 
            action="store_true"                                                   
        )                                                                         

        parser.add_argument(                                                      
            "--host",                                                             
            help="override the default host that the data is sent to",            
            action='store',                                                       
            default='kibana.munged.tld'                                     
        )                             

class CIPuller(Puller):                                                           

    def __init__(self, parser, insert_type):                                      
        self.add_arguments(parser)

        self.index_prefix = "code"                                                
        self.doc_type = "cirun"                                                   

        self.build_url = ""                                                       
        self.json_url = ""                                                        
        self.result = []                                                          

        super(CIPuller, self).__init__(parser, insert_type)                       

    def add_arguments(self, parser):                                              
        parser.add_argument(                                                      
            '--buildnumber',                                                      
            help='CI build number',                                               
            action='store',                                                       
            required=True                                                         
        )                                                                         

        parser.add_argument(                                                      
            '--testtype',                                                         
            help='Job type per CI e.g. minitest / feature',                       
            choices=['minitest', 'feature'],                                      
            required=True                                                         
        )                                                                         

        parser.add_argument(                                                      
            '--app',                                                              
            help='App e.g. sapi / stats',                                         
            choices=['sapi', 'stats'],                                            
            required=True                                                         
        )                                                                         

单元测试argparse很棘手。有一个test/test_argparse.py作为整个 Python 单元测试的一部分运行的文件。但它有一个复杂的自定义测试工具来处理大多数情况。

存在三个基本问题,1)调用parse_args使用测试值,2)测试生成的参数,3)测试错误。

测试结果args相对容易。还有argparse.Namespace类有简单的__eq__方法,以便您可以针对另一个名称空间测试一个名称空间。

有两种测试输入的方法。一是修改sys.argv。最初sys.argv有供测试人员使用的字符串。

self.args = parser.parse_args()

tests sys.argv[1:]作为默认值。所以如果你改变sys.argv您可以测试自定义值。

但你也可以给parse_args自定义列表。这argparse文档在大多数示例中都使用了它。

self.args = parser.parse_args(argv=myargv)

If myarg is None它用sys.argv[1:]。否则它会使用该自定义列表。

测试错误需要自定义parse.error方法(参见文档)或包装parse_args in a try/except可以捕获的块sys.exit例外。

如何为 python 模块的 argparse 部分编写测试?

argparse 的 python 单元测试

Argparse 单元测试:隐藏帮助消息

使用命令行参数进行单元测试

使用unittest测试argparse - 退出错误

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何测试依赖于argparse的Python类? 的相关文章

随机推荐

  • JavaScript 中的数据竞争?

    假设我运行这段代码 var score 0 for var i 0 i lt arbitrary length i async task i function score increment callback function 从理论上讲
  • Android 崩溃报告中的奇怪堆栈

    我收到一些来自 android 的崩溃报告 带有 java lang NullPointerException 但是我不明白 stacktrace 中的 null 是什么意思 below at null formatElapsedTime
  • matplotlib 或其他 python 包中的 3D 饼图

    有没有办法在 matplotlib 中渲染 3D 饼图 或者是否有可以生成 3D 饼图的 Python 包 EDIT 我其实已经知道了pygooglechart 但我正在寻找可以离线完成的东西 我很抱歉忘记包含此信息 对于那些提供pygoo
  • C++ 中的逗号运算符和逗号分隔符[重复]

    这个问题在这里已经有答案了 可能的重复 all 时逗号运算符不充当逗号运算符吗 逗号 何时充当运算符 何时充当分隔符 其后果是什么 如果可能 请也为两者提供小例子 逗号在函数调用 函数声明 初始值设定项和变量声明中充当分隔符 f a b i
  • 将数据库中特定模式的所有内容授予 PostgreSQL 中的组角色

    使用 PostgreSQL 9 0 我有一个名为 staff 的组角色 并且希望向该角色授予特定模式中表的所有 或某些 权限 没有以下工作 GRANT ALL ON SCHEMA foo TO staff GRANT ALL ON DATA
  • 我如何学习如何在 bash 中正确引用?

    当我编写 bash 脚本时 我经常对引用和评估的规则感到困惑 我知道一些基础知识 比如 和 和 之间的区别 但我似乎仍然经常出错 并且不得不尝试用各种不同的方式来表达同一件事 我通常可以通过蛮力解决任何个人问题 但我认为我的概念模型必须以某
  • Windows Phone 7 - 电话呼叫连接和电话呼叫断开时触发的事件

    我正在为 Windows Mobile 7 编写一个应用程序 它需要有关 何时发出语音呼叫 和 何时挂断或断开语音呼叫 的信息 是否有任何 API 或事件 触发器可以为我提供此信息 当前的 SDK 不提供此功能 通常 由于沙盒环境默认不提供
  • FastAPI 重定向给出方法不允许错误

    我创建了一个登录路径 在其中发布表单数据并设置 cookie 设置cookie后 我重定向到 main 在那里我得到 detail Method Not Allowed 作为回应 app post login async def login
  • ViewChild - 无法在 Angular 2 RC 1 JavaScript 中工作

    ViewChild 无法在 Angular 2 RC 1 JavaScript 中工作 我用过
  • RibbonApplicationMenu:摆脱 AuxiliaryPane

    碰巧我正在开发的应用程序不对文档进行操作 因此不需要在应用程序菜单中显示最近打开的文档列表 但是 令人烦恼的是 没有现成的房产RibbonApplicationMenu隐藏未使用的类AuxiliaryPane 奇怪的是 该属性确实存在 但被
  • 单击关闭按钮时隐藏表单而不是关闭

    When a user clicks the X button on a form how can I hide it instead of closing it 我努力了this hide in FormClosing但它仍然关闭表单 L
  • Outlook 2013“运行脚本”规则已消失

    我在 Outlook 2013 中有一些工作规则 然而 在我的笔记本电脑前几天崩溃后 我无法再运行任何规则 它们根本不起作用 我什至没有收到调试通知 检查我的宏后 我发现当我尝试单击我拥有的任何脚本时 我不断收到消息 此操作在当前模式下不可
  • iOS XMPP 框架与 Openfire Server 获取所有注册用户

    for my IOS我正在使用的聊天应用程序Openfire服务器 我正在检索特定用户好友列表 但现在我想检索所有注册用户Openfire服务器 请帮助我并提前致谢 最后 我通过使用用户名搜索用户找到了替代答案 1 对于每个联系人 我都会添
  • 如何在高分辨率设备上使用媒体查询

    我制作了一个简单的响应式网站 或多或少 我使用过媒体查询 media only screen and max width 699 99px 现在我知道当分辨率小于 699 99px 时 这会激活其中的 css 所以在电脑上没问题 但在手机上
  • 散景,套索选择表更新

    我希望每个人都做得很好 我正在尝试开发 Bokeh 交互 选择散点图的一部分将更新表格 我使用了 Bokeh 文档中的大量示例代码 我的工作场所正在运行旧版本的 Bokeh 0 12 5 因此我必须更改自定义 JS 中的最后一行 从 s2
  • Pandas:使用 Append 添加新列并使另一个全为 NaN

    我大约一周前才开始学习 pandas 现在我一直在努力处理 pandas 数据框 我的数据如下所示 State NY CA Other Total Year 2003 450 50 25 525 2004 300 75 5 380 2005
  • 在 Pandas 中合并两行(一行有值,另一行 NaN)

    我知道以前也有人问过类似的问题 如何合并数据框中的两行pandas等 但我仍然在努力执行以下操作 除了包含许多行的 pandas 数据框 team token day1 day2 day3 day4 0 abc 1 NaN NaN NaN
  • 如何获取客户端 IP 地址的时区偏移量

    我想为我的网络应用程序获取客户 IP 地址的时区偏移量 我尝试过使用 Javascripts getTimezone 函数 但是 某些客户端的时区或时间设置不正确 我想获取偏移量并根据客户端的时区将一些信息返回给客户端 感谢您花时间阅读问题
  • send() 在 Ruby 中做什么?

    有人可以告诉我下面的片段是什么吗 obj send method name 是并且确实吗 send向类层次结构中的对象实例及其祖先发送消息 直到某个方法做出反应 因为它的名称与第一个参数匹配 实际上 这些行是等效的 1 send 2 1 2
  • 如何测试依赖于argparse的Python类?

    下面的粘贴包含来自三个单独的 Python 文件的相关片段 第一个是从命令行调用的脚本 它在给定某些参数的情况下实例化 CIPuller 发生的情况是脚本被调用 类似于 script py ci 其他参数将被 argparse 吞掉 第二个