为什么coverage.py无法正确测量Django的runserver命令?
我应该知道这个问题的答案,但我不知道:如果你尝试像这样测量一个Django项目的代码覆盖率:
coverage run manage.py runserver
你会发现测量的结果漏掉了你所有的实际代码。这个过程中的某个早期环节阻止了测量,或者所有真正的工作发生在一个新的环境中,而这个环境根本没有被测量到。
有没有人能告诉我在这个过程中具体是哪个环节出了问题,这样我就可以尝试修复coverage.py,让它按照大家的期望正确测量代码覆盖率?
1 个回答
29
你运行的时候,如果这样做,会不会遇到同样的问题?
coverage run manage.py runserver --noreload
如果不加 --noreload
,后台会启动另一个进程。一个进程负责运行服务器,另一个进程则监控代码的变化,并在有变化时重启服务器。很可能你是在监控进程上运行覆盖率检查,而不是在服务进程上。
你可以看看 django/core/management/commands/runserver.py
和 django/utils/autoreload.py
。
更新:我运行了覆盖率命令,然后用 ps
和 lsof
查看发生了什么。以下是我的观察:
ps output:
UID PID PPID C STIME TTY TIME CMD
vinay 12081 2098 0 16:37 pts/0 00:00:00 /home/vinay/.virtualenvs/watfest/bin/python /home/vinay/.virtualenvs/watfest/bin/coverage run manage.py runserver
vinay 12082 12081 2 16:37 pts/0 00:00:01 /home/vinay/.virtualenvs/watfest/bin/python manage.py runserver
lsof output:
python 12082 vinay 5u IPv4 48294 0t0 TCP localhost:8000 (LISTEN)
换句话说,即使在重载之前,也有两个进程,而监听TCP端口的那个进程并不是覆盖率运行的那个进程。
这是我在使用 --noreload
时看到的情况:
ps output:
UID PID PPID C STIME TTY TIME CMD
vinay 12140 2098 5 16:44 pts/0 00:00:00 /home/vinay/.virtualenvs/watfest/bin/python /home/vinay/.virtualenvs/watfest/bin/coverage run manage.py runserver --noreload
lsof output:
coverage 12140 vinay 4u IPv4 51995 0t0 TCP localhost:8000 (LISTEN)
所以在 --noreload
的情况下,覆盖率为什么不工作并不明显。在我用 --noreload
进行的非常简单的测试中,我得到了我视图代码的覆盖率,以下是相关的摘录:
festival/__init__ 8 7 13%
manage 9 4 56%
settings 33 1 97%