tests: Make httpbin.Request a proper class.
This commit is contained in:
parent
bc96da47ef
commit
7fe9be432a
@ -99,12 +99,12 @@ def wait_for_message(quteproc, httpbin, category, message):
|
||||
@bdd.then(bdd.parsers.parse("{path} should be loaded"))
|
||||
def path_should_be_loaded(httpbin, path):
|
||||
requests = httpbin.get_requests()
|
||||
assert requests[-1] == httpbin.Request('GET', '/' + path)
|
||||
assert requests[-1] == httpbin.ExpectedRequest('GET', '/' + path)
|
||||
|
||||
|
||||
@bdd.then(bdd.parsers.parse("The requests should be:\n{pages}"))
|
||||
def list_of_loaded_pages(httpbin, pages):
|
||||
expected_requests = [httpbin.Request('GET', '/' + path.strip())
|
||||
expected_requests = [httpbin.ExpectedRequest('GET', '/' + path.strip())
|
||||
for path in pages.split('\n')]
|
||||
actual_requests = httpbin.get_requests()
|
||||
assert actual_requests == expected_requests
|
||||
|
@ -47,13 +47,6 @@ def is_ignored_qt_message(message):
|
||||
return False
|
||||
|
||||
|
||||
class NoLineMatch(Exception):
|
||||
|
||||
"""Raised by LogLine on unmatched lines."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class LogLine(testprocess.Line):
|
||||
|
||||
"""A parsed line from the qutebrowser log output.
|
||||
@ -78,7 +71,7 @@ class LogLine(testprocess.Line):
|
||||
super().__init__(data)
|
||||
match = self.LOG_RE.match(data)
|
||||
if match is None:
|
||||
raise NoLineMatch(data)
|
||||
raise testprocess.InvalidLine(data)
|
||||
|
||||
self.timestamp = datetime.datetime.strptime(match.group('timestamp'),
|
||||
'%H:%M:%S')
|
||||
@ -138,7 +131,7 @@ class QuteProc(testprocess.Process):
|
||||
def _parse_line(self, line):
|
||||
try:
|
||||
log_line = LogLine(line)
|
||||
except NoLineMatch:
|
||||
except testprocess.InvalidLine:
|
||||
if line.startswith(' '):
|
||||
# Multiple lines in some log output...
|
||||
return None
|
||||
@ -147,7 +140,7 @@ class QuteProc(testprocess.Process):
|
||||
elif is_ignored_qt_message(line):
|
||||
return None
|
||||
else:
|
||||
raise testprocess.InvalidLine
|
||||
raise
|
||||
|
||||
if (log_line.loglevel in ['INFO', 'WARNING', 'ERROR'] or
|
||||
pytest.config.getoption('--verbose')):
|
||||
|
@ -25,6 +25,7 @@ import datetime
|
||||
import pytest
|
||||
|
||||
import quteprocess
|
||||
import testprocess
|
||||
from qutebrowser.utils import log
|
||||
|
||||
|
||||
@ -113,5 +114,5 @@ def test_log_line_parse(data, attrs):
|
||||
|
||||
|
||||
def test_log_line_no_match():
|
||||
with pytest.raises(quteprocess.NoLineMatch):
|
||||
with pytest.raises(testprocess.InvalidLine):
|
||||
quteprocess.LogLine("Hello World!")
|
||||
|
@ -46,5 +46,19 @@ def test_httpbin(httpbin, qtbot, path, content, expected):
|
||||
|
||||
data = response.read().decode('utf-8')
|
||||
|
||||
assert httpbin.get_requests() == [httpbin.Request('GET', path)]
|
||||
assert httpbin.get_requests() == [httpbin.ExpectedRequest('GET', path)]
|
||||
assert (content in data) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('line, verb, path, equal', [
|
||||
('127.0.0.1 - - [01/Jan/1990 00:00:00] "GET / HTTP/1.1" 200 -',
|
||||
'GET', '/', True),
|
||||
('127.0.0.1 - - [01/Jan/1990 00:00:00] "GET / HTTP/1.1" 200 -',
|
||||
'GET', '/foo', False),
|
||||
('127.0.0.1 - - [01/Jan/1990 00:00:00] "GET / HTTP/1.1" 200 -',
|
||||
'POST', '/foo', False),
|
||||
])
|
||||
def test_expected_request(httpbin, line, verb, path, equal):
|
||||
expected = httpbin.ExpectedRequest(verb, path)
|
||||
request = httpbin.Request(line)
|
||||
assert (expected == request) == equal
|
||||
|
@ -26,7 +26,7 @@ import re
|
||||
import sys
|
||||
import socket
|
||||
import os.path
|
||||
import collections
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
@ -34,25 +34,17 @@ from PyQt5.QtCore import pyqtSignal
|
||||
import testprocess # pylint: disable=import-error
|
||||
|
||||
|
||||
Request = collections.namedtuple('Request', 'verb, path')
|
||||
class Request(testprocess.Line):
|
||||
|
||||
"""A parsed line from the httpbin/flask log output.
|
||||
|
||||
class HTTPBin(testprocess.Process):
|
||||
|
||||
"""Abstraction over a running HTTPbin server process.
|
||||
|
||||
Reads the log from its stdout and parses it.
|
||||
Attributes:
|
||||
timestamp/verb/path/status: Parsed from the log output.
|
||||
|
||||
Class attributes:
|
||||
LOG_RE: Used to parse the CLF log which httpbin outputs.
|
||||
|
||||
Signals:
|
||||
new_request: Emitted when there's a new request received.
|
||||
"""
|
||||
|
||||
new_request = pyqtSignal(Request)
|
||||
Request = Request # So it can be used from the fixture easily.
|
||||
|
||||
LOG_RE = re.compile(r"""
|
||||
(?P<host>[^ ]*)
|
||||
\ ([^ ]*) # ignored
|
||||
@ -67,6 +59,68 @@ class HTTPBin(testprocess.Process):
|
||||
\ (?P<size>[^ ]*)
|
||||
""", re.VERBOSE)
|
||||
|
||||
def __init__(self, data):
|
||||
super().__init__(data)
|
||||
match = self.LOG_RE.match(data)
|
||||
if match is None:
|
||||
raise testprocess.InvalidLine(data)
|
||||
|
||||
assert match.group('host') == '127.0.0.1'
|
||||
assert match.group('user') == '-'
|
||||
self.timestamp = datetime.datetime.strptime(match.group('date'),
|
||||
'%d/%b/%Y %H:%M:%S')
|
||||
self.verb = match.group('verb')
|
||||
|
||||
# FIXME do we need to allow other options?
|
||||
assert match.group('protocol') == 'HTTP/1.1'
|
||||
assert self.verb == 'GET'
|
||||
|
||||
self.path = match.group('path')
|
||||
self.status = int(match.group('status'))
|
||||
|
||||
missing_paths = ['/favicon.ico', '/does-not-exist']
|
||||
|
||||
if self.path in missing_paths:
|
||||
assert self.status == 404
|
||||
else:
|
||||
assert self.status < 400
|
||||
|
||||
assert match.group('size') == '-'
|
||||
|
||||
def __eq__(self, other):
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class ExpectedRequest:
|
||||
|
||||
"""Class to compare expected requests easily."""
|
||||
|
||||
def __init__(self, verb, path):
|
||||
self.verb = verb
|
||||
self.path = path
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, (Request, ExpectedRequest)):
|
||||
return (self.verb == other.verb and
|
||||
self.path == other.path)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class HTTPBin(testprocess.Process):
|
||||
|
||||
"""Abstraction over a running HTTPbin server process.
|
||||
|
||||
Reads the log from its stdout and parses it.
|
||||
|
||||
Signals:
|
||||
new_request: Emitted when there's a new request received.
|
||||
"""
|
||||
|
||||
new_request = pyqtSignal(Request)
|
||||
Request = Request # So it can be used from the fixture easily.
|
||||
ExpectedRequest = ExpectedRequest
|
||||
|
||||
KEYS = ['verb', 'path']
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@ -93,14 +147,7 @@ class HTTPBin(testprocess.Process):
|
||||
'quit)'.format(self.port)):
|
||||
self.ready.emit()
|
||||
return None
|
||||
|
||||
match = self.LOG_RE.match(line)
|
||||
if match is None:
|
||||
raise testprocess.InvalidLine
|
||||
# FIXME do we need to allow other options?
|
||||
assert match.group('protocol') == 'HTTP/1.1'
|
||||
|
||||
return Request(verb=match.group('verb'), path=match.group('path'))
|
||||
return Request(line)
|
||||
|
||||
def _executable_args(self):
|
||||
if hasattr(sys, 'frozen'):
|
||||
|
Loading…
Reference in New Issue
Block a user