python 模块的单元测试基础设施
我正在编写一个 python 模块,我想对其进行单元测试。我是 python 新手,对可用的选项有些困惑。
目前,我想将我的测试编写为 doctests 因为我喜欢声明式而不是命令式风格(但是,如果我的这种偏好被误导,请随时纠正我)。然而,这提出了一些问题:
- 我应该把测试放在哪里?在与他们正在测试的代码相同的文件中(或在文档测试的文档字符串中)?或者将它们分开到自己的目录中是否被认为更好?
- 如何从命令行一次性运行整个模块中的所有测试?
- 如何报告测试套件的代码覆盖率?
- 对于 python 中的单元测试,我还应该了解其他最佳实践吗?
I'm writing a python module and I would like to unit test it. I am new to python and somewhat bamboozled by the options available.
Currently, I would like to write my tests as doctests as I like the declarative rather than imperative style (however, feel free to disabuse me of this preference if it is misinformed). This raises a few questions, however:
- Where should I put the tests? In the same file as the code they are testing (or in docstrings for doctests)? Or is it considered better to separate them out into their own directory?
- How can I run all the tests in the whole module from the command-line in one go?
- How can I report the code coverage of the test suite?
- Any other best-practices I should be aware of for unit testing in python?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我比任何其他开源开发人员更广泛地使用了 doctest(方式 扩展了其预期使用边界),至少在单个项目中是这样 - < em>所有我的gmpy项目中的测试都是文档测试。在
gmpy
刚开始时它是全新的,这似乎是一个很棒的小技巧,如果某件事值得做,那么就值得过度做 - 对吗?-)错了。除了 gmpy 之外,将所有内容重做为正确的单元测试会带来太多的返工,我再也没有犯过这样的错误:这些天,我使用单元测试作为单元测试,而文档测试只是为了检查我的文档,因为它们一直是用来使用的。文档测试所做的(将预期结果与实际结果进行比较——仅此而已)并不是构建可靠的测试套件的良好或合理的基础。它从来没有其他意图。
我建议您查看nose。新的 Python 2.7 中的
unittest
模块更丰富、更好,如果您坚持使用 2.4、2.5 或 2.6,您仍然可以通过 unittest2 您可以下载并安装;nose
很好地补充了unittest
。如果你无法忍受单元测试(但是——尝试一下,它会在你身上成长!-),也许可以尝试 py.test,一个具有完全不同理念的替代包。
但是,请,不要使用
doctest
来测试文档中示例以外的内容!精确相等的比较经常会阻碍你,因为我不得不以我的(隐喻性的;-)代价在gmpy
中学习......I believe I used
doctest
more extensively (way stretching its intended use boundaries) than any other open source developer, at least within a single project -- all the tests in my gmpy project are doctests. It was brand new at the timegmpy
was starting, it seemed a great little trick, and if something is worth doing it's worth doing in excess -- right?-)Wrong. Except for
gmpy
, where redoing everything as proper unit tests would be too much rework, I've never made that mistake again: these days, I use unit tests as unit tests, and doctests just to check my docs, as they've always been meant to be used. What doctests do (compare an expected with an actual result for equality -- that's all) is just not a good or sound basis to build a solid test suite on. It was never intended otherwise.I would recommend you look at nose. The
unittest
module in the new Python 2.7 is much richer and nicer, and if you're stuck on 2.4, 2.5 or 2.6 you can still use the new features with the unittest2 which you can download and install;nose
complementsunittest
quite well.If you can't stand unittest (but -- give it a try, it grows on you!-), maybe try py.test, an alternative package with a pretty different philosophy.
But, please, don't stretch
doctest
to test stuff other than examples in docs! The exact-equality comparison will stand in your way far too often, as I've had to learn at my (metaphorical;-) expense ingmpy
...我不喜欢文档测试,原因如下:
此列表取自我的博客文章 关于 doctest 我不喜欢的事情,其中还有更多,还有一长串评论讨论这些观点。
关于覆盖率:我不认为 Python 中有一个覆盖率工具可以测量文档测试中的覆盖率。但由于它们只是很长的语句列表,没有分支或循环,这是一个问题吗?
I don't like doctests for these reasons:
This list was taken from my blog post Things I don't like about doctest, where there's more, and a long thread of comments debating the points.
About coverage: I don't believe there's a coverage tool for Python that will measure coverage within doctests. But since they are simply long lists of statements with no branches or loops, is that a problem?
我怀疑 Alex 在程序员的曲线上可能比我领先一些,但如果你想要有一些 Python 经验的人的观点(作为“用户”而不是专家或传播者),但又不一样联盟,我对单元测试的发现几乎相同。
一开始,文档测试对于简单的测试来说可能听起来很棒,我在家里的一些个人项目中朝着这个方向发展,因为它在其他地方被推荐了。
在工作中我们使用鼻子(尽管如此封闭和包裹,我的印象是我们直到不久前才使用 pyUnit),几个月前我在家也开始使用鼻子。
初始设置时间和管理开销,以及与实际代码的分离,一开始似乎是不必要的,特别是当您测试代码库不是那么大的东西时,但从长远来看,我发现文档测试越来越以我想做的每一次重构或重组的方式,相当难以维护,几乎不可能扩展,并且很快就抵消了最初的节省。是的,我知道单元测试与集成测试不同,但文档测试往往会过于严格地为您定义单元。
如果您认为它是有效的草图工具或开发模型,它们也不太适合基于单元的敏捷。
您可能需要花一些时间来计划,然后按照 pyUnit 或鼻子引导您的方式完善您的单元测试,但即使在短期内,您也可能会发现它实际上在很多层面上都在帮助您。我知道它对我有用,而且我对这些天正在处理的代码库的复杂性和规模还比较陌生。前几周你必须咬紧牙关。
I have this suspicion that Alex might be a fair bit ahead of me on the programmer's curve, but if you want the perspective of somebody with some Python experience (as a "user" rather than an expert or evangelist), yet not in the same league, my findings about unit testing have been pretty much the same.
Doctests might sound great for simple testing in the beginning, and I went in that direction for some personal project at home because it had been recommended elsewhere.
At work we use nose (although so canned and wrapped up I was under the impression we'd been using pyUnit until not long ago), and a few months back I moved to nose at home too.
The initial setup time and management overhead, and the separation from the actual code, might seem unnecessary in the beginning, especially when you're testing something that isn't that large a codebase, but in the long run I've found doctests getting in the way of every single refactoring or restructuring I wanted to do, rather hard to maintain, practically impossible to scale, and offsetting the initial savings very quickly. And yes, I'm aware that unit testing isn't the same as integration testing, but doctests tend to define your units for you rather too strictly.
They're also not well suited to unit based agile if you ever decide it's a valid sketching tool or dev model.
It might take you a bit to plan and then refine your unit tests the way pyUnit or nose steer you towards, but chances are that even in the short term you'll find it's actually helping you out on many levels. I know it did for me, and I'm relatively new to the complexity and scale of the codebase I'm working on these days. Just have to clench your teeth for the first few weeks.
有关覆盖范围,请查看优秀的 coverage.py。
除此之外,亚历克斯·马尔泰利写的所有内容都非常切题。
For coverage, check out the excellent coverage.py.
Otherwise, everything Alex Martelli wrote is very much on point.
doctests 非常适合快速、小型的单元测试,它描述了相关对象的一些基本用法(因为它们出现在文档字符串中,因此还有帮助(无论如何)等)。
我个人发现使用unittest模块进行广泛和更彻底的测试会更有效,现在2.7模块(向后移植到unittest2)具有更方便的断言。您可以使用单元测试框架设置测试套件和任意复杂的场景,并一次性覆盖所有不同的测试(命令行)
coverage.py,由 Ned Batchelder 和 @bstpierre 提到的将与其中任何一个一起使用,我推荐它来查看您对代码进行了测试以及什么没有。您可以将其添加到 CI 系统(即 Hudson 或任何您喜欢使用的系统)中,以了解已覆盖和未覆盖的内容,并且 HTML 报告非常适合查看测试覆盖范围内未命中的内容。 Coverage 支持 Junit xml 输出,许多 CI 系统都知道如何提供图表化的持续结果,让您看到构建随着时间的推移变得更好或更差。
doctests are great for quick, minor unit tests that describe what some of the basic usages of the objects in question, (as they show up in docstrings, and hence help(whatever), etc).
I've personally found extensive and more thorough testing to be more effective using the unittest module, and now the 2.7 module (back ported to unittest2) has even more handy assertions. You can set up test suites and as complex a scenario as you like with the unit testing framework and cover whole swaths of different tests in one go (command-line wise)
coverage.py, by Ned Batchelder and as @bstpierre mentions will work with either of these, and I recommend it for seeing what you've got tested of the code and what doesn't. You can add it into a CI system (i.e. Hudson or whatever you like to use) to keep up on what's covered and not, and the HTML reports are fantastic for seeing what hasn't been hit with testing coverage. Coverage supports Junit xml output, which many CI systems know how to provide charted on-going results to let you see the build getting better or worse over time.
我同意上述关于 doctest 不扩展的所有观点,并且我更喜欢坚持使用 unittest。
我可以贡献的一个技巧是从处理
__name__ == "__main__
的代码中调用单元测试,因此如果测试文件作为脚本运行,它将运行其测试。例如:
I agree with all the above points raised about doctest not scaling and I prefer to stick with unittest.
One tip I can contribute is to invoke the unit tests from the code handling
__name__ == "__main__
so if the test file is run as a script it will run its tests.eg: