Test suite improvements

This commit is contained in:
Jakub Roztocil 2016-03-01 23:11:06 +08:00
parent 0d2d24eac7
commit d30e28c2c7

View File

@ -6,7 +6,6 @@ import os
import sys import sys
import time import time
import json import json
import shutil
import tempfile import tempfile
import httpie import httpie
@ -30,11 +29,11 @@ HTTP_OK_COLOR = (
def no_content_type(headers): def no_content_type(headers):
return ( return (
'Content-Type' not in headers 'Content-Type' not in headers or
# We need to do also this because of this issue: # We need to do also this because of this issue:
# <https://github.com/kevin1024/pytest-httpbin/issues/5> # <https://github.com/kevin1024/pytest-httpbin/issues/5>
# TODO: remove this function once the issue is if fixed # TODO: remove this function once the issue is if fixed
or headers['Content-Type'] == 'text/plain' headers['Content-Type'] == 'text/plain'
) )
@ -53,68 +52,82 @@ class TestEnvironment(Environment):
stdout_isatty = True stdout_isatty = True
is_windows = False is_windows = False
_shutil_rmtree = shutil.rmtree # needed by __del__ (would get gc'd)
def __init__(self, **kwargs): def __init__(self, **kwargs):
if 'stdout' not in kwargs: if 'stdout' not in kwargs:
kwargs['stdout'] = tempfile.TemporaryFile('w+b') kwargs['stdout'] = tempfile.TemporaryFile(
mode='w+b',
prefix='httpie_stdout'
)
if 'stderr' not in kwargs: if 'stderr' not in kwargs:
kwargs['stderr'] = tempfile.TemporaryFile('w+t') kwargs['stderr'] = tempfile.TemporaryFile(
mode='w+t',
self.delete_config_dir = False prefix='httpie_stderr'
if 'config_dir' not in kwargs: )
kwargs['config_dir'] = mk_config_dir()
self.delete_config_dir = True
super(TestEnvironment, self).__init__(**kwargs) super(TestEnvironment, self).__init__(**kwargs)
self._delete_config_dir = False
@property
def config(self):
if not self.config_dir.startswith(tempfile.gettempdir()):
self.config_dir = mk_config_dir()
self._delete_config_dir = True
return super(TestEnvironment, self).config
def cleanup(self):
if self._delete_config_dir:
assert self.config_dir.startswith(tempfile.gettempdir())
from shutil import rmtree
rmtree(self.config_dir)
def __del__(self): def __del__(self):
if self.delete_config_dir: try:
self._shutil_rmtree(self.config_dir) self.cleanup()
except Exception:
pass
def http(*args, **kwargs): def http(*args, **kwargs):
# noinspection PyUnresolvedReferences
""" """
Run HTTPie and capture stderr/out and exit status. Run HTTPie and capture stderr/out and exit status.
Invoke `httpie.core.main()` with `args` and `kwargs`, Invoke `httpie.core.main()` with `args` and `kwargs`,
and return a `CLIResponse` subclass instance. and return a `CLIResponse` subclass instance.
The return value is either a `StrCLIResponse`, or `BytesCLIResponse` The return value is either a `StrCLIResponse`, or `BytesCLIResponse`
if unable to decode the output. if unable to decode the output.
The response has the following attributes: The response has the following attributes:
`stdout` is represented by the instance itself (print r) `stdout` is represented by the instance itself (print r)
`stderr`: text written to stderr `stderr`: text written to stderr
`exit_status`: the exit status `exit_status`: the exit status
`json`: decoded JSON (if possible) or `None` `json`: decoded JSON (if possible) or `None`
Exceptions are propagated. Exceptions are propagated.
If you pass ``error_exit_ok=True``, then error exit statuses If you pass ``error_exit_ok=True``, then error exit statuses
won't result into an exception. won't result into an exception.
Example: Example:
$ http --auth=user:password GET httpbin.org/basic-auth/user/password $ http --auth=user:password GET httpbin.org/basic-auth/user/password
>>> r = http('-a', 'user:pw', 'httpbin.org/basic-auth/user/pw') >>> httpbin = getfixture('httpbin')
>>> type(r) == StrCLIResponse >>> r = http('-a', 'user:pw', httpbin.url + '/basic-auth/user/pw')
True >>> type(r) == StrCLIResponse
>>> r.exit_status True
0 >>> r.exit_status
>>> r.stderr 0
'' >>> r.stderr
>>> 'HTTP/1.1 200 OK' in r ''
True >>> 'HTTP/1.1 200 OK' in r
>>> r.json == {'authenticated': True, 'user': 'user'} True
True >>> r.json == {'authenticated': True, 'user': 'user'}
True
""" """
error_exit_ok = kwargs.pop('error_exit_ok', False) error_exit_ok = kwargs.pop('error_exit_ok', False)
env = kwargs.get('env') env = kwargs.get('env')
if not env: if not env:
@ -174,6 +187,7 @@ def http(*args, **kwargs):
finally: finally:
stdout.close() stdout.close()
stderr.close() stderr.close()
env.cleanup()
class BaseCLIResponse(object): class BaseCLIResponse(object):
@ -221,8 +235,8 @@ class StrCLIResponse(str, BaseCLIResponse):
elif self.strip().startswith('{'): elif self.strip().startswith('{'):
# Looks like JSON body. # Looks like JSON body.
self._json = json.loads(self) self._json = json.loads(self)
elif (self.count('Content-Type:') == 1 elif (self.count('Content-Type:') == 1 and
and 'application/json' in self): 'application/json' in self):
# Looks like a whole JSON HTTP message, # Looks like a whole JSON HTTP message,
# try to extract its body. # try to extract its body.
try: try:
@ -238,4 +252,5 @@ class StrCLIResponse(str, BaseCLIResponse):
def mk_config_dir(): def mk_config_dir():
return tempfile.mkdtemp(prefix='httpie_test_config_dir_') dirname = tempfile.mkdtemp(prefix='httpie_config_')
return dirname