[Python-modules-commits] [pytest-tornado] 01/02: Imported Upstream version 0.4.4
Daniel Stender
danstender-guest at moszumanska.debian.org
Mon Jul 20 07:25:37 UTC 2015
This is an automated email from the git hooks/post-receive script.
danstender-guest pushed a commit to branch master
in repository pytest-tornado.
commit b37b6fb3c2b3f307bb080e51e81214d3ade565af
Author: Daniel Stender <debian at danielstender.com>
Date: Mon Jul 20 09:23:17 2015 +0200
Imported Upstream version 0.4.4
---
.coveralls.yml | 2 +
.gitignore | 55 ++++++++++
.travis.yml | 17 +++
LICENSE | 202 +++++++++++++++++++++++++++++++++++
README.rst | 114 ++++++++++++++++++++
pytest_tornado/__init__.py | 0
pytest_tornado/plugin.py | 156 +++++++++++++++++++++++++++
pytest_tornado/test/test_async.py | 90 ++++++++++++++++
pytest_tornado/test/test_fixtures.py | 27 +++++
pytest_tornado/test/test_param.py | 73 +++++++++++++
pytest_tornado/test/test_server.py | 70 ++++++++++++
setup.cfg | 2 +
setup.py | 41 +++++++
13 files changed, 849 insertions(+)
diff --git a/.coveralls.yml b/.coveralls.yml
new file mode 100644
index 0000000..6b11c80
--- /dev/null
+++ b/.coveralls.yml
@@ -0,0 +1,2 @@
+service_name: travis-ci
+parallel: true # if the CI is running your build in parallel
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6f5820e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,55 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+.ropeproject/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e3f0f6a
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: python
+python:
+ - 2.7
+ - 3.4
+env:
+ - TORNADO_VERSION=4.1 PYTEST_VERSION=2.7.0
+ - TORNADO_VERSION=4.1 PYTEST_VERSION=2.6.4
+ - TORNADO_VERSION=3.2.2 PYTEST_VERSION=2.6.4
+ - TORNADO_VERSION=3.2.2 PYTEST_VERSION=2.5.2
+install:
+ - pip install -q tornado==$TORNADO_VERSION pytest==$PYTEST_VERSION
+ - python setup.py install
+ - pip install pytest-cov coveralls
+script:
+ - py.test --strict --cov=pytest_tornado/plugin.py --cov-report=term-missing
+after_success:
+ - coveralls
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..16b925b
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,114 @@
+pytest-tornado
+==============
+
+.. image:: https://travis-ci.org/eugeniy/pytest-tornado.svg?branch=master
+ :target: https://travis-ci.org/eugeniy/pytest-tornado
+
+.. image:: https://coveralls.io/repos/eugeniy/pytest-tornado/badge.svg
+ :target: https://coveralls.io/r/eugeniy/pytest-tornado
+
+A py.test_ plugin providing fixtures and markers to simplify testing
+of asynchronous tornado applications.
+
+Installation
+------------
+
+::
+
+ pip install pytest-tornado
+
+
+Example
+-------
+
+.. code-block:: python
+
+ import pytest
+ import tornado.web
+
+ class MainHandler(tornado.web.RequestHandler):
+ def get(self):
+ self.write("Hello, world")
+
+ application = tornado.web.Application([
+ (r"/", MainHandler),
+ ])
+
+ @pytest.fixture
+ def app():
+ return application
+
+ @pytest.mark.gen_test
+ def test_hello_world(http_client, base_url):
+ response = yield http_client.fetch(base_url)
+ assert response.code == 200
+
+
+Running tests
+-------------
+
+::
+
+ py.test
+
+
+Fixtures
+--------
+
+io_loop
+ creates an instance of the `tornado.ioloop.IOLoop`_ for each test case
+
+http_port
+ get a port used by the test server
+
+base_url
+ get an absolute base url for the test server,
+ for example, ``http://localhost:59828``
+
+http_server
+ start a tornado HTTP server, you must create an ``app`` fixture,
+ which returns the `tornado.web.Application`_ to be tested
+
+http_client
+ get an asynchronous HTTP client
+
+
+Show fixtures provided by the plugin::
+
+ py.test --fixtures
+
+
+Markers
+-------
+
+A ``gen_test`` marker lets you write a coroutine-style tests used with the
+`tornado.gen`_ module:
+
+.. code-block:: python
+
+ @pytest.mark.gen_test
+ def test_tornado(http_client):
+ response = yield http_client.fetch('http://www.tornadoweb.org/')
+ assert response.code == 200
+
+
+Marked tests will time out after 5 seconds. The timeout can be modified by
+setting an ``ASYNC_TEST_TIMEOUT`` environment variable,
+``--async-test-timeout`` command line argument or a marker argument.
+
+.. code-block:: python
+
+ @pytest.mark.gen_test(timeout=5)
+ def test_tornado(http_client):
+ yield http_client.fetch('http://www.tornadoweb.org/')
+
+
+Show markers provided by the plugin::
+
+ py.test --markers
+
+
+.. _py.test: http://pytest.org/
+.. _`tornado.ioloop.IOLoop`: http://tornado.readthedocs.org/en/latest/ioloop.html#ioloop-objects
+.. _`tornado.web.Application`: http://tornado.readthedocs.org/en/latest/web.html#application-configuration
+.. _`tornado.gen`: http://tornado.readthedocs.org/en/latest/gen.html
diff --git a/pytest_tornado/__init__.py b/pytest_tornado/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pytest_tornado/plugin.py b/pytest_tornado/plugin.py
new file mode 100644
index 0000000..21a6f62
--- /dev/null
+++ b/pytest_tornado/plugin.py
@@ -0,0 +1,156 @@
+import os
+import types
+import inspect
+import functools
+import pytest
+import tornado
+import tornado.gen
+import tornado.testing
+import tornado.httpserver
+import tornado.httpclient
+
+
+def _get_async_test_timeout():
+ try:
+ return float(os.environ.get('ASYNC_TEST_TIMEOUT'))
+ except (ValueError, TypeError):
+ return 5
+
+
+def pytest_addoption(parser):
+ parser.addoption('--async-test-timeout', type=float,
+ default=_get_async_test_timeout(),
+ help='timeout in seconds before failing the test')
+ parser.addoption('--app-fixture', default='app',
+ help='fixture name returning a tornado application')
+
+
+def pytest_configure(config):
+ config.addinivalue_line("markers",
+ "gen_test(timeout=None): "
+ "mark the test as asynchronous, it will be "
+ "run using tornado's event loop")
+
+
+def _argnames(func):
+ spec = inspect.getargspec(func)
+ if spec.defaults:
+ return spec.args[:-len(spec.defaults)]
+ if isinstance(func, types.FunctionType):
+ return spec.args
+ # Func is a bound method, skip "self"
+ return spec.args[1:]
+
+
+def _timeout(item):
+ default_timeout = item.config.getoption('async_test_timeout')
+ gen_test = item.get_marker('gen_test')
+ if gen_test:
+ return gen_test.kwargs.get('timeout', default_timeout)
+ return default_timeout
+
+
+ at pytest.mark.tryfirst
+def pytest_pycollect_makeitem(collector, name, obj):
+ if collector.funcnamefilter(name) and inspect.isgeneratorfunction(obj):
+ item = pytest.Function(name, parent=collector)
+ if 'gen_test' in item.keywords:
+ return list(collector._genfunctions(name, obj))
+
+
+def pytest_runtest_setup(item):
+ if 'gen_test' in item.keywords and 'io_loop' not in item.fixturenames:
+ # inject an event loop fixture for all async tests
+ item.fixturenames.append('io_loop')
+
+
+ at pytest.mark.tryfirst
+def pytest_pyfunc_call(pyfuncitem):
+ if 'gen_test' in pyfuncitem.keywords:
+ io_loop = pyfuncitem.funcargs.get('io_loop')
+
+ funcargs = dict((arg, pyfuncitem.funcargs[arg])
+ for arg in _argnames(pyfuncitem.obj))
+
+ coroutine = tornado.gen.coroutine(pyfuncitem.obj)
+ io_loop.run_sync(functools.partial(coroutine, **funcargs),
+ timeout=_timeout(pyfuncitem))
+
+ # prevent other pyfunc calls from executing
+ return True
+
+
+ at pytest.fixture
+def io_loop(request):
+ """Create an instance of the `tornado.ioloop.IOLoop` for each test case.
+ """
+ io_loop = tornado.ioloop.IOLoop()
+ io_loop.make_current()
+
+ def _close():
+ io_loop.clear_current()
+ if (not tornado.ioloop.IOLoop.initialized() or
+ io_loop is not tornado.ioloop.IOLoop.instance()):
+ io_loop.close(all_fds=True)
+
+ request.addfinalizer(_close)
+ return io_loop
+
+
+ at pytest.fixture
+def _unused_port():
+ return tornado.testing.bind_unused_port()
+
+
+ at pytest.fixture
+def http_port(_unused_port):
+ """Get a port used by the test server.
+ """
+ return _unused_port[1]
+
+
+ at pytest.fixture
+def base_url(http_port):
+ """Create an absolute base url (scheme://host:port)
+ """
+ return 'http://localhost:%s' % http_port
+
+
+ at pytest.fixture
+def http_server(request, io_loop, _unused_port):
+ """Start a tornado HTTP server.
+
+ You must create an `app` fixture, which returns
+ the `tornado.web.Application` to be tested.
+
+ Raises:
+ FixtureLookupError: tornado application fixture not found
+ """
+ http_app = request.getfuncargvalue(request.config.option.app_fixture)
+ server = tornado.httpserver.HTTPServer(http_app, io_loop=io_loop)
+ server.add_socket(_unused_port[0])
+
+ def _stop():
+ server.stop()
+
+ if hasattr(server, 'close_all_connections'):
+ io_loop.run_sync(server.close_all_connections,
+ timeout=request.config.option.async_test_timeout)
+
+ request.addfinalizer(_stop)
+ return server
+
+
+ at pytest.fixture
+def http_client(request, http_server):
+ """Get an asynchronous HTTP client.
+ """
+ client = tornado.httpclient.AsyncHTTPClient(io_loop=http_server.io_loop)
+
+ def _close():
+ if (not tornado.ioloop.IOLoop.initialized() or
+ client.io_loop is not tornado.ioloop.IOLoop.instance()):
+ client.close()
+
+ request.addfinalizer(_close)
+ return client
diff --git a/pytest_tornado/test/test_async.py b/pytest_tornado/test/test_async.py
new file mode 100644
index 0000000..cd70534
--- /dev/null
+++ b/pytest_tornado/test/test_async.py
@@ -0,0 +1,90 @@
+import functools
+import pytest
+from tornado import gen
+from tornado.ioloop import TimeoutError
+
+
+ at gen.coroutine
+def dummy_coroutine(io_loop):
+ yield gen.Task(io_loop.add_callback)
+ raise gen.Return(True)
+
+
+def test_explicit_start_and_stop(io_loop):
+ future = dummy_coroutine(io_loop)
+ future.add_done_callback(lambda *args: io_loop.stop())
+ io_loop.start()
+ assert future.result()
+
+
+def test_run_sync(io_loop):
+ dummy = functools.partial(dummy_coroutine, io_loop)
+ finished = io_loop.run_sync(dummy)
+ assert finished
+
+
+ at pytest.mark.gen_test
+def test_gen_test_sync(io_loop):
+ assert True
+
+
+ at pytest.mark.gen_test
+def test_gen_test(io_loop):
+ result = yield dummy_coroutine(io_loop)
+ assert result
+
+
+ at pytest.mark.gen_test
+def test_gen_test_swallows_exceptions(io_loop):
+ with pytest.raises(ZeroDivisionError):
+ 1 / 0
+
+
+ at pytest.mark.gen_test
+def test_generator_raises(io_loop):
+ with pytest.raises(ZeroDivisionError):
+ yield gen.Task(io_loop.add_callback)
+ 1 / 0
+
+
+ at pytest.mark.gen_test
+def test_explicit_gen_test_marker(request, io_loop):
+ yield gen.Task(io_loop.add_callback)
+ assert 'gen_test' in request.keywords
+
+
+ at pytest.mark.gen_test(timeout=2.1)
+def test_gen_test_marker_with_params(request, io_loop):
+ yield gen.Task(io_loop.add_callback)
+ assert request.keywords['gen_test'].kwargs['timeout'] == 2.1
+
+
+ at pytest.mark.xfail(raises=TimeoutError)
+ at pytest.mark.gen_test(timeout=0.1)
+def test_gen_test_with_timeout(io_loop):
+ yield gen.Task(io_loop.add_timeout, io_loop.time() + 1)
+
+
+def test_sync_tests_no_gen_test_marker(request):
+ assert 'gen_test' not in request.keywords
+
+
+def test_generators_with_disabled_gen_test_marker():
+ def _dummy(a, b):
+ assert a*3 == b
+
+ for i in range(3):
+ yield _dummy, i, i*3
+
+
+class TestClass:
+ @pytest.mark.gen_test
+ def test_gen_test(self, io_loop):
+ result = yield dummy_coroutine(io_loop)
+ assert result
+
+ @pytest.mark.gen_test
+ def test_generator_raises(self, io_loop):
+ with pytest.raises(ZeroDivisionError):
+ yield gen.Task(io_loop.add_callback)
+ 1 / 0
diff --git a/pytest_tornado/test/test_fixtures.py b/pytest_tornado/test/test_fixtures.py
new file mode 100644
index 0000000..ca8fc9d
--- /dev/null
+++ b/pytest_tornado/test/test_fixtures.py
@@ -0,0 +1,27 @@
+import pytest
+from tornado import gen
+
+_used_fixture = False
+
+
+ at gen.coroutine
+def dummy(io_loop):
+ yield gen.Task(io_loop.add_callback)
+ raise gen.Return(True)
+
+
+ at pytest.fixture(scope='module')
+def preparations():
+ global _used_fixture
+ _used_fixture = True
+
+
+pytestmark = pytest.mark.usefixtures('preparations')
+
+
+ at pytest.mark.xfail(pytest.__version__ < '2.7.0',
+ reason='py.test 2.7 adds hookwrapper, fixes collection')
+ at pytest.mark.gen_test
+def test_uses_pytestmark_fixtures(io_loop):
+ assert (yield dummy(io_loop))
+ assert _used_fixture
diff --git a/pytest_tornado/test/test_param.py b/pytest_tornado/test/test_param.py
new file mode 100644
index 0000000..11602a4
--- /dev/null
+++ b/pytest_tornado/test/test_param.py
@@ -0,0 +1,73 @@
+import pytest
+from tornado import gen
+
+DUMMY_PARAMS = ['f00', 'bar']
+
+
+ at pytest.fixture(params=DUMMY_PARAMS)
+def _dummy(request):
+ return request.param
+
+
+ at pytest.mark.parametrize('input,expected', [
+ ('3+5', 8),
+ ('2+4', 6),
+])
+def test_eval(input, expected):
+ assert eval(input) == expected
+
+
+ at pytest.mark.parametrize('input,expected', [
+ ('3+5', 8),
+ ('2+4', 6),
+ pytest.mark.xfail(("6*9", 42)),
+])
+def test_eval_marking(input, expected):
+ assert eval(input) == expected
+
+
+ at pytest.mark.parametrize('input,expected', [
+ ('3+5', 8),
+ ('2+4', 6),
+])
+ at pytest.mark.gen_test
+def test_sync_eval_with_gen_test(input, expected):
+ assert eval(input) == expected
+
+
+ at pytest.mark.parametrize('input,expected', [
+ ('3+5', 8),
+ ('2+4', 6),
+])
+def test_eval_with_fixtures(input, io_loop, expected):
+ assert eval(input) == expected
+
+
+def test_param_fixture(_dummy):
+ assert _dummy in DUMMY_PARAMS
+
+
+ at pytest.mark.gen_test
+ at pytest.mark.parametrize('input,expected', [
+ ('3+5', 8),
+ ('2+4', 6),
+])
+def test_gen_test_parametrize(io_loop, input, expected):
+ yield gen.Task(io_loop.add_callback)
+ assert eval(input) == expected
+
+
+ at pytest.mark.parametrize('input,expected', [
+ ('3+5', 8),
+ ('2+4', 6),
+])
+ at pytest.mark.gen_test
+def test_gen_test_fixture_any_order(input, io_loop, expected):
+ yield gen.Task(io_loop.add_callback)
+ assert eval(input) == expected
+
+
+ at pytest.mark.gen_test
+def test_gen_test_param_fixture(io_loop, _dummy):
+ yield gen.Task(io_loop.add_callback)
+ assert _dummy in DUMMY_PARAMS
diff --git a/pytest_tornado/test/test_server.py b/pytest_tornado/test/test_server.py
new file mode 100644
index 0000000..6b6bb55
--- /dev/null
+++ b/pytest_tornado/test/test_server.py
@@ -0,0 +1,70 @@
+import functools
+import pytest
+import tornado.ioloop
+import tornado.web
+
+
+class MainHandler(tornado.web.RequestHandler):
+ def get(self):
+ self.write('Hello, world')
+
+
+application = tornado.web.Application([
+ (r'/', MainHandler),
+ (r'/f00', MainHandler),
+])
+
+
+ at pytest.fixture(scope='module')
+def app():
+ return application
+
+
+def _fetch(http_client, url):
+ return http_client.io_loop.run_sync(
+ functools.partial(http_client.fetch, url))
+
+
+def test_http_server(http_server):
+ status = {'done': False}
+
+ def _done():
+ status['done'] = True
+ http_server.io_loop.stop()
+
+ http_server.io_loop.add_callback(_done)
+ http_server.io_loop.start()
+
+ assert status['done']
+
+
+def test_http_client(http_client, base_url):
+ request = http_client.fetch(base_url)
+ request.add_done_callback(lambda future: http_client.io_loop.stop())
+ http_client.io_loop.start()
+
+ response = request.result()
+ assert response.code == 200
+
+
+def test_http_client_with_fetch_helper(http_client, base_url):
+ response = _fetch(http_client, base_url)
+ assert response.code == 200
+
+
+ at pytest.mark.gen_test
+def test_http_client_with_gen_test(http_client, base_url):
+ response = yield http_client.fetch(base_url)
+ assert response.code == 200
+
+
+ at pytest.mark.gen_test
+def test_get_url_with_path(http_client, base_url):
+ response = yield http_client.fetch('%s/f00' % base_url)
+ assert response.code == 200
+
+
+ at pytest.mark.gen_test
+def test_http_client_raises_on_404(http_client, base_url):
+ with pytest.raises(tornado.httpclient.HTTPError):
+ yield http_client.fetch('%s/bar' % base_url)
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..3c6e79c
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal=1
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..6e3561c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,41 @@
+import os
+import io
+from setuptools import setup, find_packages
+
+
+cwd = os.path.abspath(os.path.dirname(__file__))
+
+with io.open(os.path.join(cwd, 'README.rst'), encoding='utf-8') as fd:
+ long_description = fd.read()
+
+
+setup(
+ name='pytest-tornado',
+ version='0.4.4',
+ description=('A py.test plugin providing fixtures and markers '
+ 'to simplify testing of asynchronous tornado applications.'),
+ long_description=long_description,
+ url='https://github.com/eugeniy/pytest-tornado',
+ author='Eugeniy Kalinin',
+ author_email='burump at gmail.com',
+ license='Apache License, Version 2.0',
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Plugins',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Software Development',
+ 'Topic :: Software Development :: Testing',
+ ],
+ keywords=('pytest py.test tornado async asynchronous '
+ 'testing unit tests plugin'),
+ packages=find_packages(),
+ install_requires=['pytest', 'tornado'],
+ entry_points={
+ 'pytest11': ['tornado = pytest_tornado.plugin'],
+ },
+)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pytest-tornado.git
More information about the Python-modules-commits
mailing list