Add missing docs and fix lint.

This commit is contained in:
Florian Bruhin 2015-09-17 18:59:00 +02:00
parent 929957c4fb
commit c195ee225d
3 changed files with 94 additions and 2 deletions

View File

@ -1,12 +1,32 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Things needed for integration testing."""
import re import re
import sys import sys
import socket import socket
import functools
import os.path import os.path
import collections import collections
import pytest import pytest
import pytestqt.plugin import pytestqt.plugin # pylint: disable=import-error
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QProcess, QObject from PyQt5.QtCore import pyqtSlot, pyqtSignal, QProcess, QObject
@ -22,6 +42,18 @@ class InvalidLine(Exception):
class HTTPBin(QObject): class HTTPBin(QObject):
"""Abstraction over a running HTTPbin server process.
Reads the log from its stdout and parses it.
Class attributes:
LOG_RE: Used to parse the CLF log which httpbin outputs.
Signals:
ready: Emitted when the server finished starting up.
new_request: Emitted when there's a new request received.
"""
ready = pyqtSignal() ready = pyqtSignal()
new_request = pyqtSignal(Request) new_request = pyqtSignal(Request)
@ -48,6 +80,7 @@ class HTTPBin(QObject):
self.proc.setReadChannel(QProcess.StandardError) self.proc.setReadChannel(QProcess.StandardError)
def _get_port(self): def _get_port(self):
"""Get a random free port to use for the server."""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 0)) sock.bind(('localhost', 0))
port = sock.getsockname()[1] port = sock.getsockname()[1]
@ -55,12 +88,17 @@ class HTTPBin(QObject):
return port return port
def get_requests(self): def get_requests(self):
"""Get the requests to the server during this test.
Also waits for 0.5s to make sure any new requests are received.
"""
self.proc.waitForReadyRead(500) self.proc.waitForReadyRead(500)
self.read_log() self.read_log()
return self._requests return self._requests
@pyqtSlot() @pyqtSlot()
def read_log(self): def read_log(self):
"""Read the log from httpbin's stdout and parse it."""
while self.proc.canReadLine(): while self.proc.canReadLine():
line = self.proc.readLine() line = self.proc.readLine()
line = bytes(line).decode('utf-8').rstrip('\n') line = bytes(line).decode('utf-8').rstrip('\n')
@ -86,6 +124,7 @@ class HTTPBin(QObject):
self.new_request.emit(request) self.new_request.emit(request)
def start(self): def start(self):
"""Start the webserver."""
filename = os.path.join(os.path.dirname(__file__), 'webserver.py') filename = os.path.join(os.path.dirname(__file__), 'webserver.py')
self.proc.start(sys.executable, [filename, str(self.port)]) self.proc.start(sys.executable, [filename, str(self.port)])
ok = self.proc.waitForStarted() ok = self.proc.waitForStarted()
@ -93,17 +132,24 @@ class HTTPBin(QObject):
self.proc.readyRead.connect(self.read_log) self.proc.readyRead.connect(self.read_log)
def after_test(self): def after_test(self):
"""Clean request list after each test.
Also checks self._invalid so the test counts as failed if there were
unexpected output lines earlier.
"""
self._requests.clear() self._requests.clear()
if self._invalid: if self._invalid:
raise InvalidLine raise InvalidLine
def cleanup(self): def cleanup(self):
"""Clean up and shut down the process."""
self.proc.terminate() self.proc.terminate()
self.proc.waitForFinished() self.proc.waitForFinished()
@pytest.yield_fixture(scope='session', autouse=True) @pytest.yield_fixture(scope='session', autouse=True)
def httpbin(qapp): def httpbin(qapp):
"""Fixture for a httpbin object which ensures clean setup/teardown."""
httpbin = HTTPBin() httpbin = HTTPBin()
blocker = pytestqt.plugin.SignalBlocker(timeout=5000, raising=True) blocker = pytestqt.plugin.SignalBlocker(timeout=5000, raising=True)
@ -118,5 +164,6 @@ def httpbin(qapp):
@pytest.yield_fixture(autouse=True) @pytest.yield_fixture(autouse=True)
def httpbin_clean(httpbin): def httpbin_clean(httpbin):
"""Fixture to clean httpbin request list after each test."""
yield yield
httpbin.after_test() httpbin.after_test()

View File

@ -1,3 +1,24 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Test the httpbin webserver used for tests."""
import urllib.request import urllib.request
import urllib.error import urllib.error

View File

@ -1,3 +1,27 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""httpbin web server for integration tests.
This script gets called as a QProcess from integration/conftest.py.
"""
import sys import sys
import os.path import os.path