forked from loafle/openapi-generator-original
[Python/tornado] add integration tests and fix bugs (#6925)
* tests: add integration test for python-tornado * [python-tornado-client] tests: increase timeout for test_upload_file * [python-tornado-client] fix: tornado client passes tests
This commit is contained in:
committed by
William Cheng
parent
63d28cf75b
commit
4e967e696c
@@ -150,7 +150,6 @@ class ApiClient(object):
|
||||
_request_timeout=_request_timeout)
|
||||
|
||||
self.last_response = response_data
|
||||
{{^tornado}}
|
||||
|
||||
return_data = response_data
|
||||
if _preload_content:
|
||||
@@ -160,12 +159,20 @@ class ApiClient(object):
|
||||
else:
|
||||
return_data = None
|
||||
|
||||
{{^tornado}}
|
||||
if _return_http_data_only:
|
||||
return (return_data)
|
||||
else:
|
||||
return (return_data, response_data.status,
|
||||
response_data.getheaders())
|
||||
{{/tornado}}
|
||||
{{#tornado}}
|
||||
if _return_http_data_only:
|
||||
raise tornado.gen.Return(return_data)
|
||||
else:
|
||||
raise tornado.gen.Return((return_data, response_data.status,
|
||||
response_data.getheaders()))
|
||||
{{/tornado}}
|
||||
|
||||
def sanitize_for_serialization(self, obj):
|
||||
"""Builds a JSON POST object.
|
||||
|
||||
@@ -10,6 +10,7 @@ import ssl
|
||||
|
||||
import certifi
|
||||
# python 2 and python 3 compatibility library
|
||||
import six
|
||||
from six.moves.urllib.parse import urlencode
|
||||
import tornado
|
||||
import tornado.gen
|
||||
@@ -50,7 +51,7 @@ class RESTClientObject(object):
|
||||
# if not set certificate file, use Mozilla's root certificates.
|
||||
ca_certs = certifi.where()
|
||||
|
||||
self.ssl_context = ssl.SSLContext()
|
||||
self.ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
self.ssl_context.load_verify_locations(cafile=ca_certs)
|
||||
if configuration.cert_file:
|
||||
self.ssl_context.load_cert_chain(
|
||||
@@ -121,7 +122,8 @@ class RESTClientObject(object):
|
||||
elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501
|
||||
request.body = urlencode(post_params)
|
||||
elif headers['Content-Type'] == 'multipart/form-data':
|
||||
request.body = encode_multipart_formdata(post_params)
|
||||
multipart = encode_multipart_formdata(post_params)
|
||||
request.body, headers['Content-Type'] = multipart
|
||||
# Pass a `bytes` parameter directly in the body to support
|
||||
# other content types than Json when `body` argument is provided
|
||||
# in serialized form
|
||||
@@ -134,15 +136,24 @@ class RESTClientObject(object):
|
||||
declared content type."""
|
||||
raise ApiException(status=0, reason=msg)
|
||||
|
||||
r = yield self.pool_manager.fetch(request)
|
||||
r = RESTResponse(r, r.body)
|
||||
r = yield self.pool_manager.fetch(request, raise_error=False)
|
||||
|
||||
# log response body
|
||||
logger.debug("response body: %s", r.data)
|
||||
if _preload_content:
|
||||
|
||||
r = RESTResponse(r, r.body)
|
||||
# In the python 3, the response.data is bytes.
|
||||
# we need to decode it to string.
|
||||
if six.PY3:
|
||||
r.data = r.data.decode('utf8')
|
||||
|
||||
# log response body
|
||||
logger.debug("response body: %s", r.data)
|
||||
|
||||
if not 200 <= r.status <= 299:
|
||||
raise ApiException(http_resp=r)
|
||||
|
||||
raise tornado.gen.Return(r)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def GET(self, url, headers=None, query_params=None, _preload_content=True,
|
||||
_request_timeout=None):
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
nose
|
||||
tox
|
||||
coverage
|
||||
randomize
|
||||
flake8
|
||||
@@ -156,6 +156,20 @@ class ApiClient(object):
|
||||
|
||||
self.last_response = response_data
|
||||
|
||||
return_data = response_data
|
||||
if _preload_content:
|
||||
# deserialize response data
|
||||
if response_type:
|
||||
return_data = self.deserialize(response_data, response_type)
|
||||
else:
|
||||
return_data = None
|
||||
|
||||
if _return_http_data_only:
|
||||
raise tornado.gen.Return(return_data)
|
||||
else:
|
||||
raise tornado.gen.Return((return_data, response_data.status,
|
||||
response_data.getheaders()))
|
||||
|
||||
def sanitize_for_serialization(self, obj):
|
||||
"""Builds a JSON POST object.
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import ssl
|
||||
|
||||
import certifi
|
||||
# python 2 and python 3 compatibility library
|
||||
import six
|
||||
from six.moves.urllib.parse import urlencode
|
||||
import tornado
|
||||
import tornado.gen
|
||||
@@ -59,7 +60,7 @@ class RESTClientObject(object):
|
||||
# if not set certificate file, use Mozilla's root certificates.
|
||||
ca_certs = certifi.where()
|
||||
|
||||
self.ssl_context = ssl.SSLContext()
|
||||
self.ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
self.ssl_context.load_verify_locations(cafile=ca_certs)
|
||||
if configuration.cert_file:
|
||||
self.ssl_context.load_cert_chain(
|
||||
@@ -130,7 +131,8 @@ class RESTClientObject(object):
|
||||
elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501
|
||||
request.body = urlencode(post_params)
|
||||
elif headers['Content-Type'] == 'multipart/form-data':
|
||||
request.body = encode_multipart_formdata(post_params)
|
||||
multipart = encode_multipart_formdata(post_params)
|
||||
request.body, headers['Content-Type'] = multipart
|
||||
# Pass a `bytes` parameter directly in the body to support
|
||||
# other content types than Json when `body` argument is provided
|
||||
# in serialized form
|
||||
@@ -143,15 +145,24 @@ class RESTClientObject(object):
|
||||
declared content type."""
|
||||
raise ApiException(status=0, reason=msg)
|
||||
|
||||
r = yield self.pool_manager.fetch(request)
|
||||
r = RESTResponse(r, r.body)
|
||||
r = yield self.pool_manager.fetch(request, raise_error=False)
|
||||
|
||||
# log response body
|
||||
logger.debug("response body: %s", r.data)
|
||||
if _preload_content:
|
||||
|
||||
r = RESTResponse(r, r.body)
|
||||
# In the python 3, the response.data is bytes.
|
||||
# we need to decode it to string.
|
||||
if six.PY3:
|
||||
r.data = r.data.decode('utf8')
|
||||
|
||||
# log response body
|
||||
logger.debug("response body: %s", r.data)
|
||||
|
||||
if not 200 <= r.status <= 299:
|
||||
raise ApiException(http_resp=r)
|
||||
|
||||
raise tornado.gen.Return(r)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def GET(self, url, headers=None, query_params=None, _preload_content=True,
|
||||
_request_timeout=None):
|
||||
|
||||
32
samples/client/petstore/python-tornado/test_python2_and_3.sh
Executable file
32
samples/client/petstore/python-tornado/test_python2_and_3.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
REQUIREMENTS_FILE=dev-requirements.txt
|
||||
REQUIREMENTS_OUT=dev-requirements.txt.log
|
||||
SETUP_OUT=*.egg-info
|
||||
VENV=.venv
|
||||
DEACTIVE=false
|
||||
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
### set virtualenv
|
||||
if [ -z "$VIRTUAL_ENV" ]; then
|
||||
virtualenv $VENV --no-site-packages --always-copy
|
||||
source $VENV/bin/activate
|
||||
DEACTIVE=true
|
||||
fi
|
||||
|
||||
### install dependencies
|
||||
pip install -r $REQUIREMENTS_FILE | tee -a $REQUIREMENTS_OUT
|
||||
python setup.py develop
|
||||
|
||||
### run tests
|
||||
tox
|
||||
|
||||
### static analysis of code
|
||||
flake8 --show-source petstore_api/
|
||||
|
||||
### deactivate virtualenv
|
||||
#if [ $DEACTIVE == true ]; then
|
||||
# deactivate
|
||||
#fi
|
||||
BIN
samples/client/petstore/python-tornado/testfiles/foo.png
Normal file
BIN
samples/client/petstore/python-tornado/testfiles/foo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
221
samples/client/petstore/python-tornado/tests/test_pet_api.py
Normal file
221
samples/client/petstore/python-tornado/tests/test_pet_api.py
Normal file
@@ -0,0 +1,221 @@
|
||||
# coding: utf-8
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
"""
|
||||
Run the tests.
|
||||
$ pip install nose (optional)
|
||||
$ cd petstore_api-python
|
||||
$ nosetests -v
|
||||
"""
|
||||
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from tornado.testing import AsyncTestCase, gen_test
|
||||
from tornado.ioloop import IOLoop
|
||||
|
||||
import petstore_api
|
||||
from petstore_api import Configuration
|
||||
from petstore_api.rest import ApiException
|
||||
|
||||
from .util import id_gen
|
||||
|
||||
import json
|
||||
|
||||
import urllib3
|
||||
|
||||
HOST = 'http://petstore.swagger.io/v2'
|
||||
|
||||
|
||||
class PetApiTests(AsyncTestCase):
|
||||
|
||||
def setUp(self):
|
||||
AsyncTestCase.setUp(self)
|
||||
config = Configuration()
|
||||
config.host = HOST
|
||||
self.api_client = petstore_api.ApiClient(config)
|
||||
self.pet_api = petstore_api.PetApi(self.api_client)
|
||||
self.setUpModels()
|
||||
self.setUpFiles()
|
||||
|
||||
def setUpModels(self):
|
||||
self.category = petstore_api.Category()
|
||||
self.category.id = id_gen()
|
||||
self.category.name = "dog"
|
||||
self.tag = petstore_api.Tag()
|
||||
self.tag.id = id_gen()
|
||||
self.tag.name = "swagger-codegen-python-pet-tag"
|
||||
self.pet = petstore_api.Pet(name="hello kity", photo_urls=["http://foo.bar.com/1", "http://foo.bar.com/2"])
|
||||
self.pet.id = id_gen()
|
||||
self.pet.status = "sold"
|
||||
self.pet.category = self.category
|
||||
self.pet.tags = [self.tag]
|
||||
|
||||
def setUpFiles(self):
|
||||
self.test_file_dir = os.path.join(os.path.dirname(__file__), "..", "testfiles")
|
||||
self.test_file_dir = os.path.realpath(self.test_file_dir)
|
||||
self.foo = os.path.join(self.test_file_dir, "foo.png")
|
||||
|
||||
def get_new_ioloop(self):
|
||||
return IOLoop.instance()
|
||||
|
||||
@gen_test
|
||||
def test_separate_default_client_instances(self):
|
||||
pet_api = petstore_api.PetApi()
|
||||
pet_api2 = petstore_api.PetApi()
|
||||
self.assertNotEqual(pet_api.api_client, pet_api2.api_client)
|
||||
|
||||
pet_api.api_client.user_agent = 'api client 3'
|
||||
pet_api2.api_client.user_agent = 'api client 4'
|
||||
|
||||
self.assertNotEqual(pet_api.api_client.user_agent, pet_api2.api_client.user_agent)
|
||||
|
||||
@gen_test
|
||||
def test_separate_default_config_instances(self):
|
||||
pet_api = petstore_api.PetApi()
|
||||
pet_api2 = petstore_api.PetApi()
|
||||
self.assertNotEqual(pet_api.api_client.configuration, pet_api2.api_client.configuration)
|
||||
|
||||
pet_api.api_client.configuration.host = 'somehost'
|
||||
pet_api2.api_client.configuration.host = 'someotherhost'
|
||||
self.assertNotEqual(pet_api.api_client.configuration.host, pet_api2.api_client.configuration.host)
|
||||
|
||||
@gen_test
|
||||
def test_async_request(self):
|
||||
# It works but tornado is async by default and creating threadpool
|
||||
# to do it looks crazy ;)
|
||||
thread = self.pet_api.add_pet(body=self.pet, async=True)
|
||||
response = yield thread.get()
|
||||
self.assertIsNone(response)
|
||||
|
||||
thread = self.pet_api.get_pet_by_id(self.pet.id, async=True)
|
||||
result = yield thread.get()
|
||||
self.assertIsInstance(result, petstore_api.Pet)
|
||||
|
||||
@gen_test
|
||||
def test_async_with_result(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
|
||||
thread = self.pet_api.get_pet_by_id(self.pet.id, async=True)
|
||||
thread2 = self.pet_api.get_pet_by_id(self.pet.id, async=True)
|
||||
|
||||
response = yield thread.get()
|
||||
response2 = yield thread2.get()
|
||||
|
||||
self.assertEquals(response.id, self.pet.id)
|
||||
self.assertIsNotNone(response2.id, self.pet.id)
|
||||
|
||||
@gen_test
|
||||
def test_tornado_async_with_result(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
|
||||
query1 = self.pet_api.get_pet_by_id(self.pet.id)
|
||||
query2 = self.pet_api.get_pet_by_id(self.pet.id)
|
||||
|
||||
response1 = yield query1
|
||||
response2 = yield query2
|
||||
|
||||
self.assertEquals(response1.id, self.pet.id)
|
||||
self.assertIsNotNone(response2.id, self.pet.id)
|
||||
|
||||
@gen_test
|
||||
def test_add_pet_and_get_pet_by_id(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
|
||||
fetched = yield self.pet_api.get_pet_by_id(pet_id=self.pet.id)
|
||||
self.assertIsNotNone(fetched)
|
||||
self.assertEqual(self.pet.id, fetched.id)
|
||||
self.assertIsNotNone(fetched.category)
|
||||
self.assertEqual(self.pet.category.name, fetched.category.name)
|
||||
|
||||
@gen_test
|
||||
def test_add_pet_and_get_pet_by_id_with_http_info(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
|
||||
fetched = yield self.pet_api.get_pet_by_id_with_http_info(pet_id=self.pet.id)
|
||||
self.assertIsNotNone(fetched)
|
||||
self.assertEqual(self.pet.id, fetched[0].id)
|
||||
self.assertIsNotNone(fetched[0].category)
|
||||
self.assertEqual(self.pet.category.name, fetched[0].category.name)
|
||||
|
||||
@gen_test
|
||||
def test_update_pet(self):
|
||||
self.pet.name = "hello kity with updated"
|
||||
yield self.pet_api.update_pet(body=self.pet)
|
||||
|
||||
fetched = yield self.pet_api.get_pet_by_id(pet_id=self.pet.id)
|
||||
self.assertIsNotNone(fetched)
|
||||
self.assertEqual(self.pet.id, fetched.id)
|
||||
self.assertEqual(self.pet.name, fetched.name)
|
||||
self.assertIsNotNone(fetched.category)
|
||||
self.assertEqual(fetched.category.name, self.pet.category.name)
|
||||
|
||||
@gen_test
|
||||
@unittest.skip('skipping the test as the method sometimes invalid Petstore object with incorrect status')
|
||||
def test_find_pets_by_status(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
pets = yield self.pet_api.find_pets_by_status(status=[self.pet.status])
|
||||
self.assertIn(
|
||||
self.pet.id,
|
||||
list(map(lambda x: getattr(x, 'id'), pets))
|
||||
)
|
||||
|
||||
@gen_test
|
||||
@unittest.skip("skipping the test as the method sometimes invalid Petstore object with incorrect status")
|
||||
def test_find_pets_by_tags(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
pets = yield self.pet_api.find_pets_by_tags(tags=[self.tag.name])
|
||||
self.assertIn(
|
||||
self.pet.id,
|
||||
list(map(lambda x: getattr(x, 'id'), pets))
|
||||
)
|
||||
|
||||
@gen_test
|
||||
def test_update_pet_with_form(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
|
||||
name = "hello kity with form updated"
|
||||
status = "pending"
|
||||
yield self.pet_api.update_pet_with_form(pet_id=self.pet.id, name=name, status=status)
|
||||
|
||||
fetched = yield self.pet_api.get_pet_by_id(pet_id=self.pet.id)
|
||||
self.assertEqual(self.pet.id, fetched.id)
|
||||
self.assertEqual(name, fetched.name)
|
||||
self.assertEqual(status, fetched.status)
|
||||
|
||||
@gen_test(timeout=10)
|
||||
def test_upload_file(self):
|
||||
# upload file with form parameter
|
||||
try:
|
||||
additional_metadata = "special"
|
||||
yield self.pet_api.upload_file(
|
||||
pet_id=self.pet.id,
|
||||
additional_metadata=additional_metadata,
|
||||
file=self.foo
|
||||
)
|
||||
except ApiException as e:
|
||||
self.fail("upload_file() raised {0} unexpectedly".format(type(e)))
|
||||
|
||||
# upload only file
|
||||
try:
|
||||
yield self.pet_api.upload_file(pet_id=self.pet.id, file=self.foo)
|
||||
except ApiException as e:
|
||||
self.fail("upload_file() raised {0} unexpectedly".format(type(e)))
|
||||
|
||||
@gen_test
|
||||
def test_delete_pet(self):
|
||||
yield self.pet_api.add_pet(body=self.pet)
|
||||
yield self.pet_api.delete_pet(pet_id=self.pet.id, api_key="special-key")
|
||||
|
||||
try:
|
||||
yield self.pet_api.get_pet_by_id(pet_id=self.pet.id)
|
||||
raise Exception("expected an error")
|
||||
except ApiException as e:
|
||||
self.assertEqual(404, e.status)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
unittest.main()
|
||||
8
samples/client/petstore/python-tornado/tests/util.py
Normal file
8
samples/client/petstore/python-tornado/tests/util.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# flake8: noqa
|
||||
|
||||
import random
|
||||
|
||||
|
||||
def id_gen(bits=32):
|
||||
""" Returns a n-bit randomly generated int """
|
||||
return int(random.getrandbits(bits))
|
||||
Reference in New Issue
Block a user