Skip to content

Commit

Permalink
Lazy import requests to improve test run time
Browse files Browse the repository at this point in the history
  • Loading branch information
isaulv authored and BeyondEvil committed Jul 17, 2020
1 parent 6e355ce commit ca7c066
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 9 deletions.
4 changes: 3 additions & 1 deletion pytest_selenium/drivers/browserstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import pytest
import requests

from pytest_selenium.drivers.cloud import Provider

Expand Down Expand Up @@ -43,6 +42,9 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):
session_id = item._driver.session_id
api_url = provider.API.format(session=session_id)

# lazy import requests for projects that don't need requests
import requests

try:
job_info = requests.get(api_url, auth=provider.auth, timeout=10).json()
job_url = job_info["automation_session"]["browser_url"]
Expand Down
7 changes: 6 additions & 1 deletion pytest_selenium/drivers/crossbrowsertesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from py.xml import html
import pytest
import requests

from pytest_selenium.drivers.cloud import Provider

Expand Down Expand Up @@ -40,6 +39,9 @@ def pytest_selenium_capture_debug(item, report, extra):
if not provider.uses_driver(item.config.getoption("driver")):
return

# lazy import requests for projects that don't need requests
import requests

videos = (
requests.get(
provider.API.format(session=item._driver.session_id),
Expand All @@ -63,6 +65,9 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):

passed = report.passed or (report.failed and hasattr(report, "wasxfail"))

# lazy import requests for projects that don't need requests
import requests

# Add the test URL to the summary
info = requests.get(
provider.API.format(session=item._driver.session_id),
Expand Down
4 changes: 3 additions & 1 deletion pytest_selenium/drivers/saucelabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from py.xml import html
import pytest
import requests

from pytest_selenium.drivers.cloud import Provider

Expand Down Expand Up @@ -68,6 +67,9 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):
# Add the job URL to the HTML report
extra.append(pytest_html.extras.url(job_url, "{0} Job".format(provider.name)))

# lazy import requests for projects that don't need requests
import requests

try:
# Update the job result
api_url = provider.API.format(session=session_id, username=provider.username)
Expand Down
9 changes: 6 additions & 3 deletions pytest_selenium/drivers/testingbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import pytest
import requests

from hashlib import md5

import pytest
from py.xml import html

from pytest_selenium.drivers.cloud import Provider

HOST = "hub.testingbot.com"
Expand Down Expand Up @@ -72,6 +72,9 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):
# Add the job URL to the HTML report
extra.append(pytest_html.extras.url(job_url, "{0} Job".format(provider.name)))

# lazy import requests for projects that don't need requests
import requests

try:
# Update the job result
api_url = provider.API.format(session=session_id)
Expand Down
3 changes: 1 addition & 2 deletions pytest_selenium/pytest_selenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
import logging

import pytest
from requests.structures import CaseInsensitiveDict
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.event_firing_webdriver import EventFiringWebDriver

from .utils import CaseInsensitiveDict
from . import drivers

LOGGER = logging.getLogger(__name__)


SUPPORTED_DRIVERS = CaseInsensitiveDict(
{
"BrowserStack": webdriver.Remote,
Expand Down
5 changes: 4 additions & 1 deletion pytest_selenium/safety.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import re

import pytest
import requests


def pytest_addoption(parser):
Expand Down Expand Up @@ -56,6 +55,10 @@ def sensitive_url(request, base_url):
# consider this environment sensitive if the base url or any redirection
# history matches the regular expression
urls = [base_url]

# lazy import requests for projects that don't need requests
import requests

try:
response = requests.get(base_url, timeout=10)
urls.append(response.url)
Expand Down
71 changes: 71 additions & 0 deletions pytest_selenium/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from collections.abc import Mapping, MutableMapping


class CaseInsensitiveDict(MutableMapping):
"""A case-insensitive ``dict``-like object.
Implements all methods and operations of
``MutableMapping`` as well as dict's ``copy``. Also
provides ``lower_items``.
All keys are expected to be strings. The structure remembers the
case of the last key to be set, and ``iter(instance)``,
``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()``
will contain case-sensitive keys. However, querying and contains
testing is case insensitive::
cid = CaseInsensitiveDict()
cid['Accept'] = 'application/json'
cid['aCCEPT'] == 'application/json' # True
list(cid) == ['Accept'] # True
For example, ``headers['content-encoding']`` will return the
value of a ``'Content-Encoding'`` response header, regardless
of how the header name was originally stored.
If the constructor, ``.update``, or equality comparison
operations are given keys that have equal ``.lower()``s, the
behavior is undefined.
"""

def __init__(self, data=None, **kwargs):
self._store = dict()
if data is None:
data = {}
self.update(data, **kwargs)

def __setitem__(self, key, value):
# Use the lowercased key for lookups, but store the actual
# key alongside the value.
self._store[key.lower()] = (key, value)

def __getitem__(self, key):
return self._store[key.lower()][1]

def __delitem__(self, key):
del self._store[key.lower()]

def __iter__(self):
return (casedkey for casedkey, mappedvalue in self._store.values())

def __len__(self):
return len(self._store)

def lower_items(self):
"""Like iteritems(), but with all lowercase keys."""
return ((lowerkey, keyval[1]) for lowerkey, keyval in self._store.items())

def __eq__(self, other):
if isinstance(other, Mapping):
other = CaseInsensitiveDict(other)
else:
return NotImplemented
# Compare insensitively
return dict(self.lower_items()) == dict(other.lower_items())

# Copy is required
def copy(self):
return CaseInsensitiveDict(self._store.values())

def __repr__(self):
return str(dict(self.items()))

0 comments on commit ca7c066

Please sign in to comment.