diff --git a/cornice_swagger/converters/schema.py b/cornice_swagger/converters/schema.py
index 343b357..45686cb 100644
--- a/cornice_swagger/converters/schema.py
+++ b/cornice_swagger/converters/schema.py
@@ -62,7 +62,7 @@ def convert_regex_validator(validator):
         converted = {}
 
         if hasattr(colander, 'url') and validator is colander.url:
-            converted['format'] = 'uri'
+            converted['format'] = 'url'
         elif isinstance(validator, colander.Email):
             converted['format'] = 'email'
         else:
@@ -96,7 +96,7 @@ class ValidatorConversionDispatcher(object):
         if isinstance(validator, colander.All):
             converted = {}
             for v in validator.validators:
-                ret = self(v)
+                ret = self(None, v)
                 converted.update(ret)
             return converted
         else:
diff --git a/cornice_swagger/swagger.py b/cornice_swagger/swagger.py
index 4fff44e..035a3d9 100644
--- a/cornice_swagger/swagger.py
+++ b/cornice_swagger/swagger.py
@@ -1,5 +1,6 @@
 """Cornice Swagger 2.0 documentor"""
 import re
+import six
 
 import colander
 from cornice.validators import colander_validator, colander_body_validator
@@ -100,7 +101,7 @@ class CorniceSwagger(object):
 
                     if default_tag not in [t['name'] for t in tags]:
                         tag = {'name': default_tag}
-                        if cornice_swagger.util.is_string(view):
+                        if isinstance(view, six.string_types):
                             ob = args['klass']
                             desc = cornice_swagger.util.trim(ob.__doc__)
                             tag['description'] = desc
@@ -198,7 +199,7 @@ class CorniceSwagger(object):
                 op['parameters'] = parameters
 
         # Get summary from docstring
-        if cornice_swagger.util.is_string(view):
+        if isinstance(view, six.string_types):
             if 'klass' in args:
                 ob = args['klass']
                 view_ = getattr(ob, view.lower())
@@ -308,7 +309,7 @@ class ParameterHandler(object):
 
         params = []
 
-        if not cornice_swagger.util.is_object(schema_node):
+        if not isinstance(schema_node, colander.Schema):
             schema_node = schema_node()
 
         if colander_validator in validators:
@@ -364,9 +365,6 @@ class ParameterHandler(object):
 
         name = base_name or param.get('title', '') or param.get('name', '')
 
-        if not name:
-            raise CorniceSwaggerException('Parameter needs a name')
-
         pointer = self.json_pointer + name
         self.parameters[name] = param
 
diff --git a/cornice_swagger/util.py b/cornice_swagger/util.py
index 7ff9f54..c896bf6 100644
--- a/cornice_swagger/util.py
+++ b/cornice_swagger/util.py
@@ -1,24 +1,8 @@
 import sys
-import inspect
 
 
 PY3 = sys.version_info[0] == 3
 
-if PY3:
-    builtin_str = str
-    str = str
-    bytes = bytes
-    basestring = (str, bytes)
-else:
-    builtin_str = str
-    bytes = str
-    str = unicode  # noqa
-    basestring = basestring
-
-
-def is_string(s):
-    return isinstance(s, basestring)
-
 
 def trim(docstring):
     """
@@ -32,54 +16,9 @@ def trim(docstring):
     # Convert tabs to spaces (following the normal Python rules)
     # and split into a list of lines:
     lines = docstring.expandtabs().splitlines()
-    # Determine minimum indentation (first line doesn't count):
-    indent = sys.maxsize
-    for line in lines[1:]:
-        stripped = line.lstrip()
-        if stripped:
-            indent = min(indent, len(line) - len(stripped))
-    # Remove indentation (first line is special):
-    trimmed = [lines[0].strip()]
-    if indent < sys.maxsize:
-        for line in lines[1:]:
-            trimmed.append(line[indent:].rstrip())
-    # Strip off trailing and leading blank lines:
-    while trimmed and not trimmed[-1]:
-        trimmed.pop()
-    while trimmed and not trimmed[0]:
-        trimmed.pop(0)
-    # Return a single string:
-    res = '\n'.join(trimmed)
-    if not PY3 and not isinstance(res, str):
-        res = res.decode('utf8')
+    res = '\n'.join(lines)
     return res
 
 
 def get_class_that_defined_method(meth):
-    if hasattr(meth, "im_class"):
-        return meth.im_class
-    if PY3:
-        if inspect.ismethod(meth):
-            for cls in inspect.getmro(meth.__self__.__class__):
-                if cls.__dict__.get(meth.__name__) is meth:
-                    return cls
-            # fallback to __qualname__ parsing
-            meth = meth.__func__
-        if inspect.isfunction(meth):
-            cls = getattr(
-                inspect.getmodule(meth),
-                meth.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0])
-            if isinstance(cls, type):
-                return cls
-    return None
-
-
-def is_object(obj):
-    if not hasattr(obj, '__dict__'):
-        return False
-    if inspect.isroutine(obj):
-        return False
-    if inspect.isclass(obj):
-        return False
-    else:
-        return True
+    return getattr(meth, 'im_class', None)

Reach and ensure 100% coverage
diff --git a/tests/converters/test_parameters.py b/tests/converters/test_parameters.py
index 3dd4ee9..60c4bf0 100644
--- a/tests/converters/test_parameters.py
+++ b/tests/converters/test_parameters.py
@@ -3,6 +3,7 @@ import unittest
 import colander
 
 from cornice_swagger.converters import convert_parameter, convert_schema
+from cornice_swagger.converters.exceptions import NoSuchConverter
 
 
 class ParameterConversionTest(unittest.TestCase):
@@ -51,3 +52,7 @@ class ParameterConversionTest(unittest.TestCase):
             'required': True,
             'schema': convert_schema(MyBody(title='MyBody')),
         })
+
+    def test_raise_no_such_converter_on_invalid_location(self):
+        node = colander.SchemaNode(colander.String(), name='foo')
+        self.assertRaises(NoSuchConverter, convert_parameter, 'aaa', node)
diff --git a/tests/converters/test_schema.py b/tests/converters/test_schema.py
index d432759..6fd9504 100644
--- a/tests/converters/test_schema.py
+++ b/tests/converters/test_schema.py
@@ -2,6 +2,28 @@ import unittest
 import colander
 
 from cornice_swagger.converters import convert_schema as convert
+from cornice_swagger.converters.exceptions import NoSuchConverter
+
+
+class ConversionTest(unittest.TestCase):
+
+    def test_validate_all(self):
+        node = colander.SchemaNode(colander.String(),
+                                   validator=colander.All(
+                                       colander.Length(12, 42),
+                                       colander.Regex(r'foo*bar')
+                                   ))
+        ret = convert(node)
+        self.assertDictEqual(ret, {
+            'type': 'string',
+            'pattern': 'foo*bar',
+            'maxLength': 42,
+            'minLength': 12,
+        })
+
+    def test_raise_no_such_converter_on_invalid_type(self):
+        node = colander.SchemaNode(dict)
+        self.assertRaises(NoSuchConverter, convert, node)
 
 
 class StringConversionTest(unittest.TestCase):
@@ -49,6 +71,15 @@ class StringConversionTest(unittest.TestCase):
             'format': 'email',
         })
 
+    def test_validate_regex_url(self):
+        node = colander.SchemaNode(colander.String(),
+                                   validator=colander.url)
+        ret = convert(node)
+        self.assertDictEqual(ret, {
+            'type': 'string',
+            'format': 'url',
+        })
+
     def test_validate_oneof(self):
         node = colander.SchemaNode(colander.String(),
                                    validator=colander.OneOf(["one", "two"]))
diff --git a/tests/support.py b/tests/support.py
new file mode 100644
index 0000000..72a995d
--- /dev/null
+++ b/tests/support.py
@@ -0,0 +1,23 @@
+import colander
+
+
+class MyNestedSchema(colander.MappingSchema):
+    my_precious = colander.SchemaNode(colander.Boolean())
+
+
+class BodySchema(colander.MappingSchema):
+    id = colander.SchemaNode(colander.String())
+    timestamp = colander.SchemaNode(colander.Int())
+    obj = MyNestedSchema()
+
+
+class QuerySchema(colander.MappingSchema):
+    foo = colander.SchemaNode(colander.String(), missing=colander.drop)
+
+
+class HeaderSchema(colander.MappingSchema):
+    bar = colander.SchemaNode(colander.String())
+
+
+class PathSchema(colander.MappingSchema):
+    meh = colander.SchemaNode(colander.String(), default='default')
diff --git a/tests/test_cornice_swagger.py b/tests/test_generate_swagger_spec.py
similarity index 100%
rename from tests/test_cornice_swagger.py
rename to tests/test_generate_swagger_spec.py
diff --git a/tests/test_parameter_handler.py b/tests/test_parameter_handler.py
index 29a9f30..d44b999 100644
--- a/tests/test_parameter_handler.py
+++ b/tests/test_parameter_handler.py
@@ -6,28 +6,7 @@ from cornice.validators import colander_validator, colander_body_validator
 
 from cornice_swagger.swagger import ParameterHandler
 from cornice_swagger.converters import convert_schema
-
-
-class MyNestedSchema(colander.MappingSchema):
-    my_precious = colander.SchemaNode(colander.Boolean())
-
-
-class BodySchema(colander.MappingSchema):
-    id = colander.SchemaNode(colander.String())
-    timestamp = colander.SchemaNode(colander.Int())
-    obj = MyNestedSchema()
-
-
-class QuerySchema(colander.MappingSchema):
-    foo = colander.SchemaNode(colander.String(), missing=colander.drop)
-
-
-class HeaderSchema(colander.MappingSchema):
-    bar = colander.SchemaNode(colander.String())
-
-
-class PathSchema(colander.MappingSchema):
-    meh = colander.SchemaNode(colander.String(), default='default')
+from .support import BodySchema, PathSchema, QuerySchema, HeaderSchema
 
 
 class SchemaParamConversionTest(unittest.TestCase):
diff --git a/tests/test_swagger.py b/tests/test_swagger.py
new file mode 100644
index 0000000..be08c4e
--- /dev/null
+++ b/tests/test_swagger.py
@@ -0,0 +1,171 @@
+import unittest
+
+import colander
+from cornice.validators import colander_validator
+from cornice.service import Service
+
+from cornice_swagger.swagger import CorniceSwagger
+from .support import BodySchema, QuerySchema
+
+
+class GetRequestSchema(colander.MappingSchema):
+    querystring = QuerySchema()
+
+
+class PutRequestSchema(colander.MappingSchema):
+    querystring = QuerySchema()
+    body = BodySchema()
+
+
+class TestCorniceSwaggerGenerator(unittest.TestCase):
+
+    def setUp(self):
+
+        service = Service("IceCream", "/icecream/{flavour}")
+
+        class IceCream(object):
+            """
+            Ice cream service
+            """
+
+            @service.get(validators=(colander_validator, ), schema=GetRequestSchema())
+            def view_get(self, request):
+                """Serve icecream"""
+                return self.request.validated
+
+            @service.put(validators=(colander_validator, ), schema=PutRequestSchema())
+            def view_put(self, request):
+                """Add flavour"""
+                return self.request.validated
+
+        self.service = service
+        self.swagger = CorniceSwagger([self.service])
+        self.spec = self.swagger('IceCreamAPI', '4.2')
+
+    def test_path(self):
+        self.assertIn('/icecream/{flavour}', self.spec['paths'])
+
+    def test_path_methods(self):
+        path = self.spec['paths']['/icecream/{flavour}']
+        self.assertIn('get', path)
+        self.assertIn('put', path)
+
+    def test_path_parameters(self):
+        parameters = self.spec['paths']['/icecream/{flavour}']['parameters']
+        self.assertEquals(len(parameters), 1)
+        self.assertEquals(parameters[0]['name'], 'flavour')
+
+    def test_path_default_tags(self):
+        tags = self.spec['paths']['/icecream/{flavour}']['get']['tags']
+        self.assertEquals(tags, ['icecream'])
+
+    def test_with_schema_ref(self):
+        swagger = CorniceSwagger([self.service], def_ref_depth=1)
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertIn('definitions', spec)
+
+    def test_with_param_ref(self):
+        swagger = CorniceSwagger([self.service], param_ref=True)
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertIn('parameters', spec)
+
+
+class TestExtractContentTypes(unittest.TestCase):
+
+    def test_json_renderer(self):
+
+        service = Service("IceCream", "/icecream/{flavour}")
+
+        class IceCream(object):
+            """Ice cream service"""
+            @service.get(validators=(colander_validator, ), schema=GetRequestSchema(),
+                         renderer='json')
+            def view_get(self, request):
+                """Serve icecream"""
+                return self.request.validated
+
+        swagger = CorniceSwagger([service])
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertEquals(spec['paths']['/icecream/{flavour}']['get']['produces'],
+                          set(['application/json']))
+
+    def test_xml_renderer(self):
+
+        service = Service("IceCream", "/icecream/{flavour}")
+
+        class IceCream(object):
+            """Ice cream service"""
+            @service.get(validators=(colander_validator, ), schema=GetRequestSchema(),
+                         renderer='xml')
+            def view_get(self, request):
+                """Serve icecream"""
+                return self.request.validated
+
+        swagger = CorniceSwagger([service])
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertEquals(spec['paths']['/icecream/{flavour}']['get']['produces'],
+                          set(['text/xml']))
+
+    def test_unkown_renderer(self):
+
+        service = Service("IceCream", "/icecream/{flavour}")
+
+        class IceCream(object):
+            """Ice cream service"""
+            @service.get(validators=(colander_validator, ), schema=GetRequestSchema(),
+                         renderer='')
+            def view_get(self, request):
+                """Serve icecream"""
+                return self.request.validated
+
+        swagger = CorniceSwagger([service])
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertNotIn('produces', spec['paths']['/icecream/{flavour}']['get'])
+
+    def test_ctypes(self):
+
+        service = Service("IceCream", "/icecream/{flavour}")
+
+        class IceCream(object):
+            """Ice cream service"""
+            @service.put(validators=(colander_validator, ), schema=GetRequestSchema(),
+                         content_type=['application/json'])
+            def view_put(self, request):
+                """Serve icecream"""
+                return self.request.validated
+
+        swagger = CorniceSwagger([service])
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertEquals(spec['paths']['/icecream/{flavour}']['put']['consumes'],
+                          set(['application/json']))
+
+    def test_multiple_views_with_different_ctypes(self):
+
+        service = Service("IceCream", "/icecream/{flavour}")
+
+        class IceCream(object):
+            """Ice cream service"""
+
+            def view_put(self, request):
+                """Serve icecream"""
+                return "red"
+
+        service.add_view(
+            "put",
+            IceCream.view_put,
+            validators=(colander_validator, ),
+            schema=PutRequestSchema(),
+            content_type=['application/json'],
+        )
+        service.add_view(
+            "put",
+            IceCream.view_put,
+            validators=(colander_validator, ),
+            schema=PutRequestSchema(),
+            content_type=['text/xml'],
+        )
+
+        swagger = CorniceSwagger([service])
+        spec = swagger('IceCreamAPI', '4.2')
+        self.assertEquals(spec['paths']['/icecream/{flavour}']['put']['produces'],
+                          set(['application/json']))

pip install -e .[test]
parse_log_pytest
requirements.txt
pytest flex
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi==2025.1.31
charset-normalizer==3.4.1
click==8.1.8
colander==2.0
cornice==6.1.0
-e git+https://github.com/Cornices/cornice.ext.swagger.git@1ee8267504d47acc13ba364f89f189b31c87b7ea#egg=cornice_swagger
coverage==7.8.0
exceptiongroup==1.2.2
flex==6.14.1
hupper==1.12.1
idna==3.10
iniconfig==2.1.0
iso8601==2.1.0
jsonpointer==3.0.0
packaging==24.2
PasteDeploy==3.1.0
plaster==1.1.2
plaster-pastedeploy==1.0.1
pluggy==1.5.0
pyramid==2.0.2
pytest==8.3.5
PyYAML==6.0.2
requests==2.32.3
rfc3987==1.3.8
six==1.17.0
strict-rfc3339==0.7
tomli==2.2.1
translationstring==1.4
urllib3==2.3.0
validate_email==1.3
venusian==3.1.1
WebOb==1.8.9
zope.deprecation==5.1
zope.interface==7.2

name: cornice.ext.swagger
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - click==8.1.8
      - colander==2.0
      - cornice==6.1.0
      - coverage==7.8.0
      - exceptiongroup==1.2.2
      - flex==6.14.1
      - hupper==1.12.1
      - idna==3.10
      - iniconfig==2.1.0
      - iso8601==2.1.0
      - jsonpointer==3.0.0
      - packaging==24.2
      - pastedeploy==3.1.0
      - plaster==1.1.2
      - plaster-pastedeploy==1.0.1
      - pluggy==1.5.0
      - pyramid==2.0.2
      - pytest==8.3.5
      - pyyaml==6.0.2
      - requests==2.32.3
      - rfc3987==1.3.8
      - six==1.17.0
      - strict-rfc3339==0.7
      - tomli==2.2.1
      - translationstring==1.4
      - urllib3==2.3.0
      - validate-email==1.3
      - venusian==3.1.1
      - webob==1.8.9
      - zope-deprecation==5.1
      - zope-interface==7.2
prefix: /opt/conda/envs/cornice.ext.swagger

tests/converters/test_schema.py::ConversionTest::test_validate_all tests/converters/test_schema.py::StringConversionTest::test_validate_regex_url
tests/converters/test_parameters.py::ParameterConversionTest::test_body tests/converters/test_parameters.py::ParameterConversionTest::test_header tests/converters/test_parameters.py::ParameterConversionTest::test_path tests/converters/test_parameters.py::ParameterConversionTest::test_query tests/converters/test_parameters.py::ParameterConversionTest::test_raise_no_such_converter_on_invalid_location tests/converters/test_schema.py::ConversionTest::test_raise_no_such_converter_on_invalid_type tests/converters/test_schema.py::StringConversionTest::test_description tests/converters/test_schema.py::StringConversionTest::test_sanity tests/converters/test_schema.py::StringConversionTest::test_title tests/converters/test_schema.py::StringConversionTest::test_validate_default tests/converters/test_schema.py::StringConversionTest::test_validate_length tests/converters/test_schema.py::StringConversionTest::test_validate_oneof tests/converters/test_schema.py::StringConversionTest::test_validate_regex tests/converters/test_schema.py::StringConversionTest::test_validate_regex_email tests/converters/test_schema.py::IntegerConversionTest::test_default tests/converters/test_schema.py::IntegerConversionTest::test_enum tests/converters/test_schema.py::IntegerConversionTest::test_range tests/converters/test_schema.py::IntegerConversionTest::test_sanity tests/converters/test_schema.py::DateTimeConversionTest::test_sanity tests/converters/test_schema.py::MappingConversionTest::test_nested_schema tests/converters/test_schema.py::MappingConversionTest::test_not_required tests/converters/test_schema.py::MappingConversionTest::test_open_schema tests/converters/test_schema.py::MappingConversionTest::test_required tests/converters/test_schema.py::MappingConversionTest::test_sanity tests/test_generate_swagger_spec.py::TestSwaggerService::test_declerative tests/test_generate_swagger_spec.py::TestSwaggerService::test_imperative tests/test_generate_swagger_spec.py::TestSwaggerService::test_schema_not_instantiated tests/test_generate_swagger_spec.py::TestSwaggerService::test_with_klass tests/test_generate_swagger_spec.py::TestSwaggerResource::test_resource tests/test_parameter_handler.py::SchemaParamConversionTest::test_convert_descriptions tests/test_parameter_handler.py::SchemaParamConversionTest::test_convert_multiple_with_request_validator_schema tests/test_parameter_handler.py::SchemaParamConversionTest::test_covert_body_with_request_validator_schema tests/test_parameter_handler.py::SchemaParamConversionTest::test_covert_headers_with_request_validator_schema tests/test_parameter_handler.py::SchemaParamConversionTest::test_covert_path_with_request_validator_schema tests/test_parameter_handler.py::SchemaParamConversionTest::test_covert_query_with_request_validator_schema tests/test_parameter_handler.py::SchemaParamConversionTest::test_covert_with_body_validator_schema tests/test_parameter_handler.py::SchemaParamConversionTest::test_sanity tests/test_parameter_handler.py::PathParamConversionTest::test_from_path tests/test_parameter_handler.py::RefParamTest::test_ref_from_body_validator_schema tests/test_parameter_handler.py::RefParamTest::test_ref_from_path tests/test_parameter_handler.py::RefParamTest::test_ref_from_request_validator_schema tests/test_swagger.py::TestCorniceSwaggerGenerator::test_path tests/test_swagger.py::TestCorniceSwaggerGenerator::test_path_default_tags tests/test_swagger.py::TestCorniceSwaggerGenerator::test_path_methods tests/test_swagger.py::TestCorniceSwaggerGenerator::test_path_parameters tests/test_swagger.py::TestCorniceSwaggerGenerator::test_with_param_ref tests/test_swagger.py::TestCorniceSwaggerGenerator::test_with_schema_ref tests/test_swagger.py::TestExtractContentTypes::test_ctypes tests/test_swagger.py::TestExtractContentTypes::test_json_renderer tests/test_swagger.py::TestExtractContentTypes::test_multiple_views_with_different_ctypes tests/test_swagger.py::TestExtractContentTypes::test_unkown_renderer tests/test_swagger.py::TestExtractContentTypes::test_xml_renderer
cornice_swagger/converters/schema.py cornice_swagger/util.py cornice_swagger/swagger.py
cornice_swagger/converters/schema.py cornice_swagger/util.py cornice_swagger/swagger.py