reorganize tests - run on installed suds version + do not require py2to3

The test suite is no longer installed together with the project and can now be
run from the project's source distribution. This resolves the issue of the suds
test suite confusing users by getting installed as a top level tests package in
their Python environment.

Project to be tested now need to be explicitly installed prior to running its
tests using pytest, except in case of Python 2 tests being run from the top
level project folder. This requires the user to install the project (suggested
way is to install it in editable mode using 'pip install -e') but also allows
him to run the tests on other non-sandbox project versions, e.g. an externally
installed version.

Project testing now requires the six Python 2/3 compatibility support package
(installed automatically, together with other test requirements).
Test support code now moved to a separate testutils package located under the
tests folder.
Updated project README.rst & HACKING.rst docs.
Minor stylistic changes.
This commit is contained in:
Jurko Gospodnetić 2014-05-17 14:08:18 +02:00
parent 34bcf2a476
commit 1618ae351f
30 changed files with 729 additions and 517 deletions

View File

@ -102,7 +102,7 @@ TOP-LEVEL PROJECT FILES & FOLDERS
module search path) the same as if installed using ``easy_install -e`` or
``pip install -e``
``setup.py test``
run the project's test suite (requires ``pytest``)
run the project test suite (requires ``pytest``)
PYTHON COMPATIBILITY
@ -114,6 +114,10 @@ states aiming for Python 2.4 compatibility we should do so as well.
The Python 3.0 minor release is not supported. See `Python 3.0 support`_
subsection below for more detailed information.
Test & setup code needs to be implemented using Python 2 & 3 compatible source
code. Setup & setup related scripts need to be implemented so they do not rely
on other pre-installed libraries.
These backward compatibility requirements do not affect internal development
operations such as ``setup.py`` support for uploading a new project distribution
package to PyPI. Such operations need to be supported on the latest Python 2 & 3
@ -286,25 +290,23 @@ respectively.
Setting up the development & testing environment
------------------------------------------------
``tools/setup_base_environments.py`` script should be used for setting up your
basic Python environments so they support testing our project. The script can
be configured configured from the main project Python configuration file
``setup.cfg``. It implements all the backward compatibility tweaks that would
otherwise need to be done manually in order to be able to test our project in
those environments. These tweaks are no longer documented elsewhere so anyone
interested in the details should consult the script's sources.
``tools/setup_base_environments.py`` script should be used for setting up the
basic Python environments so they support testing our project. The script can be
configured from the main project Python configuration file ``setup.cfg``. It
implements all the backward compatibility tweaks and performs additional
required package installation that would otherwise need to be done manually in
order to be able to test our project in those environments.
Project's test suite requires the ``pytest`` testing framework to run. The test
code base is compatible with pytest 2.4.0+ (prior versions do not support
non-string ``skipif`` expressions).
These exact requirements and their related version specific tweaks are not
documented elsewhere so anyone interested in the details should consult the
script's sources.
The testing environment is generally set up as follows:
1. Install Python.
#. Install ``setuptools`` (using ``setup_ez.py`` or from its source
distribution).
#. Install ``pip`` using ``setuptools`` (optional).
#. Install ``pytest`` using ``pip`` or ``setuptools``.
1. Install clean target Python environments.
#. Update the project's ``setup.py`` configuration with information on your
installed Python environments.
#. Run the ``tools/setup_base_environments.py`` script.
Some older Python environments may have slight issues caused by varying support
levels in different used Python packages, but the basic testing functionality
@ -313,53 +315,151 @@ possible.
Examples of such issues:
* Colors not getting displayed on a Windows console terminal, and possibly
ANSI color code escape sequences getting displayed instead.
* ``pip`` utility not being runnable from the command-line using the ``py -m
pip`` syntax for some older versions.
* Some specific older Python versions having no SSL support and so must reuse
installations downloaded by other Python versions.
* Colors not getting displayed on a Windows console terminal, with possibly ANSI
color code escape sequences getting displayed instead.
* ``pip`` utility can not be run from the command-line using the ``py -m pip``
syntax for some older versions. In such cases use the more portable ``py -c
"import pip;pip.main()"`` syntax instead.
* Some specific older Python versions (e.g. 2.4.3) have no SSL support and so
have to reuse installations downloaded by other Python versions.
Running the project tests
-------------------------
Running the project tests - ``tools/run_all_tests.cmd`` script
--------------------------------------------------------------
``tools/run_all_tests.cmd`` script is a basic *poor man's tox* development
script that can be used for running the full project test suite using multiple
Python interpreter versions on a Windows development machine. It is intended to
be replaced by a more portable ``tox`` based or similar automated testing
solution some time in the future.
Python interpreter versions on a Windows development machine.
To run all of the project unit tests with a specific interpreter without
additional configuration options run the project's ``setup.py`` script with the
'test' parameter and an appropriate Python interpreter. E.g. run any of the
following from the top level project folder::
Intended to be replaced by a more portable ``tox`` based or similar automated
testing solution some time in the future.
Can be configured by tweaking the script's sources directly:
* List of target Python environments.
* Each target Python environment's invocation command.
Requires the target Python environment already be set up, and all the packages
required for running the project test suite installed. See the `Setting up the
development & testing environment`_ section for more detailed information.
Automatically installs the project in editable mode in all tested Python
environments.
Caveats:
* This method does not allow you to provide any extra ``pytest`` options when
running the project test suite.
Running the project tests - ``setup.py test`` command
-----------------------------------------------------
Project tests can also be run for a specific Python environment by running the
project's ``setup.py`` script in that environment and invoking its ``test``
command. E.g. run a command like one of the following ones from the top level
project folder::
py243 setup.py test
py27 setup.py test
py3 setup.py test
To have more control over the test suite and be able to specify additional
``pytest`` options on the command-line, run it from the top level project folder
using ``pytest``, e.g.
Note that the ``setup.py`` script always needs to be called from the top level
project folder.
* Using a Python 2.x interpreter::
For most Python versions, the target Python environment needs not be set up
prior to running this command. Where possible (e.g. not for Python 2.4.x or
3.1.x versions), any missing testing requirements will be installed
automatically, but not directly into the target environment but in the current
folder instead. This functionality should be considered a band-aid though, and
setting up the target environment can be better done as described in the
`Setting up the development & testing environment`_ section.
py2 -m pytest
The ``setup.py test`` command will build the project if needed and run its
complete test suite in the target Python environment. The project does not need
to be preinstalled into the target Python environment for this operation to
work, and neither will the operation leave it installed.
* Using a Python 3.x interpreter::
Caveats:
py3 setup.py build & py3 -m pytest build
* This method does not allow you to provide any extra ``pytest`` options when
running the project test suite.
In both cases, tests run using Python interpreter version 3.x will be run in the
build folder constructed by the ``setup.py`` script running the ``py2to3`` tool
on the project's sources.
Running the project tests - using ``pytest`` directly
-----------------------------------------------------
You might need to manually remove the build folder in order to have its contents
regenerated when wanting to run the test suite using a different Python 3.x
interpreter version, as those sources are regenerated based solely on the
original & processed source file timestamp information and not the Python
version used to process them.
To have greater control over the test suite and be able to specify additional
``pytest`` options on the command-line, or be able to run the tests on a
different project installation (e.g. official release installed directly from
PyPI), do the following:
1. Install the project into the target Python environment.
* Installing the project can be done by either installing it directly into the
target Python environment using one of the following commands (paths used
assume the commands are being run from the top level project folder)::
setup.py install
easy_install .
pip install .
Or the project can be installed in editable mode using one of the following
commands (so it does not need to be reinstalled after every source code
change)::
setup.py develop
easy_install -e .
pip install -e .
* The installation step can be skipped if running Python 2 based project
tests, and doing so from the top level project folder.
2. Run tests using ``pytest``.
* If using Python 2.x:
* Run ``pytest`` from the project's top level or ``tests`` folder::
py2 -m pytest
* If using Python 3.x:
* Since the project uses py2to3 source conversion, you need to build the
project in order to generate the project's Python 3 sources before they
can be tested. If the project has been installed in editable mode, then
simply run the following from the top level project folder::
setup.py build
and if it has not then rebuild and reinstall it using one of the following
commands::
setup.py develop
setup.py install
Note that you might need to manually remove the build folder in order to
have its contents regenerated when wanting to run the test suite using a
different Python 3.x interpreter version, as those sources are regenerated
based solely on the original & processed source file timestamp information
and not the Python version used to process them.
* Run ``pytest`` from the the project's ``tests`` folder::
py3 -m pytest
Each specific test module can also be run directly as a script.
Notes on the folder from which to run the tests:
* When running tests from a folder other than the top level project folder, the
tested project version needs to first be installed in the used Python
environment.
* Python 2 tests can be run from the top level project folder, in which case
they will work even if the project has not been explicitly installed in the
used Python environment. And even if another project version has been
installed into the used Python environment, that one will be ignored and the
one in the current folder used instead.
* Python 3 tests can not be run from the top level project folder or they would
attempt and fail to use Python 2 based project sources found in the current
folder.
See the ``pytest`` documentation for a detailed list of available command-line
options. Some interesting ones:

View File

@ -15,6 +15,9 @@ include TODO.txt
include notes/*.rst
include notes/*.txt
# Tests.
recursive-include tests *.py
# Tools.
prune tools/__* # local cache folders
include tools/*.cmd

View File

@ -54,6 +54,9 @@ Here are the basic instructions for 3 different installation methods:
Installation troubleshooting:
-----------------------------
* Released prior to ``0.7`` have many known installation issues requiring the
target Python environment to be manually prepared when using some ancient
Python versions, e.g. 2.4, 2.5 or 3.1.
* Releases ``0.4.1. jurko 5 < x <= 0.6`` may not be installed using ``pip`` into
a Python environment with an already installed ``setuptools`` package older
than the version expected by our project. Displayed error message includes
@ -323,6 +326,9 @@ version 0.7 (development)
effectively just leaving the installed ``setuptools`` package with one
defective test module, but fully operational at run-time.
* When installing the project into a Window Python 2.5 environment, you no
longer need to manually install a compatible ``colorama`` package versions
in order to be able to run the project tests.
* Package meta-data may now contain non-ASCII characters on platforms where
that is allowed, namely with all Python versions except Python 3.x prior to
3.2.2.
@ -335,12 +341,21 @@ version 0.7 (development)
* Test suite improvements.
* Test suite no longer installed together with the project, thus no longer
causing confusion by existing in the target Python environment as a global
``tests`` package.
* The tests may now be run from the source archive, and will always run on
the suds version found installed in the used Python environment.
* Refactored the quick & dirty batch script used to run all the project tests
in multiple Python environments to remove much code duplication.
* Automated project testing in several additional Python environment versions.
* Added more detailed XSD modeling tests.
* Added tests demonstrating how additional or replacement built-in XSD types
can be registered with suds.
* All project tests now using Python 2 & 3 compatible source code and so no
longer need to be built separately for Python 3.
* Added new and updated existing ``suds.cache`` module related tests.
* Documented that all ``pytest`` test parametrizations should be prepared so
they get ordered the same on all test runs. See ``Project implementation

View File

@ -533,6 +533,13 @@ def test_requirements():
import argparse
except ImportError:
result.append("argparse")
# 'six' release 1.5 broke compatibility with Python 2.4.x.
if sys.version_info < (2, 5):
result.append("six<1.5")
else:
result.append("six")
return result
test_error = None
@ -575,15 +582,8 @@ else:
self.test_suite = True
def run_tests(self):
# Make sure the tests are run on the correct test sources. E.g.
# when using Python 3, the tests need to be run in the build folder
# where they have been previously processed using py2to3. Running
# them directly on the original source tree would fail due to
# Python 2/3 source code incompatibility.
ei_cmd = self.get_finalized_command("egg_info")
build_path = _normalize_path(ei_cmd.egg_base)
import pytest
sys.exit(pytest.main(["--pyargs", build_path]))
sys.exit(pytest.main(["--pyargs", "tests"]))
distutils_cmdclass["test"] = TestCommand
@ -685,7 +685,7 @@ setup(
keywords=["SOAP", "web", "service", "client"],
url=project_url,
download_url=download_url,
packages=recursive_package_list("suds", "tests"),
packages=recursive_package_list("suds"),
author="Jeff Ortel",
author_email="jortel@redhat.com",

View File

@ -28,4 +28,4 @@ pytest configuration file for the suds test suite.
# folder constructed by 'setup.py build' using 'py.test build --markers'. The
# plugin will still get loaded correctly when actually running the tests. This
# has already been reported as a pytest issue.
pytest_plugins = "tests.indirect_parametrize"
pytest_plugins = "testutils.indirect_parametrize"

View File

@ -27,14 +27,12 @@ specific to a particular web service operation binding.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import suds.argparser
import tests
import pytest
@ -148,7 +146,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
</wsdl:service>
</wsdl:definitions>
""" % (binding_style,))
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
pytest.raises(MyException, client.service.f)
pytest.raises(MyException, client.service.f, "x")
pytest.raises(MyException, client.service.f, "x", "y")
@ -198,7 +196,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
</wsdl:service>
</wsdl:definitions>
""" % (binding_style,))
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
pytest.raises(MyException, client.service.f)
pytest.raises(MyException, client.service.f, "x")
pytest.raises(MyException, client.service.f, "x", "y")
@ -607,4 +605,4 @@ def _expect_error(expected_exception, expected_error_text, test_function,
else:
assert str(e) == expected_error_text
finally:
del e
del e # explicitly break circular reference chain in Python 3

View File

@ -22,17 +22,16 @@ Implemented using the 'pytest' testing framework.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import suds.cache
import suds.sax.parser
import tests
import pytest
from six import b, next, u
import datetime
import os
@ -164,16 +163,18 @@ class MockPickleLoad:
# Hardcoded values used in different caching test cases.
value_empty = suds.byte_str("")
value_f2 = suds.byte_str("fifi2")
value_f22 = suds.byte_str("fifi22")
value_f3 = suds.byte_str("fifi3")
value_p1 = suds.byte_str("pero1")
value_p11 = suds.byte_str("pero11")
value_p111 = suds.byte_str("pero111")
value_p2 = suds.byte_str("pero2")
value_p22 = suds.byte_str("pero22")
value_unicode = suds.byte_str(u"€ 的 čćžšđČĆŽŠĐ")
value_empty = b("")
value_f2 = b("fifi2")
value_f22 = b("fifi22")
value_f3 = b("fifi3")
value_p1 = b("pero1")
value_p11 = b("pero11")
value_p111 = b("pero111")
value_p2 = b("pero2")
value_p22 = b("pero22")
value_unicode = u("\u20AC \u7684 "
"\u010D\u0107\u017E\u0161\u0111"
"\u010C\u0106\u017D\u0160\u0110").encode("utf-8")
# FileCache item expiration test data - duration, current_time, expect_remove.
@ -214,8 +215,11 @@ def test_Cache_methods_abstract(monkeypatch, method_name, params):
cache = suds.cache.Cache()
f = getattr(cache, method_name)
e = pytest.raises(Exception, f, *params).value
assert e.__class__ is Exception
assert str(e) == "not-implemented"
try:
assert e.__class__ is Exception
assert str(e) == "not-implemented"
finally:
del e # explicitly break circular reference chain in Python 3
class TestDefaultFileCacheLocation:
@ -313,7 +317,7 @@ check_cache_folder(True, 1, "final caches with default location")
"fake_cache_folder": fake_cache_folder})
assert not os.path.exists(cache_folder)
tests.run_test_process(test_file)
testutils.run_test_process(test_file)
@pytest.mark.parametrize("removal_enabled", (True, False))
def test_remove_on_exit(self, tmpdir, removal_enabled):
@ -363,14 +367,14 @@ if not os.path.isdir(cache_folder):
""" % {"cache_folder": cache_folder, "removal_enabled": removal_enabled})
assert not os.path.exists(cache_folder)
tests.run_test_process(test_file)
testutils.run_test_process(test_file)
if removal_enabled:
assert not os.path.exists(cache_folder)
else:
assert os.path.isdir(cache_folder)
# TODO: DocumentCache class interface seems silly. Its get() operation returns
#TODO: DocumentCache class interface seems silly. Its get() operation returns
# an XML document while its put() operation takes an XML element. The put()
# operation also silently ignores passed data of incorrect type.
class TestDocumentCache:
@ -392,7 +396,7 @@ class TestDocumentCache:
Constructed content may be parametrized with the given element name.
"""
# TODO: Update the tests in this group to no longer depend on the exact
#TODO: Update the tests in this group to no longer depend on the exact
# input XML data formatting. They currently expect it to be formatted
# exactly as what gets read back from their DocumentCache.
content = suds.byte_str("""\
@ -885,13 +889,19 @@ def test_NoCache(monkeypatch):
cache.put("id", "something")
assert cache.get("id") == None
# TODO: It should not be an error to call clear() or purge() on a NoCache
#TODO: It should not be an error to call clear() or purge() on a NoCache
# instance.
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(Exception, cache.purge, "id").value
assert str(e) == "not-implemented"
try:
assert str(e) == "not-implemented"
finally:
del e # explicitly break circular reference chain in Python 3
e = pytest.raises(Exception, cache.clear).value
assert str(e) == "not-implemented"
try:
assert str(e) == "not-implemented"
finally:
del e # explicitly break circular reference chain in Python 3
class TestObjectCache:
@ -1015,7 +1025,7 @@ def _assert_empty_cache_folder(folder, expected=True):
assert os.path.isdir(folder)
def walk_error(error):
pytest.fail("Error walking through cache folder content.")
root, folders, files = os.walk(folder, onerror=walk_error).next()
root, folders, files = next(os.walk(folder, onerror=walk_error))
assert root == folder
empty = len(folders) == 0 and len(files) == 1 and files[0] == 'version'
if expected:

View File

@ -22,21 +22,19 @@ Implemented using the 'pytest' testing framework.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import suds.cache
import suds.store
import suds.transport
import suds.transport.https
import tests
import pytest
import httplib
from six import iteritems, itervalues, next
from six.moves import http_client
class MyException(Exception):
@ -147,7 +145,7 @@ class MockTransport(suds.transport.Transport):
self.mock_log.append(("send", [request.url, request.message]))
if not self.mock_send_data:
pytest.fail("Unexpected MockTransport.send() operation call.")
status = httplib.OK
status = http_client.OK
headers = {}
data = self.__next_operation_result(self.mock_send_data)
return suds.transport.Reply(status, headers, data)
@ -169,7 +167,7 @@ class MockTransport(suds.transport.Transport):
#TODO: Once a WSDL import bug illustrated by test_WSDL_import() is fixed, this
# test data may be simplified to just:
# > wsdl_target_namespace = "bingo-bongo"
# > wsdl = tests.wsdl("", wsdl_target_namespace=wsdl_target_namespace)
# > wsdl = testutils.wsdl("", wsdl_target_namespace=wsdl_target_namespace)
# > wsdl_wrapper = suds.byte_str("""\
# > <?xml version='1.0' encoding='UTF-8'?>
# > <definitions targetNamespace="%(tns)s"
@ -256,7 +254,7 @@ class TestCacheStoreTransportUsage:
cache=cache, documentStore=store1, transport=MockTransport())
assert store1.mock_log == ["suds://wsdl", "suds://wsdl_imported"]
assert len(cache.mock_data) == 1
wsdl_object_id, wsdl_object = cache.mock_data.items()[0]
wsdl_object_id, wsdl_object = next(iteritems(cache.mock_data))
assert wsdl_object.__class__ is suds.wsdl.Definitions
# Reuse from cache.
@ -270,7 +268,7 @@ class TestCacheStoreTransportUsage:
def test_avoid_external_XSD_fetching(self):
# Prepare document content.
xsd_target_namespace = "balancana"
wsdl = tests.wsdl("""\
wsdl = testutils.wsdl("""\
<xsd:import schemaLocation="suds://imported_xsd"/>
<xsd:include schemaLocation="suds://included_xsd"/>""",
xsd_target_namespace=xsd_target_namespace)
@ -291,7 +289,7 @@ class TestCacheStoreTransportUsage:
assert store1.mock_log == ["suds://wsdl", "suds://imported_xsd",
"suds://included_xsd"]
assert len(cache.mock_data) == 1
wsdl_object_id, wsdl_object = cache.mock_data.items()[0]
wsdl_object_id, wsdl_object = next(iteritems(cache.mock_data))
assert wsdl_object.__class__ is suds.wsdl.Definitions
# Reuse from cache.
@ -393,7 +391,7 @@ class TestCacheStoreTransportUsage:
# Add to cache, making sure the WSDL schema is read from the document
# store and not fetched using the client's registered transport.
cache = MockCache()
store1 = MockDocumentStore(umpala=tests.wsdl(""))
store1 = MockDocumentStore(umpala=testutils.wsdl(""))
c1 = suds.client.Client("suds://umpala", cachingpolicy=caching_policy,
cache=cache, documentStore=store1, transport=MockTransport())
assert [x for x, y in cache.mock_log] == ["get", "put"]
@ -402,12 +400,12 @@ class TestCacheStoreTransportUsage:
assert len(cache.mock_data) == 1
if caching_policy == 0:
# Cache contains SAX XML documents.
wsdl_document = cache.mock_data.values()[0]
wsdl_document = next(itervalues(cache.mock_data))
assert wsdl_document.__class__ is suds.sax.document.Document
wsdl_cached_root = wsdl_document.root()
else:
# Cache contains complete suds WSDL objects.
wsdl = cache.mock_data.values()[0]
wsdl = next(itervalues(cache.mock_data))
assert wsdl.__class__ is suds.wsdl.Definitions
wsdl_cached_root = wsdl.root
assert c1.wsdl.root is wsdl_cached_root
@ -442,7 +440,7 @@ class TestCacheStoreTransportUsage:
"""
# Prepare document content.
xsd_target_namespace = "my xsd namespace"
wsdl = tests.wsdl('<xsd:%s schemaLocation="suds://external"/>' % (
wsdl = testutils.wsdl('<xsd:%s schemaLocation="suds://external"/>' % (
external_reference_tag,),
xsd_target_namespace=xsd_target_namespace)
external_schema = suds.byte_str("""\
@ -554,8 +552,11 @@ class TestCacheUsage:
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(AttributeError, suds.client.Client,
"suds://some_URL", cache=cache).value
expected_error = '"cache" must be: (%r,)'
assert str(e) == expected_error % (suds.cache.Cache,)
try:
expected_error = '"cache" must be: (%r,)'
assert str(e) == expected_error % (suds.cache.Cache,)
finally:
del e # explicitly break circular reference chain in Python 3
class TestStoreUsage:
@ -566,15 +567,18 @@ class TestStoreUsage:
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(AttributeError, suds.client.Client,
"suds://some_URL", documentStore=store, cache=None).value
expected_error = '"documentStore" must be: (%r,)'
assert str(e) == expected_error % (suds.store.DocumentStore,)
try:
expected_error = '"documentStore" must be: (%r,)'
assert str(e) == expected_error % (suds.store.DocumentStore,)
finally:
del e # explicitly break circular reference chain in Python 3
class TestTransportUsage:
"""suds.client.Client transport component usage tests."""
def test_default_transport(self):
client = tests.client_from_wsdl(tests.wsdl(""))
client = testutils.client_from_wsdl(testutils.wsdl(""))
expected = suds.transport.https.HttpAuthenticated
assert client.options.transport.__class__ is expected
@ -586,12 +590,15 @@ class TestTransportUsage:
transport = MockTransport(open_data=exception)
e_info = pytest.raises(exception.__class__, suds.client.Client, "url",
cache=None, transport=transport)
assert e_info.value is exception
try:
assert e_info.value is exception
finally:
del e_info # explicitly break circular reference chain in Python 3
def test_error_on_send__non_transport(self):
e = MyException()
t = MockTransport(send_data=e)
store = MockDocumentStore(wsdl=tests.wsdl("", operation_name="g"))
store = MockDocumentStore(wsdl=testutils.wsdl("", operation_name="g"))
client = suds.client.Client("suds://wsdl", documentStore=store,
cache=None, transport=t)
assert pytest.raises(MyException, client.service.g).value is e
@ -610,24 +617,27 @@ class TestTransportUsage:
def test_error_on_send__transport(self, monkeypatch):
monkeypatch.delitem(locals(), "e", False)
t = MockTransport(send_data=suds.transport.TransportError("huku", 666))
store = MockDocumentStore(wsdl=tests.wsdl("", operation_name="g"))
store = MockDocumentStore(wsdl=testutils.wsdl("", operation_name="g"))
client = suds.client.Client("suds://wsdl", documentStore=store,
cache=None, transport=t)
e = pytest.raises(Exception, client.service.g).value
assert e.__class__ is Exception
assert e.args == ((666, "huku"),)
try:
assert e.__class__ is Exception
assert e.args == ((666, "huku"),)
finally:
del e # explicitly break circular reference chain in Python 3
def test_nosend_should_avoid_transport_sends(self):
wsdl = tests.wsdl("")
wsdl = testutils.wsdl("")
t = MockTransport()
client = tests.client_from_wsdl(wsdl, nosend=True, transport=t)
client = testutils.client_from_wsdl(wsdl, nosend=True, transport=t)
client.service.f()
def test_operation_request_and_reply(self):
xsd_content = '<xsd:element name="Data" type="xsd:string"/>'
web_service_URL = "Great minds think alike"
xsd_target_namespace = "omicron psi"
wsdl = tests.wsdl(suds.byte_str(xsd_content), operation_name="pi",
wsdl = testutils.wsdl(suds.byte_str(xsd_content), operation_name="pi",
xsd_target_namespace=xsd_target_namespace, input="Data",
output="Data", web_service_URL=web_service_URL)
test_input_data = "Riff-raff"
@ -657,13 +667,16 @@ class TestTransportUsage:
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(AttributeError, suds.client.Client,
"suds://some_URL", transport=transport, cache=None).value
expected_error = '"transport" must be: (%r,)'
assert str(e) == expected_error % (suds.transport.Transport,)
try:
expected_error = '"transport" must be: (%r,)'
assert str(e) == expected_error % (suds.transport.Transport,)
finally:
del e # explicitly break circular reference chain in Python 3
@pytest.mark.parametrize("url", test_URL_data)
def test_WSDL_transport(self, url):
store = MockDocumentStore()
t = MockTransport(open_data=tests.wsdl(""))
t = MockTransport(open_data=testutils.wsdl(""))
suds.client.Client(url, cache=None, documentStore=store, transport=t)
assert t.mock_log == [("open", [url])]
@ -682,7 +695,7 @@ class TestTransportUsage:
def test_external_XSD_transport(self, url, external_reference_tag):
xsd_content = '<xsd:%(tag)s schemaLocation="%(url)s"/>' % dict(
tag=external_reference_tag, url=url)
store = MockDocumentStore(wsdl=tests.wsdl(xsd_content))
store = MockDocumentStore(wsdl=testutils.wsdl(xsd_content))
t = MockTransport(open_data=suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"/>
@ -695,7 +708,7 @@ class TestTransportUsage:
@pytest.mark.xfail(reason="WSDL import buggy")
def test_WSDL_import():
wsdl_target_namespace = "bingo-bongo"
wsdl = tests.wsdl("", wsdl_target_namespace=wsdl_target_namespace)
wsdl = testutils.wsdl("", wsdl_target_namespace=wsdl_target_namespace)
wsdl_wrapper = suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<definitions targetNamespace="%(tns)s"

View File

@ -23,10 +23,11 @@ CompareSAX testing utility unit tests.
import suds
import suds.sax.document
import suds.sax.parser
from tests.assertion import assert_no_output
from tests.compare_sax import CompareSAX
from testutils.assertion import assert_no_output
from testutils.compare_sax import CompareSAX
import pytest
from six import text_type, u
import xml.sax
@ -74,14 +75,14 @@ class TestMatched:
('<a xmlns="one"/>', '<ns:a xmlns:ns="one"/>'),
('<ns1:b xmlns:ns1="two"/>', '<ns2:b xmlns:ns2="two"/>'),
# Numeric unicode character references.
(u"<a>☆</a>", "<a>&#9734;</a>")))
(u("<a>\u2606</a>"), "<a>&#%d;</a>" % (0x2606,))))
def test_data2data(self, data1, data2, capsys):
CompareSAX.data2data(data1, data2)
assert_no_output(capsys)
@skip_test_if_CompareSAX_assertions_disabled
@pytest.mark.parametrize("type1", (suds.byte_str, unicode))
@pytest.mark.parametrize("type2", (suds.byte_str, unicode))
@pytest.mark.parametrize("type1", (suds.byte_str, text_type))
@pytest.mark.parametrize("type2", (suds.byte_str, text_type))
def test_string_input_types(self, type1, type2, capsys):
xml = "<a/>"
CompareSAX.data2data(type1(xml), type2(xml))
@ -90,7 +91,7 @@ class TestMatched:
@skip_test_if_CompareSAX_assertions_disabled
def test_xml_encoding(self, capsys):
"""Test that the encoding listed in the XML declaration is honored."""
xml_format = u'<?xml version="1.0" encoding="%s"?><a>Ø</a>'
xml_format = u('<?xml version="1.0" encoding="%s"?><a>\u00D8</a>')
data1 = (xml_format % ("UTF-8",)).encode('utf-8')
data2 = (xml_format % ("latin1",)).encode('latin1')
CompareSAX.data2data(data1, data2)
@ -103,50 +104,50 @@ class TestMismatched:
@skip_test_if_CompareSAX_assertions_disabled
@pytest.mark.parametrize(("data1", "data2", "expected_context"), (
# Different element namespaces.
("<a/>", '<a xmlns="x"/>', u"data2data.<a>.namespace"),
('<a xmlns="1"/>', '<a xmlns="2"/>', u"data2data.<a>.namespace"),
("<a/>", '<a xmlns="x"/>', "data2data.<a>.namespace"),
('<a xmlns="1"/>', '<a xmlns="2"/>', "data2data.<a>.namespace"),
('<r><a xmlns="1"/></r>', '<r><a xmlns="2"/></r>',
u"data2data.<r>.<a>.namespace"),
"data2data.<r>.<a>.namespace"),
('<r><tag><a xmlns="1"/></tag><y/></r>',
'<r><tag><a xmlns="2"/></tag><y/></r>',
u"data2data.<r>.<tag(1/2)>.<a>.namespace"),
"data2data.<r>.<tag(1/2)>.<a>.namespace"),
# Different textual content in text only nodes.
("<a>one</a>", "<a>two</a>", u"data2data.<a>.text"),
("<a>x</a>", "<a>x </a>", u"data2data.<a>.text"),
("<a>x</a>", "<a>x </a>", u"data2data.<a>.text"),
("<a>x </a>", "<a>x </a>", u"data2data.<a>.text"),
("<a> x</a>", "<a>x</a>", u"data2data.<a>.text"),
("<a> x</a>", "<a>x</a>", u"data2data.<a>.text"),
("<a> x</a>", "<a> x</a>", u"data2data.<a>.text"),
("<a>one</a>", "<a>two</a>", "data2data.<a>.text"),
("<a>x</a>", "<a>x </a>", "data2data.<a>.text"),
("<a>x</a>", "<a>x </a>", "data2data.<a>.text"),
("<a>x </a>", "<a>x </a>", "data2data.<a>.text"),
("<a> x</a>", "<a>x</a>", "data2data.<a>.text"),
("<a> x</a>", "<a>x</a>", "data2data.<a>.text"),
("<a> x</a>", "<a> x</a>", "data2data.<a>.text"),
("<a><b><c>x</c><c2/></b></a>", "<a><b><c>X</c><c2/></b></a>",
u"data2data.<a>.<b>.<c(1/2)>.text"),
"data2data.<a>.<b>.<c(1/2)>.text"),
("<a><b><c>x</c><d>y</d></b></a>", "<a><b><c>x</c><d>Y</d></b></a>",
u"data2data.<a>.<b>.<d(2/2)>.text"),
"data2data.<a>.<b>.<d(2/2)>.text"),
# Different textual content in mixed content nodes with children.
("<a>42<b/><b/>42</a>", "<a>42<b/> <b/>42</a>", u"data2data.<a>.text"),
("<a>42<b/><b/>42</a>", "<a>42<b/> <b/>42</a>", "data2data.<a>.text"),
# Differently named elements.
("<a/>", "<b/>", u"data2data.<a/b>"),
("<a><b/></a>", "<a><c/></a>", u"data2data.<a>.<b/c>"),
("<a><b/><x/></a>", "<a><c/><x/></a>", u"data2data.<a>.<b/c(1/2)>"),
("<a><x/><b/></a>", "<a><x/><c/></a>", u"data2data.<a>.<b/c(2/2)>"),
("<a/>", "<b/>", "data2data.<a/b>"),
("<a><b/></a>", "<a><c/></a>", "data2data.<a>.<b/c>"),
("<a><b/><x/></a>", "<a><c/><x/></a>", "data2data.<a>.<b/c(1/2)>"),
("<a><x/><b/></a>", "<a><x/><c/></a>", "data2data.<a>.<b/c(2/2)>"),
("<a><b><c/></b></a>", "<a><b><d/></b></a>",
u"data2data.<a>.<b>.<c/d>"),
"data2data.<a>.<b>.<c/d>"),
("<a><b><y1/><y2/><c/></b><x/></a>",
"<a><b><y1/><y2/><d/></b><x/></a>",
u"data2data.<a>.<b(1/2)>.<c/d(3/3)>"),
"data2data.<a>.<b(1/2)>.<c/d(3/3)>"),
# Extra/missing non-root element.
("<a><b/></a>", "<a/>", u"data2data.<a>"),
("<a/>", "<a><b/></a>", u"data2data.<a>"),
("<a><x/><b/></a>", "<a><b/></a>", u"data2data.<a>"),
("<a><b/><x/></a>", "<a><b/></a>", u"data2data.<a>"),
("<a><b/></a>", "<a><x/><b/></a>", u"data2data.<a>"),
("<a><b/></a>", "<a><b/><x/></a>", u"data2data.<a>"),
("<a><b/></a>", "<a/>", "data2data.<a>"),
("<a/>", "<a><b/></a>", "data2data.<a>"),
("<a><x/><b/></a>", "<a><b/></a>", "data2data.<a>"),
("<a><b/><x/></a>", "<a><b/></a>", "data2data.<a>"),
("<a><b/></a>", "<a><x/><b/></a>", "data2data.<a>"),
("<a><b/></a>", "<a><b/><x/></a>", "data2data.<a>"),
# Multiple differences.
("<a><b/></a>", "<c><d/></c>", u"data2data.<a/c>"),
("<a><b/></a>", '<a xmlns="o"><c/></a>', u"data2data.<a>.namespace"),
("<r><a><b/></a></r>", "<r><c><d/></c></r>", u"data2data.<r>.<a/c>"),
("<a><b/></a>", "<c><d/></c>", "data2data.<a/c>"),
("<a><b/></a>", '<a xmlns="o"><c/></a>', "data2data.<a>.namespace"),
("<r><a><b/></a></r>", "<r><c><d/></c></r>", "data2data.<r>.<a/c>"),
("<r><a><b/></a></r>", '<r><a xmlns="o"><c/></a></r>',
u"data2data.<r>.<a>.namespace")))
"data2data.<r>.<a>.namespace")))
def test_data2data(self, data1, data2, expected_context, capsys):
pytest.raises(AssertionError, CompareSAX.data2data, data1, data2)
_assert_context_output(capsys, expected_context)
@ -237,4 +238,4 @@ def _assert_context_output(capsys, context):
"""
out, err = capsys.readouterr()
assert not out
assert err == u"Failed SAX XML comparison context:\n %s\n" % (context,)
assert err == "Failed SAX XML comparison context:\n %s\n" % (context,)

View File

@ -21,13 +21,11 @@ Implemented using the 'pytest' testing framework.
"""
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
import testutils
testutils.run_using_pytest(globals())
from suds.sax.date import (FixedOffsetTimezone, Date, DateTime, Time,
UtcTimezone)
import tests
import pytest

View File

@ -23,9 +23,8 @@ Implemented using the 'pytest' testing framework.
"""
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
import testutils
testutils.run_using_pytest(globals())
import suds
import suds.store

View File

@ -35,13 +35,11 @@ operation's input parameters correctly.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import tests
import pytest
@ -246,7 +244,7 @@ class TestUnsupportedParameterDefinitions:
else:
assert str(e) == expected_error_text
finally:
del e
del e # explicitly break circular reference chain in Python 3
def init_function_params(self, params, **kwargs):
"""
@ -265,8 +263,8 @@ class TestUnsupportedParameterDefinitions:
"""
input = '<xsd:element name="Wrapper">%s</xsd:element>' % (params,)
assert not hasattr(self, "service")
wsdl = tests.wsdl(input, input="Wrapper", **kwargs)
client = tests.client_from_wsdl(wsdl, nosend=True)
wsdl = testutils.wsdl(input, input="Wrapper", **kwargs)
client = testutils.client_from_wsdl(wsdl, nosend=True)
self.service = client.service
@pytest.mark.parametrize("test_args_required", (
@ -383,7 +381,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
</wsdl:port>
</wsdl:service>
</wsdl:definitions>""" % (part_name,))
client = tests.client_from_wsdl(wsdl, nosend=True)
client = testutils.client_from_wsdl(wsdl, nosend=True)
# Collect references to required WSDL model content.
method = client.wsdl.services[0].ports[0].methods["f"]
@ -405,7 +403,7 @@ def test_explicitly_wrapped_parameter(part_name):
"""
input_schema = sequence_choice_with_element_and_two_element_sequence.xsd
wsdl = _unwrappable_wsdl(part_name, input_schema)
client = tests.client_from_wsdl(wsdl, nosend=True, unwrap=False)
client = testutils.client_from_wsdl(wsdl, nosend=True, unwrap=False)
# Collect references to required WSDL model content.
method = client.wsdl.services[0].ports[0].methods["f"]
@ -473,7 +471,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
</wsdl:service>
</wsdl:definitions>""")
wsdl = suds.byte_str("".join(wsdl))
client = tests.client_from_wsdl(wsdl, nosend=True)
client = testutils.client_from_wsdl(wsdl, nosend=True)
# Collect references to required WSDL model content.
method = client.wsdl.services[0].ports[0].methods["f"]
@ -505,7 +503,7 @@ def test_unwrapped_parameter(xsd_type):
"""Test recognizing unwrapped web service operation input structures."""
input_schema = sequence_choice_with_element_and_two_element_sequence.xsd
wsdl = _unwrappable_wsdl("part_name", input_schema)
client = tests.client_from_wsdl(wsdl, nosend=True)
client = testutils.client_from_wsdl(wsdl, nosend=True)
# Collect references to required WSDL model content.
method = client.wsdl.services[0].ports[0].methods["f"]
@ -530,7 +528,7 @@ def test_unwrapped_parameter_part_name(part_name):
"""
input_schema = sequence_choice_with_element_and_two_element_sequence.xsd
wsdl = _unwrappable_wsdl(part_name, input_schema)
client = tests.client_from_wsdl(wsdl, nosend=True)
client = testutils.client_from_wsdl(wsdl, nosend=True)
# Collect references to required WSDL model content.
method = client.wsdl.services[0].ports[0].methods["f"]

View File

@ -22,15 +22,13 @@ Implemented using the 'pytest' testing framework.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import suds.options
import suds.reader
import tests
class TestCacheItemNameMangling:
@ -70,7 +68,7 @@ assert mangled == '%(expected)s'
""" % {"expected": expected,
"test_item_name": test_item_name,
"test_item_suffix": test_item_suffix})
tests.run_test_process(test_file)
testutils.run_test_process(test_file)
def test_repeatable__different_readers(self):
test_item_name = "R2D2"

View File

@ -22,49 +22,48 @@ Implemented using the 'pytest' testing framework.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import tests
import pytest
from six import itervalues, next, u
from six.moves import http_client
import httplib
import xml.sax
def test_ACCEPTED_and_NO_CONTENT_status_reported_as_None_with_faults():
client = tests.client_from_wsdl(_wsdl__simple_f, faults=True)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=True)
def f(reply, status):
inject = {"reply": suds.byte_str(reply), "status": status}
return client.service.f(__inject=inject)
assert f("", None) is None
pytest.raises(Exception, f, "", httplib.INTERNAL_SERVER_ERROR)
assert f("", httplib.ACCEPTED) is None
assert f("", httplib.NO_CONTENT) is None
assert f("bla-bla", httplib.ACCEPTED) is None
assert f("bla-bla", httplib.NO_CONTENT) is None
pytest.raises(Exception, f, "", http_client.INTERNAL_SERVER_ERROR)
assert f("", http_client.ACCEPTED) is None
assert f("", http_client.NO_CONTENT) is None
assert f("bla-bla", http_client.ACCEPTED) is None
assert f("bla-bla", http_client.NO_CONTENT) is None
def test_ACCEPTED_and_NO_CONTENT_status_reported_as_None_without_faults():
client = tests.client_from_wsdl(_wsdl__simple_f, faults=False)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=False)
def f(reply, status):
inject = {"reply": suds.byte_str(reply), "status": status}
return client.service.f(__inject=inject)
assert f("", None) is not None
assert f("", httplib.INTERNAL_SERVER_ERROR) is not None
assert f("", httplib.ACCEPTED) is None
assert f("", httplib.NO_CONTENT) is None
assert f("bla-bla", httplib.ACCEPTED) is None
assert f("bla-bla", httplib.NO_CONTENT) is None
assert f("", http_client.INTERNAL_SERVER_ERROR) is not None
assert f("", http_client.ACCEPTED) is None
assert f("", http_client.NO_CONTENT) is None
assert f("bla-bla", http_client.ACCEPTED) is None
assert f("bla-bla", http_client.NO_CONTENT) is None
def test_badly_formed_reply_XML():
for faults in (True, False):
client = tests.client_from_wsdl(_wsdl__simple_f, faults=faults)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=faults)
pytest.raises(xml.sax.SAXParseException, client.service.f,
__inject={"reply": suds.byte_str("bad food")})
@ -74,7 +73,7 @@ def test_badly_formed_reply_XML():
# restriction's underlying data type.
@pytest.mark.xfail
def test_restriction_data_types():
client_unnamed = tests.client_from_wsdl(tests.wsdl("""\
client_unnamed = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Elemento">
<xsd:simpleType>
<xsd:restriction base="xsd:int">
@ -85,7 +84,7 @@ def test_restriction_data_types():
</xsd:simpleType>
</xsd:element>""", output="Elemento"))
client_named = tests.client_from_wsdl(tests.wsdl("""\
client_named = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:simpleType name="MyType">
<xsd:restriction base="xsd:int">
<xsd:enumeration value="1"/>
@ -95,7 +94,7 @@ def test_restriction_data_types():
</xsd:simpleType>
<xsd:element name="Elemento" type="ns:MyType"/>""", output="Elemento"))
client_twice_restricted = tests.client_from_wsdl(tests.wsdl("""\
client_twice_restricted = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:simpleType name="MyTypeGeneric">
<xsd:restriction base="xsd:int">
<xsd:enumeration value="1"/>
@ -127,7 +126,7 @@ def test_restriction_data_types():
def test_disabling_automated_simple_interface_unwrapping():
client = tests.client_from_wsdl(tests.wsdl("""\
client = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -155,33 +154,35 @@ def test_disabling_automated_simple_interface_unwrapping():
def test_empty_reply():
client = tests.client_from_wsdl(_wsdl__simple_f, faults=False)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=False)
def f(status=None, description=None):
inject = dict(reply=suds.byte_str(), status=status,
description=description)
return client.service.f(__inject=inject)
status, reason = f()
assert status == httplib.OK
assert status == http_client.OK
assert reason is None
status, reason = f(httplib.OK)
assert status == httplib.OK
status, reason = f(http_client.OK)
assert status == http_client.OK
assert reason is None
status, reason = f(httplib.INTERNAL_SERVER_ERROR)
assert status == httplib.INTERNAL_SERVER_ERROR
status, reason = f(http_client.INTERNAL_SERVER_ERROR)
assert status == http_client.INTERNAL_SERVER_ERROR
assert reason == "injected reply"
status, reason = f(httplib.FORBIDDEN)
assert status == httplib.FORBIDDEN
status, reason = f(http_client.FORBIDDEN)
assert status == http_client.FORBIDDEN
assert reason == "injected reply"
status, reason = f(httplib.FORBIDDEN, "kwack")
assert status == httplib.FORBIDDEN
status, reason = f(http_client.FORBIDDEN, "kwack")
assert status == http_client.FORBIDDEN
assert reason == "kwack"
def test_fault_reply_with_unicode_faultstring(monkeypatch):
monkeypatch.delitem(locals(), "e", False)
unicode_string = u"€ Jurko Gospodnetić ČĆŽŠĐčćžšđ"
fault_xml = suds.byte_str(u"""\
unicode_string = u("\u20AC Jurko Gospodneti\u0107 "
"\u010C\u0106\u017D\u0160\u0110"
"\u010D\u0107\u017E\u0161\u0111")
fault_xml = suds.byte_str(u("""\
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
@ -191,18 +192,21 @@ def test_fault_reply_with_unicode_faultstring(monkeypatch):
</env:Fault>
</env:Body>
</env:Envelope>
""" % (unicode_string,))
""") % (unicode_string,))
client = tests.client_from_wsdl(_wsdl__simple_f, faults=True)
inject = dict(reply=fault_xml, status=httplib.INTERNAL_SERVER_ERROR)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=True)
inject = dict(reply=fault_xml, status=http_client.INTERNAL_SERVER_ERROR)
e = pytest.raises(suds.WebFault, client.service.f, __inject=inject).value
assert e.fault.faultstring == unicode_string
assert e.document.__class__ is suds.sax.document.Document
try:
assert e.fault.faultstring == unicode_string
assert e.document.__class__ is suds.sax.document.Document
finally:
del e # explicitly break circular reference chain in Python 3
client = tests.client_from_wsdl(_wsdl__simple_f, faults=False)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=False)
status, fault = client.service.f(__inject=dict(reply=fault_xml,
status=httplib.INTERNAL_SERVER_ERROR))
assert status == httplib.INTERNAL_SERVER_ERROR
status=http_client.INTERNAL_SERVER_ERROR))
assert status == http_client.INTERNAL_SERVER_ERROR
assert fault.faultstring == unicode_string
@ -223,14 +227,17 @@ def test_invalid_fault_namespace(monkeypatch):
</env:Body>
</env:Envelope>
""")
client = tests.client_from_wsdl(_wsdl__simple_f, faults=False)
inject = dict(reply=fault_xml, status=httplib.OK)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=False)
inject = dict(reply=fault_xml, status=http_client.OK)
e = pytest.raises(Exception, client.service.f, __inject=inject).value
assert e.__class__ is Exception
assert str(e) == "<faultcode/> not mapped to message part"
try:
assert e.__class__ is Exception
assert str(e) == "<faultcode/> not mapped to message part"
finally:
del e # explicitly break circular reference chain in Python 3
for http_status in (httplib.INTERNAL_SERVER_ERROR,
httplib.PAYMENT_REQUIRED):
for http_status in (http_client.INTERNAL_SERVER_ERROR,
http_client.PAYMENT_REQUIRED):
status, reason = client.service.f(__inject=dict(reply=fault_xml,
status=http_status, description="trla baba lan"))
assert status == http_status
@ -243,7 +250,7 @@ def test_missing_wrapper_response():
interpreting received SOAP Response XML.
"""
client = tests.client_from_wsdl(tests.wsdl("""\
client = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -266,88 +273,100 @@ def test_missing_wrapper_response():
def test_reply_error_with_detail_with_fault(monkeypatch):
monkeypatch.delitem(locals(), "e", False)
client = tests.client_from_wsdl(_wsdl__simple_f, faults=True)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=True)
for http_status in (httplib.OK, httplib.INTERNAL_SERVER_ERROR):
for http_status in (http_client.OK, http_client.INTERNAL_SERVER_ERROR):
inject = dict(reply=_fault_reply__with_detail, status=http_status)
e = pytest.raises(suds.WebFault, client.service.f, __inject=inject)
e = e.value
_test_fault(e.fault, True)
assert e.document.__class__ is suds.sax.document.Document
assert str(e) == "Server raised fault: 'Dummy error.'"
try:
e = e.value
_test_fault(e.fault, True)
assert e.document.__class__ is suds.sax.document.Document
assert str(e) == "Server raised fault: 'Dummy error.'"
finally:
del e # explicitly break circular reference chain in Python 3
inject = dict(reply=_fault_reply__with_detail, status=httplib.BAD_REQUEST,
description="quack-quack")
inject = dict(reply=_fault_reply__with_detail,
status=http_client.BAD_REQUEST, description="quack-quack")
e = pytest.raises(Exception, client.service.f, __inject=inject).value
assert e.__class__ is Exception
assert e.args[0][0] == httplib.BAD_REQUEST
assert e.args[0][1] == "quack-quack"
try:
assert e.__class__ is Exception
assert e.args[0][0] == http_client.BAD_REQUEST
assert e.args[0][1] == "quack-quack"
finally:
del e # explicitly break circular reference chain in Python 3
def test_reply_error_with_detail_without_fault():
client = tests.client_from_wsdl(_wsdl__simple_f, faults=False)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=False)
for http_status in (httplib.OK, httplib.INTERNAL_SERVER_ERROR):
for http_status in (http_client.OK, http_client.INTERNAL_SERVER_ERROR):
status, fault = client.service.f(__inject=dict(
reply=_fault_reply__with_detail, status=http_status))
assert status == httplib.INTERNAL_SERVER_ERROR
assert status == http_client.INTERNAL_SERVER_ERROR
_test_fault(fault, True)
status, fault = client.service.f(__inject=dict(
reply=_fault_reply__with_detail, status=httplib.BAD_REQUEST))
assert status == httplib.BAD_REQUEST
reply=_fault_reply__with_detail, status=http_client.BAD_REQUEST))
assert status == http_client.BAD_REQUEST
assert fault == "injected reply"
status, fault = client.service.f(__inject=dict(
reply=_fault_reply__with_detail, status=httplib.BAD_REQUEST,
reply=_fault_reply__with_detail, status=http_client.BAD_REQUEST,
description="haleluja"))
assert status == httplib.BAD_REQUEST
assert status == http_client.BAD_REQUEST
assert fault == "haleluja"
def test_reply_error_without_detail_with_fault(monkeypatch):
monkeypatch.delitem(locals(), "e", False)
client = tests.client_from_wsdl(_wsdl__simple_f, faults=True)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=True)
for http_status in (httplib.OK, httplib.INTERNAL_SERVER_ERROR):
for http_status in (http_client.OK, http_client.INTERNAL_SERVER_ERROR):
inject = dict(reply=_fault_reply__without_detail, status=http_status)
e = pytest.raises(suds.WebFault, client.service.f, __inject=inject)
e = e.value
_test_fault(e.fault, False)
assert e.document.__class__ is suds.sax.document.Document
assert str(e) == "Server raised fault: 'Dummy error.'"
try:
e = e.value
_test_fault(e.fault, False)
assert e.document.__class__ is suds.sax.document.Document
assert str(e) == "Server raised fault: 'Dummy error.'"
finally:
del e # explicitly break circular reference chain in Python 3
inject = dict(reply=_fault_reply__with_detail, status=httplib.BAD_REQUEST,
description="quack-quack")
inject = dict(reply=_fault_reply__with_detail,
status=http_client.BAD_REQUEST, description="quack-quack")
e = pytest.raises(Exception, client.service.f, __inject=inject).value
assert e.__class__ is Exception
assert e.args[0][0] == httplib.BAD_REQUEST
assert e.args[0][1] == "quack-quack"
try:
assert e.__class__ is Exception
assert e.args[0][0] == http_client.BAD_REQUEST
assert e.args[0][1] == "quack-quack"
finally:
del e # explicitly break circular reference chain in Python 3
def test_reply_error_without_detail_without_fault():
client = tests.client_from_wsdl(_wsdl__simple_f, faults=False)
client = testutils.client_from_wsdl(_wsdl__simple_f, faults=False)
for http_status in (httplib.OK, httplib.INTERNAL_SERVER_ERROR):
for http_status in (http_client.OK, http_client.INTERNAL_SERVER_ERROR):
status, fault = client.service.f(__inject=dict(
reply=_fault_reply__without_detail, status=http_status))
assert status == httplib.INTERNAL_SERVER_ERROR
assert status == http_client.INTERNAL_SERVER_ERROR
_test_fault(fault, False)
status, fault = client.service.f(__inject=dict(
reply=_fault_reply__without_detail, status=httplib.BAD_REQUEST,
reply=_fault_reply__without_detail, status=http_client.BAD_REQUEST,
description="kung-fu-fui"))
assert status == httplib.BAD_REQUEST
assert status == http_client.BAD_REQUEST
assert fault == "kung-fu-fui"
def test_simple_bare_and_wrapped_output():
# Prepare web service proxies.
client_bare = tests.client_from_wsdl(tests.wsdl("""\
client_bare = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="fResponse" type="xsd:string"/>""",
output="fResponse"))
client_wrapped = tests.client_from_wsdl(tests.wsdl("""\
client_wrapped = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -390,7 +409,7 @@ def test_simple_bare_and_wrapped_output():
def test_wrapped_sequence_output():
client = tests.client_from_wsdl(tests.wsdl("""\
client = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -439,7 +458,8 @@ def _attributes(object):
def _isOutputWrapped(client, method_name):
assert len(client.wsdl.bindings) == 1
operation = client.wsdl.bindings.values()[0].operations[method_name]
binding = next(itervalues(client.wsdl.bindings))
operation = binding.operations[method_name]
return operation.soap.output.body.wrapped
@ -483,7 +503,7 @@ _fault_reply__without_detail = suds.byte_str("""\
</env:Envelope>
""")
_wsdl__simple_f = tests.wsdl("""\
_wsdl__simple_f = testutils.wsdl("""\
<xsd:element name="fResponse">
<xsd:complexType>
<xsd:sequence>

View File

@ -28,25 +28,24 @@ then passing that wrapper object instead.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import suds.store
import tests
from tests.compare_sax import CompareSAX
from testutils.compare_sax import CompareSAX
import pytest
from six import iterkeys, itervalues, next, u
# TODO: Update the current restriction type output parameter handling so such
#TODO: Update the current restriction type output parameter handling so such
# parameters get converted to the correct Python data type based on the
# restriction's underlying data type.
@pytest.mark.xfail
def test_bare_input_restriction_types():
client_unnamed = tests.client_from_wsdl(tests.wsdl("""\
client_unnamed = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Elemento">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
@ -57,7 +56,7 @@ def test_bare_input_restriction_types():
</xsd:simpleType>
</xsd:element>""", input="Elemento", operation_name="f"))
client_named = tests.client_from_wsdl(tests.wsdl("""\
client_named = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:simpleType name="MyType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="alfa"/>
@ -380,9 +379,9 @@ def parametrize_single_element_input_test(param_names, param_values):
))
def test_document_literal_request_for_single_element_input(xsd,
external_element_name, args, request_body):
wsdl = tests.wsdl(xsd, input=external_element_name,
wsdl = testutils.wsdl(xsd, input=external_element_name,
xsd_target_namespace="dr. Doolittle", operation_name="f")
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
_assert_request_content(client.service.f(*args), """\
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
@ -393,7 +392,7 @@ def test_document_literal_request_for_single_element_input(xsd,
def test_disabling_automated_simple_interface_unwrapping():
xsd_target_namespace = "woof"
wsdl = tests.wsdl("""\
wsdl = testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -402,7 +401,7 @@ def test_disabling_automated_simple_interface_unwrapping():
</xsd:complexType>
</xsd:element>""", input="Wrapper", operation_name="f",
xsd_target_namespace=xsd_target_namespace)
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True,
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True,
unwrap=False)
assert not _is_input_wrapped(client, "f")
element_data = "Wonderwall"
@ -510,7 +509,7 @@ def test_invalid_input_parameter_type_handling():
"""
xsd_target_namespace = "1234567890"
wsdl = tests.wsdl("""\
wsdl = testutils.wsdl("""\
<xsd:complexType name="Freakazoid">
<xsd:sequence>
<xsd:element name="freak1" type="xsd:string"/>
@ -528,7 +527,7 @@ def test_invalid_input_parameter_type_handling():
</xsd:complexType>
</xsd:element>""", input="Wrapper", operation_name="f",
xsd_target_namespace=xsd_target_namespace)
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
# Passing an unrelated Python type value.
class SomeType:
@ -573,7 +572,7 @@ def test_invalid_input_parameter_type_handling():
def test_missing_parameters():
"""Missing non-optional parameters should get passed as empty values."""
xsd_target_namespace = "plonker"
service = _service_from_wsdl(tests.wsdl("""\
service = _service_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -596,17 +595,17 @@ def test_missing_parameters():
</Body>
</Envelope>""" % (xsd_target_namespace,))
_assert_request_content(service.f(u"Pero Ždero"), """\
_assert_request_content(service.f((u("Pero \u017Ddero"))), u("""\
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Header/>
<Body>
<Wrapper xmlns="%s">
<aString>Pero Ždero</aString>
<aString>Pero \u017Ddero</aString>
<anInteger/>
</Wrapper>
</Body>
</Envelope>""" % (xsd_target_namespace,))
</Envelope>""") % (xsd_target_namespace,))
_assert_request_content(service.f(anInteger=666), """\
<?xml version="1.0" encoding="UTF-8"?>
@ -657,7 +656,7 @@ def test_named_parameter():
# Test different ways to make the same web service operation call.
xsd_target_namespace = "qwerty"
service = _service_from_wsdl(tests.wsdl("""\
service = _service_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -686,7 +685,7 @@ def test_named_parameter():
# The order of parameters in the constructed SOAP request should depend
# only on the initial WSDL schema.
xsd_target_namespace = "abracadabra"
service = _service_from_wsdl(tests.wsdl("""\
service = _service_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -716,7 +715,7 @@ def test_named_parameter():
def test_optional_parameter_handling():
"""Missing optional parameters should not get passed at all."""
xsd_target_namespace = "RoOfIe"
service = _service_from_wsdl(tests.wsdl("""\
service = _service_from_wsdl(testutils.wsdl("""\
<xsd:element name="Wrapper">
<xsd:complexType>
<xsd:sequence>
@ -843,7 +842,7 @@ def test_SOAP_headers():
</wsdl:definitions>
""")
header_data = "fools rush in where angels fear to tread"
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client.options.soapheaders = header_data
_assert_request_content(client.service.my_operation(), """\
<?xml version="1.0" encoding="UTF-8"?>
@ -862,7 +861,7 @@ def test_twice_wrapped_parameter():
"""
xsd_target_namespace = "spank me"
wsdl = tests.wsdl("""\
wsdl = testutils.wsdl("""\
<xsd:element name="Wrapper1">
<xsd:complexType>
<xsd:sequence>
@ -877,7 +876,7 @@ def test_twice_wrapped_parameter():
</xsd:complexType>
</xsd:element>""", input="Wrapper1", operation_name="f",
xsd_target_namespace=xsd_target_namespace)
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
assert _is_input_wrapped(client, "f")
@ -905,13 +904,13 @@ def test_twice_wrapped_parameter():
# Web service operation calls made with 'invalid' parameters.
def test_invalid_parameter(**kwargs):
assert len(kwargs) == 1
element = kwargs.keys()[0]
expected = "f() got an unexpected keyword argument '%s'" % (element,)
keyword = next(iterkeys(kwargs))
expected = "f() got an unexpected keyword argument '%s'" % (keyword,)
e = pytest.raises(TypeError, client.service.f, **kwargs).value
try:
assert str(e) == expected
finally:
del e
del e # explicitly break circular reference chain in Python 3
test_invalid_parameter(Elemento=value)
test_invalid_parameter(Wrapper1=value)
@ -921,9 +920,9 @@ def test_wrapped_parameter(monkeypatch):
# Prepare web service proxies.
def client(xsd, *input):
wsdl = tests.wsdl(xsd, input=input, xsd_target_namespace="toolyan",
wsdl = testutils.wsdl(xsd, input=input, xsd_target_namespace="toolyan",
operation_name="f")
return tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
return testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client_bare_single = client("""\
<xsd:element name="Elemento" type="xsd:string"/>""", "Elemento")
client_bare_multiple_simple = client("""\
@ -995,7 +994,11 @@ def test_wrapped_parameter(monkeypatch):
# Suds library's automatic structure unwrapping prevents us from specifying
# the external wrapper structure directly.
e = pytest.raises(TypeError, client_wrapped_unnamed.service.f, Wrapper="A")
assert str(e.value) == "f() got an unexpected keyword argument 'Wrapper'"
try:
expected = "f() got an unexpected keyword argument 'Wrapper'"
assert str(e.value) == expected
finally:
del e # explicitly break circular reference chain in Python 3
# Multiple parameter web service operations are never automatically
# unwrapped.
@ -1030,7 +1033,8 @@ def _assert_request_content(request, expected_xml):
def _is_input_wrapped(client, method_name):
assert len(client.wsdl.bindings) == 1
operation = client.wsdl.bindings.values()[0].operations[method_name]
binding = next(itervalues(client.wsdl.bindings))
operation = binding.operations[method_name]
return operation.soap.input.body.wrapped
@ -1042,4 +1046,4 @@ def _service_from_wsdl(wsdl):
invocation requests and does not attempt to actually send them.
"""
return tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True).service
return testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True).service

View File

@ -23,9 +23,8 @@ Implemented using the 'pytest' testing framework.
"""
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
import testutils
testutils.run_using_pytest(globals())
import suds.sax.enc

View File

@ -25,16 +25,15 @@ tests get added to it and it acquires more structure.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import tests
from tests.compare_sax import CompareSAX
from testutils.compare_sax import CompareSAX
import pytest
from six import itervalues, next
import re
import xml.sax
@ -59,7 +58,7 @@ def test_choice_parameter_implementation_inconsistencies():
"""
def client(x, y):
return tests.client_from_wsdl(tests.wsdl(x, input=y))
return testutils.client_from_wsdl(testutils.wsdl(x, input=y))
client_simple_short = client("""\
<xsd:element name="Elemento" type="xsd:string"/>""", "Elemento")
@ -90,13 +89,13 @@ def test_choice_parameter_implementation_inconsistencies():
def test_converting_client_to_string_must_not_raise_an_exception():
client = tests.client_from_wsdl(suds.byte_str(
client = testutils.client_from_wsdl(suds.byte_str(
"<?xml version='1.0' encoding='UTF-8'?><root/>"))
str(client)
def test_converting_metadata_to_string():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -145,19 +144,23 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_empty_invalid_WSDL(monkeypatch):
wsdl = suds.byte_str("")
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(xml.sax.SAXParseException, tests.client_from_wsdl, wsdl)
assert e.value.getMessage() == "no element found"
e = pytest.raises(xml.sax.SAXParseException, testutils.client_from_wsdl,
wsdl)
try:
assert e.value.getMessage() == "no element found"
finally:
del e # explicitly break circular reference chain in Python 3
def test_empty_valid_WSDL():
client = tests.client_from_wsdl(suds.byte_str(
client = testutils.client_from_wsdl(suds.byte_str(
"<?xml version='1.0' encoding='UTF-8'?><root/>"))
assert not client.wsdl.services, "No service definitions must be read " \
"from an empty WSDL."
def test_enumeration_type_string_should_contain_its_value():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -211,7 +214,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_global_sequence_in_a_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -296,7 +299,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_local_choice():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -373,7 +376,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_local_choice_in_a_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -473,7 +476,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_local_sequence_in_a_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -577,7 +580,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_sequence_in_a_choice():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -666,7 +669,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_sequence_in_a_choice_in_a_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -753,7 +756,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_function_parameters_strings():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -831,7 +834,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_global_enumeration():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -894,7 +897,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_global_sequence_in_a_global_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -980,7 +983,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_global_string_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1062,7 +1065,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_local_sequence_in_a_global_sequence():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1153,7 +1156,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_no_trailing_comma_in_function_prototype_description_string__0():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1200,7 +1203,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_no_trailing_comma_in_function_prototype_description_string__1():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1249,7 +1252,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_no_trailing_comma_in_function_prototype_description_string__3():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1300,7 +1303,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_no_types():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1336,10 +1339,14 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_parameter_referencing_missing_element(monkeypatch):
wsdl = tests.wsdl("", input="missingElement", xsd_target_namespace="aaa")
wsdl = testutils.wsdl("", input="missingElement",
xsd_target_namespace="aaa")
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(suds.TypeNotFound, tests.client_from_wsdl, wsdl).value
assert str(e) == "Type not found: '(missingElement, aaa, )'"
e = pytest.raises(suds.TypeNotFound, testutils.client_from_wsdl, wsdl)
try:
assert str(e.value) == "Type not found: '(missingElement, aaa, )'"
finally:
del e # explicitly break circular reference chain in Python 3
#TODO: Update the current restriction type input parameter handling so they get
@ -1347,7 +1354,7 @@ def test_parameter_referencing_missing_element(monkeypatch):
# interpreted as a separate input parameter.
@pytest.mark.xfail
def test_restrictions():
client_unnamed = tests.client_from_wsdl(tests.wsdl("""\
client_unnamed = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:element name="Elemento">
<xsd:simpleType>
<xsd:restriction base="xsd:int">
@ -1358,7 +1365,7 @@ def test_restrictions():
</xsd:simpleType>
</xsd:element>""", input="Elemento"))
client_named = tests.client_from_wsdl(tests.wsdl("""\
client_named = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:simpleType name="MyType">
<xsd:restriction base="xsd:int">
<xsd:enumeration value="1"/>
@ -1368,7 +1375,7 @@ def test_restrictions():
</xsd:simpleType>
<xsd:element name="Elemento" type="ns:MyType"/>""", input="Elemento"))
client_twice_restricted = tests.client_from_wsdl(tests.wsdl("""\
client_twice_restricted = testutils.client_from_wsdl(testutils.wsdl("""\
<xsd:simpleType name="MyTypeGeneric">
<xsd:restriction base="xsd:int">
<xsd:enumeration value="1"/>
@ -1420,7 +1427,7 @@ def test_restrictions():
def test_schema_node_occurrences():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1509,7 +1516,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_schema_node_resolve():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1590,7 +1597,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_schema_node_resolve__nobuiltin_caching():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1638,7 +1645,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_schema_node_resolve__invalid_type():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1667,7 +1674,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_schema_node_resolve__references():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1744,7 +1751,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_schema_object_child_access_by_index():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1813,7 +1820,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_simple_wsdl():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
@ -1923,7 +1930,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
assert binding_qname == ("dummy", "my-namespace")
assert binding.__class__ is suds.wsdl.Binding
assert len(binding.operations) == 1
operation = binding.operations.values()[0]
operation = next(itervalues(binding.operations))
input = operation.soap.input.body
output = operation.soap.output.body
assert len(input.parts) == 1
@ -1960,7 +1967,7 @@ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
def test_wsdl_schema_content():
client = tests.client_from_wsdl(suds.byte_str("""\
client = testutils.client_from_wsdl(suds.byte_str("""\
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="my-namespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

View File

@ -23,12 +23,10 @@ Implemented using the 'pytest' testing framework.
"""
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
import testutils
testutils.run_using_pytest(globals())
from suds.sax.date import FixedOffsetTimezone, UtcTimezone
import tests
import pytest

View File

@ -23,15 +23,15 @@ Implemented using the 'pytest' testing framework.
"""
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
import testutils
testutils.run_using_pytest(globals())
import suds
from suds.transport import Reply, Request, Transport
import suds.transport.options
import pytest
from six import b, text_type, u, unichr
import sys
@ -48,45 +48,49 @@ class TestBaseTransportClass:
transport = Transport()
f = getattr(transport, method_name)
e = pytest.raises(Exception, f, "whatever").value
assert e.__class__ is Exception
assert str(e) == "not-implemented"
try:
assert e.__class__ is Exception
assert str(e) == "not-implemented"
finally:
del e # explicitly break circular reference chain in Python 3
class TestReply:
@pytest.mark.parametrize(("code", "headers", "message"), (
(1, {}, None),
(1, {}, "ola"),
(1, {}, suds.byte_str("ola")),
(1, {}, u("ola")),
(1, {}, b("ola")),
(1, {}, object()),
(1, {}, u"šuć-muć 中原千军逐蒋\n城楼万众检阅".encode("utf-8")),
(2, {"semper": "fi"}, u"中原千军逐蒋\n城楼万众检阅")))
(1, {}, u("\u0161u\u0107-mu\u0107 \u4E2D\u539F\u5343\n\u57CE")),
(2, {"semper": "fi"}, u("\u4E2D\u539F\u5343\n\u57CE"))))
def test_construction(self, code, headers, message):
reply = Reply(code, headers, message)
assert reply.code is code
assert reply.headers is headers
assert reply.message is message
@pytest.mark.parametrize("message", [x.encode("utf-8") for x in (
u"",
u"for a bitch it's haaaard...",
u"""\
@pytest.mark.parametrize("message", [u(x).encode("utf-8") for x in (
"",
"for a bitch it's haaaard...",
"""\
I'm here to kick ass,
and chew bubble gum...
and I'm all out of gum.""",
u"šuć-muć pa ožeži.. za 100 €\n\nwith multiple\nlines...",
u"\n\n\n\n\n\n",
u"中原千军逐蒋")])
"\u0161u\u0107-mu\u0107 pa o\u017Ee\u017Ei.. za 100 \u20AC\n\n"
"with multiple\nlines...",
"\n\n\n\n\n\n",
"\u4E2D\u539F\u5343\u519B\u9010\u848B")])
def test_string_representation(self, message):
code = 17
reply = Reply(code, {"aaa": 1}, message)
expected = u"""\
expected = u("""\
CODE: %s
HEADERS: %s
MESSAGE:
%s""" % (code, reply.headers, message.decode("raw_unicode_escape"))
assert unicode(reply) == expected
if sys.version_info < (3, 0):
%s""") % (code, reply.headers, message.decode("raw_unicode_escape"))
assert text_type(reply) == expected
if sys.version_info < (3,):
assert str(reply) == expected.encode("utf-8")
@ -95,7 +99,7 @@ class TestRequest:
@pytest.mark.parametrize("message", (
None,
"it's hard out here...",
u"城楼万众检阅"))
u("\u57CE\u697C\u4E07\u4F17\u68C0\u9605")))
def test_construct(self, message):
# Always use the same URL as different ways to specify a Request's URL
# are tested separately.
@ -111,10 +115,10 @@ class TestRequest:
assert request.message is None
test_non_ASCII_URLs = [
u"中原千军逐蒋",
u"城楼万众检阅"] + [
u("\u4E2D\u539F\u5343\u519B\u9010\u848B"),
u("\u57CE\u697C\u4E07\u4F17\u68C0\u9605")] + [
url_prefix + url_suffix
for url_prefix in (u"", u"Jurko")
for url_prefix in (u(""), u("Jurko"))
for url_suffix in (unichr(128), unichr(200), unichr(1000))]
@pytest.mark.parametrize("url",
test_non_ASCII_URLs + # unicode strings
@ -131,29 +135,30 @@ class TestRequest:
I'm here to kick ass,
and chew bubble gum...
and I'm all out of gum."""),
("", {}, u"šuć-muć pa ožeži.. za 100 €\n\nwith multiple\nlines..."),
("", {}, u("\u0161u\u0107-mu\u0107 pa o\u017Ee\u017Ei.. za 100 "
"\u20AC\n\nwith multiple\nlines...")),
("", {}, "\n\n\n\n\n\n"),
("", {}, u"中原千军逐蒋")))
("", {}, u("\u4E2D\u539F\u5343\u519B\u9010\u848B"))))
def test_string_representation_with_message(self, url, headers, message):
for key, value in headers.items():
old_key = key
if isinstance(key, unicode):
if isinstance(key, text_type):
key = key.encode("utf-8")
del headers[old_key]
if isinstance(value, unicode):
if isinstance(value, text_type):
value = value.encode("utf-8")
headers[key] = value
if isinstance(message, unicode):
if isinstance(message, text_type):
message = message.encode("utf-8")
request = Request(url, message)
request.headers = headers
expected = u"""\
expected = u("""\
URL: %s
HEADERS: %s
MESSAGE:
%s""" % (url, request.headers, message.decode("raw_unicode_escape"))
assert unicode(request) == expected
if sys.version_info < (3, 0):
%s""") % (url, request.headers, message.decode("raw_unicode_escape"))
assert text_type(request) == expected
if sys.version_info < (3,):
assert str(request) == expected.encode("utf-8")
def test_string_representation_with_no_message(self):
@ -161,23 +166,23 @@ MESSAGE:
headers = {suds.byte_str("yuck"): suds.byte_str("ptooiii...")}
request = Request(url)
request.headers = headers
expected = u"""\
expected = u("""\
URL: %s
HEADERS: %s""" % (url, request.headers)
assert unicode(request) == expected
if sys.version_info < (3, 0):
HEADERS: %s""") % (url, request.headers)
assert text_type(request) == expected
if sys.version_info < (3,):
assert str(request) == expected.encode("utf-8")
test_URLs = [
u"",
u"http://host/path/name",
u"cogito://ergo/sum",
u"haleluya",
u"look at me flyyyyyyyy",
u(""),
u("http://host/path/name"),
u("cogito://ergo/sum"),
u("haleluya"),
u("look at me flyyyyyyyy"),
unichr(0),
unichr(127),
u"Jurko" + unichr(0),
u"Jurko" + unichr(127)]
u("Jurko") + unichr(0),
u("Jurko") + unichr(127)]
@pytest.mark.parametrize("url", test_URLs + [
url.encode("ascii") for url in test_URLs])
def test_URL(self, url):
@ -191,7 +196,7 @@ HEADERS: %s""" % (url, request.headers)
assert isinstance(request.url, str)
if url.__class__ is str:
assert request.url is url
elif url.__class__ is unicode:
elif url.__class__ is u:
assert request.url == url.encode("ascii") # Python 2.
else:
assert request.url == url.decode("ascii") # Python 3.

View File

@ -22,28 +22,31 @@ Implemented using the 'pytest' testing framework.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds
import suds.transport
import suds.transport.http
import tests
import pytest
from six import u
from six.moves import http_client
from six.moves.urllib.error import HTTPError
from six.moves.urllib.request import ProxyHandler
import base64
import httplib
import re
import sys
import urllib2
if sys.version_info >= (3, 0):
urllib_request = urllib.request
# We can not use six.moves modules for this since we want to monkey-patch the
# exact underlying urllib2/urllib.request module in our tests and not just
# their six.moves proxy module.
if sys.version_info < (3,):
import urllib2 as urllib_request
else:
urllib_request = urllib2
import urllib.request as urllib_request
class MustNotBeCalled(Exception):
@ -103,11 +106,11 @@ class CountedMock(object):
class MockFP:
"""
Mock FP 'File object' as stored inside a urllib2.HTTPError exception.
Mock FP 'File object' as stored inside Python's HTTPError exception.
Must have several 'File object' methods defined on it as Python's
urllib2.HTTPError implementation expects them and stores references to them
internally, at least with Python 2.4.
Must have several 'File object' methods defined on it as Python's HTTPError
implementation expects them and stores references to them internally, at
least with Python 2.4.
"""
@ -171,7 +174,7 @@ def assert_default_transport(transport):
assert transport.urlopener is None
def create_request(url="protocol://default-url", data=u"Rumpelstiltskin"):
def create_request(url="protocol://default-url", data=u("Rumpelstiltskin")):
"""Test utility constructing a suds.transport.Request instance."""
return suds.transport.Request(url, data)
@ -304,7 +307,7 @@ def test_sending_using_network_sockets(send_method, monkeypatch):
url_relative = "svc"
url = "http://%s/%s" % (host_port, url_relative)
partial_ascii_byte_data = suds.byte_str("Muka-laka-hiki")
non_ascii_byte_data = u"Дмитровский район".encode("utf-8")
non_ascii_byte_data = u("\u0414\u043C\u0438 \u0442\u0440").encode("utf-8")
non_ascii_byte_data += partial_ascii_byte_data
mocker = Mocker(host, port)
monkeypatch.setattr("socket.getaddrinfo", mocker.getaddrinfo)
@ -359,7 +362,7 @@ class TestSendingToURLWithAMissingProtocolIdentifier:
"my no-protocol URL",
":my no-protocol URL"))
@pytest.mark.skipif(sys.version_info >= (3, 0), reason="Python 2 specific")
@pytest.mark.skipif(sys.version_info >= (3,), reason="Python 2 specific")
@invalid_URL_parametrization
def test_python2(self, url, send_method):
transport = suds.transport.http.HttpTransport()
@ -367,7 +370,7 @@ class TestSendingToURLWithAMissingProtocolIdentifier:
request = create_request(url)
pytest.raises(MyException, send_method, transport, request)
@pytest.mark.skipif(sys.version_info < (3, 0), reason="Python 3+ specific")
@pytest.mark.skipif(sys.version_info < (3,), reason="Python 3+ specific")
@invalid_URL_parametrization
def test_python3(self, url, send_method, monkeypatch):
monkeypatch.delitem(locals(), "e", False)
@ -375,7 +378,10 @@ class TestSendingToURLWithAMissingProtocolIdentifier:
transport.urlopener = MockURLOpenerSaboteur()
request = create_request(url)
e = pytest.raises(ValueError, send_method, transport, request)
assert "unknown url type" in str(e)
try:
assert "unknown url type" in str(e)
finally:
del e # explicitly break circular reference chain in Python 3
class TestURLOpenerUsage:
@ -406,20 +412,20 @@ class TestURLOpenerUsage:
msg = object()
if hdrs is Undefined:
hdrs = object()
return urllib2.HTTPError(url=url, code=code, msg=msg, hdrs=hdrs, fp=fp)
return HTTPError(url=url, code=code, msg=msg, hdrs=hdrs, fp=fp)
@pytest.mark.parametrize("status_code", (
httplib.ACCEPTED,
httplib.NO_CONTENT,
httplib.RESET_CONTENT,
httplib.MOVED_PERMANENTLY,
httplib.BAD_REQUEST,
httplib.PAYMENT_REQUIRED,
httplib.FORBIDDEN,
httplib.NOT_FOUND,
httplib.INTERNAL_SERVER_ERROR,
httplib.NOT_IMPLEMENTED,
httplib.HTTP_VERSION_NOT_SUPPORTED))
http_client.ACCEPTED,
http_client.NO_CONTENT,
http_client.RESET_CONTENT,
http_client.MOVED_PERMANENTLY,
http_client.BAD_REQUEST,
http_client.PAYMENT_REQUIRED,
http_client.FORBIDDEN,
http_client.NOT_FOUND,
http_client.INTERNAL_SERVER_ERROR,
http_client.NOT_IMPLEMENTED,
http_client.HTTP_VERSION_NOT_SUPPORTED))
def test_open_propagating_HTTPError_exceptions(self, status_code,
monkeypatch):
"""
@ -437,16 +443,18 @@ class TestURLOpenerUsage:
# Execute.
e = pytest.raises(suds.transport.TransportError, t.open, request).value
# Verify.
assert e.args == (str(e_original),)
assert e.httpcode is status_code
assert e.fp is fp
try:
# Verify.
assert e.args == (str(e_original),)
assert e.httpcode is status_code
assert e.fp is fp
finally:
del e # explicitly break circular reference chain in Python 3
@pytest.mark.xfail(reason="original suds library bug")
@pytest.mark.parametrize("status_code", (
httplib.ACCEPTED,
httplib.NO_CONTENT))
http_client.ACCEPTED,
http_client.NO_CONTENT))
def test_operation_invoke_with_urlopen_accept_no_content__data(self,
status_code):
"""
@ -459,15 +467,15 @@ class TestURLOpenerUsage:
e = self.create_HTTPError(code=status_code)
transport = suds.transport.http.HttpTransport()
transport.urlopener = MockURLOpenerSaboteur(open_exception=e)
wsdl = tests.wsdl('<xsd:element name="o" type="xsd:string"/>',
wsdl = testutils.wsdl('<xsd:element name="o" type="xsd:string"/>',
output="o", operation_name="f")
client = tests.client_from_wsdl(wsdl, transport=transport)
client = testutils.client_from_wsdl(wsdl, transport=transport)
pytest.raises(suds.transport.TransportError, client.service.f)
@pytest.mark.xfail(reason="original suds library bug")
@pytest.mark.parametrize("status_code", (
httplib.ACCEPTED,
httplib.NO_CONTENT))
http_client.ACCEPTED,
http_client.NO_CONTENT))
def test_operation_invoke_with_urlopen_accept_no_content__no_data(self,
status_code):
"""
@ -487,9 +495,9 @@ class TestURLOpenerUsage:
e = self.create_HTTPError(code=status_code)
transport = suds.transport.http.HttpTransport()
transport.urlopener = MockURLOpenerSaboteur(open_exception=e)
wsdl = tests.wsdl('<xsd:element name="o" type="xsd:string"/>',
wsdl = testutils.wsdl('<xsd:element name="o" type="xsd:string"/>',
output="o", operation_name="f")
client = tests.client_from_wsdl(wsdl, transport=transport)
client = testutils.client_from_wsdl(wsdl, transport=transport)
assert client.service.f() is None
def test_propagating_non_HTTPError_exceptions(self, send_method):
@ -504,15 +512,15 @@ class TestURLOpenerUsage:
assert pytest.raises(e.__class__, t.open, create_request()).value is e
@pytest.mark.parametrize("status_code", (
httplib.RESET_CONTENT,
httplib.MOVED_PERMANENTLY,
httplib.BAD_REQUEST,
httplib.PAYMENT_REQUIRED,
httplib.FORBIDDEN,
httplib.NOT_FOUND,
httplib.INTERNAL_SERVER_ERROR,
httplib.NOT_IMPLEMENTED,
httplib.HTTP_VERSION_NOT_SUPPORTED))
http_client.RESET_CONTENT,
http_client.MOVED_PERMANENTLY,
http_client.BAD_REQUEST,
http_client.PAYMENT_REQUIRED,
http_client.FORBIDDEN,
http_client.NOT_FOUND,
http_client.INTERNAL_SERVER_ERROR,
http_client.NOT_IMPLEMENTED,
http_client.HTTP_VERSION_NOT_SUPPORTED))
def test_send_transforming_HTTPError_exceptions(self, status_code,
monkeypatch):
"""
@ -532,16 +540,18 @@ class TestURLOpenerUsage:
# Execute.
e = pytest.raises(suds.transport.TransportError, t.send, request).value
# Verify.
assert len(e.args) == 1
assert e.args[0] is e_original.msg
assert e.httpcode is status_code
assert e.fp is fp
try:
# Verify.
assert len(e.args) == 1
assert e.args[0] is e_original.msg
assert e.httpcode is status_code
assert e.fp is fp
finally:
del e # explicitly break circular reference chain in Python 3
@pytest.mark.parametrize("status_code", (
httplib.ACCEPTED,
httplib.NO_CONTENT))
http_client.ACCEPTED,
http_client.NO_CONTENT))
def test_send_transforming_HTTPError_exceptions__accepted_no_content(self,
status_code):
"""
@ -563,7 +573,7 @@ class TestURLOpenerUsage:
"""
def my_build_urlopener(*handlers):
assert len(handlers) == 1
assert handlers[0].__class__ is urllib2.ProxyHandler
assert handlers[0].__class__ is ProxyHandler
raise MyException
monkeypatch.setattr(urllib_request, "build_opener", my_build_urlopener)
transport = suds.transport.http.HttpTransport()
@ -581,9 +591,9 @@ class TestURLOpenerUsage:
"""
class MockURLOpener:
def open(self, urllib_request, timeout=None):
assert urllib_request.__class__ is urllib2.Request
assert urllib_request.get_full_url() == url
def open(self, request, timeout=None):
assert request.__class__ is urllib_request.Request
assert request.get_full_url() == url
raise MyException
transport = suds.transport.http.HttpTransport()
transport.urlopener = MockURLOpener()

View File

@ -22,17 +22,15 @@ Implemented using the 'pytest' testing framework.
"""
import testutils
if __name__ == "__main__":
import __init__
__init__.run_using_pytest(globals())
testutils.run_using_pytest(globals())
import suds.client
import suds.sax.date
from suds.xsd.sxbuiltin import (Factory, XAny, XBoolean, XBuiltin, XDate,
XDateTime, XDecimal, XFloat, XInteger, XLong, XString, XTime)
import tests
from tests.compare_sax import CompareSAX
from testutils.compare_sax import CompareSAX
import pytest
@ -43,6 +41,8 @@ import sys
if sys.version_info >= (2, 6):
import fractions
if sys.version_info >= (3,):
long = int
class _Dummy:
@ -164,9 +164,9 @@ class TestXBoolean:
@pytest.mark.parametrize("source", (
None,
pytest.mark.skipif(sys.version_info >= (3, 0),
pytest.mark.skipif(sys.version_info >= (3,),
reason="int == long since Python 3.0")(long(0)),
pytest.mark.skipif(sys.version_info >= (3, 0),
pytest.mark.skipif(sys.version_info >= (3,),
reason="int == long since Python 3.0")(long(1)),
"x",
"True",
@ -447,13 +447,16 @@ class TestXFloat:
"""
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(ValueError, MockXFloat().translate, source).value
# Using different Python interpreter versions and different source
# strings results in different exception messages here.
try:
float(source)
pytest.fail("Bad test data.")
except ValueError, expected_e:
assert str(e) == str(expected_e)
# Using different Python interpreter versions and different source
# strings results in different exception messages here.
try:
float(source)
pytest.fail("Bad test data.")
except ValueError:
assert str(e) == str(sys.exc_info()[1])
finally:
del e # explicitly break circular reference chain in Python 3
class TestXInteger:
@ -470,10 +473,10 @@ class TestXInteger:
1,
50,
# long
pytest.mark.skipif(sys.version_info >= (3, 0),
reason="int == long since Python 3.0")(long(0)),
pytest.mark.skipif(sys.version_info >= (3, 0),
reason="int == long since Python 3.0")(long(1)),
long(-50),
long(0),
long(1),
long(50),
# str
"x",
# other
@ -504,13 +507,16 @@ class TestXInteger:
"""
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(ValueError, MockXInteger().translate, source).value
# Using different Python interpreter versions and different source
# strings results in different exception messages here.
try:
int(source)
pytest.fail("Bad test data.")
except ValueError, expected_e:
assert str(e) == str(expected_e)
# Using different Python interpreter versions and different source
# strings results in different exception messages here.
try:
int(source)
pytest.fail("Bad test data.")
except ValueError:
assert str(e) == str(sys.exc_info()[1])
finally:
del e # explicitly break circular reference chain in Python 3
class TestXLong:
@ -567,13 +573,16 @@ class TestXLong:
"""
monkeypatch.delitem(locals(), "e", False)
e = pytest.raises(ValueError, MockXLong().translate, source).value
# Using different Python interpreter versions and different source
# strings results in different exception messages here.
try:
long(source)
pytest.fail("Bad test data.")
except ValueError, expected_e:
assert str(e) == str(expected_e)
# Using different Python interpreter versions and different source
# strings results in different exception messages here.
try:
long(source)
pytest.fail("Bad test data.")
except ValueError:
assert str(e) == str(sys.exc_info()[1])
finally:
del e # explicitly break circular reference chain in Python 3
class TestXTime:
@ -678,8 +687,9 @@ def test_resolving_builtin_types(monkeypatch):
pass
Factory.maptag("osama", MockXInteger)
wsdl = tests.wsdl('<xsd:element name="wu" type="xsd:osama"/>', input="wu")
client = tests.client_from_wsdl(wsdl)
wsdl = testutils.wsdl('<xsd:element name="wu" type="xsd:osama"/>',
input="wu")
client = testutils.client_from_wsdl(wsdl)
element, schema_object = client.sd[0].params[0]
assert element.name == "wu"
@ -705,11 +715,11 @@ def test_translation(monkeypatch):
Factory.maptag("woof", MockType)
namespace = "I'm a little tea pot, short and stout..."
wsdl = tests.wsdl("""\
wsdl = testutils.wsdl("""\
<xsd:element name="wi" type="xsd:woof"/>
<xsd:element name="wo" type="xsd:woof"/>""", input="wi", output="wo",
xsd_target_namespace=namespace, operation_name="f")
client = tests.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
client = testutils.client_from_wsdl(wsdl, nosend=True, prettyxml=True)
# Check suds library's XSD schema input parameter information.
schema = client.wsdl.schema
@ -757,8 +767,8 @@ def _create_dummy_schema():
#TODO: Find out how to construct this XSD schema object directly without
# first having to construct a suds.client.Client from a complete WSDL
# schema.
wsdl = tests.wsdl('<xsd:element name="dummy"/>', input="dummy")
client = tests.client_from_wsdl(wsdl)
wsdl = testutils.wsdl('<xsd:element name="dummy"/>', input="dummy")
client = testutils.client_from_wsdl(wsdl)
return client.wsdl.schema

View File

@ -15,6 +15,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# written by: Jurko Gospodnetić ( jurko.gospodnetic@pke.hr )
"""
Package containing different utilities used for suds project testing.
"""
import suds.client
import suds.store

View File

@ -20,4 +20,4 @@ Assertion test utility functions shared between multiple test modules.
"""
from assertion__pytest_assert_rewrite_needed import *
from testutils.assertion__pytest_assert_rewrite_needed import *

View File

@ -20,4 +20,4 @@ CompareSAX test utility class.
"""
from compare_sax__pytest_assert_rewrite_needed import *
from testutils.compare_sax__pytest_assert_rewrite_needed import *

View File

@ -31,6 +31,8 @@ import suds.sax.document
import suds.sax.element
import suds.sax.parser
from six import text_type, u
import sys
@ -90,7 +92,7 @@ class CompareSAX:
"""Compares two SAX XML documents."""
self = cls()
try:
self.__document2document(lhs, rhs, context=u"document2document")
self.__document2document(lhs, rhs, context="document2document")
except Exception:
self.__report_context()
raise
@ -105,7 +107,7 @@ class CompareSAX:
"""
self = cls()
self.__push_context(u"document2element")
self.__push_context("document2element")
try:
assert document.__class__ is suds.sax.document.Document
assert element.__class__ is suds.sax.element.Element
@ -119,7 +121,7 @@ class CompareSAX:
def element2element(cls, lhs, rhs):
"""Compares two SAX XML elements."""
self = cls()
self.__push_context(u"element2element")
self.__push_context("element2element")
try:
self.__element2element(lhs, rhs)
except Exception:
@ -133,7 +135,7 @@ class CompareSAX:
try:
lhs_doc = self.__parse_data(lhs)
rhs_doc = self.__parse_data(rhs)
self.__document2document(lhs_doc, rhs_doc, context=u"data2data")
self.__document2document(lhs_doc, rhs_doc, context="data2data")
except Exception:
self.__report_context()
raise
@ -148,7 +150,7 @@ class CompareSAX:
self = cls()
try:
rhs_doc = self.__parse_data(rhs)
self.__document2document(lhs, rhs_doc, context=u"document2data")
self.__document2document(lhs, rhs_doc, context="document2data")
except Exception:
self.__report_context()
raise
@ -174,7 +176,7 @@ class CompareSAX:
"""
#TODO: Make suds SAX element model consistently represent empty/missing
# namespaces and then update both this method and its docstring.
self.__push_context(u"namespace")
self.__push_context("namespace")
lhs_namespace = lhs.namespace()[1]
rhs_namespace = rhs.namespace()[1]
if not lhs_namespace:
@ -198,7 +200,7 @@ class CompareSAX:
"""
#TODO: Make suds SAX element model consistently represent empty/missing
# text content and then update both this method and its docstring.
self.__push_context(u"text")
self.__push_context("text")
lhs_text = lhs.text
rhs_text = rhs.text
if not lhs_text:
@ -225,9 +227,11 @@ class CompareSAX:
def __element_name(element):
"""Returns a given SAX element's name as unicode or '???' on error."""
try:
return unicode(element.name)
return text_type(element.name)
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
return u"???"
return u("???")
def __element2element(self, lhs, rhs, context_info=(0, 1)):
"""
@ -266,10 +270,10 @@ class CompareSAX:
if context_lhs_name == context_rhs_name:
context_name = context_lhs_name
else:
context_name = u"%s/%s" % (context_lhs_name, context_rhs_name)
context_name = "%s/%s" % (context_lhs_name, context_rhs_name)
if count == 1:
return u"<%s>" % (context_name,)
return u"<%s(%d/%d)>" % (context_name, n + 1, count)
return "<%s>" % (context_name,)
return "<%s(%d/%d)>" % (context_name, n + 1, count)
@staticmethod
def __parse_data(data):
@ -278,7 +282,7 @@ class CompareSAX:
bytes object.
"""
if isinstance(data, unicode):
if isinstance(data, text_type):
data = data.encode("utf-8")
return suds.sax.parser.Parser().parse(string=data)
@ -291,4 +295,4 @@ class CompareSAX:
def __report_context(self):
if self.__context:
sys.stderr.write("Failed SAX XML comparison context:\n")
sys.stderr.write(u" %s\n" % (u".".join(self.__context)))
sys.stderr.write(" %s\n" % (".".join(self.__context)))

View File

@ -14,9 +14,8 @@
@for %%i in ("%~f0\..\..") do @set PROJECT_FOLDER=%%~fi
@cd /d "%PROJECT_FOLDER%"
:: Python command-line options used for running specific scripts.
:: Used pytest command-line options.
@set PYTEST_OPTIONS=-m pytest -q -x --tb=short
@set SETUP_OPTIONS=setup.py -q develop
@call :test "3.4.0 x64" "py340" || goto :fail
@call :test "2.4.3 x86" "py243" || goto :fail
@ -50,16 +49,18 @@
@setlocal
@set TITLE=%~1
@set PYTHON="%~2"
@set LOCATION=tests
@if "%TITLE:~0,1%" == "2" goto :test__skip_build
@echo ---------------------------------------------------------------
@echo --- Building suds for Python %TITLE%
@echo ---------------------------------------------------------------
@set LOCATION=build/lib/%LOCATION%
@if exist "build\" (rd /s /q build || exit /b -2)
@call %PYTHON% %SETUP_OPTIONS% || exit /b -2
@echo.
:test__skip_build
:: Install the project into the target Python environment in editable mode.
:: This will actually build Python 3 sources in case we are using a Python 3
:: environment.
@call %PYTHON% setup.py -q develop || exit /b -2
@cd tests
@echo.
@echo ---------------------------------------------------------------
@echo --- Testing suds with Python %TITLE%
@echo ---------------------------------------------------------------

View File

@ -25,6 +25,7 @@ The environments should have the following Python packages installed:
* setuptools (for installing pip)
* pip (for installing everything except itself)
* pytest (for running the project's test suite)
* six (Python 2/3 compatibility layer used in the project's test suite)
* virtualenv (for creating virtual Python environments)
plus certain specific Python versions may require additional backward
compatibility support packages.
@ -746,6 +747,7 @@ def process_pip(env, actions):
# ----------------------------------
v1_4_16 = _lowest_version_string_with_prefix("1.4_16")
v1_5 = _lowest_version_string_with_prefix("1.5")
v1_8 = _lowest_version_string_with_prefix("1.8")
v1_10 = _lowest_version_string_with_prefix("1.10")
@ -831,6 +833,15 @@ def add_pytest_requirements(env, requirements):
requirements.append(requirement_spec("pytest", pytest_version))
def add_six_requirements(env_version_info, requirements):
# six release 1.5 broke compatibility with Python 2.4.x.
if env_version_info < (2, 5):
version_spec = "<", v1_5
else:
version_spec = None
requirements.append(requirement_spec("six", version_spec))
def add_virtualenv_requirements(env_version_info, requirements):
# virtualenv releases supported on older Python versions:
# * Python 2.4 - virtualenv 1.7.2 (not supported in 1.8.x).
@ -887,6 +898,7 @@ def prepare_pip_requirements_file_if_needed(requirements):
def prepare_pip_requirements(env):
requirements = []
add_pytest_requirements(env, requirements)
add_six_requirements(env.sys_version_info, requirements)
add_virtualenv_requirements(env.sys_version_info, requirements)
janitor = prepare_pip_requirements_file_if_needed(requirements)
return requirements, janitor

View File

@ -23,6 +23,10 @@ Basic configuration support shared in different development utility scripts.
import os.path
import sys
# Must not use the six Python 2/3 compatibility package from here as this
# module gets used from the script for setting up basic development
# environments, and that script needs to be runnable even before the six
# package has been installed.
if sys.version_info < (3,):
import ConfigParser as configparser
else: