Rebased to current upstream/master. (#4514)

Tests for python client, comprising support for additional_properties and arrays.
There are ugly workarounds for when there are discriminators, since the python client generator does not fully handle them.
Cool indentation of test files.
This commit is contained in:
Michele Albano 2020-01-22 15:08:53 +01:00 committed by William Cheng
parent fc4563baef
commit bf57a9960d
12 changed files with 443 additions and 54 deletions

View File

@ -695,6 +695,184 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
return addRegularExpressionDelimiter(pattern);
}
@Override
public String toExampleValue(Schema schema) {
return toExampleValueRecursive(schema, new ArrayList<String>(), 5);
}
private String toExampleValueRecursive(Schema schema, List<String> included_schemas, int indentation) {
String indentation_string = "";
for (int i=0 ; i< indentation ; i++) indentation_string += " ";
String example = super.toExampleValue(schema);
// correct "true"s into "True"s, since super.toExampleValue uses "toString()" on Java booleans
if (ModelUtils.isBooleanSchema(schema) && null!=example) {
if ("false".equalsIgnoreCase(example)) example = "False";
else example = "True";
}
// correct "&#39;"s into "'"s after toString()
if (ModelUtils.isStringSchema(schema) && schema.getDefault() != null) {
example = (String) schema.getDefault();
}
if (StringUtils.isNotBlank(example) && !"null".equals(example)) {
if (ModelUtils.isStringSchema(schema)) {
example = "'" + example + "'";
}
return example;
}
if (schema.getEnum() != null && !schema.getEnum().isEmpty()) {
// Enum case:
example = schema.getEnum().get(0).toString();
if (ModelUtils.isStringSchema(schema)) {
example = "'" + escapeText(example) + "'";
}
if (null == example)
LOGGER.warn("Empty enum. Cannot built an example!");
return example;
} else if (null != schema.get$ref()) {
// $ref case:
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
String ref = ModelUtils.getSimpleRef(schema.get$ref());
if (allDefinitions != null) {
Schema refSchema = allDefinitions.get(ref);
if (null == refSchema) {
return "None";
} else {
String refTitle = refSchema.getTitle();
if (StringUtils.isBlank(refTitle) || "null".equals(refTitle)) {
refSchema.setTitle(ref);
}
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
return toExampleValueRecursive(refSchema, included_schemas, indentation);
}
} else {
LOGGER.warn("allDefinitions not defined in toExampleValue!\n");
}
}
if (ModelUtils.isDateSchema(schema)) {
example = "datetime.datetime.strptime('1975-12-30', '%Y-%m-%d').date()";
return example;
} else if (ModelUtils.isDateTimeSchema(schema)) {
example = "datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f')";
return example;
} else if (ModelUtils.isBinarySchema(schema)) {
example = "bytes(b'blah')";
return example;
} else if (ModelUtils.isByteArraySchema(schema)) {
example = "YQ==";
} else if (ModelUtils.isStringSchema(schema)) {
// a BigDecimal:
if ("Number".equalsIgnoreCase(schema.getFormat())) {return "1";}
if (StringUtils.isNotBlank(schema.getPattern())) return "'a'"; // I cheat here, since it would be too complicated to generate a string from a regexp
int len = 0;
if (null != schema.getMinLength()) len = schema.getMinLength().intValue();
if (len < 1) len = 1;
example = "";
for (int i=0;i<len;i++) example += i;
} else if (ModelUtils.isIntegerSchema(schema)) {
if (schema.getMinimum() != null)
example = schema.getMinimum().toString();
else
example = "56";
} else if (ModelUtils.isNumberSchema(schema)) {
if (schema.getMinimum() != null)
example = schema.getMinimum().toString();
else
example = "1.337";
} else if (ModelUtils.isBooleanSchema(schema)) {
example = "True";
} else if (ModelUtils.isArraySchema(schema)) {
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
ArraySchema arrayschema = (ArraySchema) schema;
example = "[\n" + indentation_string + toExampleValueRecursive(arrayschema.getItems(), included_schemas, indentation+1) + "\n" + indentation_string + "]";
} else if (ModelUtils.isMapSchema(schema)) {
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
Object additionalObject = schema.getAdditionalProperties();
if (additionalObject instanceof Schema) {
Schema additional = (Schema) additionalObject;
String the_key = "'key'";
if (additional.getEnum() != null && !additional.getEnum().isEmpty()) {
the_key = additional.getEnum().get(0).toString();
if (ModelUtils.isStringSchema(additional)) {
the_key = "'" + escapeText(the_key) + "'";
}
}
example = "{\n" + indentation_string + the_key + " : " + toExampleValueRecursive(additional, included_schemas, indentation+1) + "\n" + indentation_string + "}";
} else {
example = "{ }";
}
} else if (ModelUtils.isObjectSchema(schema)) {
if (StringUtils.isBlank(schema.getTitle())) {
example = "None";
return example;
}
// I remove any property that is a discriminator, since it is not well supported by the python generator
String toExclude = null;
if (schema.getDiscriminator()!=null) {
toExclude = schema.getDiscriminator().getPropertyName();
}
example = packageName + ".models." + underscore(schema.getTitle())+"."+schema.getTitle()+"(";
// if required only:
// List<String> reqs = schema.getRequired();
// if required and optionals
List<String> reqs = new ArrayList<String>();
for (Object toAdd : schema.getProperties().keySet())
reqs.add((String)toAdd);
Map<String, Schema> properties = schema.getProperties();
Set<String> propkeys = null;
if (properties != null) propkeys = properties.keySet();
if (toExclude != null && reqs.contains(toExclude)) {
reqs.remove(toExclude);
}
for (String toRemove : included_schemas) {
if (reqs.contains(toRemove)) {
reqs.remove(toRemove);
}
}
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
if (null != schema.getRequired()) for (Object toAdd : schema.getRequired()) {
reqs.add((String)toAdd);
}
if (null!=propkeys) for (String propname : propkeys) {
Schema schema2 = properties.get(propname);
if (reqs.contains(propname)) {
String refTitle = schema2.getTitle();
if (StringUtils.isBlank(refTitle) || "null".equals(refTitle)) {
schema2.setTitle(propname);
}
example += "\n" + indentation_string + underscore(propname) + " = "+
toExampleValueRecursive(schema2, included_schemas, indentation+1)+", ";
}
}
example +=")";
} else {
LOGGER.warn("Type " + schema.getType() + " not handled properly in toExampleValue");
}
if (ModelUtils.isStringSchema(schema)) {
example = "'" + escapeText(example) + "'";
}
return example;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;

View File

@ -5,6 +5,7 @@
from __future__ import absolute_import
import unittest
import datetime
{{#models}}
{{#model}}
@ -12,7 +13,6 @@ import {{packageName}}
from {{modelPackage}}.{{classFilename}} import {{classname}} # noqa: E501
from {{packageName}}.rest import ApiException
class Test{{classname}}(unittest.TestCase):
"""{{classname}} unit test stubs"""
@ -22,11 +22,31 @@ class Test{{classname}}(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test {{classname}}
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501
if include_optional :
return {{classname}}(
{{#vars}}
{{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}{{#hasMore}}, {{/hasMore}}
{{/vars}}
)
else :
return {{classname}}(
{{#vars}}
{{#required}}
{{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}},
{{/required}}
{{/vars}}
)
def test{{classname}}(self):
"""Test {{classname}}"""
# FIXME: construct object with mandatory attributes with example values
# model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
{{/model}}
{{/models}}

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.animal import Animal # noqa: E501
from petstore_api.rest import ApiException
class TestAnimal(unittest.TestCase):
"""Animal unit test stubs"""
@ -28,11 +28,26 @@ class TestAnimal(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test Animal
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.animal.Animal() # noqa: E501
if include_optional :
return Animal(
class_name = '0',
color = 'red'
)
else :
return Animal(
class_name = '0',
)
def testAnimal(self):
"""Test Animal"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.animal.Animal() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.cat import Cat # noqa: E501
from petstore_api.rest import ApiException
class TestCat(unittest.TestCase):
"""Cat unit test stubs"""
@ -28,11 +28,24 @@ class TestCat(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test Cat
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.cat.Cat() # noqa: E501
if include_optional :
return Cat(
declawed = True
)
else :
return Cat(
)
def testCat(self):
"""Test Cat"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.cat.Cat() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.category import Category # noqa: E501
from petstore_api.rest import ApiException
class TestCategory(unittest.TestCase):
"""Category unit test stubs"""
@ -28,11 +28,26 @@ class TestCategory(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test Category
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.category.Category() # noqa: E501
if include_optional :
return Category(
id = 56,
name = 'default-name'
)
else :
return Category(
name = 'default-name',
)
def testCategory(self):
"""Test Category"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.category.Category() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.enum_class import EnumClass # noqa: E501
from petstore_api.rest import ApiException
class TestEnumClass(unittest.TestCase):
"""EnumClass unit test stubs"""
@ -28,11 +28,23 @@ class TestEnumClass(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test EnumClass
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.enum_class.EnumClass() # noqa: E501
if include_optional :
return EnumClass(
)
else :
return EnumClass(
)
def testEnumClass(self):
"""Test EnumClass"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.enum_class.EnumClass() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.file import File # noqa: E501
from petstore_api.rest import ApiException
class TestFile(unittest.TestCase):
"""File unit test stubs"""
@ -28,11 +28,24 @@ class TestFile(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test File
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.file.File() # noqa: E501
if include_optional :
return File(
source_uri = '0'
)
else :
return File(
)
def testFile(self):
"""Test File"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.file.File() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.file_schema_test_class import FileSchemaTestClass # noqa: E501
from petstore_api.rest import ApiException
class TestFileSchemaTestClass(unittest.TestCase):
"""FileSchemaTestClass unit test stubs"""
@ -28,11 +28,29 @@ class TestFileSchemaTestClass(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test FileSchemaTestClass
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.file_schema_test_class.FileSchemaTestClass() # noqa: E501
if include_optional :
return FileSchemaTestClass(
file = petstore_api.models.file.File(
source_uri = '0', ),
files = [
petstore_api.models.file.File(
source_uri = '0', )
]
)
else :
return FileSchemaTestClass(
)
def testFileSchemaTestClass(self):
"""Test FileSchemaTestClass"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.file_schema_test_class.FileSchemaTestClass() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.format_test import FormatTest # noqa: E501
from petstore_api.rest import ApiException
class TestFormatTest(unittest.TestCase):
"""FormatTest unit test stubs"""
@ -28,11 +28,41 @@ class TestFormatTest(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test FormatTest
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.format_test.FormatTest() # noqa: E501
if include_optional :
return FormatTest(
integer = 1E+1,
int32 = 2E+1,
int64 = 56,
number = 32.1,
float = 54.3,
double = 67.8,
string = 'a',
byte = 'YQ==',
binary = bytes(b'blah'),
date = datetime.datetime.strptime('1975-12-30', '%Y-%m-%d').date(),
date_time = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
uuid = '72f98069-206d-4f12-9f12-3d1e525a8e84',
password = '0123456789',
big_decimal = 1
)
else :
return FormatTest(
number = 32.1,
byte = 'YQ==',
date = datetime.datetime.strptime('1975-12-30', '%Y-%m-%d').date(),
password = '0123456789',
)
def testFormatTest(self):
"""Test FormatTest"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.format_test.FormatTest() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.map_test import MapTest # noqa: E501
from petstore_api.rest import ApiException
class TestMapTest(unittest.TestCase):
"""MapTest unit test stubs"""
@ -28,11 +28,37 @@ class TestMapTest(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test MapTest
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.map_test.MapTest() # noqa: E501
if include_optional :
return MapTest(
map_map_of_string = {
'key' : {
'key' : '0'
}
},
map_of_enum_string = {
'UPPER' : 'UPPER'
},
direct_map = {
'key' : True
},
indirect_map = {
'key' : True
}
)
else :
return MapTest(
)
def testMapTest(self):
"""Test MapTest"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.map_test.MapTest() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.mixed_properties_and_additional_properties_class import MixedPropertiesAndAdditionalPropertiesClass # noqa: E501
from petstore_api.rest import ApiException
class TestMixedPropertiesAndAdditionalPropertiesClass(unittest.TestCase):
"""MixedPropertiesAndAdditionalPropertiesClass unit test stubs"""
@ -28,11 +28,30 @@ class TestMixedPropertiesAndAdditionalPropertiesClass(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test MixedPropertiesAndAdditionalPropertiesClass
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.mixed_properties_and_additional_properties_class.MixedPropertiesAndAdditionalPropertiesClass() # noqa: E501
if include_optional :
return MixedPropertiesAndAdditionalPropertiesClass(
uuid = '0',
date_time = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
map = {
'key' : petstore_api.models.animal.Animal(
class_name = '0',
color = 'red', )
}
)
else :
return MixedPropertiesAndAdditionalPropertiesClass(
)
def testMixedPropertiesAndAdditionalPropertiesClass(self):
"""Test MixedPropertiesAndAdditionalPropertiesClass"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.mixed_properties_and_additional_properties_class.MixedPropertiesAndAdditionalPropertiesClass() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
@ -13,12 +13,12 @@
from __future__ import absolute_import
import unittest
import datetime
import petstore_api
from petstore_api.models.pet import Pet # noqa: E501
from petstore_api.rest import ApiException
class TestPet(unittest.TestCase):
"""Pet unit test stubs"""
@ -28,11 +28,41 @@ class TestPet(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional):
"""Test Pet
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# model = petstore_api.models.pet.Pet() # noqa: E501
if include_optional :
return Pet(
id = 56,
category = petstore_api.models.category.Category(
id = 56,
name = 'default-name', ),
name = 'doggie',
photo_urls = [
'0'
],
tags = [
petstore_api.models.tag.Tag(
id = 56,
name = '0', )
],
status = 'available'
)
else :
return Pet(
name = 'doggie',
photo_urls = [
'0'
],
)
def testPet(self):
"""Test Pet"""
# FIXME: construct object with mandatory attributes with example values
# model = petstore_api.models.pet.Pet() # noqa: E501
pass
inst_req_only = self.make_instance(include_optional=False)
inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':