我可以将nose覆盖输出限制为目录而不是包吗?

20 投票
8 回答
10470 浏览
提问于 2025-04-15 11:33

我的测试代码看起来是这样的:

foo.py
bar.py
tests/__init__.py [empty]
tests/foo_tests.py
tests/bar_tests.py
tests/integration/__init__.py [empty]
tests/integration/foo_tests.py
tests/integration/bar_tests.py

当我运行 nosetests --with-coverage 时,我会看到很多我其实不想关注的模块的详细信息。但是我不能使用 --cover-package=PACKAGE 这个选项,因为 foo.pybar.py 并不在一个包里。(关于我为什么不把它们放在包里的原因,可以参考这个链接:http://lists.idyll.org/pipermail/testing-in-python/2008-November/001091.html

我能不能把覆盖率的输出限制在只有 foo.py 和 bar.py 上呢?

更新 - 假设没有比下面 Nadia 的回答更好的答案,我又问了一个后续问题:“我该如何写一个(bash)脚本,把目录中所有匹配的文件名转换为命令行选项?”

8 个回答

4

我有很多顶层的Python文件和包,手动一个一个列出来用--cover-package实在太麻烦了,所以我给自己做了两个别名。别名nosetests_cover会运行覆盖率测试,并自动列出你所有顶层的Python文件和包。别名nosetests_cover_sort也会做同样的事情,还会根据覆盖率百分比对结果进行排序。

nosetests_cover_cmd="nosetests --with-coverage --cover-erase --cover-inclusive --cover-package=\$( ls | sed -r 's/[.]py$//' | fgrep -v '.' | paste -s -d ',' )"
alias nosetests_cover=$nosetests_cover_cmd
alias nosetests_cover_sort="$nosetests_cover_cmd 2>&1 | fgrep '%' | sort -nr -k 4"

注意事项:

  • 这些内容来自我的.bashrc文件。如果你不使用bash,请根据自己的情况进行修改。
  • 这些命令必须在你的顶层目录下运行。否则,包名会不正确,覆盖率测试会默默失败(也就是说,它不会告诉你--cover-package不正确,而是表现得好像你根本没有提供这个选项)。
  • 我目前在Ubuntu 13.10上使用Python 2.7.6,nose版本是1.3.0,覆盖率版本是3.7.1。这是我测试这些命令的唯一环境。
  • 在使用时,如果--cover-erase和--cover-inclusive不符合你的需求,可以去掉它们。
  • 如果你想按正常顺序排序,而不是反向排序,可以把-nr替换成-n
  • 这些命令假设你所有的顶层Python文件和包的名字中没有点(除了“.py”中的点)。如果不是这样,请阅读下面的详细说明,理解命令的组成部分,然后根据需要修改命令。

详细说明:

我并不认为这些是实现我想要结果的最有效命令。这只是我碰巧想到的命令。 =P

主要需要解释的是--cover-package的参数。它会生成一个以逗号分隔的顶层Python文件/包名列表(文件名中的“.py”会被去掉),具体过程如下:

  • \$ -- 在双引号字符串中转义$字符。
  • $( ) -- 插入括号内命令的结果。
  • ls -- 列出当前目录下的所有名字(必须是顶层Python目录)。
  • | sed -r 's/[.]py$//' -- 在列表中,把“foo_bar.py”替换成“foo_bar”。
  • | fgrep -v '.' -- 在列表中,去掉所有没有点的名字(例如,去掉foo_bar.pyc和notes.txt)。
  • | paste -s -d ',' -- 把列表从换行分隔改成逗号分隔。

我还应该解释一下排序的部分。

  • 2>&1 -- 合并标准错误输出和标准输出。
  • | fgrep '%' -- 去掉所有没有%字符的输出行。
  • | sort -nr -k 4 -- 按照第四列(覆盖率百分比)以反向数字顺序排序剩下的行。如果你想要正常顺序而不是反向顺序,可以把-nr替换成-n

希望这对某些人有帮助! =)

15

你可以使用:

--cover-package=.

或者甚至可以设置环境变量

NOSE_COVER_PACKAGE=.

这是在nose 1.1.2版本下测试过的

22

你可以这样使用它:

--cover-package=foo --cover-package=bar

我快速查看了一下nose的源代码来确认:这一行代码

    if options.cover_packages:
        for pkgs in [tolist(x) for x in options.cover_packages]:

撰写回答