Coverage for /usr/local/lib/python3.7/site-packages/pytest_flask/plugin.py : 12%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4 A py.test plugin which helps testing Flask applications.
6 :copyright: (c) by Vital Kudzelka
7 :license: MIT
8"""
9import sys
11import pytest
13from flask import json
14from werkzeug.utils import cached_property
16from .fixtures import (
17 client, config, accept_json, accept_jsonp, accept_any, accept_mimetype,
18 client_class, live_server, request_ctx
19)
20from .pytest_compat import getfixturevalue
23class JSONResponse(object):
24 """Mixin with testing helper methods for JSON responses."""
26 @cached_property
27 def json(self):
28 """Try to deserialize response data (a string containing a valid JSON
29 document) to a Python object by passing it to the underlying
30 :mod:`flask.json` module.
31 """
32 return json.loads(self.data)
34 def __eq__(self, other):
35 if isinstance(other, int):
36 return self.status_code == other
37 # even though the Python 2-specific code works on Python 3, keep the two versions
38 # separate so we can simplify the code once Python 2 support is dropped
39 if sys.version_info[0] == 2:
40 try:
41 super_eq = super(JSONResponse, self).__eq__
42 except AttributeError:
43 return NotImplemented
44 else:
45 return super_eq(other)
46 else:
47 return super(JSONResponse, self).__eq__(other)
49 def __ne__(self, other):
50 return not self == other
53def pytest_assertrepr_compare(op, left, right):
54 if isinstance(left, JSONResponse) and op == '==' and isinstance(right, int):
55 return [
56 'Mismatch in status code for response: {} != {}'.format(
57 left.status_code,
58 right,
59 ),
60 'Response status: {}'.format(left.status),
61 ]
62 return None
65def _make_test_response_class(response_class):
66 """Extends the response class with special attribute to test JSON
67 responses. Don't override user-defined `json` attribute if any.
69 :param response_class: An original response class.
70 """
71 if 'json' in response_class.__dict__:
72 return response_class
74 return type(str(JSONResponse), (response_class, JSONResponse), {})
77@pytest.fixture(autouse=True)
78def _monkeypatch_response_class(request, monkeypatch):
79 """Set custom response class before test suite and restore the original
80 after. Custom response has `json` property to easily test JSON responses::
82 @app.route('/ping')
83 def ping():
84 return jsonify(ping='pong')
86 def test_json(client):
87 res = client.get(url_for('ping'))
88 assert res.json == {'ping': 'pong'}
90 """
91 if 'app' not in request.fixturenames:
92 return
94 app = getfixturevalue(request, 'app')
95 monkeypatch.setattr(app, 'response_class',
96 _make_test_response_class(app.response_class))
99@pytest.fixture(autouse=True)
100def _push_request_context(request):
101 """During tests execution request context has been pushed, e.g. `url_for`,
102 `session`, etc. can be used in tests as is::
104 def test_app(app, client):
105 assert client.get(url_for('myview')).status_code == 200
107 """
108 if 'app' not in request.fixturenames:
109 return
111 app = getfixturevalue(request, 'app')
113 # Get application bound to the live server if ``live_server`` fixture
114 # is applied. Live server application has an explicit ``SERVER_NAME``,
115 # so ``url_for`` function generates a complete URL for endpoint which
116 # includes application port as well.
117 if 'live_server' in request.fixturenames:
118 app = getfixturevalue(request, 'live_server').app
120 ctx = app.test_request_context()
121 ctx.push()
123 def teardown():
124 ctx.pop()
126 request.addfinalizer(teardown)
129@pytest.fixture(autouse=True)
130def _configure_application(request, monkeypatch):
131 """Use `pytest.mark.options` decorator to pass options to your application
132 factory::
134 @pytest.mark.options(debug=False)
135 def test_something(app):
136 assert not app.debug, 'the application works not in debug mode!'
138 """
139 if 'app' not in request.fixturenames:
140 return
142 app = getfixturevalue(request, 'app')
143 for options in request.node.iter_markers('options'):
144 for key, value in options.kwargs.items():
145 monkeypatch.setitem(app.config, key.upper(), value)
148def pytest_addoption(parser):
149 group = parser.getgroup('flask')
150 group.addoption('--start-live-server',
151 action="store_true", dest="start_live_server", default=True,
152 help="start server automatically when live_server "
153 "fixture is applied (enabled by default).")
154 group.addoption('--no-start-live-server',
155 action="store_false", dest="start_live_server",
156 help="don't start server automatically when live_server "
157 "fixture is applied.")
158 group.addoption('--live-server-clean-stop',
159 action="store_true", dest="live_server_clean_stop", default=True,
160 help="attempt to kill the live server cleanly.")
161 group.addoption('--no-live-server-clean-stop',
162 action="store_false", dest="live_server_clean_stop",
163 help="terminate the server forcefully after stop.")
164 group.addoption('--live-server-host', action='store', default='localhost', type=str,
165 help='use a host where to listen (default localhost).')
166 group.addoption('--live-server-port', action='store', default=0, type=int,
167 help='use a fixed port for the live_server fixture.')
170def pytest_configure(config):
171 config.addinivalue_line(
172 'markers',
173 'app(options): pass options to your application factory')
174 config.addinivalue_line('markers', 'options: app config manipulation')