在gunicorn运行时如何从django应用程序获取覆盖率数据?

时间:2022-06-22 22:53:30

How do I get code coverage out of a Django project's view code (and code called by view code)?

如何从Django项目的视图代码(以及视图代码调用的代码)中获得代码覆盖率?

coverage gunicorn <params> does not show any lines being hit.

覆盖率gunicorn 没有显示任何线被击中。

1 个解决方案

#1


12  

coverage gunicorn <params> does not work, because gunicorn creates worker processes, and the coverage module can't work across forks (basically, creation of new processes). You can use the coverage API, though, for example in the python module that contains your WSGI application:

覆盖率gunicorn 不起作用,因为gunicorn创建worker进程,而覆盖率模块不能跨fork工作(基本上,创建新进程)。不过,您可以使用覆盖率API,例如在包含WSGI应用程序的python模块中:

# wsgi_with_coverage.py
import atexit
import sys
import coverage
cov = coverage.coverage()
cov.start()

from wsgi import application  # adjust to python module containing your wsgi application


def save_coverage():
    print >> sys.stderr, "saving coverage"
    cov.stop()
    cov.save()

atexit.register(save_coverage)

Then run gunicorn -w 1 wsgi_with_coverage:application <other params>.

然后运行gunicorn - w1 wsgi_with_coverage:应用程序 <其他params> 。

The problem is, the atexit functions are not called if you kill the gunicorn process, for example via CTRL+C. But they are called on SIGHUP, so if you do kill -HUP $(cat <gunicorn_pidfile_here>), the coverage data should be saved (by default to ".coverage" in the current directory).

问题是,如果您杀死了gunicorn进程,则不调用atexit函数,例如通过CTRL+C。但是它们在SIGHUP上被调用,所以如果您确实杀死-HUP $(cat ),那么应该保存覆盖率数据(默认为”)。“当前目录中的覆盖率”)。

A possible caveat is that this won't work with more than one gunicorn worker, because they would all overwrite the ".coverage" file. If you absolutely need more than one worker, you could write to ".coverage-%d" % os.getpid() (set the file name via the data_file parameter to the coverage constructor) and use the combine() method to merge the individual measurements.

一个可能的警告是,这对于一个以上的枪手工人来说是行不通的,因为他们会覆盖“。报道”文件。如果你绝对需要一个以上的工人,你可以写信给”。getpid()(通过data_file参数将文件名设置为覆盖构造函数),并使用组合()方法合并单独的度量。

This should work on other WSGI servers, too, depending on whether they allow their worker processes to clean up via the atexit method.

这也应该适用于其他的WSGI服务器,这取决于它们是否允许其工作进程通过atexit方法进行清理。

#1


12  

coverage gunicorn <params> does not work, because gunicorn creates worker processes, and the coverage module can't work across forks (basically, creation of new processes). You can use the coverage API, though, for example in the python module that contains your WSGI application:

覆盖率gunicorn 不起作用,因为gunicorn创建worker进程,而覆盖率模块不能跨fork工作(基本上,创建新进程)。不过,您可以使用覆盖率API,例如在包含WSGI应用程序的python模块中:

# wsgi_with_coverage.py
import atexit
import sys
import coverage
cov = coverage.coverage()
cov.start()

from wsgi import application  # adjust to python module containing your wsgi application


def save_coverage():
    print >> sys.stderr, "saving coverage"
    cov.stop()
    cov.save()

atexit.register(save_coverage)

Then run gunicorn -w 1 wsgi_with_coverage:application <other params>.

然后运行gunicorn - w1 wsgi_with_coverage:应用程序 <其他params> 。

The problem is, the atexit functions are not called if you kill the gunicorn process, for example via CTRL+C. But they are called on SIGHUP, so if you do kill -HUP $(cat <gunicorn_pidfile_here>), the coverage data should be saved (by default to ".coverage" in the current directory).

问题是,如果您杀死了gunicorn进程,则不调用atexit函数,例如通过CTRL+C。但是它们在SIGHUP上被调用,所以如果您确实杀死-HUP $(cat ),那么应该保存覆盖率数据(默认为”)。“当前目录中的覆盖率”)。

A possible caveat is that this won't work with more than one gunicorn worker, because they would all overwrite the ".coverage" file. If you absolutely need more than one worker, you could write to ".coverage-%d" % os.getpid() (set the file name via the data_file parameter to the coverage constructor) and use the combine() method to merge the individual measurements.

一个可能的警告是,这对于一个以上的枪手工人来说是行不通的,因为他们会覆盖“。报道”文件。如果你绝对需要一个以上的工人,你可以写信给”。getpid()(通过data_file参数将文件名设置为覆盖构造函数),并使用组合()方法合并单独的度量。

This should work on other WSGI servers, too, depending on whether they allow their worker processes to clean up via the atexit method.

这也应该适用于其他的WSGI服务器,这取决于它们是否允许其工作进程通过atexit方法进行清理。