jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/329644 )
Change subject: Using pytest-httpbin
......................................................................
Using pytest-httpbin
Now http_tests use pytest-httpbin if pytest is used to run the tests
Otherwise,
http://httpbin.org is used
Bug: T153560
Change-Id: I2000fed5e5273dbfef5d51ac81698a32c7fc5676
---
M dev-requirements.txt
M tests/aspects.py
A tests/conftest.py
M tests/http_tests.py
4 files changed, 97 insertions(+), 34 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/dev-requirements.txt b/dev-requirements.txt
index edd5005..44a3038 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -7,6 +7,7 @@
pytest-runner
pytest-cov
pytest-attrib
+pytest-httpbin
six
diff --git a/tests/aspects.py b/tests/aspects.py
index 3ac9ca6..305c4be 100644
--- a/tests/aspects.py
+++ b/tests/aspects.py
@@ -29,6 +29,7 @@
UITestCase:
Not integrated; direct subclass of unittest.TestCase.
"""
+import imp
import inspect
import itertools
import os
@@ -483,6 +484,20 @@
if not hasattr(cls, 'sites'):
return
+ # Check is pytest is used and pytest_httpbin module is installed.
+ if hasattr(sys, '_test_runner_pytest'):
+ try:
+ imp.find_module('pytest_httpbin')
+ httpbin_used = True
+ except ImportError:
+ httpbin_used = False
+ else:
+ httpbin_used = False
+
+ # If pytest_httpbin will be used during tests, then remove httpbin.org from
sites.
+ if httpbin_used:
+ cls.sites = {k: v for k, v in cls.sites.items() if 'httpbin.org' not
in v['hostname']}
+
for key, data in cls.sites.items():
if 'hostname' not in data:
raise Exception('%s: hostname not defined for %s'
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..24965e0
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+"""Used by pytest to do some preparation work before running
tests."""
+#
+# (C) Pywikibot team, 2017
+#
+# Distributed under the terms of the MIT license.
+#
+from __future__ import absolute_import, unicode_literals
+
+import sys
+
+
+def pytest_configure(config):
+ """Set the sys._test_runner_pytest flag to True, if pytest is used to
run tests."""
+ sys._test_runner_pytest = True
diff --git a/tests/http_tests.py b/tests/http_tests.py
index e62b390..72db94c 100644
--- a/tests/http_tests.py
+++ b/tests/http_tests.py
@@ -27,6 +27,56 @@
from tests import join_images_path
from tests.aspects import unittest, TestCase, DeprecationTestCase, require_modules
+try:
+ import pytest_httpbin
+ optional_pytest_httpbin_cls_decorator = pytest_httpbin.use_class_based_httpbin
+except ImportError:
+ pytest_httpbin = None
+
+ def optional_pytest_httpbin_cls_decorator(f):
+ """Empty decorator in case pytest_httpbin is not
installed."""
+ return f
+
+
+@optional_pytest_httpbin_cls_decorator
+class HttpbinTestCase(TestCase):
+
+ """
+ Custom test case class, which allows doing dry httpbin tests using pytest-httpbin.
+
+ Test cases, which use httpbin, need to inherit this class.
+ """
+
+ sites = {
+ 'httpbin': {
+ 'hostname': 'httpbin.org',
+ },
+ }
+
+ def get_httpbin_url(self, path=''):
+ """
+ Return url of httpbin.
+
+ If pytest is used, returns url of local httpbin server.
+ Otherwise, returns:
http://httpbin.org
+ """
+ if hasattr(self, 'httpbin'):
+ return self.httpbin.url + path
+ else:
+ return 'http://httpbin.org' + path
+
+ def get_httpbin_hostname(self):
+ """
+ Return httpbin hostname.
+
+ If pytest is used, returns hostname of local httpbin server.
+ Otherwise, returns: httpbin.org
+ """
+ if hasattr(self, 'httpbin'):
+ return '{0}:{1}'.format(self.httpbin.host, self.httpbin.port)
+ else:
+ return 'httpbin.org'
+
class HttpTestCase(TestCase):
@@ -157,7 +207,7 @@
'InsecureRequestWarning')
-class TestHttpStatus(TestCase):
+class TestHttpStatus(HttpbinTestCase):
"""Test HTTP status code handling and errors."""
@@ -177,7 +227,7 @@
"""Test that a HTTP 504 raises the correct
exception."""
self.assertRaises(pywikibot.Server504Error,
http.fetch,
-
uri='http://httpbin.org/status/504')
+ uri=self.get_httpbin_url('/status/504'))
def test_server_not_found(self):
"""Test server not found exception."""
@@ -316,15 +366,9 @@
self._test_fake_user_agent_randomness()
-class LiveFakeUserAgentTestCase(TestCase):
+class LiveFakeUserAgentTestCase(HttpbinTestCase):
"""Test the usage of fake user agent."""
-
- sites = {
- 'httpbin': {
- 'hostname': 'httpbin.org',
- },
- }
def setUp(self):
"""Set up the unit test."""
@@ -340,22 +384,22 @@
"""Test `use_fake_user_agent` argument of
http.fetch."""
# Existing headers
r = http.fetch(
- 'http://httpbin.org/status/200', headers={'user-agent':
'EXISTING'})
+ self.get_httpbin_url('/status/200'), headers={'user-agent':
'EXISTING'})
self.assertEqual(r.headers['user-agent'], 'EXISTING')
# Argument value changes
- r = http.fetch('http://httpbin.org/status/200',
use_fake_user_agent=True)
+ r = http.fetch(self.get_httpbin_url('/status/200'),
use_fake_user_agent=True)
self.assertNotEqual(r.headers['user-agent'], http.user_agent())
- r = http.fetch('http://httpbin.org/status/200',
use_fake_user_agent=False)
+ r = http.fetch(self.get_httpbin_url('/status/200'),
use_fake_user_agent=False)
self.assertEqual(r.headers['user-agent'], http.user_agent())
r = http.fetch(
- 'http://httpbin.org/status/200',
use_fake_user_agent='ARBITRARY')
+ self.get_httpbin_url('/status/200'),
use_fake_user_agent='ARBITRARY')
self.assertEqual(r.headers['user-agent'], 'ARBITRARY')
# Manually overridden domains
- config.fake_user_agent_exceptions = {'httpbin.org':
'OVERRIDDEN'}
+ config.fake_user_agent_exceptions = {self.get_httpbin_hostname():
'OVERRIDDEN'}
r = http.fetch(
- 'http://httpbin.org/status/200', use_fake_user_agent=False)
+ self.get_httpbin_url('/status/200'), use_fake_user_agent=False)
self.assertEqual(r.headers['user-agent'], 'OVERRIDDEN')
@require_modules('browseragents')
@@ -561,7 +605,7 @@
self.assertIs(main_module_cookie_jar, http.cookie_jar)
-class QueryStringParamsTestCase(TestCase):
+class QueryStringParamsTestCase(HttpbinTestCase):
"""
Test the query string parameter of request methods.
@@ -570,15 +614,9 @@
urldecoded query string parameters.
"""
- sites = {
- 'httpbin': {
- 'hostname': 'httpbin.org',
- },
- }
-
def test_no_params(self):
"""Test fetch method with no parameters."""
- r = http.fetch(uri='https://httpbin.org/get', params={})
+ r = http.fetch(uri=self.get_httpbin_url('/get'), params={})
self.assertEqual(r.status, 200)
content = json.loads(r.content)
@@ -591,7 +629,7 @@
HTTPBin returns the args in their urldecoded form, so what we put in should be
the same as what we get out.
"""
- r = http.fetch(uri='https://httpbin.org/get',
params={'fish&chips': 'delicious'})
+ r = http.fetch(uri=self.get_httpbin_url('/get'),
params={'fish&chips': 'delicious'})
self.assertEqual(r.status, 200)
content = json.loads(r.content)
@@ -604,7 +642,7 @@
HTTPBin returns the args in their urldecoded form, so what we put in should be
the same as what we get out.
"""
- r = http.fetch(uri='https://httpbin.org/get',
+ r = http.fetch(uri=self.get_httpbin_url('/get'),
params={'fish%26chips': 'delicious'})
self.assertEqual(r.status, 200)
@@ -612,20 +650,14 @@
self.assertDictEqual(content['args'], {'fish%26chips':
'delicious'})
-class DataBodyParameterTestCase(TestCase):
+class DataBodyParameterTestCase(HttpbinTestCase):
"""Test that the data and body parameters of fetch/request methods are
equivalent."""
-
- sites = {
- 'httpbin': {
- 'hostname': 'httpbin.org',
- },
- }
def test_fetch(self):
"""Test that using the data parameter and body parameter produce
same results."""
- r_data = http.fetch(uri='https://httpbin.org/post',
method='POST',
+ r_data = http.fetch(uri=self.get_httpbin_url('/post'),
method='POST',
data={'fish&chips': 'delicious'})
- r_body = http.fetch(uri='https://httpbin.org/post',
method='POST',
+ r_body = http.fetch(uri=self.get_httpbin_url('/post'),
method='POST',
body={'fish&chips': 'delicious'})
self.assertDictEqual(json.loads(r_data.content),
--
To view, visit
https://gerrit.wikimedia.org/r/329644
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I2000fed5e5273dbfef5d51ac81698a32c7fc5676
Gerrit-PatchSet: 13
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Phantom42 <nikitav30(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: MtDu <justin.d128(a)gmail.com>
Gerrit-Reviewer: Phantom42 <nikitav30(a)gmail.com>
Gerrit-Reviewer: jenkins-bot <>