【问题标题】:How can I measure the coverage (in production system)?如何测量覆盖率(在生产系统中)?
【发布时间】:2020-09-09 01:45:10
【问题描述】:

我想测量在生产系统中执行的 Python 代码的覆盖率。

我想回答这个问题:

哪些行经常执行(热点),哪些行从不使用(死代码)?

当然,这不能减慢我的生产站点。

不是谈论衡量测试的覆盖率。

【问题讨论】:

  • 你想要什么样的代码? Django Web 服务器还有别的吗?另外我希望你明白,在生产中做这样的事情是不推荐的
  • 我也不太清楚“在生产系统中执行的代码”究竟是什么意思 - 但您可以将确切的代码移动到私有存储库并配置持续集成以进行覆盖。

标签: python code-coverage performance-testing


【解决方案1】:

我假设您不是在谈论另一个答案所指的测试套件代码覆盖率。这确实是 CI 的工作。

如果您想知道在您的生产系统中哪些代码路径经常被命中,那么您将不得不进行一些检测/分析。这将是有代价的。您不能免费添加测量值。不过,您可以廉价地执行此操作,并且通常只运行很短的时间,直到获得数据为止。

Python 有 cProfile 进行全面分析、测量每个函数的调用次数等。这将为您提供最准确的数据,但可能会对性能产生相对较高的影响。

或者,您可以进行统计分析,这基本上意味着您在计时器上对堆栈进行采样,而不是检测所有内容。即使采样率很高,这也可以便宜得多!缺点当然是精度下降。

尽管在 Python 中做起来非常容易,但这里的答案仍然有点多。不过,在这个确切的主题上有一个出色的blog post by the Nylas team

下面的采样器是从 Nylas 博客中提取的,并进行了一些调整。启动后,它会每毫秒触发一次中断并记录当前调用堆栈:

import collections
import signal

class Sampler(object):
    def __init__(self, interval=0.001):
        self.stack_counts = collections.defaultdict(int)
        self.interval = interval

    def start(self): 
        signal.signal(signal.VTALRM, self._sample)
        signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)

    def _sample(self, signum, frame):
        stack = []
        while frame is not None:
            formatted_frame = '{}({})'.format(
                frame.f_code.co_name,
                frame.f_globals.get('__name__'))
            stack.append(formatted_frame)
            frame = frame.f_back
        formatted_stack = ';'.join(reversed(stack))
        self.stack_counts[formatted_stack] += 1
        signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)

您检查stack_counts 以查看您的程序已经完成了什么。这些数据可以绘制在flame-graph 中,这样可以很明显地看到您的程序在哪些代码路径中花费的时间最多。

【讨论】:

  • 所以“生产系统”覆盖范围是在生产中部署的代码的覆盖范围?例如编译成可执行文件并查看代码在用户使用时执行的频率——实际上,我的答案无关紧要
  • 我们不得不从问题中猜测,所以谁知道呢。我想这就是他的意思,是的:-)
  • +1 表示“这需要付费。您不能免费添加测量值。”任何形式的测量都会带来一些开销。
【解决方案2】:

如果我理解正确,您想了解应用程序的哪些部分最常被用户使用。


TL;DR;

如果您不想手动操作,请使用 Python 的度量框架之一。其中一些在上面:


通常由功能级别完成,实际上取决于应用程序;

  • 如果是可以上网的桌面应用:

    您可以创建一个简单的数据库并收集您的函数被调用的次数。为了实现它,您可以编写一个简单的函数并在您要跟踪的每个函数中调用它。之后,您可以定义一个异步任务将您的数据上传到互联网。

  • 如果是网页应用:

    您可以跟踪从 js(主要用于用户行为跟踪)或 Web api 调用的函数。从外到内是一个很好的做法。首先检测哪些端点被频繁调用(如果您使用的是像 nginx 这样的代理,您可以分析服务器日志以收集信息。这是最简单和最干净的方法)。之后,将记录器插入到您想要跟踪的每个其他函数中,并简单地分析每周或每月的日志。

但是您想逐行分析您的生产代码(这是一个非常糟糕的主意),您可以使用 python 分析器启动您的应用程序。 Python 已经有一个:cProfile

【讨论】:

    【解决方案3】:

    也许制作一个文本文件并通过您的每个程序方法只需附加一些引用它的文本,例如“方法一已执行”。像查看器一样彻底运行 Web 应用程序 10 次,然后创建一个 python 程序来读取文件并计算文件的特定部分,甚至可能是模式并将其添加到变量中并输出变量。

    【讨论】:

      猜你喜欢
      • 2013-05-02
      • 1970-01-01
      • 2014-10-27
      • 2015-07-07
      • 2013-11-09
      • 2019-06-22
      • 2010-10-06
      • 2017-04-06
      • 2020-03-03
      相关资源
      最近更新 更多