修复对 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 的移除。所以我有两个问题:

谢谢。

遇到了同样的事情,做了一些挖掘,这是我发现的...

测试通过是因为,在 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 装饰器。再一次,彻底的测试让我真正思考了我的代码结构!