【问题标题】:Find out how many return-values a function has找出一个函数有多少个返回值
【发布时间】:2015-07-01 15:26:07
【问题描述】:

我正在为某些激光驱动器功能创建一些测试。对于某些激光器,支持一个子功能,在其他激光器上,我应该预期会出现错误(并因此测试是否引发了错误)。 子功能当然是(为了保持简单;-))不是一个功能,而是多个功能。所以给定激光,某个功能的测试应该通过或失败。

通过案例不是问题,但是当它应该失败并且一个函数有多个返回值时,我们创建的通用断言的问题是它不知道它应该返回多少个返回值给测试函数因此我们的通用断言仅在激光器不支持子功能的情况下返回 1 个无值。

因此,我们必须在测试中检查具有多个返回值的函数是否应该失败或通过,并且只有这样我们才能以正确的方式调用我们的通用断言。
但这有点难看,恕我直言,因为在这种情况下,我们会检查子功能是否被支持两次(通用断言的目标是在一个地方执行此操作)。

有没有办法确定一个函数在调用该函数之前有多少个返回值?

伪代码中的问题:

通用断言(加上测试的基本设置):

import functionality_under_test as fut

class Functionality( unittest.TestCase ):
    def shared_setup( self ):
        Functionality._issupported = fut.subfunctionality.is_supported()

    def _assert_sub_functionality( self, func, *args, **kwargs ):
        retval = None # We don't know how many retvals there will be

        if not self._issupported:
            # Here is the place where it should determine how many
            # return-values func really has and initialize retval as
            # with the correct number of None's in a tuple / one None.
            self.assert_raises( <expected error>, func, *args, **kwargs )
        else:
            # retval will be filled with either 1 value or a tuple by
            # successful call.
            retval = func( *args, **kwargs )

        return retval

对于具有 1 个返回值的函数没有问题,因此我们可以这样做:

   def test_subfunc_func_1_retval( self ):
       only_retval = self._assert_sub_functionality( subfunc_func_1_retval, <args>, <kwargs> )

       <checks based on retval not being None>

但是对于具有多个返回值的测试函数,这不起作用(引发错误,因为在测试函数期望多个返回值的情况下只给出 1 个返回值)。所以我们把它做成这样:

def test_subfunc_func_2_retvals( self ):
    if not self._issupported:
        # 'Fail' case, where an error is expected
        retval1, retval2 = None
        _ = self._assert_sub_functionality( subfunc_func_2_retvals, <args>, <kwargs> )
    else:
        # Pass-case, no error expected. This works fine.
        retval1, retval2 = self._assert_sub_functionality( subfunc_func_2_retvals, <args>, <kwargs> )

    <checks based on the retvals not being None>

这里对 self._issupported 的额外检查有点难看,恕我直言。

这可以用不同的方式完成吗?

_assert_sub_functionality 是否可以确定一个函数有多少个返回值,并在不支持子功能的情况下返回多少次 None?

TIA

【问题讨论】:

  • 你在python中真的只有一个返回值。 return 0, 1 只是 return (0, 1) 的语法糖。所以...如果你得到一个元组,你可能有多个返回值。或者实际上返回了一个元组。
  • 是的,但这只有在函数调用成功时才有效。如果引发错误,则不会。我需要事先确定一个函数是否有多个返回值

标签: python unit-testing


【解决方案1】:

首先,函数只有一个返回值,但 it could be a tuple

所以,您的问题是,您能否静态分析 Python 函数并推断它仅返回特定元组,即具有特定大小的元组。

很遗憾,答案是否定的 - 很容易证明这可以解决 Halting Problem

【讨论】:

  • +1 用于停止问题参考。只是在想你可以用康托尔对角线论证来证明这是不可能的
【解决方案2】:

查看 Ami Tavory 和 David Ehrmann 给出的答案(以及在 Halting Problem wiki-page ;-))我得出了以下解决方案:

def _assert_sub_functionality( self, func, *args, **kwargs ):
    supported = self._issupported
    retval = None

    if not supported:
        self.assert_raises( <expected error>, func, *args, **kwargs )
    else:
        # retval will be filled with either 1 value or a tuple by
        # successful call.
        retval = func( *args, **kwargs )

    return supported, retval

def test_subfunc_func_1_retval( self ):
   retval = self._assert_sub_functionality( subfunc_func_1_retval, <args>, <kwargs> )

   issupported = retval[0]
   if issupported:
      real_retval = retval[1]
      <tests with real_retval>

def test_subfunc_func_2_retvals( self ):
    retval = self._assert_sub_functionality( subfunc_func_2_retvals, <args>, <kwargs> )

    issupported = retval[0]
    if issupported:
        (real_retval1, real_retval2) = retval[1]
            <checks with the real_retvals>

对两者都表示敬意。 (解决方案检查也应该在大卫发表评论之前;-))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-10
    • 2020-05-04
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    相关资源
    最近更新 更多