修复对 python 的 @staticmethod 声明所做的更改
Fixing mutations done on python's @staticmethod declaration
我在 python 3 中有这个 class 静态方法,带有必要的测试代码
example.py:
class ExampleClass{
...
@staticmethod
def get_new_id: str, id: str):
return {
"new_id": "{}_{}_{}".format(
datetime.utcnow().strftime("%Y%m%d%H%M%S"),
id,
name
),
"old_id": id
}
...
}
测试_example.py:
...
class TestExampleId(TestCase):
@patch("example_folder.example.datetime", Mock(utcnow=Mock(return_value=datetime(1992, 1, 26, 12, 0, 0))))
def given_id_name_example_object_returned(self):
self.assertEqual(
{
'old_id': 'xxx',
'new_id': '19920916120000_xxx_test_name'
}, ExampleClass.get_new_id("xxx", "test_name")
)
这是关于突变可以做什么的。但是在 mutmut 中,有一个幸存的突变,那就是 @staticmethod
的移除。所以我有两个问题:
- 如果调用的方法来自未实例化的class,没有@staticmethod 声明,测试如何通过?
- 需要什么额外的测试用例来防止突变在没有@staticmethod 的情况下存活?
谢谢。
遇到了同样的事情,做了一些挖掘,这是我发现的...
测试通过是因为,在 Python 3 中,调用 class 本身的方法(而不是 class 的实例)运行该方法,就好像它是静态的一样.我无法找到 'official python' 的文档来引用它,但可以引用 this Whosebug question 的公认答案。如果有人发现这实际上记录在任何地方,那么欢迎编辑!
考虑到 Python 3 就是这样工作的,这让我开始思考为什么甚至需要 @staticmethod
装饰器。由于 Python 3 在 class 上调用时将静态调用该方法,装饰器仅在我们在 实例 上调用它时发挥作用 =28=]。所以你可能会做这样的事情:
class TestExampleId(TestCase):
@patch("example_folder.example.datetime", Mock(utcnow=Mock(return_value=datetime(1992, 1, 26, 12, 0, 0))))
def given_id_name_example_object_returned(self):
instance = ExampleClass()
self.assertEqual(
{
'old_id': 'xxx',
'new_id': '19920916120000_xxx_test_name'
}, instance.get_new_id("xxx", "test_name")
)
...然后突变将失败,因为方法输入不正确。在我的例子中,我的静态方法实际上是 class 的工厂方法,在 class 的实例上调用我的工厂方法是无稽之谈。如果用户试图在 class 的实例上调用工厂方法,我决定抛出一个特定的错误,并测试该错误被抛出,然后覆盖 @staticmethod
装饰器。再一次,彻底的测试让我真正思考了我的代码结构!
我在 python 3 中有这个 class 静态方法,带有必要的测试代码
example.py:
class ExampleClass{
...
@staticmethod
def get_new_id: str, id: str):
return {
"new_id": "{}_{}_{}".format(
datetime.utcnow().strftime("%Y%m%d%H%M%S"),
id,
name
),
"old_id": id
}
...
}
测试_example.py:
...
class TestExampleId(TestCase):
@patch("example_folder.example.datetime", Mock(utcnow=Mock(return_value=datetime(1992, 1, 26, 12, 0, 0))))
def given_id_name_example_object_returned(self):
self.assertEqual(
{
'old_id': 'xxx',
'new_id': '19920916120000_xxx_test_name'
}, ExampleClass.get_new_id("xxx", "test_name")
)
这是关于突变可以做什么的。但是在 mutmut 中,有一个幸存的突变,那就是 @staticmethod
的移除。所以我有两个问题:
- 如果调用的方法来自未实例化的class,没有@staticmethod 声明,测试如何通过?
- 需要什么额外的测试用例来防止突变在没有@staticmethod 的情况下存活?
谢谢。
遇到了同样的事情,做了一些挖掘,这是我发现的...
测试通过是因为,在 Python 3 中,调用 class 本身的方法(而不是 class 的实例)运行该方法,就好像它是静态的一样.我无法找到 'official python' 的文档来引用它,但可以引用 this Whosebug question 的公认答案。如果有人发现这实际上记录在任何地方,那么欢迎编辑!
考虑到 Python 3 就是这样工作的,这让我开始思考为什么甚至需要 @staticmethod
装饰器。由于 Python 3 在 class 上调用时将静态调用该方法,装饰器仅在我们在 实例 上调用它时发挥作用 =28=]。所以你可能会做这样的事情:
class TestExampleId(TestCase):
@patch("example_folder.example.datetime", Mock(utcnow=Mock(return_value=datetime(1992, 1, 26, 12, 0, 0))))
def given_id_name_example_object_returned(self):
instance = ExampleClass()
self.assertEqual(
{
'old_id': 'xxx',
'new_id': '19920916120000_xxx_test_name'
}, instance.get_new_id("xxx", "test_name")
)
...然后突变将失败,因为方法输入不正确。在我的例子中,我的静态方法实际上是 class 的工厂方法,在 class 的实例上调用我的工厂方法是无稽之谈。如果用户试图在 class 的实例上调用工厂方法,我决定抛出一个特定的错误,并测试该错误被抛出,然后覆盖 @staticmethod
装饰器。再一次,彻底的测试让我真正思考了我的代码结构!