运行烧瓶服务器,nosetests和覆盖范围

时间:2015-06-12 15:14:57

标签: python flask code-coverage nosetests

我在Flask写一个api。我有几个视图返回json响应,我已经编写了一些单元测试,将检查这些视图是否正常工作并返回正确的数据。然后我打开鼻子测试的覆盖插件(在我的情况下是鼻子 - cov)。

这就是我的问题开始的地方,覆盖范围并没有将我的观点视为由测试执行。

首先为您提供完整图片的基本代码:

我的观点:

def get_user(uid):
    """Retrieve user.

    Args:
        uid (url): valid uid value

    Usage: ::

        GET user/<uid>/

    Returns:
      obj:
       ::

        {
            'data': {
                `response.User`,
            },
            'success': True,
            'status': 'get'
        }
    """
    if not uid:
        raise exception.ValueError("Uid is empty")

    obj = db_layer.user.get_user(uid=value)

    return {
        'data': {
            obj.to_dict(),  # to_dict is helper method that converts part of orm into dict
        },
        'success': True,
        'status': 'get'
    }

我的测试:

class TestUserViews(base.TestViewsBase):
    def test_get_user(self):
        uid = 'some_uid_from_fixtures'
        name = 'some_name_from_fixtures'

        response = self.get(u'user/uid/{}/'.format(uid))
        self.assertEqual(response.status_code, 200)

        user_data = json.loads(response.text)['data']
        self.assertEqual(name, user_data['username'])
        self.assertEqual(uid, user_data['uid'])

    def get(self, method, headers=None):
        """
        Wrapper around requests.get, reassures that authentication is
        sorted for us.
        """
        kwargs = {
            'headers': self._build_headers(headers),
        }

        return requests.get(self.get_url(method), **kwargs)

    def get_url(self, method):
        return '{}/{}/{}'.format(self.domain, self.version, method)

    def _build_headers(self, headers=None):
        if headers is None:
            headers = {}

        headers.update({
            'X-Auth-Token': 'some-token',
            'X-Auth-Token-Test-User-Id': 'some-uid',
        })

        return headers

要运行测试套件,我有一个特殊的shell脚本,可以为我执行一些操作:

#!/usr/bin/env bash

HOST="0.0.0.0"
PORT="5001"

ENVS="PYTHONPATH=$PYTHONPATH:$PWD"

# start server 
START_SERVER="$ENVS python $PWD/server.py --port=$PORT --host=$HOST"

eval "$START_SERVER&"

PID=$!

eval "$ENVS nosetests -s --nologcapture --cov-report html --with-cov"

kill -9 $PID

报告该视图未被执行。

1 个答案:

答案 0 :(得分:3)

好的,12小时后,我找到了一个解决方案。我检查了烧瓶,werkzeug,请求,子进程和线程库。只知道问题是在其他地方。解决方案很简单。必须修改的代码位是server.py的执行。我们还需要覆盖它,然后合并server.py生成的结果并由nosetests生成。修改后的test-runner.sh如下所示:

#!/usr/bin/env bash

HOST="0.0.0.0"
PORT="5001"

ENVS="COVERAGE_PROCESS_START=$PWD/.apirc PYTHONPATH=$PYTHONPATH:$PWD"

START_SERVER="$ENVS coverage run --rcfile=.apirc $PWD/server.py --port=$PORT --host=$HOST"

eval "$START_SERVER&"

eval "$ENVS nosetests -s --nologcapture --cov-config=.apirc --cov-report html --with-cov"

# this is important bit, we have to stop flask server gracefully otherwise
# coverage won't get a chance to collect and save all results
eval "curl -X POST http://$HOST:$PORT/0.0/shutdown/"

# this will merge results from both coverage runs
coverage combine  --rcfile=.apirc
coverage html --rcfile=.apirc

在我的案例中.apirc的内容如下:

[run]
branch = True
parallel = True
source = files_to_cover/

[html]
directory = cover

我们需要做的最后一件事是构建我们的烧瓶,查看将允许我们慷慨地关闭服务器。以前我用kill -9蛮力杀死它,它不仅用来杀死服务器而且还用来杀死它。

请遵循以下代码段:http://flask.pocoo.org/snippets/67/

我的观点是这样的:

def shutdown():
    if config.SHUTDOWN_ALLOWED:
        func = request.environ.get('werkzeug.server.shutdown')
        if func is None:
            raise RuntimeError('Not running with the Werkzeug Server')
        func()

        return 'Server shutting down...'

使用nose-cov而不是标准coverage插件非常重要,因为它使用rcfile并允许配置更多。在我们的情况下,parallel是键,请注意data_files变量不适用于nose-coverage,所以你不能在.apirc中覆盖它,你必须使用默认值。

在完成所有这些之后,你的报道几乎都是有效的价值。

我希望它对那里的人有所帮助。