Django测试覆盖率 vs 代码覆盖率

37

我已成功安装并配置了django-nosecoverage。问题是,如果我只是在./manage.py shell中运行coverage,然后退出该shell,它会显示我37%的代码覆盖率。我完全理解执行的代码并不意味着被测试的代码。我的唯一问题是--现在怎么办?

我的设想是,在执行任何测试之前,能够导入所有Python模块并进行“稳定”,并直接与coverage通信,告诉它“好的,在这里开始计算已到达的代码。”

理想情况下,nose将在执行每个测试套件之前重置代码的“触摸”行。

我不知道从哪里开始寻找/开发。我在网上搜索了一番,没有找到有用的信息。非常感谢任何帮助/指导。

P.S.

我尝试执行类似于以下内容的命令:

DJANGO_SETTINGS_MODULE=app.settings_dev coverage run app/tests/gme_test.py

它有效了(显示了1%的覆盖率),但我无法弄清如何对整个应用程序执行此操作。

编辑:这是我的覆盖配置:

[run]
source = .
branch = False
timid = True
[report]
show_missing = False
include = *.py
omit =
    tests.py
    *_test.py
    *_tests.py
    */site-packages/*
    */migrations/*
[html]
title = Code Coverage
directory = local_coverage_report

DJANGO_SETTINGS_MODULE=app.settings_dev coverage ./manage.py test app1 app2 ... appn 怎么样? - Robert Jørgensgaard Engdahl
这并没有帮助。请阅读我的第二句话 - 只要涉及manage.py,我就会得到错误的覆盖率。 - Mikhail
“在执行每个测试套件之前重置已触及的代码行”很容易实现。您需要帮忙吗?-- 只需为每个测试套件创建一个新的覆盖实例(您可以在测试运行器专业化中完成此操作)。 - Robert Jørgensgaard Engdahl
4个回答

47

由于您使用了Django-nose,因此有两种运行覆盖率的选项。第一种已经被DaveB指出:

coverage run ./manage.py test myapp

以上实际上运行了覆盖率,然后监测测试命令执行的所有代码。

此外,django-nose包中默认包含了一个nose覆盖率插件(http://nose.readthedocs.org/en/latest/plugins/cover.html)。您可以按照以下方式使用它:

./manage.py test myapp --with-coverage

还有一些额外的选项,比如应该涵盖哪些模块,是否包括 HTML 报告等等。这些都在上面的链接中有文档记录 - 您也可以键入 ./manage.py test --help 来获取一些快速信息。

运行 nose 覆盖插件将导致覆盖率在执行 Django 引导代码后运行,因此相应的代码不会被报告为已覆盖。

当以原始方式运行覆盖率时,您看到大多数报告为覆盖的代码是导入语句、类定义、类成员等。由于 Python 在导入时计算它们,因此覆盖率自然会标记它们为已覆盖。但是,运行 nose 插件不会报告引导代码为已覆盖,因为测试运行器是在加载 Django 环境后启动的。当然,这样做的一个副作用就是您永远无法实现 100% 的覆盖率(...或接近 :)),因为您的全局范围语句永远不会被覆盖。

在来回切换并尝试各种覆盖率选项后,我现在使用以下方式使用覆盖率:

coverage run --source=myapp,anotherapp --omit=*/migrations/* ./manage.py test

这样做的目的是:

a. 覆盖率报告将会报告导入语句、类成员定义等被覆盖的部分(这其实是真的——这段代码已经成功地被导入和解释)。

b. 它只会覆盖我的代码,而不是Django代码或我使用的任何其他第三方应用程序。覆盖率百分比将反映出我的项目有多少得到了覆盖。

希望能对您有所帮助!


我已经更新了我的配置到原始帖子中。你认为成功导入意味着代码已经被测试过了吗?对我来说,被测试的部分只有一行,而不是导入文件中的每一行。 - Mikhail
只要这些代码行没有逻辑问题,我会说是的,代码已经覆盖了。这可能是一个感知问题,我猜有人会持相反的观点。你仍然可以选择使用nose插件,它非常方便。 - ppetrid
运行 manage.py --with-coverage 实际上似乎报告了比运行 coverage run... 更高的代码覆盖率。我仍在尝试各种标志,最有趣的一个是 --cover-inclusive,它似乎具有与我预期相反的行为。 - Mikhail
你的意思是说 --cover-inclusive 实际上会导致更高的覆盖率吗?你同时使用了 --cover-package 选项吗?对于相同的一组包,--cover-inclusive 理论上应该会导致较少的(最多相等的)覆盖率。这很奇怪。 - ppetrid

3
我遇到了同样的问题。我创建了一个.coveragerc文件,其中指定了与bounty-awarded答案中概述的类似的选项,这样可以节省一些时间。
现在运行'coverage run manage.py test'然后再运行'coverage report -m',就能显示测试覆盖率报告和未被覆盖的代码行。
(请参阅此处关于.coveragerc文件的详细信息:http://nedbatchelder.com/code/coverage/config.html

3

“Ok,start counting reached code here.” 可以通过覆盖模块的API来实现。您可以通过shell来查看此功能。直接从http://nedbatchelder.com/code/coverage/api.html中获取。

import coverage

cov = coverage.coverage()
cov.start()

# .. call your code ..

cov.stop()
cov.save()

cov.html_report()

您可以制作自己的测试运行器,以完全满足您的需求(有些人认为从任何单元测试生成的覆盖率是可以接受的,而另一些人则只接受由该单元测试引起的单元覆盖率。)

这是否意味着我必须编写自己的覆盖率运行程序?目前,如果你所说的“...调用你的代码...”部分包括一个import语句,那么该代码也将被视为已覆盖。 - Mikhail
你可以自行决定现有的运行程序是否足够。我只是建议,如果你有特殊需求,可能需要编写自己的程序。coverage.py 跟踪执行的代码,而不是解析的代码,即仅仅因为导入了代码并不会被跟踪为已执行。然而,很容易让在导入时就执行的代码被跟踪到。 - Robert Jørgensgaard Engdahl
Robert,我发帖的整个意图就是要表明我知道“覆盖率”跟踪执行的代码的问题。我指出并不是所有执行的代码都是经过测试的代码。 - Mikhail
在您的观点中,覆盖的代码的__哪些部分__被认为是已经测试过的? - Robert Jørgensgaard Engdahl
测试意味着我编写代码来执行相关代码,然后确认执行结果符合预期。它必须包含一些“断言”。如果我只是执行一些代码,这并不意味着我已经测试过它了。执行代码:a = sum(2,2)。测试代码:assert(a == 4) - Mikhail
单元测试通常是这种形式:a = sum([2,2]) self.assertEqual(a,4)。但很容易覆盖您自己的自定义 TestCase 专业化上的断言方法以进行覆盖率记录。我相信这些可以通过 API 或使用相同的覆盖率元文件进行组合。 - Robert Jørgensgaard Engdahl

1

我有点困惑你在这里试图实现什么。

Django的测试非常详细,可以在这里找到:https://docs.djangoproject.com/en/dev/topics/testing/overview/

您可以在test.py中编写应用程序的测试 - 我不认为需要使用nose,因为Django的标准方式非常简单。

然后运行它们,如coverage run ./manage.py test main - 其中“main”是您的应用程序名称

按照此处记录的方式指定代码的源文件:http://nedbatchelder.com/code/coverage/cmd.html 这样只计算您的代码

例如:coverage run --source=main ./manage.py test main

即使使用提供的简单测试,您仍将获得一定百分比的覆盖率。这是因为为了启动服务器(例如模块中的定义等),执行了代码的某些部分。


2
Nose非常快速和灵活。而且实际上这不是核心问题。你最后一句话正是我开设悬赏的原因。“你仍然会得到一定百分比的标记为已覆盖”——这是一个巨大的问题!正如我所指出的,在我的情况下,“某个特定的百分比”是37%,是代码_被覆盖_但没有_测试_的部分。我对此不满意。 - Mikhail
覆盖率工具永远无法保证您的代码是否经过适当的测试。只有通过仔细制定测试并了解系统的所有部分,才能实现这一点。覆盖率仅有助于突出测试中的漏洞。 - DaveB
大家对此感到满意吗?这个“帮助突出漏洞”的工具真的很糟糕,因为它并不能突出所有的漏洞!这就像说“哦,这是计算机科学中不起作用的部分”。 - Mikhail
这个内容比较老,但值得注意的是我们都认为覆盖率工具无法判断您是否已经测试了代码(只能判断代码行是否运行)。如果它可以告诉您一切都测试得很好,那么它也可以为您编写代码...最终,您需要编写字符来告诉处理器该做什么,您需要对测试做同样的事情。 - Trent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接