Skip to content

Commit

Permalink
Fix/robust tests (#145)
Browse files Browse the repository at this point in the history
* robust tests

* flake8

* flake8

* better range ports

* other port usage rule

* raise if timeout

* some fallback

* pytest-timeout

* skipping http2 tests
  • Loading branch information
sonic182 committed Sep 22, 2020
1 parent 255c43b commit a271efd
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 36 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ logs/*.log*
*.csv
.mypy_cache/
junit/
env/
venv*/
2 changes: 1 addition & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ DJANGO_SETTINGS_MODULE = djangotestproj.djangotestproj.settings
python_files = **/*.py
testpaths = tests/
python_functions = test_*
addopts = --cov=aiosonic --cov-report term --cov-report html --mypy --mypy-ignore-missing-imports
addopts = --cov=aiosonic --cov-report term --cov-report html --mypy --mypy-ignore-missing-imports --doctest-modules
1 change: 1 addition & 0 deletions test-requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ pytest-django
pytest-mock
pytest-mypy
pytest-sugar
pytest-timeout
uvicorn
3 changes: 2 additions & 1 deletion test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ pytest-django==3.9.0 # via -r test-requirements.in
pytest-mock==3.1.0 # via -r test-requirements.in
pytest-mypy==0.6.2 # via -r test-requirements.in
pytest-sugar==0.9.3 # via -r test-requirements.in
pytest==5.4.2 # via -r test-requirements.in, pytest-aiohttp, pytest-asyncio, pytest-cov, pytest-django, pytest-mock, pytest-mypy, pytest-sugar
pytest-timeout==1.4.2 # via -r test-requirements.in
pytest==5.4.2 # via -r test-requirements.in, pytest-aiohttp, pytest-asyncio, pytest-cov, pytest-django, pytest-mock, pytest-mypy, pytest-sugar, pytest-timeout
pytz==2020.1 # via django
requests==2.23.0 # via coveralls
rfc3986==1.4.0 # via httpx
Expand Down
3 changes: 2 additions & 1 deletion tests/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var myArgs = process.argv.slice(2);
const server = createSecureServer(
{ cert, key, allowHTTP1: true },
onRequest
).listen(myArgs [0]);
).listen(myArgs[0]);

function onRequest(req, res) {
// Detects if it is a HTTPS request or HTTP/2
Expand All @@ -21,3 +21,4 @@ function onRequest(req, res) {

res.end('Hello World')
}
console.log(`server listen on port ${myArgs[0]}`);
49 changes: 24 additions & 25 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import asyncio
from datetime import datetime
from datetime import timedelta
import gzip
import multiprocessing as mp
import os
import random
import gzip
import socket
import signal
import ssl
import subprocess
from time import sleep
from urllib.request import urlopen
from urllib.error import URLError
import zlib

import aiohttp
Expand Down Expand Up @@ -146,30 +145,30 @@ def ssl_context():
return context


def node_http2(port):
os.system(f'node tests/app.js {port}')


@pytest.fixture
def http2_serv():
"""Sample aiohttp app."""
port = random.randint(1000, 9999)
p = mp.Process(target=node_http2, args=(port, ))
p.start()
port = random.randint(3000, 4000)

kwargs = dict(
stdin=subprocess.PIPE,
shell=True)

proc = subprocess.Popen(f"node tests/app.js {port}", **kwargs)
url = f'https://localhost:{port}/'

# This restores the same behavior as before.
context = ssl._create_unverified_context()

max_wait = datetime.now() + timedelta(seconds=2)
while True:
try:
with urlopen(url, context=context) as response:
response.read()
break
except URLError:
sleep(0.1)
if datetime.now() > max_wait:
raise
max_wait = datetime.utcnow() + timedelta(seconds=3)
while not __is_port_in_use(port):
sleep(0.2)
if datetime.utcnow() > max_wait:
raise Exception('cannot run node http2 server')
yield url
p.terminate()
proc.send_signal(signal.SIGINT)
proc.terminate()


def __is_port_in_use(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result_of_check = sock.connect_ex(("localhost", port))
return result_of_check == 0
29 changes: 21 additions & 8 deletions tests/test_aiosonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
from aiosonic.timeout import Timeouts


skip_http2 = pytest.mark.skip(reason="WIP")


@pytest.mark.asyncio
async def test_simple_get(app, aiohttp_server):
"""Test simple get."""
server = await aiohttp_server(app)
url = 'http://localhost:%d' % server.port

client = aiosonic.HTTPClient()
connector = TCPConnector(timeouts=Timeouts(sock_connect=3, sock_read=4))
client = aiosonic.HTTPClient(connector)
res = await client.get(url)
assert res.status_code == 200
assert await res.content() == b'Hello, world'
Expand All @@ -36,24 +40,28 @@ async def test_simple_get(app, aiohttp_server):


@pytest.mark.asyncio
async def test_get_python():
@skip_http2
@pytest.mark.timeout(3)
async def test_get_python(http2_serv):
"""Test simple get."""
url = 'https://www.python.org/'
url = http2_serv

client = aiosonic.HTTPClient()
connector = TCPConnector(timeouts=Timeouts(sock_connect=3, sock_read=4))
client = aiosonic.HTTPClient(connector)
res = await client.get(
url,
verify=False,
headers={
'user-agent':
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0)'
' Gecko/20100101 Firefox/70.0')
},
http2=True)
assert res.status_code == 200
assert '<title>Welcome to Python.org</title>' in await res.text()
}, http2=True)
assert 'Hello World' in await res.text()


@pytest.mark.asyncio
@skip_http2
@pytest.mark.timeout(3)
async def test_get_http2(http2_serv):
"""Test simple get to node http2 server."""
url = http2_serv
Expand All @@ -66,6 +74,8 @@ async def test_get_http2(http2_serv):


@pytest.mark.asyncio
@skip_http2
@pytest.mark.timeout(3)
async def test_method_lower(http2_serv):
"""Test simple get to node http2 server."""
url = http2_serv
Expand All @@ -77,6 +87,7 @@ async def test_method_lower(http2_serv):

class MyConnection(Connection):
"""Connection to count keeped alives connections."""

def __init__(self, *args, **kwargs):
self.counter = 0
super(MyConnection, self).__init__(*args, **kwargs)
Expand Down Expand Up @@ -656,6 +667,8 @@ class WrongEvent:


@pytest.mark.asyncio
@skip_http2
@pytest.mark.timeout(3)
async def test_http2_wrong_event(mocker):
"""Test json response parsing."""
mocker.patch('aiosonic.http2.Http2Handler.__init__', lambda x: None)
Expand Down

0 comments on commit a271efd

Please sign in to comment.