Migrate test runner to py.test
Migrating test runner from `unittest2`/`nose` to `pytest`.
The pytest runner is also compatible with both unittest and nose tests.
Some of the benefits of PyTest include:
* using plain asserts
* function-based fixtures instead of setUp and tearDown
* no strange camelCase methods
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@ docs/_build
|
|||||||
|
|
||||||
# Test files
|
# Test files
|
||||||
.tox/
|
.tox/
|
||||||
|
.cache/
|
||||||
|
|
||||||
# Django test database
|
# Django test database
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
"""Test package set-up."""
|
|
||||||
|
|
||||||
from oauth2client import _helpers
|
|
||||||
|
|
||||||
__author__ = 'afshar@google.com (Ali Afshar)'
|
|
||||||
|
|
||||||
|
|
||||||
def setup_package():
|
|
||||||
"""Run on testing package."""
|
|
||||||
_helpers.positional_parameters_enforcement = _helpers.POSITIONAL_EXCEPTION
|
|
||||||
|
|||||||
46
tests/conftest.py
Normal file
46
tests/conftest.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Common testing tools for OAuth2Client tests."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from six.moves import reload_module
|
||||||
|
|
||||||
|
from oauth2client import util
|
||||||
|
|
||||||
|
|
||||||
|
def set_up_gae_environment(gae_sdk_path):
|
||||||
|
"""Set up appengine SDK third-party imports."""
|
||||||
|
if 'google' in sys.modules:
|
||||||
|
# Some packages, such as protobuf, clobber the google
|
||||||
|
# namespace package. This prevents that.
|
||||||
|
reload_module(sys.modules['google'])
|
||||||
|
|
||||||
|
# This sets up google-provided libraries.
|
||||||
|
sys.path.insert(0, gae_sdk_path)
|
||||||
|
import dev_appserver
|
||||||
|
dev_appserver.fix_sys_path()
|
||||||
|
|
||||||
|
# Fixes timezone and other os-level items.
|
||||||
|
import google.appengine.tools.os_compat # noqa: unused import
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_configure(config):
|
||||||
|
"""Pytest hook function for setting up test session."""
|
||||||
|
# Set up Google SDK modules unless specified not to
|
||||||
|
if not config.option.no_gae:
|
||||||
|
set_up_gae_environment(config.option.sdk_path)
|
||||||
|
# Default of POSITIONAL_WARNING is too verbose for testing
|
||||||
|
util.positional_parameters_enforcement = util.POSITIONAL_EXCEPTION
|
||||||
@@ -18,10 +18,6 @@ import os
|
|||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import dev_appserver
|
|
||||||
|
|
||||||
dev_appserver.fix_sys_path()
|
|
||||||
|
|
||||||
from google.appengine.api import apiproxy_stub
|
from google.appengine.api import apiproxy_stub
|
||||||
from google.appengine.api import apiproxy_stub_map
|
from google.appengine.api import apiproxy_stub_map
|
||||||
from google.appengine.api import app_identity
|
from google.appengine.api import app_identity
|
||||||
|
|||||||
@@ -235,9 +235,13 @@ class PEMCryptTestsOpenSSL(CryptTests):
|
|||||||
class SignedJwtAssertionCredentialsTests(unittest2.TestCase):
|
class SignedJwtAssertionCredentialsTests(unittest2.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.orig_signer = crypt.Signer
|
||||||
self.format_ = 'p12'
|
self.format_ = 'p12'
|
||||||
crypt.Signer = crypt.OpenSSLSigner
|
crypt.Signer = crypt.OpenSSLSigner
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
crypt.Signer = self.orig_signer
|
||||||
|
|
||||||
def _make_credentials(self):
|
def _make_credentials(self):
|
||||||
private_key = datafile('privatekey.' + self.format_)
|
private_key = datafile('privatekey.' + self.format_)
|
||||||
signer = crypt.Signer.from_string(private_key)
|
signer = crypt.Signer.from_string(private_key)
|
||||||
@@ -310,17 +314,25 @@ class PEMSignedJwtAssertionCredentialsOpenSSLTests(
|
|||||||
SignedJwtAssertionCredentialsTests):
|
SignedJwtAssertionCredentialsTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.orig_signer = crypt.Signer
|
||||||
self.format_ = 'pem'
|
self.format_ = 'pem'
|
||||||
crypt.Signer = crypt.OpenSSLSigner
|
crypt.Signer = crypt.OpenSSLSigner
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
crypt.Signer = self.orig_signer
|
||||||
|
|
||||||
|
|
||||||
class PEMSignedJwtAssertionCredentialsPyCryptoTests(
|
class PEMSignedJwtAssertionCredentialsPyCryptoTests(
|
||||||
SignedJwtAssertionCredentialsTests):
|
SignedJwtAssertionCredentialsTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.orig_signer = crypt.Signer
|
||||||
self.format_ = 'pem'
|
self.format_ = 'pem'
|
||||||
crypt.Signer = crypt.PyCryptoSigner
|
crypt.Signer = crypt.PyCryptoSigner
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
crypt.Signer = self.orig_signer
|
||||||
|
|
||||||
|
|
||||||
class TestHasOpenSSLFlag(unittest2.TestCase):
|
class TestHasOpenSSLFlag(unittest2.TestCase):
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ def datafile(filename):
|
|||||||
class ServiceAccountCredentialsTests(unittest2.TestCase):
|
class ServiceAccountCredentialsTests(unittest2.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.orig_signer = crypt.Signer
|
||||||
|
self.orig_verifier = crypt.Verifier
|
||||||
self.client_id = '123'
|
self.client_id = '123'
|
||||||
self.service_account_email = 'dummy@google.com'
|
self.service_account_email = 'dummy@google.com'
|
||||||
self.private_key_id = 'ABCDEF'
|
self.private_key_id = 'ABCDEF'
|
||||||
@@ -58,6 +60,10 @@ class ServiceAccountCredentialsTests(unittest2.TestCase):
|
|||||||
client_id=self.client_id,
|
client_id=self.client_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
crypt.Signer = self.orig_signer
|
||||||
|
crypt.Verifier = self.orig_verifier
|
||||||
|
|
||||||
def test__to_json_override(self):
|
def test__to_json_override(self):
|
||||||
signer = object()
|
signer = object()
|
||||||
creds = service_account.ServiceAccountCredentials(
|
creds = service_account.ServiceAccountCredentials(
|
||||||
|
|||||||
76
tox.ini
76
tox.ini
@@ -7,7 +7,8 @@ basedeps = mock>=1.3.0
|
|||||||
cryptography>=1.0
|
cryptography>=1.0
|
||||||
pyopenssl>=0.14
|
pyopenssl>=0.14
|
||||||
webtest
|
webtest
|
||||||
nose
|
pytest
|
||||||
|
pytest-beds
|
||||||
flask
|
flask
|
||||||
unittest2
|
unittest2
|
||||||
sqlalchemy
|
sqlalchemy
|
||||||
@@ -18,60 +19,54 @@ deps = {[testenv]basedeps}
|
|||||||
setenv =
|
setenv =
|
||||||
pypy: with_gmp=no
|
pypy: with_gmp=no
|
||||||
DJANGO_SETTINGS_MODULE=tests.contrib.django_util.settings
|
DJANGO_SETTINGS_MODULE=tests.contrib.django_util.settings
|
||||||
commands = nosetests --ignore-files=test_appengine\.py --ignore-files=test__appengine_ndb\.py {posargs}
|
commands =
|
||||||
|
py.test \
|
||||||
|
--no-gae \
|
||||||
|
--ignore=tests/contrib/test_appengine.py \
|
||||||
|
--ignore=tests/contrib/test__appengine_ndb.py \
|
||||||
|
{posargs}
|
||||||
|
|
||||||
[coverbase]
|
[coverbase]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
commands =
|
commands =
|
||||||
nosetests \
|
py.test \
|
||||||
--with-coverage \
|
--no-gae \
|
||||||
--cover-package=oauth2client \
|
--cov=oauth2client \
|
||||||
--cover-package=tests \
|
--cov=tests \
|
||||||
--cover-erase \
|
--ignore=tests/contrib/test_appengine.py \
|
||||||
--cover-tests \
|
--ignore=tests/contrib/test__appengine_ndb.py
|
||||||
--cover-branches \
|
py.test \
|
||||||
--ignore-files=test_appengine\.py \
|
--cov=oauth2client \
|
||||||
--ignore-files=test__appengine_ndb\.py
|
--cov=tests \
|
||||||
nosetests \
|
--cov-append \
|
||||||
--with-coverage \
|
--sdk-path={env:GAE_PYTHONPATH:google_appengine} \
|
||||||
--cover-package=oauth2client.contrib.appengine \
|
|
||||||
--cover-package=oauth2client.contrib._appengine_ndb \
|
|
||||||
--cover-package=tests.contrib.test_appengine \
|
|
||||||
--cover-package=tests.contrib.test__appengine_ndb \
|
|
||||||
--with-gae \
|
|
||||||
--cover-tests \
|
|
||||||
--cover-branches \
|
|
||||||
--gae-application=tests/data \
|
|
||||||
--gae-lib-root={env:GAE_PYTHONPATH:google_appengine} \
|
|
||||||
--logging-level=INFO \
|
|
||||||
tests/contrib/test_appengine.py \
|
tests/contrib/test_appengine.py \
|
||||||
tests/contrib/test__appengine_ndb.py
|
tests/contrib/test__appengine_ndb.py
|
||||||
deps = {[testenv]deps}
|
deps = {[testenv]deps}
|
||||||
coverage
|
coverage
|
||||||
nosegae
|
pytest-cov
|
||||||
|
|
||||||
[testenv:py33]
|
[testenv:py33]
|
||||||
basepython =
|
basepython =
|
||||||
python3.3
|
python3.3
|
||||||
commands =
|
commands =
|
||||||
nosetests \
|
py.test \
|
||||||
--ignore-files=test_appengine\.py \
|
--no-gae \
|
||||||
--ignore-files=test__appengine_ndb\.py \
|
--ignore=tests/contrib/test_appengine.py \
|
||||||
--ignore-files=test_django_orm\.py \
|
--ignore=tests/contrib/test__appengine_ndb.py \
|
||||||
--ignore-files=test_django_settings\.py \
|
--ignore=tests/contrib/test_django_orm.py \
|
||||||
--ignore-files=test_django_util\.py \
|
--ignore=tests/contrib/test_django_settings.py \
|
||||||
--exclude-dir=oauth2client/contrib/django_util \
|
--ignore=oauth2client/contrib/django_util \
|
||||||
--exclude-dir=tests/contrib/django_util \
|
--ignore=tests/contrib/django_util \
|
||||||
{posargs}
|
{posargs}
|
||||||
deps = {[testenv]basedeps}
|
deps = {[testenv]basedeps}
|
||||||
keyring
|
keyring
|
||||||
nose-exclude
|
|
||||||
|
|
||||||
[testenv:cover]
|
[testenv:cover]
|
||||||
basepython = {[coverbase]basepython}
|
basepython = {[coverbase]basepython}
|
||||||
commands =
|
commands =
|
||||||
{[coverbase]commands}
|
{[coverbase]commands}
|
||||||
coverage report --show-missing --cover-min-percentage=100
|
coverage report --show-missing --fail-under=100
|
||||||
deps =
|
deps =
|
||||||
{[coverbase]deps}
|
{[coverbase]deps}
|
||||||
|
|
||||||
@@ -100,13 +95,9 @@ commands = {toxinidir}/scripts/build_docs.sh
|
|||||||
[testenv:gae]
|
[testenv:gae]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps = {[testenv]basedeps}
|
deps = {[testenv]basedeps}
|
||||||
nosegae
|
|
||||||
commands =
|
commands =
|
||||||
nosetests \
|
py.test \
|
||||||
--with-gae \
|
--sdk-path={env:GAE_PYTHONPATH:google_appengine} \
|
||||||
--gae-lib-root={env:GAE_PYTHONPATH:google_appengine} \
|
|
||||||
--gae-application=tests/data \
|
|
||||||
--logging-level=INFO \
|
|
||||||
tests/contrib/test_appengine.py \
|
tests/contrib/test_appengine.py \
|
||||||
tests/contrib/test__appengine_ndb.py
|
tests/contrib/test__appengine_ndb.py
|
||||||
|
|
||||||
@@ -153,11 +144,8 @@ exclude = .tox,.git,./*.egg,build,
|
|||||||
application-import-names = oauth2client
|
application-import-names = oauth2client
|
||||||
putty-ignore =
|
putty-ignore =
|
||||||
# E402 module level import not at top of file
|
# E402 module level import not at top of file
|
||||||
# These files have needed configurations defined before import
|
# This file has needed configurations defined before import
|
||||||
docs/conf.py : E402
|
docs/conf.py : E402
|
||||||
tests/contrib/test_appengine.py : E402
|
|
||||||
# Additionally, ignore E100 (imports in wrong order) for Django configuration
|
|
||||||
tests/contrib/test_django_orm.py : E402,I100
|
|
||||||
# E501 line too long
|
# E501 line too long
|
||||||
# Ignore lines over 80 chars that include "http:" or "https:"
|
# Ignore lines over 80 chars that include "http:" or "https:"
|
||||||
/http:/ : E501
|
/http:/ : E501
|
||||||
|
|||||||
Reference in New Issue
Block a user