【问题标题】:AssertionError: <bound method object> returned during python unittest and propertiesAssertionError: <bound method object> 在 python 单元测试和属性期间返回
【发布时间】:2022-11-10 01:44:13
【问题描述】:

我正在接受 python 测试,但不清楚测试中出现的内容。该测试使用了测试驱动开发,因此我们得到了一个包含 unittest 断言的文件,该文件调用了我们需要创建的模块。因此,我无法更改在测试文件中进行调用的方式。

以下是关注我的问题的两个文件的基础知识:

test_yahtzee.py:

  from yahtzee import Roll, Type
      import yahtzee
    
  class TestYahtzee(unittest.TestCase):
    # ... 
    # tests
    # ... 
      def testFindUpperBest(self):
         '''Finds best scoring opportunity from upper part of scorepad'''
         self.assertEqual(Type.SIXES,  Roll(1, 6, 1, 2, 3).up_best)

在 yahtzee.py 中:

class Type(Enum):
    SIXES = 1
    #...
    # more enum values
    #

class Roll():

    def __init__(self, d1, d2, d3, d4, d5) -> None:
      pass

    @property # BUT WHAT IF THIS WEREN'T HERE?
    def up_best(self) -> Type:
      print('Found me!')
      ## Will return a Type later ... 

这是让我感到困惑的部分:

请注意,test_yahtzee.py 文件没有使用 Roll 的实例,而是看起来 unittest 模块必须将 <Class.fun> 方法(即 Roll(...).up_best)绑定到它可以调用的东西上。 . 再次我无法更改此文件。

我不明白这种语法如何与我定义类方法的方式相互作用。以下是使用 python3 -m unittest test_yahtzee.py 时的四种可能

有人可以解释这四种情况下发生了什么,以便我更好地理解细微差别吗?

yahtzee.py test_yahtze.py result
with @property as above Roll(...).up_best 'Found me', test passes
no @property Roll(...).up_best AssertionError: <Type.SIXES> != <bound method Roll.up_best of ...
with @property as above Roll(...).up_best() 'Found me', but 'Type' object is not callable
no @property Roll(...).up_best() 'Found me', test passes

编写测试文件的方式......似乎假设这必须是具有@property 属性的getter,因为这是唯一可行的可能性?

【问题讨论】:

  • up_best 是什么?您只向我们展示了best_upper
  • 抱歉,编辑没有我想象的那么完成。

标签: python python-3.x unit-testing properties


【解决方案1】:

请注意,test_yahtzee.py 文件没有使用 Roll 的实例,而是看起来 unittest 模块必须将 <Class.fun> 方法(即 Roll(...).up_best)绑定到它可以调用的东西.. . 再次我无法更改此文件。

我不确定“test_yahtzee.py 文件不使用 Roll 的实例”是什么意思。考试使用 Roll 的实例。 Roll(1, 6, 1, 2, 3) 创建一个 Roll 的实例。

至于您的问题,您是正确的,测试代码假设 up_best 是该类的属性。

属性的 documentation 声明:

调用 property() 是构建数据描述符的一种简洁方法,该描述符在访问属性时触发函数调用。

基本上,您可以将函数呈现为属性。

在测试代​​码中,Roll(1, 6, 1, 2, 3).up_best 创建了一个 Roll 实例,然后访问其上的 up_best 属性。访问up_best 会返回一个类型,并且大概Type.SIXES 也是一个类型。

我将尝试解释您列举的四种情况。

使用 @property 和 Roll().up_best

这里有一个匹配项,其中用@property 装饰的方法将通过访问属性来调用,而Roll().up_best 正在通过attribute 访问。这工作正常。

没有 @property 和 Roll().up_best

在这里你有一个不匹配,因为up_best 现在是一个普通的method,因为你删除了@property,它必须通过调用而不是属性来访问。 .方法是一个可调用函数,Roll().up_best 正在访问 up_best 作为属性。你得到一个错误。

使用 @property 和 Roll().up_best()

这里还有另一个不匹配,因为up_best 是一个必须由属性访问的属性,而up_best() 正试图将其作为方法调用。您收到错误,因为 Type 不可调用。

没有 @property 和 Roll().up_best()

这里又是一场比赛。由于您删除了 @property 装饰器,up_best 现在是一个必须调用的普通方法,Roll().up_best() 正在调用 up_best 作为函数。这工作正常。

希望这可以帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多