如何为基于http的集成测试生成覆盖率报告?

时间:2018-06-04 23:08:16

标签: python unit-testing pytest coverage.py

我正在为一个项目编写集成测试,我正在进行HTTP调用并测试它们是否成功。

由于我没有导入任何模块而没有直接调用函数,因此coverage.py报告为0%。

我想知道如何为此类集成HTTP请求测试生成覆盖率报告?

2 个答案:

答案 0 :(得分:5)

配方就是这样:

  1. 确保后端以代码覆盖率模式启动
  2. 运行测试
  3. 确保将后端覆盖范围写入文件
  4. 从文件中读取coverage并将其附加到测试运行覆盖率
  5. 示例:

    后端

    想象一下,你有一个虚拟的后端服务器,它响应了一个" Hello World"关于GET请求的页面:

    # backend.py
    from http.server import BaseHTTPRequestHandler, HTTPServer
    
    
    class DummyHandler(BaseHTTPRequestHandler):
    
        def do_GET(self):
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.end_headers()
            self.wfile.write('<html><body><h1>Hello World</h1></body></html>'.encode())
    
    
    if __name__ == '__main__':
        HTTPServer(('127.0.0.1', 8000), DummyHandler).serve_forever()
    

    测试

    发出HTTP请求并验证响应的简单测试包含&#34; Hello World&#34;:

    # tests/test_server.py
    import requests
    
    
    def test_GET():
        resp = requests.get('http://127.0.0.1:8000')
        resp.raise_for_status()
        assert 'Hello World' in resp.text
    

    配方

    # tests/conftest.py
    import os
    import signal
    import subprocess
    import time
    import coverage.data
    import pytest
    
    
    
    @pytest.fixture(autouse=True)
    def run_backend(cov):
        # 1.
        env = os.environ.copy()
        env['COVERAGE_FILE'] = '.coverage.backend'
        serverproc = subprocess.Popen(['coverage', 'run', 'backend.py'], env=env,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      preexec_fn=os.setsid)
        time.sleep(3)
        yield  # 2.
        # 3.
        serverproc.send_signal(signal.SIGINT)
        time.sleep(1)
        # 4.
        backendcov = coverage.data.CoverageData()
        with open('.coverage.backend') as fp:
            backendcov.read_fileobj(fp)
        cov.data.update(backendcov)
    

    covpytest-covdocs)提供的工具。

    运行测试会将backend.py的覆盖范围添加到整体覆盖范围,但只选择了tests

    $ pytest --cov=tests --cov-report term -vs
    =============================== test session starts ===============================
    platform linux -- Python 3.6.5, pytest-3.4.1, py-1.5.3, pluggy-0.6.0 -- 
    /data/gentoo64/usr/bin/python3.6
    cachedir: .pytest_cache
    rootdir: /data/gentoo64/home/u0_a82/projects/stackoverflow/so-50689940, inifile:
    plugins: mock-1.6.3, cov-2.5.1
    collected 1 item
    
    tests/test_server.py::test_GET PASSED
    
    ----------- coverage: platform linux, python 3.6.5-final-0 -----------
    Name                   Stmts   Miss  Cover
    ------------------------------------------
    backend.py                12      0   100%
    tests/conftest.py         18      0   100%
    tests/test_server.py       5      0   100%
    ------------------------------------------
    TOTAL                     35      0   100%
    
    
    ============================ 1 passed in 5.09 seconds =============================
    

答案 1 :(得分:0)

使用Coverage 5.1,基于"Measuring sub-processes" section of the coverage.py docs,您可以设置COVERAGE_PROCESS_START env-var,在代码中的某个位置调用coverage.process_startup()。如果您在parallel=True中设置了.coveragerc

  1. 在过程中的某个地方,调用以下代码:

    import coverage
    coverage.process_startup()
    

    这可以在全局sitecustomize.py中完成,但就我而言,很容易将其添加到应用程序的__init__.py中,我在其中添加了

    import os
    if 'COVERAGE_PROCESS_START' in os.environ:
        import coverage
        coverage.process_startup()
    

    为了安全起见,我在此if语句中添加了另一项检查(检查是否还设置了MYAPP_COVERAGE_SUBPROCESS

  2. 在测试用例中,将COVERAGE_PROCESS_START设置为.coveragerc文件的路径(如果不需要此配置,则为空字符串),例如:

    import os
    import subprocess
    
    env = os.environ.copy()
    env['COVERAGE_PROCESS_START'] = '.coveragerc'
    
    cmd = [sys.executable, 'run_my_app.py']
    
    p  = subprocess.Popen(cmd, env=env)
    p.communicate()
    assert p.returncode == 0 # ..etc
    
  3. 最后,您创建包含以下内容的.coveragerc

    [run]
    parallel = True
    source = myapp # Which module to collect coverage for
    

    这可确保由每个进程创建的.coverage文件进入一个唯一文件,该文件pytest-cov似乎会自动合并(或可以通过coverage combine手动完成)。它还描述了要收集数据的模块(--cov=myapp arg不会传递给子进程)

  4. 要运行测试,只需调用pytest --cov=