Skip to content

Commit

Permalink
Merge pull request #1424 from KeepSafe/test_docs
Browse files Browse the repository at this point in the history
Test docs
  • Loading branch information
asvetlov authored Nov 24, 2016
2 parents 6ce9707 + 5688cf5 commit 49c71c3
Show file tree
Hide file tree
Showing 11 changed files with 454 additions and 142 deletions.
12 changes: 11 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ CHANGES

- Support task attribute for StreamResponse #1410

- Drop `TestClient.app` property, use `TestClient.server.app` instead
(BACKWARD INCOMPATIBLE)

- Drop `TestClient.handler` property, use `TestClient.server.handler` instead
(BACKWARD INCOMPATIBLE)

- `TestClient.server` property returns a test server instance, was
`asyncio.AbstractServer` (BACKWARD INCOMPATIBLE)

- Follow gunicorn's signal semantics in `Gunicorn[UVLoop]WebWorker` #1201

- Call worker_int and worker_abort callbacks in `Gunicorn[UVLoop]WebWorker` #1202
- Call worker_int and worker_abort callbacks in
`Gunicorn[UVLoop]WebWorker` #1202

-

Expand Down
6 changes: 2 additions & 4 deletions aiohttp/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
from aiohttp.web import Application

from .test_utils import unused_port as _unused_port
from .test_utils import (RawTestServer, TestClient,
TestServer,
loop_context, setup_test_loop,
teardown_test_loop)
from .test_utils import (RawTestServer, TestClient, TestServer, loop_context,
setup_test_loop, teardown_test_loop)


@contextlib.contextmanager
Expand Down
62 changes: 8 additions & 54 deletions aiohttp/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def start_server(self, **kwargs):

@abstractmethod # pragma: no cover
@asyncio.coroutine
def _make_factory(self):
def _make_factory(self, **kwargs):
pass

def make_url(self, path):
Expand Down Expand Up @@ -164,7 +164,8 @@ def __init__(self, handler,

@asyncio.coroutine
def _make_factory(self, **kwargs):
return WebServer(self._handler, loop=self._loop)
self.handler = WebServer(self._handler, loop=self._loop, **kwargs)
return self.handler

@asyncio.coroutine
def _close_hook(self):
Expand Down Expand Up @@ -217,10 +218,6 @@ def __init__(self, app_or_server, *, scheme=sentinel, host=sentinel,
def start_server(self):
yield from self._server.start_server()

@property
def app(self):
return self._server.app

@property
def host(self):
return self._server.host
Expand All @@ -229,17 +226,13 @@ def host(self):
def port(self):
return self._server.port

@property
def handler(self):
return self._server.handler

@property
def server(self):
return self._server.server
return self._server

@property
def session(self):
"""A raw handler to the aiohttp.ClientSession.
"""An internal aiohttp.ClientSession.
Unlike the methods on the TestClient, client session requests
do not automatically include the host in the url queried, and
Expand All @@ -253,11 +246,11 @@ def make_url(self, path):

@asyncio.coroutine
def request(self, method, path, *args, **kwargs):
"""Routes a request to the http server.
"""Routes a request to tested http server.
The interface is identical to asyncio.ClientSession.request,
except the loop kwarg is overridden by the instance used by the
application.
test server.
"""
resp = yield from self._session.request(
Expand Down Expand Up @@ -313,7 +306,7 @@ def delete(self, path, *args, **kwargs):
def ws_connect(self, path, *args, **kwargs):
"""Initiate websocket connection.
The api is identical to aiohttp.ClientSession.ws_connect.
The api corresponds to aiohttp.ClientSession.ws_connect.
"""
ws = yield from self._session.ws_connect(
Expand Down Expand Up @@ -487,45 +480,6 @@ def make_mocked_request(method, path, headers=None, *,
Useful in unit tests, when spinning full web server is overkill or
specific conditions and errors are hard to trigger.
:param method: str, that represents HTTP method, like; GET, POST.
:type method: str
:param path: str, The URL including *PATH INFO* without the host or scheme
:type path: str
:param headers: mapping containing the headers. Can be anything accepted
by the multidict.CIMultiDict constructor.
:type headers: dict, multidict.CIMultiDict, list of pairs
:param version: namedtuple with encoded HTTP version
:type version: aiohttp.protocol.HttpVersion
:param closing: flag indicates that connection should be closed after
response.
:type closing: bool
:param app: the aiohttp.web application attached for fake request
:type app: aiohttp.web.Application
:param reader: object for storing and managing incoming data
:type reader: aiohttp.parsers.StreamParser
:param writer: object for managing outcoming data
:type wirter: aiohttp.parsers.StreamWriter
:param transport: asyncio transport instance
:type transport: asyncio.transports.Transport
:param payload: raw payload reader object
:type payload: aiohttp.streams.FlowControlStreamReader
:param sslcontext: ssl.SSLContext object, for HTTPS connection
:type sslcontext: ssl.SSLContext
:param secure_proxy_ssl_header: A tuple representing a HTTP header/value
combination that signifies a request is secure.
:type secure_proxy_ssl_header: tuple
"""

if version < HttpVersion(1, 1):
Expand Down
24 changes: 23 additions & 1 deletion aiohttp/web_server.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Low level HTTP server."""

import asyncio
import traceback
from html import escape as html_escape

from .helpers import TimeService
from .server import ServerHttpProtocol
from .web_exceptions import HTTPException
from .web_exceptions import HTTPException, HTTPInternalServerError
from .web_reqrep import BaseRequest

__all__ = ('RequestHandler', 'WebServer')
Expand Down Expand Up @@ -59,6 +61,26 @@ def handle_request(self, message, payload):
resp = yield from self._handler(request)
except HTTPException as exc:
resp = exc
except Exception as exc:
msg = "<h1>500 Internal Server Error</h1>"
if self.debug:
try:
tb = traceback.format_exc()
tb = html_escape(tb)
msg += '<br><h2>Traceback:</h2>\n<pre>'
msg += tb
msg += '</pre>'
except: # pragma: no cover
pass
else:
msg += "Server got itself in trouble"
msg = ("<html><head><title>500 Internal Server Error</title>"
"</head><body>" + msg + "</body></html>")
resp = HTTPInternalServerError(text=msg,
content_type='text/html')
self.logger.exception(
"Error handling request",
exc_info=exc)

resp_msg = yield from resp.prepare(request)
yield from resp.write_eof()
Expand Down
1 change: 1 addition & 0 deletions docs/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ hostnames
HTTPException
HttpProcessingError
https
incapsulates
impl
Indices
infos
Expand Down
Loading

0 comments on commit 49c71c3

Please sign in to comment.