在Python中使用契约devise

我正在寻找开始在工作中使用大量基于Python的项目的DBC,并想知道其他人有什么经验。 到目前为止,我的研究成果如下:

  • http://www.python.org/dev/peps/pep-0316/ – PEP 316是为了标准化Pythondevise合同而推迟的。 这个PEPbuild议使用文档。
  • http://www.wayforward.net/pycontract/ – Python合同。 这似乎是一个完整的,但没有维护的框架使用文档。
  • http://www.nongnu.org/pydbc/ – 使用元类实现契约的PyDBC。 也没有维持几年。

我的问题是:你用Python的DBC成熟的生产代码? 它的工作效果如何?值得付出吗? 你会推荐哪些工具?

你find的PEP还没有被接受,所以没有一个标准或可接受的方法来做到这一点(然而,你可以自己实施PEP!)。 但是,有几种不同的方法,正如你所发现的那样。

也许最轻量级只是简单地使用Python装饰器。 Python Decorator库中有一组用于前/后条件的装饰器 ,可以直接使用。 以下是该页面的一个示例:

>>> def in_ge20(inval): ... assert inval >= 20, 'Input value < 20' ... >>> def out_lt30(retval, inval): ... assert retval < 30, 'Return value >= 30' ... >>> @precondition(in_ge20) ... @postcondition(out_lt30) ... def inc(value): ... return value + 1 ... >>> inc(5) Traceback (most recent call last): ... AssertionError: Input value < 20 

现在,你提到类不variables。 这些有点困难,但是我会这样做的方式是定义一个可调用来检查不variables,然后像post-condition装饰器那样检查每个方法调用结束时的不variables。 作为第一个剪辑,你可以直接使用后置装饰器。

以我的经验来看,即使没有语言支持,按合同devise也是值得的。 对于没有被覆盖的断言的方法,以及docstrings对于前置条件和后置条件都是足够的。 对于被覆盖的方法,我们将方法分为两部分:检查前置条件和后置条件的公共方法,以及提供实现的受保护方法,并可能被子类覆盖。 这里是后者的一个例子:

 class Math: def square_root(self, number) """ Calculate the square-root of C{number} @precondition: C{number >= 0} @postcondition: C{abs(result * result - number) < 0.01} """ assert number >= 0 result = self._square_root(number) assert abs(result * result - number) < 0.01 return result def _square_root(self, number): """ Abstract method for implementing L{square_root()} """ raise NotImplementedError() 

我从软件工程收音机devise合同的一集( http://www.se-radio.net/2007/03/episode-51-按合同devise/ )。 他们还提到需要语言支持,因为断言对确保Liskov替代原则没有帮助,尽pipe我上面的例子旨在certificate另外一些。 我还应该提到C ++ pimpl(私有实现)成语作为灵感的来源,尽pipe这有一个完全不同的目的。

在我的工作中,我最近把这种契约检查重构成了一个更大的阶级体系(合同已经被logging,但没有经过系统的testing)。 现有的unit testing显示,合同被多次违反。 我只能断定这应该是很久以前的事了,一旦按合同devise,unit testing覆盖率就会更高。 我希望任何尝试这种技术组合的人都能做出同样的观察。

更好的工具支持可能会在未来为我们提供更多的动力,我对此表示欢迎。

我没有使用Python的合同devise,所以我不能回答你所有的问题。 不过,我花了一些时间看最近版本的合同库,它看起来不错。

在reddit上有关于这个库的一些讨论。

虽然不是完全按合同devise ,但一些testing框架倾向于属性testing方法在概念上非常接近。

随机testing,如果某些属性保留在运行时允许轻松检查:

  • 不变
  • input和输出值的域
  • 其他前置和后置条件

对于Python,有一些QuickCheck风格的testing框架:

  • 薪水
  • QC