[Python-modules-commits] [pytest-httpbin] 01/06: Imported Upstream version 0.1.1
Daniel Stender
danstender-guest at moszumanska.debian.org
Thu Nov 19 17:31:11 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-httpbin.
commit 98d7365a5755073a515e51820773c10e4235f474
Author: Daniel Stender <debian at danielstender.com>
Date: Thu Nov 19 18:11:34 2015 +0100
Imported Upstream version 0.1.1
---
.travis.yml | 11 +++
DESCRIPTION.rst | 30 +++++++
MANIFEST.in | 3 +
README.md | 168 ++++++++++++++++++++++++++++++++++++++++
pytest_httpbin/__init__.py | 14 ++++
pytest_httpbin/certs.py | 21 +++++
pytest_httpbin/certs/cacert.pem | 63 +++++++++++++++
pytest_httpbin/certs/cert.pem | 73 +++++++++++++++++
pytest_httpbin/certs/key.pem | 28 +++++++
pytest_httpbin/plugin.py | 41 ++++++++++
pytest_httpbin/serve.py | 95 +++++++++++++++++++++++
pytest_httpbin/version.py | 1 +
runtests.sh | 3 +
setup.cfg | 5 ++
setup.py | 61 +++++++++++++++
tests/conftest.py | 6 ++
tests/test_httpbin.py | 53 +++++++++++++
tests/test_server.py | 62 +++++++++++++++
tests/util.py | 30 +++++++
tox.ini | 9 +++
20 files changed, 777 insertions(+)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..2e736a4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: python
+sudo: false
+python:
+- 2.6
+- 2.7
+- 3.4
+- pypy
+install:
+- pip install requests
+- python setup.py install
+script: ./runtests.sh
diff --git a/DESCRIPTION.rst b/DESCRIPTION.rst
new file mode 100644
index 0000000..4e0cba8
--- /dev/null
+++ b/DESCRIPTION.rst
@@ -0,0 +1,30 @@
+pytest-httpbin
+==============
+
+httpbin is an amazing web service for testing HTTP libraries. It has several
+great endpoints that can test pretty much everything you need in a HTTP
+library. The only problem is: maybe you don't want to wait for your tests to
+travel across the Internet and back to make assertions against a remote web
+service.
+
+Enter pytest-httpbin. Pytest-httpbin creates a pytest "fixture" that is
+dependency-injected into your tests. It automatically starts up a HTTP server
+in a separate thread running httpbin and provides your test with the URL in the
+fixture. Check out this example:
+
+.. code-block:: python
+
+ def test_that_my_library_works_kinda_ok(httpbin):
+ assert requests.get(httpbin.url + '/get/').status_code == 200
+
+This replaces a test that might have looked like this before:
+
+.. code-block:: python
+
+ def test_that_my_library_works_kinda_ok():
+ assert requests.get('http://httpbin.org/get').status_code == 200
+
+pytest-httpbin also supports https and includes its own CA cert you can use.
+Check out `the full documentation`_ on the github page.
+
+.. _the full documentation: https://github.com/kevin1024/pytest-httpbin
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..68a01e1
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,3 @@
+# If using Python 2.6 or less, then have to include package data, even though
+# it's already declared in setup.py
+include pytest_httpbin/certs/*
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..03c4adb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,168 @@
+# pytest-httpbin
+
+[](https://travis-ci.org/kevin1024/pytest-httpbin)
+
+[httpbin](https://httpbin.org/) is an amazing web service for testing HTTP libraries. It has several great endpoints that can test pretty much everything you need in a HTTP library. The only problem is: maybe you don't want to wait for your tests to travel across the Internet and back to make assertions against a remote web service (speed), and maybe you want to work offline (convenience).
+
+Enter **pytest-httpbin**. Pytest-httpbin creates a [pytest fixture](http://pytest.org/latest/fixture.html) that is dependency-injected into your tests. It automatically starts up a HTTP server in a separate thread running httpbin and provides your test with the URL in the fixture. Check out this example:
+
+```python
+def test_that_my_library_works_kinda_ok(httpbin):
+ assert requests.get(httpbin.url + '/get').status_code == 200
+```
+
+This replaces a test that might have looked like this before:
+
+```python
+def test_that_my_library_works_kinda_ok():
+ assert requests.get('http://httpbin.org/get').status_code == 200
+```
+
+If you're making a lot of requests to httpbin, it can radically speed up your tests.
+
+
+
+
+# HTTPS support
+
+pytest-httpbin also supports HTTPS:
+
+```python
+def test_that_my_library_works_kinda_ok(httpbin_secure):
+ assert requests.get(httpbin_secure.url + '/get/').status_code == 200
+```
+
+It's actually starting 2 web servers in separate threads in the background: one HTTP and one HTTPS. The servers are started on a random port, on the loopback interface on your machine. Pytest-httpbin includes a self-signed certificate. If your library verifies certificates against a CA (and it should), you'll have to add the CA from pytest-httpbin. The path to the pytest-httpbin CA bundle can by found like this `python -m pytest_httpbin.certs`.
+
+For example in requests, you can set the `REQUESTS_CA_BUNDLE` python path. You can run your tests like this:
+
+```bash
+REQUESTS_CA_BUNDLE=`python -m pytest_httpbin.certs` py.test tests/
+```
+
+# API of the injected object
+
+The injected object has the following attributes:
+
+ * url
+ * port
+ * host
+
+and the following methods:
+
+ * join(string): Returns the results of calling `urlparse.urljoin` with the url from the injected server automatically applied as the first argument. You supply the second argument
+
+Also, I defined `__add__` on the object to append to `httpbin.url`. This means you can do stuff like `httpbin + '/get'` instead of `httpbin.url + '/get'`.
+
+## Testing both HTTP and HTTPS endpoints with one test
+
+If you ever find yourself needing to test both the http and https version of and endpoint, you can use the `httpbin_both` funcarg like this:
+
+
+```python
+def test_that_my_library_works_kinda_ok(httpbin_both):
+ assert requests.get(httpbin_both.url + '/get/').status_code == 200
+```
+
+Through the magic of pytest parametrization, this function will actually execute twice: once with an http url and once with an https url.
+
+## Using pytest-httpbin with unittest-style test cases
+
+I have provided 2 additional fixtures to make testing with class-based tests easier. I have also provided a couple decorators that provide some syntactic sugar around the pytest method of adding the fixtures to class-based tests. Just add the `use_class_based_httpbin` and/or `use_class_based_httpbin_secure` class decorators to your class, and then you can access httpbin using self.httpbin and self.httpbin_secure.
+
+```python
+import pytest_httpbin
+
+ at pytest_httpbin.use_class_based_httpbin
+ at pytest_httpbin.use_class_based_httpbin_secure
+class TestClassBassedTests(unittest.TestCase):
+ def test_http(self):
+ assert requests.get(self.httpbin.url + '/get').response
+
+ def test_http_secure(self):
+ assert requests.get(self.httpbin_secure.url + '/get').response
+```
+
+## Installation
+
+All you need to do is this:
+
+```bash
+pip install pytest-httpbin
+```
+
+and your tests executed by pytest all will have access to the `httpbin` and `httpbin_secure` funcargs. Cool right?
+
+## Support and dependencies
+
+pytest-httpbin suports Python 2.6, 2.7, 3.4, and pypy. It will automatically install httpbin and flask when you install it from pypi.
+
+## Running the pytest-httpbin test suite
+
+If you want to run pytest-httpbin's test suite, you'll need to install requests and pytest, and then use the ./runtests.sh script.
+
+```bash
+pip install pytest
+/.runtests.sh
+```
+
+Also, you can use tox to run the tests on all supported python versions:
+
+```bash
+pip install tox
+tox
+```
+
+## Changelog
+
+* 0.1.1:
+ * Fix weird hang with SSL on pypy (again)
+* 0.1.0:
+ * Update server to use multithreaded werkzeug server
+* 0.0.7:
+ * Update the certificates (they expired)
+* 0.0.6:
+ * Fix an issue where pypy was hanging when a request was made with an invalid
+ certificate
+* 0.0.5:
+ * Fix broken version parsing in 0.0.4
+* 0.0.4:
+ * **Bad release: Broken version parsing**
+ * Fix `BadStatusLine` error that occurs when sending multiple requests
+ in a single session (PR #16). Thanks @msabramo!
+ * Fix #9 ("Can't be installed at the same time than pytest?") (PR
+ #14). Thanks @msabramo!
+ * Add `httpbin_ca_bundle` pytest fixture. With this fixture there is
+ no need to specify the bundle on every request, as it will
+ automatically set `REQUESTS_CA_BUNDLE` if using
+ [requests](http://docs.python-requests.org/). And you don't have to
+ care about where it is located (PR #8). Thanks @t-8ch!
+* 0.0.3: Add a couple test fixtures to make testing old class-based test suites
+ easier
+* 0.0.2: Fixed a couple bugs with the wsgiref server to bring behavior in line
+ with httpbin.org, thanks @jakubroztocil for the bug reports
+* 0.0.1: Initial release
+
+## License
+
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kevin McCarthy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/pytest_httpbin/__init__.py b/pytest_httpbin/__init__.py
new file mode 100644
index 0000000..cf3d818
--- /dev/null
+++ b/pytest_httpbin/__init__.py
@@ -0,0 +1,14 @@
+import os
+
+import pytest
+
+
+here = os.path.dirname(__file__)
+version_file = os.path.join(here, "version.py")
+
+with open(version_file) as f:
+ code = compile(f.read(), version_file, 'exec')
+ exec(code)
+
+use_class_based_httpbin = pytest.mark.usefixtures("class_based_httpbin")
+use_class_based_httpbin_secure = pytest.mark.usefixtures("class_based_httpbin_secure")
diff --git a/pytest_httpbin/certs.py b/pytest_httpbin/certs.py
new file mode 100644
index 0000000..c099cfa
--- /dev/null
+++ b/pytest_httpbin/certs.py
@@ -0,0 +1,21 @@
+"""
+certs.py
+~~~~~~~~
+
+This module returns the preferred default CA certificate bundle.
+
+If you are packaging pytest-httpbin, e.g., for a Linux distribution or a
+managed environment, you can change the definition of where() to return a
+separately packaged CA bundle.
+"""
+
+import os.path
+
+
+def where():
+ """Return the preferred certificate bundle."""
+ # vendored bundle inside Requests
+ return os.path.join(os.path.dirname(__file__), 'certs', 'cacert.pem')
+
+if __name__ == '__main__':
+ print(where())
diff --git a/pytest_httpbin/certs/cacert.pem b/pytest_httpbin/certs/cacert.pem
new file mode 100644
index 0000000..d9a47aa
--- /dev/null
+++ b/pytest_httpbin/certs/cacert.pem
@@ -0,0 +1,63 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ dd:39:30:16:60:55:90:7c
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=Hawaii, O=kevin1024, CN=pytest-httpbin Certificate Authority
+ Validity
+ Not Before: Jun 26 18:16:59 2015 GMT
+ Not After : Jun 18 18:16:59 2045 GMT
+ Subject: C=US, ST=Hawaii, O=kevin1024, CN=pytest-httpbin Certificate Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:bd:80:fd:e4:96:0e:3b:5e:35:9b:83:00:34:88:
+ 64:5a:50:53:0e:1d:94:76:c9:dc:e7:b5:59:1e:d4:
+ 82:55:36:a6:b4:41:2c:60:ad:76:f0:cd:42:a0:0f:
+ 4a:1c:0d:d7:29:da:c3:d9:c0:ea:f1:48:e0:66:4d:
+ 4b:7c:ff:d6:5e:e0:73:89:53:8b:6e:6c:57:7d:bd:
+ e9:d0:46:39:5d:85:a5:f1:3a:d4:3d:83:19:03:44:
+ 93:71:2c:5e:d7:61:8e:db:cc:80:d0:f1:c0:47:bf:
+ 98:8f:06:40:e1:f7:41:ee:ed:a7:57:0d:a6:4c:26:
+ 75:8e:f1:78:d3:80:ad:9c:e9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ AE:05:EF:BD:A9:CE:BB:A6:D8:0E:EB:C4:8C:72:2F:13:E5:CD:AA:CA
+ X509v3 Authority Key Identifier:
+ keyid:AE:05:EF:BD:A9:CE:BB:A6:D8:0E:EB:C4:8C:72:2F:13:E5:CD:AA:CA
+ DirName:/C=US/ST=Hawaii/O=kevin1024/CN=pytest-httpbin Certificate Authority
+ serial:DD:39:30:16:60:55:90:7C
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ bc:0c:b4:21:03:bf:35:bf:88:9f:de:06:23:f4:e3:8f:bc:34:
+ b5:8b:af:bf:31:5d:17:44:2c:72:c9:88:25:d1:c7:d0:1c:70:
+ 06:82:a5:fa:fa:d7:b9:16:64:c2:08:54:1e:4c:93:9f:22:4e:
+ e5:4f:a7:71:e5:6e:14:31:e9:41:e2:33:23:8b:c8:01:c3:2a:
+ 66:a8:d8:df:ef:ee:7b:bb:84:f4:78:a6:ca:8f:29:aa:d5:fa:
+ 8a:73:94:0c:32:53:c8:93:bd:fc:c4:60:4d:9a:80:4f:c6:d4:
+ 27:44:a2:37:63:6c:97:04:ce:e3:6a:6f:d3:84:0d:b4:74:1f:
+ 49:eb
+-----BEGIN CERTIFICATE-----
+MIIDBzCCAnCgAwIBAgIJAN05MBZgVZB8MA0GCSqGSIb3DQEBBQUAMGExCzAJBgNV
+BAYTAlVTMQ8wDQYDVQQIEwZIYXdhaWkxEjAQBgNVBAoTCWtldmluMTAyNDEtMCsG
+A1UEAxMkcHl0ZXN0LWh0dHBiaW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE1
+MDYyNjE4MTY1OVoXDTQ1MDYxODE4MTY1OVowYTELMAkGA1UEBhMCVVMxDzANBgNV
+BAgTBkhhd2FpaTESMBAGA1UEChMJa2V2aW4xMDI0MS0wKwYDVQQDEyRweXRlc3Qt
+aHR0cGJpbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAL2A/eSWDjteNZuDADSIZFpQUw4dlHbJ3Oe1WR7UglU2prRBLGCt
+dvDNQqAPShwN1ynaw9nA6vFI4GZNS3z/1l7gc4lTi25sV3296dBGOV2FpfE61D2D
+GQNEk3EsXtdhjtvMgNDxwEe/mI8GQOH3Qe7tp1cNpkwmdY7xeNOArZzpAgMBAAGj
+gcYwgcMwHQYDVR0OBBYEFK4F772pzrum2A7rxIxyLxPlzarKMIGTBgNVHSMEgYsw
+gYiAFK4F772pzrum2A7rxIxyLxPlzarKoWWkYzBhMQswCQYDVQQGEwJVUzEPMA0G
+A1UECBMGSGF3YWlpMRIwEAYDVQQKEwlrZXZpbjEwMjQxLTArBgNVBAMTJHB5dGVz
+dC1odHRwYmluIENlcnRpZmljYXRlIEF1dGhvcml0eYIJAN05MBZgVZB8MAwGA1Ud
+EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAvAy0IQO/Nb+In94GI/Tjj7w0tYuv
+vzFdF0QscsmIJdHH0BxwBoKl+vrXuRZkwghUHkyTnyJO5U+nceVuFDHpQeIzI4vI
+AcMqZqjY3+/ue7uE9Himyo8pqtX6inOUDDJTyJO9/MRgTZqAT8bUJ0SiN2NslwTO
+42pv04QNtHQfSes=
+-----END CERTIFICATE-----
diff --git a/pytest_httpbin/certs/cert.pem b/pytest_httpbin/certs/cert.pem
new file mode 100644
index 0000000..5d4452b
--- /dev/null
+++ b/pytest_httpbin/certs/cert.pem
@@ -0,0 +1,73 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ dd:39:30:16:60:55:90:7e
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=Hawaii, O=kevin1024, CN=pytest-httpbin Certificate Authority
+ Validity
+ Not Before: Jun 26 18:20:35 2015 GMT
+ Not After : Jun 23 18:20:35 2025 GMT
+ Subject: C=US, ST=Hawaii, O=kevin1024, OU=kevin1024, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:ce:b4:0f:0b:86:17:68:24:6f:7c:25:32:73:81:
+ bd:55:38:05:ae:09:29:00:c0:f1:99:30:5a:7f:05:
+ 9f:e7:e9:d3:ce:d0:dd:4f:73:c8:bf:65:04:94:e5:
+ 11:8e:1d:91:f0:88:85:3e:48:d3:09:5b:3f:8f:97:
+ 95:34:bf:8d:00:cb:70:d2:c1:2b:34:dd:99:1d:86:
+ 9b:90:54:a5:de:18:c4:03:3d:53:f0:dd:cc:6d:ec:
+ fb:b9:93:ab:19:85:05:63:2d:34:a6:47:42:71:3b:
+ e4:1e:4a:4c:d9:60:d4:6b:d6:51:a8:4a:30:70:2e:
+ 6c:62:a2:34:da:cf:30:34:97:a4:9d:17:72:0b:b2:
+ 37:69:e2:ca:b6:d5:9f:46:c5:eb:cf:dc:46:b0:fe:
+ ef:37:5e:4f:eb:f3:50:4d:2c:4e:c2:0c:e4:0c:63:
+ c2:d8:ab:a3:d6:a0:12:bf:d6:fc:3f:b6:4c:dc:2b:
+ 9b:c5:ae:83:4d:3b:3c:19:85:50:88:82:a2:5f:ff:
+ de:98:60:fc:12:3a:55:c3:4f:0a:e9:1f:aa:12:cb:
+ f8:ce:14:d6:ed:89:ff:c7:ea:3b:fe:97:87:54:eb:
+ 62:de:cd:ef:6b:e2:9e:47:82:77:55:59:4f:b8:ad:
+ 1b:e0:9d:1a:28:16:9f:6a:cb:b2:44:f9:65:c3:c4:
+ 03:09
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 1E:28:41:6B:12:03:41:29:64:0D:E5:C3:E3:F7:9E:82:0C:66:1E:B9
+ X509v3 Authority Key Identifier:
+ keyid:AE:05:EF:BD:A9:CE:BB:A6:D8:0E:EB:C4:8C:72:2F:13:E5:CD:AA:CA
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 67:8c:6d:a1:2f:b3:35:87:a3:c0:04:92:5d:8a:8b:f8:51:6e:
+ 94:88:59:ed:66:b2:54:b0:a2:3d:7a:05:ee:19:17:a6:0b:3b:
+ 20:f7:d2:73:2c:f0:b9:ad:2e:5d:45:11:5d:8d:33:5c:69:7f:
+ 4a:c5:8c:10:3e:35:b4:39:d7:52:66:bc:02:d8:4d:d0:ba:a1:
+ ae:55:f5:36:01:17:97:40:1a:9d:6a:e0:b8:33:be:2d:98:b7:
+ 5b:92:6a:77:a7:d9:f5:5b:a4:5f:fa:aa:5b:c1:6b:4d:0c:b7:
+ 5a:4c:47:b2:f7:90:a3:ff:6f:8c:fd:f2:60:38:53:29:71:48:
+ d7:69
+-----BEGIN CERTIFICATE-----
+MIIDODCCAqGgAwIBAgIJAN05MBZgVZB+MA0GCSqGSIb3DQEBBQUAMGExCzAJBgNV
+BAYTAlVTMQ8wDQYDVQQIEwZIYXdhaWkxEjAQBgNVBAoTCWtldmluMTAyNDEtMCsG
+A1UEAxMkcHl0ZXN0LWh0dHBiaW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE1
+MDYyNjE4MjAzNVoXDTI1MDYyMzE4MjAzNVowWjELMAkGA1UEBhMCVVMxDzANBgNV
+BAgTBkhhd2FpaTESMBAGA1UEChMJa2V2aW4xMDI0MRIwEAYDVQQLEwlrZXZpbjEw
+MjQxEjAQBgNVBAMTCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAM60DwuGF2gkb3wlMnOBvVU4Ba4JKQDA8ZkwWn8Fn+fp087Q3U9zyL9l
+BJTlEY4dkfCIhT5I0wlbP4+XlTS/jQDLcNLBKzTdmR2Gm5BUpd4YxAM9U/DdzG3s
++7mTqxmFBWMtNKZHQnE75B5KTNlg1GvWUahKMHAubGKiNNrPMDSXpJ0XcguyN2ni
+yrbVn0bF68/cRrD+7zdeT+vzUE0sTsIM5Axjwtiro9agEr/W/D+2TNwrm8Wug007
+PBmFUIiCol//3phg/BI6VcNPCukfqhLL+M4U1u2J/8fqO/6Xh1TrYt7N72vinkeC
+d1VZT7itG+CdGigWn2rLskT5ZcPEAwkCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglg
+hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
+BBYEFB4oQWsSA0EpZA3lw+P3noIMZh65MB8GA1UdIwQYMBaAFK4F772pzrum2A7r
+xIxyLxPlzarKMA0GCSqGSIb3DQEBBQUAA4GBAGeMbaEvszWHo8AEkl2Ki/hRbpSI
+We1mslSwoj16Be4ZF6YLOyD30nMs8LmtLl1FEV2NM1xpf0rFjBA+NbQ511JmvALY
+TdC6oa5V9TYBF5dAGp1q4Lgzvi2Yt1uSanen2fVbpF/6qlvBa00Mt1pMR7L3kKP/
+b4z98mA4UylxSNdp
+-----END CERTIFICATE-----
diff --git a/pytest_httpbin/certs/key.pem b/pytest_httpbin/certs/key.pem
new file mode 100644
index 0000000..041c4b6
--- /dev/null
+++ b/pytest_httpbin/certs/key.pem
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAzrQPC4YXaCRvfCUyc4G9VTgFrgkpAMDxmTBafwWf5+nTztDd
+T3PIv2UElOURjh2R8IiFPkjTCVs/j5eVNL+NAMtw0sErNN2ZHYabkFSl3hjEAz1T
+8N3Mbez7uZOrGYUFYy00pkdCcTvkHkpM2WDUa9ZRqEowcC5sYqI02s8wNJeknRdy
+C7I3aeLKttWfRsXrz9xGsP7vN15P6/NQTSxOwgzkDGPC2Kuj1qASv9b8P7ZM3Cub
+xa6DTTs8GYVQiIKiX//emGD8EjpVw08K6R+qEsv4zhTW7Yn/x+o7/peHVOti3s3v
+a+KeR4J3VVlPuK0b4J0aKBafasuyRPllw8QDCQIDAQABAoIBAQCJ//iTbwCtjLXJ
+omPebd3jyTUxjfgMAsTJy1h/uVea06ePSi6W3uxFq8G1ToG76c4HUn3yqVgLxRnY
+WhFJWCFhSHGYo1KfRtr0tWuinoDmmI40w3sJMmtLcI5WxVnT/dUs839VC/o18xBH
+kL9h2Z24KSv3OSDBpJzD9Rtogi7izK8DSQoANBMDEmPPJ5UJBLPjdZn04i6BYZCM
+U/+ZADHKXbq6I+7RAcbPJbkvrbBEP234KZvIdw1eIAIZufQBQuDhnwS0Fi9iY/EP
+awoYa9HLgFjh+iprhwh+2SDyIp8DA+4HrY1tXAyzCqjgLn/X8wifOUrZECYj1i65
+EOiryxMBAoGBAPjmvIwBRxnr1OsKX3gCFoZr+Zu5RjACD9IOSV17cv7glZQVfXBR
+REDBoL7CmZrhsW4zBK0YWz30Dx7TGBniTFJ3e8IZJ7Th8PSOhIRYWqqFQ78YBHFi
+VcpPOBswy1i8BM9FE0GyF1zusmz8Ak2hFr/IHVkIqHwWvkTI6gGhbJ2RAoGBANSZ
+OqEWJKbRX9nuRqSdROqLOtUgWXZ78yvcQaaifyZHEFSKZZjc5MXT96lVd1PyGGAY
+uyjAqdd5LiwsS9Rw1cuC5fix2ihH5KFq7EnEJA/zdy91YdO6xmAyBOtjuTHsNj93
+if4ilib290/mRKXeI1zpzzWHsvL9Az5spqlkljH5AoGAfln7ewMnCfSbCJoibrR4
+pNJpSvEZvUM+rr6L5cXGUbbGl/70x7CpekoRBOWavnI19SA3Dnvfzap4hohYosMr
+RW3cSGMmsf9Ep5E1mk2T8R5njrltf/WQYXwnmj4B7FC+DE4fgWkbzRRrRUIFFU1i
+VAcNRuZLSXruKdLoX92HWtECgYEAhpTlf3n0A8JBKkVjZOvF56/xs19CIvY+LsLE
+sIbndMTBurLNs+IJ1I3llsVqv7Je6d5eBGNKYQPuTbpQ2o//V1Bq4m88CgnQ2rpE
+EEJhDdPy3BEzt4Ph9p1Tbet4HflJMg4rRbyBTvNCBctgI5wmyLeeG2Xmy1mNhyPi
+sRLi3YkCgYEAiHMsniJc1gZBevjtnqGTPdUo0syAnkZ7RUk/Piur/c0Altkgu5vK
+I7p3DbkHBAMDjpAZs1kpfmR4sTYKke+IQDxj2pOZEyYnmQxlGdy8xxoE9dWQeDeg
+Le+R83OAKjU4LHpH7hhJMR8X60MJaWC1BDACFO35kqIzvtCYxgEoOiI=
+-----END RSA PRIVATE KEY-----
+
diff --git a/pytest_httpbin/plugin.py b/pytest_httpbin/plugin.py
new file mode 100644
index 0000000..4eb9b51
--- /dev/null
+++ b/pytest_httpbin/plugin.py
@@ -0,0 +1,41 @@
+from __future__ import absolute_import
+import pytest
+from httpbin import app as httpbin_app
+from . import serve, certs
+
+ at pytest.fixture(scope='session')
+def httpbin(request):
+ server = serve.Server(application=httpbin_app)
+ server.start()
+ request.addfinalizer(server.stop)
+ return server
+
+
+ at pytest.fixture(scope='session')
+def httpbin_secure(request):
+ server = serve.SecureServer(application=httpbin_app)
+ server.start()
+ request.addfinalizer(server.stop)
+ return server
+
+
+ at pytest.fixture(scope='session', params=['http', 'https'])
+def httpbin_both(request, httpbin, httpbin_secure):
+ if request.param == 'http':
+ return httpbin
+ elif request.param == 'https':
+ return httpbin_secure
+
+
+ at pytest.fixture(scope='class')
+def class_based_httpbin(request, httpbin):
+ request.cls.httpbin = httpbin
+
+ at pytest.fixture(scope='class')
+def class_based_httpbin_secure(request, httpbin_secure):
+ request.cls.httpbin_secure = httpbin_secure
+
+
+ at pytest.fixture(scope='function')
+def httpbin_ca_bundle(monkeypatch):
+ monkeypatch.setenv('REQUESTS_CA_BUNDLE', certs.where())
diff --git a/pytest_httpbin/serve.py b/pytest_httpbin/serve.py
new file mode 100644
index 0000000..59a8c17
--- /dev/null
+++ b/pytest_httpbin/serve.py
@@ -0,0 +1,95 @@
+import os
+import pytest_httpbin
+import threading
+import ssl
+from werkzeug.serving import ThreadedWSGIServer, load_ssl_context, WSGIRequestHandler
+from six.moves.urllib.parse import urljoin
+
+CERT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'certs')
+
+class Handler(WSGIRequestHandler):
+ server_version = 'pytest-httpbin/' + pytest_httpbin.__version__
+
+ def make_environ(self):
+ """
+ werkzeug server adds content-type text/plain to everything, this
+ removes it if it's not actually in the headers.
+ """
+ # Note: Can't use super since this is an oldstyle class in python 2.x
+ environ = super(Handler, self).make_environ().copy()
+ if self.headers.get('content-type') is None:
+ del environ['CONTENT_TYPE']
+ return environ
+
+class ThreadedWSGIServerWithSSLTimeout(ThreadedWSGIServer):
+ """
+ This whole subclass exists just to set the ssl timeout before wrapping the
+ socket. That's because on pypy, if there's an SSL failure opening the
+ connection, it will hang forever.
+ """
+
+ def __init__(self, *args, **kwargs):
+ self.protocol = kwargs.pop('protocol')
+ super(ThreadedWSGIServerWithSSLTimeout, self).__init__(*args, **kwargs)
+
+ def finish_request(self, request, client_address):
+ """
+ Negotiates SSL and then mimics BaseServer behavior.
+ """
+ if self.protocol == 'https':
+ request.settimeout(1.0)
+ ssock = ssl.wrap_socket(
+ request,
+ keyfile=os.path.join(CERT_DIR, 'key.pem'),
+ certfile=os.path.join(CERT_DIR, 'cert.pem'),
+ server_side=True
+ )
+ self.RequestHandlerClass(ssock, client_address, self)
+ else:
+ self.RequestHandlerClass(request, client_address, self)
+
+class Server(threading.Thread):
+ """
+ HTTP server running a WSGI application in its own thread.
+ """
+
+ def __init__(self, host='127.0.0.1', port=0, application=None, protocol='http', **kwargs):
+ self.app = application
+ self._server = ThreadedWSGIServerWithSSLTimeout(
+ host,
+ port,
+ self.app,
+ handler=Handler,
+ protocol=protocol,
+ **kwargs
+ )
+ self.host = self._server.server_address[0]
+ self.port = self._server.server_address[1]
+ self.protocol = protocol
+
+ super(Server, self).__init__(
+ name=self.__class__,
+ target=self._server.serve_forever,
+ )
+
+ def __del__(self):
+ self.stop()
+
+ def __add__(self, other):
+ return self.url + other
+
+ def stop(self):
+ self._server.shutdown()
+
+ @property
+ def url(self):
+ return '{0}://{1}:{2}'.format(self.protocol, self.host, self.port)
+
+ def join(self, url, allow_fragments=True):
+ return urljoin(self.url, url, allow_fragments=allow_fragments)
+
+
+class SecureServer(Server):
+ def __init__(self, host='127.0.0.1', port=0, application=None, **kwargs):
+ super(SecureServer, self).__init__(host, port, application, protocol='https', **kwargs)
+ self.protocol = 'https'
diff --git a/pytest_httpbin/version.py b/pytest_httpbin/version.py
new file mode 100644
index 0000000..df9144c
--- /dev/null
+++ b/pytest_httpbin/version.py
@@ -0,0 +1 @@
+__version__ = '0.1.1'
diff --git a/runtests.sh b/runtests.sh
new file mode 100755
index 0000000..6115f03
--- /dev/null
+++ b/runtests.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+py.test $1 -v -s
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..79bc678
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[bdist_wheel]
+# This flag says that the code is written to work on both Python 2 and Python
+# 3. If at all possible, it is good practice to do this. If you cannot, you
+# will need to generate wheels for each Python version that you support.
+universal=1
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..11c649c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,61 @@
+from setuptools import setup, find_packages
+import codecs
+import os
+import re
+
+with open("pytest_httpbin/version.py") as f:
+ code = compile(f.read(), "pytest_httpbin/version.py", 'exec')
+ exec(code)
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+# Get the long description from the relevant file
+with codecs.open(os.path.join(here, 'DESCRIPTION.rst'), encoding='utf-8') as f:
+ long_description = f.read()
+
+setup(
+ name="pytest-httpbin",
+
+ # There are various approaches to referencing the version. For a discussion,
+ # see http://packaging.python.org/en/latest/tutorial.html#version
+ version=__version__,
+
+ description="Easily test your HTTP library against a local copy of httpbin",
+ long_description=long_description,
+
+ # The project URL.
+ url='https://github.com/kevin1024/pytest-httpbin',
+
+ # Author details
+ author='Kevin McCarthy',
+ author_email='me at kevinmccarthy.org',
+
+ # Choose your license
+ license='MIT',
+
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Intended Audience :: Developers',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: Software Development :: Libraries',
+ 'License :: OSI Approved :: MIT License',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ ],
+
+ # What does your project relate to?
+ keywords='pytest-httpbin testing pytest httpbin',
+ packages=find_packages(exclude=["contrib", "docs", "tests*"]),
+ include_package_data = True, # include files listed in MANIFEST.in
+ install_requires = ['Flask','decorator','httpbin','six'],
+
+ # the following makes a plugin available to pytest
+ entry_points = {
+ 'pytest11': [
+ 'httpbin = pytest_httpbin.plugin',
+ ]
+ },
+)
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..0d5df6d
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,6 @@
+import pytest
+
+from pytest_httpbin.plugin import httpbin_ca_bundle
+
+
+pytest.fixture(autouse=True)(httpbin_ca_bundle)
diff --git a/tests/test_httpbin.py b/tests/test_httpbin.py
new file mode 100644
index 0000000..35eddbf
--- /dev/null
+++ b/tests/test_httpbin.py
@@ -0,0 +1,53 @@
+import unittest
+import requests
+import pytest_httpbin
+
+
+def test_httpbin_gets_injected(httpbin):
+ assert httpbin.url
+
+
+def test_httpbin_accepts_get_requests(httpbin):
+ assert requests.get(httpbin.url + '/get').status_code == 200
+
+
+def test_httpbin_secure_accepts_get_requests(httpbin_secure):
+ assert requests.get(httpbin_secure.url + '/get').status_code == 200
+
+
+def test_httpbin_secure_accepts_lots_of_get_requests(httpbin_secure):
+ for i in range(10):
+ assert requests.get(httpbin_secure.url + '/get').status_code == 200
+
+
+def test_httpbin_accepts_lots_of_get_requests_in_single_session(httpbin):
+ session = requests.Session()
+
+ for i in range(10):
+ assert session.get(httpbin.url + '/get').status_code == 200
+
+
+def test_httpbin_both(httpbin_both):
+ # this test will get called twice, once with an http url, once with an
+ # https url
+ assert requests.get(httpbin_both.url + '/get').status_code == 200
+
+
+def test_httpbin_join(httpbin):
+ assert httpbin.join('foo') == httpbin.url + '/foo'
+
+
+def test_httpbin_str(httpbin):
+ assert httpbin + '/foo' == httpbin.url + '/foo'
+
+def test_chunked_encoding(httpbin_both):
+ assert requests.get(httpbin_both.url + '/stream/20').status_code == 200
+
+ at pytest_httpbin.use_class_based_httpbin
+ at pytest_httpbin.use_class_based_httpbin_secure
+class TestClassBassedTests(unittest.TestCase):
+ def test_http(self):
+ assert requests.get(self.httpbin.url + '/get').status_code == 200
+
+ def test_http_secure(self):
+ assert requests.get(self.httpbin_secure.url + '/get').status_code == 200
diff --git a/tests/test_server.py b/tests/test_server.py
new file mode 100644
index 0000000..38d5c65
--- /dev/null
+++ b/tests/test_server.py
@@ -0,0 +1,62 @@
+# coding=utf8
+# -*- coding: utf8 -*-
+# vim: set fileencoding=utf8 :
+
+import requests
+import pytest
+from util import get_raw_http_response
+
+try:
+ from multiprocessing.pool import ThreadPool
+except ImportError:
+ ThreadPool = None
+
+
+def test_content_type_header_not_automatically_added(httpbin):
+ """
+ The server was automatically adding this for some reason, see issue #5
+ """
+ resp = requests.get(httpbin + '/headers').json()['headers']
+ assert 'Content-Type' not in resp
+
+
+def test_unicode_data(httpbin):
+ """
+ UTF-8 was not getting recognized for what it was and being encoded as if it
+ was binary, see issue #7
+ """
+ resp = requests.post(
+ httpbin + '/post',
+ data=u'оживлённым'.encode('utf-8'),
+ headers={
+ 'content-type': 'text/html; charset=utf-8',
+ }
+ )
+ assert resp.json()['data'] == u'оживлённым'
+
+
+
+def test_server_should_handle_concurrent_connections(httpbin):
+ url = httpbin + '/get'
+ session = requests.Session()
+
+ def do_request(i):
+ r = session.get(url)
+ if ThreadPool is not None:
+ pool = ThreadPool(processes=50)
+ pool.map(do_request, range(100))
+
+
+def test_dont_crash_on_certificate_problems(httpbin_secure):
+ with pytest.raises(Exception):
+ # this request used to hang
+ requests.get(
+ httpbin_secure + '/get',
+ verify = True,
+ cert=__file__
+ )
+ # and this request would never happen
+ requests.get(
+ httpbin_secure + '/get',
+ verify = True,
+ )
diff --git a/tests/util.py b/tests/util.py
new file mode 100644
index 0000000..23063db
--- /dev/null
+++ b/tests/util.py
@@ -0,0 +1,30 @@
+import socket
+
+
+def get_raw_http_response(host, port, path):
+
+ CRLF = b"\r\n"
+
+ request = [
+ b"GET " + path.encode('ascii') + b" HTTP/1.1",
+ b"Host: " + host.encode('ascii'),
+ b"Connection: Close",
+ b"",
+ b"",
+ ]
+
+ # Connect to the server
+ s = socket.socket()
+ s.connect((host, port))
+
+ # Send an HTTP request
+ s.send(CRLF.join(request))
+
+ # Get the response (in several parts, if necessary)
+ response = b''
+ buffer = s.recv(4096)
+ while buffer:
+ response += buffer
+ buffer = s.recv(4096)
+
+ return response
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..472b865
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,9 @@
+# content of: tox.ini , put in same dir as setup.py
+
+[tox]
+envlist = py26, py27, py33, py34, pypy
+
+[testenv]
+deps = pytest
+ requests
+commands = ./runtests.sh {posargs:tests/}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pytest-httpbin.git
More information about the Python-modules-commits
mailing list