将nosetests 与Python 合约相结合

发布于 2024-07-24 13:04:38 字数 3338 浏览 10 评论 0 原文

我使用 Python 合约 来指定前置条件/​​后置条件/不变量。 我还使用 doctests 进行单元测试。

我希望在启用合同的情况下运行所有​​ doctest 单元测试,并且我希望使用 鼻子。 不幸的是,如果我用鼻子运行测试,它不会执行前/后/不变断言。 我放置了 设置函数< /a> 在每个 .py 文件中以确保调用 contract.checkmod

def setup():
    import contract
    contract.checkmod(__name__)

我可以确认该函数在运行测试之前正在由鼻子执行,但合约仍然没有被执行。

另一方面,如果我通过调用 doctest.testmod 运行 doctest,则 pre/post/inv 确实会被调用:

def _test():
    import contract
    contract.checkmod(__name__)
    import doctest
    doctest.testmod()

if __name__=='__main__':    
    _test()

这是一个 Python 脚本的示例,如果直接调用,该脚本的测试将成功,但会失败如果用鼻子调用:

import os

def setup():
    import contract
    contract.checkmod(__name__)

def delete_file(path):
    """Delete a file. File must be present.

    >>> import minimock
    >>> minimock.mock('os.remove')
    >>> minimock.mock('os.path.exists', returns=True)

    >>> delete_file('/tmp/myfile.txt')
    Called os.path.exists('/tmp/myfile.txt')
    Called os.remove('/tmp/myfile.txt')

    >>> minimock.restore()

    pre: os.path.exists(path)
    """
    os.remove(path)

if __name__ == '__main__':
    setup()
    import doctest
    doctest.testmod()

当我独立运行上述文件时,测试通过:

$ python contracttest.py -v
Trying:
    import minimock
Expecting nothing
ok
Trying:
    minimock.mock('os.remove')
Expecting nothing
ok
Trying:
    minimock.mock('os.path.exists', returns=True)
Expecting nothing
ok
Trying:
    delete_file('/tmp/myfile.txt')
Expecting:
    Called os.path.exists('/tmp/myfile.txt')
    Called os.remove('/tmp/myfile.txt')
ok
Trying:
    minimock.restore()
Expecting nothing
ok
2 items had no tests:
    __main__
    __main__.setup
1 items passed all tests:
   5 tests in __main__.delete_file
5 tests in 3 items.
5 passed and 0 failed.
Test passed.

这是用鼻子:

$ nosetests --with-doctest contracttest.py
F
======================================================================
FAIL: Doctest: contracttest.delete_file
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/doctest.py", line 2131, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for contracttest.delete_file
  File "/Users/lorin/Desktop/contracttest.py", line 10, in delete_file

----------------------------------------------------------------------
File "/Users/lorin/Desktop/contracttest.py", line 17, in contracttest.delete_file
Failed example:
    delete_file('/tmp/myfile.txt')
Expected:
    Called os.path.exists('/tmp/myfile.txt')
    Called os.remove('/tmp/myfile.txt')
Got:
    Called os.remove('/tmp/myfile.txt')


----------------------------------------------------------------------
Ran 1 test in 0.055s

I'm using contracts for Python to specify preconditons/postconditions/invariants. I'm also using doctests for doing unit testing.

I'd like to have all of my doctest unit tests run with contracts enabled, and I'd like to run my tests using nose. Unfortunately, if I run the tests with nose, it does not execute the pre/post/invariant assertions. I put a setup function in each .py file to make sure that contract.checkmod gets called

def setup():
    import contract
    contract.checkmod(__name__)

I can confirm that this function is being executed by nose before it runs the tests, but the contracts still don't get executed.

On the other hand, if I run the doctest by calling doctest.testmod, the pre/post/inv do get called:

def _test():
    import contract
    contract.checkmod(__name__)
    import doctest
    doctest.testmod()

if __name__=='__main__':    
    _test()

Here's an example of a Python script whose test will succeed if called directly, but failed if called with nose:

import os

def setup():
    import contract
    contract.checkmod(__name__)

def delete_file(path):
    """Delete a file. File must be present.

    >>> import minimock
    >>> minimock.mock('os.remove')
    >>> minimock.mock('os.path.exists', returns=True)

    >>> delete_file('/tmp/myfile.txt')
    Called os.path.exists('/tmp/myfile.txt')
    Called os.remove('/tmp/myfile.txt')

    >>> minimock.restore()

    pre: os.path.exists(path)
    """
    os.remove(path)

if __name__ == '__main__':
    setup()
    import doctest
    doctest.testmod()

When I run the above file standalone, the tests pass:

$ python contracttest.py -v
Trying:
    import minimock
Expecting nothing
ok
Trying:
    minimock.mock('os.remove')
Expecting nothing
ok
Trying:
    minimock.mock('os.path.exists', returns=True)
Expecting nothing
ok
Trying:
    delete_file('/tmp/myfile.txt')
Expecting:
    Called os.path.exists('/tmp/myfile.txt')
    Called os.remove('/tmp/myfile.txt')
ok
Trying:
    minimock.restore()
Expecting nothing
ok
2 items had no tests:
    __main__
    __main__.setup
1 items passed all tests:
   5 tests in __main__.delete_file
5 tests in 3 items.
5 passed and 0 failed.
Test passed.

Here it is with nose:

$ nosetests --with-doctest contracttest.py
F
======================================================================
FAIL: Doctest: contracttest.delete_file
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/doctest.py", line 2131, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for contracttest.delete_file
  File "/Users/lorin/Desktop/contracttest.py", line 10, in delete_file

----------------------------------------------------------------------
File "/Users/lorin/Desktop/contracttest.py", line 17, in contracttest.delete_file
Failed example:
    delete_file('/tmp/myfile.txt')
Expected:
    Called os.path.exists('/tmp/myfile.txt')
    Called os.remove('/tmp/myfile.txt')
Got:
    Called os.remove('/tmp/myfile.txt')


----------------------------------------------------------------------
Ran 1 test in 0.055s

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文