diff --git a/.travis.yml b/.travis.yml index efac0f91..3916fa3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,33 +4,45 @@ matrix: include: # CPython 2.7 - python: 2.7 - env: TOXENV=py27-local-slow + env: TOXENV=py27-travis-local-slow - python: 2.7 - env: TOXENV=py27-integ-slow + env: TOXENV=py27-travis-integ-slow + - python: 2.7 + env: TOXENV=py27-travis-isolation # CPython 3.4 - python: 3.4 - env: TOXENV=py34-local-slow + env: TOXENV=py34-travis-local-slow + - python: 3.4 + env: TOXENV=py34-travis-integ-slow - python: 3.4 - env: TOXENV=py34-integ-slow + env: TOXENV=py34-travis-isolation # CPython 3.5 - python: 3.5 - env: TOXENV=py35-local-slow + env: TOXENV=py35-travis-local-slow - python: 3.5 - env: TOXENV=py35-integ-slow + env: TOXENV=py35-travis-integ-slow + - python: 3.5 + env: TOXENV=py35-travis-isolation # CPython 3.6 - python: 3.6 - env: TOXENV=py36-local-slow + env: TOXENV=py36-travis-local-slow + - python: 3.6 + env: TOXENV=py36-travis-integ-slow - python: 3.6 - env: TOXENV=py36-integ-slow + env: TOXENV=py36-travis-isolation # CPython 3.7 # xenial + sudo are currently needed to get 3.7 # https://github.com/travis-ci/travis-ci/issues/9815 - python: 3.7 - env: TOXENV=py37-local-slow + env: TOXENV=py37-travis-local-slow + dist: xenial + sudo: true + - python: 3.7 + env: TOXENV=py37-travis-integ-slow dist: xenial sudo: true - python: 3.7 - env: TOXENV=py37-integ-slow + env: TOXENV=py37-travis-isolation dist: xenial sudo: true # Upstream tests diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 00000000..13447e91 --- /dev/null +++ b/examples/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2018 Amazon.com, Inc. or its affiliates. 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. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file 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. +"""Stub to allow relative imports of examples from tests.""" diff --git a/examples/test/examples_test_utils.py b/examples/test/examples_test_utils.py new file mode 100644 index 00000000..4674aaf0 --- /dev/null +++ b/examples/test/examples_test_utils.py @@ -0,0 +1,10 @@ +""" +Helper utilities for use while testing examples. +""" +import os +import sys + +os.environ["AWS_ENCRYPTION_SDK_EXAMPLES_TESTING"] = "yes" +sys.path.extend([os.sep.join([os.path.dirname(__file__), "..", "..", "test", "integration"])]) + +from integration_test_utils import cmk_arn, ddb_table_name # noqa pylint: disable=unused-import diff --git a/examples/test/test_aws_kms_encrypted_examples.py b/examples/test/test_aws_kms_encrypted_examples.py index 8b8b5551..f7df24b3 100644 --- a/examples/test/test_aws_kms_encrypted_examples.py +++ b/examples/test/test_aws_kms_encrypted_examples.py @@ -11,23 +11,10 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Test ``aws_kms_encrypted_*`` examples.""" -import os -import sys - -sys.path.extend( - [ # noqa - os.sep.join([os.path.dirname(__file__), "..", "..", "test", "integration"]), - os.sep.join([os.path.dirname(__file__), "..", "src"]), - ] -) - import pytest -import aws_kms_encrypted_client # noqa -import aws_kms_encrypted_item # noqa -import aws_kms_encrypted_resource # noqa -import aws_kms_encrypted_table # noqa -from integration_test_utils import cmk_arn, ddb_table_name # noqa pylint: disable=unused-import +from ..src import aws_kms_encrypted_client, aws_kms_encrypted_item, aws_kms_encrypted_resource, aws_kms_encrypted_table +from .examples_test_utils import cmk_arn, ddb_table_name # noqa pylint: disable=unused-import pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_most_recent_provider_encrypted_examples.py b/examples/test/test_most_recent_provider_encrypted_examples.py index 7db4160b..8894001c 100644 --- a/examples/test/test_most_recent_provider_encrypted_examples.py +++ b/examples/test/test_most_recent_provider_encrypted_examples.py @@ -11,23 +11,15 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Test most recent provider examples.""" -import os -import sys - -sys.path.extend( - [ # noqa - os.sep.join([os.path.dirname(__file__), "..", "..", "test", "integration"]), - os.sep.join([os.path.dirname(__file__), "..", "src"]), - ] -) import uuid import boto3 import pytest from dynamodb_encryption_sdk.material_providers.store.meta import MetaStore -import most_recent_provider_encrypted_table # noqa -from integration_test_utils import cmk_arn, ddb_table_name # noqa pylint: disable=unused-import + +from ..src import most_recent_provider_encrypted_table +from .examples_test_utils import cmk_arn, ddb_table_name # noqa pylint: disable=unused-import pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_wrapped_encrypted_examples.py b/examples/test/test_wrapped_encrypted_examples.py index fc69f186..f6bb7aa2 100644 --- a/examples/test/test_wrapped_encrypted_examples.py +++ b/examples/test/test_wrapped_encrypted_examples.py @@ -11,22 +11,12 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Test ``wrapped_*_encrypted_*`` examples.""" -import os -import sys - -sys.path.extend( - [ # noqa - os.sep.join([os.path.dirname(__file__), "..", "..", "test", "integration"]), - os.sep.join([os.path.dirname(__file__), "..", "src"]), - ] -) - import pytest from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey -import wrapped_rsa_encrypted_table # noqa -import wrapped_symmetric_encrypted_table # noqa -from integration_test_utils import ddb_table_name # noqa pylint: disable=unused-import + +from ..src import wrapped_rsa_encrypted_table, wrapped_symmetric_encrypted_table +from .examples_test_utils import ddb_table_name # noqa pylint: disable=unused-import pytestmark = [pytest.mark.examples] diff --git a/setup.cfg b/setup.cfg index 0a82e619..fd572544 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,7 @@ markers = slow: mark a test as being known to take a long time to complete (order 5s < t < 60s) veryslow: mark a test as being known to take a very long time to complete (order t > 60s) nope: mark a test as being so slow that it should only be very infrequently (order t > 30m) + travis_isolation: mark a test that crashes Travis CI when run with other tests log_level=NOTSET # Flake8 Configuration diff --git a/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/authentication.py b/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/authentication.py index 3b26a86b..a40c4a62 100644 --- a/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/authentication.py +++ b/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/authentication.py @@ -27,6 +27,7 @@ from dynamodb_encryption_sdk.exceptions import InvalidAlgorithmError, SignatureVerificationError, SigningError from dynamodb_encryption_sdk.identifiers import LOGGER_NAME, EncryptionKeyType, KeyEncodingType +from dynamodb_encryption_sdk.internal.identifiers import MinimumKeySizes from dynamodb_encryption_sdk.internal.validators import callable_validator from .primitives import load_rsa_key @@ -37,7 +38,6 @@ # We only actually need these imports when running the mypy checks pass - __all__ = ("JavaAuthenticator", "JavaMac", "JavaSignature", "JAVA_AUTHENTICATOR") _LOGGER = logging.getLogger(LOGGER_NAME) @@ -138,6 +138,9 @@ def load_key(self, key, key_type, key_encoding): if not (key_type is EncryptionKeyType.SYMMETRIC and key_encoding is KeyEncodingType.RAW): raise ValueError("Key type must be symmetric and encoding must be raw.") + if len(key) * 8 < MinimumKeySizes.HMAC.value: + _LOGGER.warning("HMAC keys smaller than %d bits are unsafe" % MinimumKeySizes.HMAC.value) + return key def validate_algorithm(self, algorithm): diff --git a/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/primitives.py b/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/primitives.py index 8d99fcf7..29497fc9 100644 --- a/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/primitives.py +++ b/src/dynamodb_encryption_sdk/internal/crypto/jce_bridge/primitives.py @@ -35,6 +35,7 @@ WrappingError, ) from dynamodb_encryption_sdk.identifiers import LOGGER_NAME, EncryptionKeyType, KeyEncodingType +from dynamodb_encryption_sdk.internal.identifiers import MinimumKeySizes from dynamodb_encryption_sdk.internal.validators import callable_validator try: # Python 3.5.0 and 3.5.1 have incompatible typing modules @@ -451,7 +452,12 @@ def load_rsa_key(key, key_type, key_encoding): if key_type is EncryptionKeyType.PRIVATE: kwargs["password"] = None - return loader(**kwargs) + loaded_key = loader(**kwargs) + + if loaded_key.key_size < MinimumKeySizes.RSA.value: + _LOGGER.warning("RSA keys smaller than %d bits are unsafe" % MinimumKeySizes.RSA.value) + + return loaded_key _KEY_LOADERS = {rsa: load_rsa_key} diff --git a/src/dynamodb_encryption_sdk/internal/identifiers.py b/src/dynamodb_encryption_sdk/internal/identifiers.py index 80183870..b0474ec8 100644 --- a/src/dynamodb_encryption_sdk/internal/identifiers.py +++ b/src/dynamodb_encryption_sdk/internal/identifiers.py @@ -32,6 +32,7 @@ "SignatureValues", "MaterialDescriptionKeys", "MaterialDescriptionValues", + "MinimumKeySizes", ) #: Encoding to use for all text values. @@ -39,6 +40,13 @@ TEXT_ENCODING = "utf-8" +class MinimumKeySizes(Enum): + """Minimum safe key sizes for algorithms.""" + + RSA = 2048 + HMAC = 128 + + class ReservedAttributes(Enum): """Item attributes reserved for use by DynamoDBEncryptionClient""" diff --git a/test/functional/delegated_keys/test_jce.py b/test/functional/delegated_keys/test_jce.py index a1e25d80..ba880399 100644 --- a/test/functional/delegated_keys/test_jce.py +++ b/test/functional/delegated_keys/test_jce.py @@ -11,11 +11,17 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Functional test suite for ``dynamodb_encryption_sdk.delegated_keys.jce``.""" +from __future__ import division + +import logging + import pytest from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey +from dynamodb_encryption_sdk.internal.crypto.jce_bridge.authentication import JAVA_AUTHENTICATOR +from dynamodb_encryption_sdk.internal.identifiers import MinimumKeySizes pytestmark = [pytest.mark.functional, pytest.mark.local] @@ -26,7 +32,7 @@ def _find_aes_key_length(key): def _find_rsa_key_length(key): loaded_key = serialization.load_der_private_key(data=key, password=None, backend=default_backend()) - return loaded_key._key_size + return loaded_key.key_size @pytest.mark.parametrize( @@ -49,3 +55,30 @@ def test_generate_correct_key_length(algorithm, requested_bits, expected_bits, l test = JceNameLocalDelegatedKey.generate(algorithm, requested_bits) assert length_finder(test.key) == expected_bits + + +def build_short_key_cases(): + for algorithm in JAVA_AUTHENTICATOR: + if algorithm.upper().startswith("HMAC"): + message = "HMAC keys smaller than {} bits are unsafe".format(MinimumKeySizes.HMAC.value) + yield (algorithm, MinimumKeySizes.HMAC.value, False, message) + yield (algorithm, MinimumKeySizes.HMAC.value - 1, True, message) + + elif algorithm.upper().endswith("RSA"): + message = "RSA keys smaller than {} bits are unsafe".format(MinimumKeySizes.RSA.value) + yield (algorithm, MinimumKeySizes.RSA.value, False, message) + yield (algorithm, MinimumKeySizes.RSA.value // 2, True, message) + + message = "RSA keys smaller than {} bits are unsafe".format(MinimumKeySizes.RSA.value) + yield ("RSA", MinimumKeySizes.RSA.value, False, message) + yield ("RSA", MinimumKeySizes.RSA.value // 2, True, message) + + +@pytest.mark.travis_isolation +@pytest.mark.parametrize("algorithm, key_bits, too_short, error_message", build_short_key_cases()) +def test_warn_on_short_keys(caplog, algorithm, key_bits, too_short, error_message): + with caplog.at_level(logging.DEBUG): + _test = JceNameLocalDelegatedKey.generate(algorithm, key_bits) + + logging_results = caplog.text + assert (too_short and error_message in logging_results) or (not too_short and error_message not in logging_results) diff --git a/test/functional/encrypted/test_client.py b/test/functional/encrypted/test_client.py index f7a76b56..c928a55e 100644 --- a/test/functional/encrypted/test_client.py +++ b/test/functional/encrypted/test_client.py @@ -80,6 +80,7 @@ def test_ephemeral_batch_item_cycle_slow(example_table, all_the_cmps, parametriz _client_cycle_batch_items_check(all_the_cmps, parametrized_actions, parametrized_item) +@pytest.mark.travis_isolation @pytest.mark.slow @pytest.mark.hypothesis @SLOW_SETTINGS diff --git a/test/functional/encrypted/test_resource.py b/test/functional/encrypted/test_resource.py index 31e66d7f..3400906f 100644 --- a/test/functional/encrypted/test_resource.py +++ b/test/functional/encrypted/test_resource.py @@ -40,6 +40,7 @@ def test_ephemeral_batch_item_cycle(example_table, some_cmps, parametrized_actio _resource_cycle_batch_items_check(some_cmps, parametrized_actions, parametrized_item) +@pytest.mark.travis_isolation @pytest.mark.slow def test_ephemeral_batch_item_cycle_slow(example_table, all_the_cmps, parametrized_actions, parametrized_item): """Test ALL THE CMPS against a small number of curated items.""" diff --git a/test/functional/encrypted/test_table.py b/test/functional/encrypted/test_table.py index 6a0d1d55..4759edfe 100644 --- a/test/functional/encrypted/test_table.py +++ b/test/functional/encrypted/test_table.py @@ -60,6 +60,7 @@ def test_ephemeral_item_cycle_batch_writer_slow(example_table, all_the_cmps, par table_cycle_batch_writer_check(all_the_cmps, parametrized_actions, parametrized_item, TEST_TABLE_NAME, "us-west-2") +@pytest.mark.travis_isolation @pytest.mark.slow @pytest.mark.hypothesis @SLOW_SETTINGS diff --git a/test/functional/functional_test_utils.py b/test/functional/functional_test_utils.py index 4f8f2ec6..3c69427a 100644 --- a/test/functional/functional_test_utils.py +++ b/test/functional/functional_test_utils.py @@ -15,11 +15,14 @@ import copy import itertools +import logging +import os from collections import defaultdict from decimal import Decimal import boto3 import pytest +import six from boto3.dynamodb.types import Binary from moto import mock_dynamodb2 @@ -36,6 +39,7 @@ from dynamodb_encryption_sdk.structures import AttributeActions from dynamodb_encryption_sdk.transform import ddb_to_dict, dict_to_ddb +RUNNING_IN_TRAVIS = "TRAVIS" in os.environ _DELEGATED_KEY_CACHE = defaultdict(lambda: defaultdict(dict)) TEST_TABLE_NAME = "my_table" TEST_INDEX = { @@ -44,7 +48,7 @@ } SECONARY_INDEX = { "secondary_index_1": {"type": "B", "value": Binary(b"\x00\x01\x02")}, - "secondary_index_1": {"type": "S", "value": "another_value"}, + "secondary_index_2": {"type": "S", "value": "another_value"}, } TEST_KEY = {name: value["value"] for name, value in TEST_INDEX.items()} TEST_BATCH_INDEXES = [ diff --git a/test/integration/integration_test_utils.py b/test/integration/integration_test_utils.py index f63729e8..c037cf3d 100644 --- a/test/integration/integration_test_utils.py +++ b/test/integration/integration_test_utils.py @@ -18,7 +18,11 @@ from dynamodb_encryption_sdk.material_providers.aws_kms import AwsKmsCryptographicMaterialsProvider # convenience imports -from ..functional import functional_test_utils, hypothesis_strategies +try: + from ..functional import functional_test_utils, hypothesis_strategies +except (ImportError, ValueError, SystemError): + if "AWS_ENCRYPTION_SDK_EXAMPLES_TESTING" not in os.environ: + raise AWS_KMS_KEY_ID = "AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID" DDB_TABLE_NAME = "DDB_ENCRYPTION_CLIENT_TEST_TABLE_NAME" @@ -52,7 +56,7 @@ def ddb_table_name(): except KeyError: raise ValueError( ( - 'Environment variable "{}" must be set to the correct DynamoDB table name' + "Environment variable '{}' must be set to the correct DynamoDB table name" " for integration tests to run" - ).format(AWS_KMS_KEY_ID) + ).format(DDB_TABLE_NAME) ) diff --git a/test/requirements.txt b/test/requirements.txt index 1a608aea..9831193f 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,7 +1,7 @@ hypothesis==3.63.0 mock moto>=1.3.3 -pytest>=3.3.1 +pytest>=3.4.0 pytest-cov pytest-mock pytest-xdist diff --git a/test/upstream-requirements-py27.txt b/test/upstream-requirements-py27.txt index 8045e37e..9a12a7b1 100644 --- a/test/upstream-requirements-py27.txt +++ b/test/upstream-requirements-py27.txt @@ -1,7 +1,7 @@ apipkg==1.5 asn1crypto==0.24.0 -atomicwrites==1.2.0 -attrs==18.1.0 +atomicwrites==1.2.1 +attrs==18.2.0 aws-xray-sdk==0.95 backports.ssl-match-hostname==3.5.0.1 backports.tempfile==1.0 @@ -42,8 +42,8 @@ py==1.6.0 pyaml==17.12.1 pycparser==2.18 pycryptodome==3.6.6 -pytest==3.7.4 -pytest-cov==2.5.1 +pytest==3.8.0 +pytest-cov==2.6.0 pytest-forked==0.2 pytest-mock==1.10.0 pytest-xdist==1.23.0 @@ -57,7 +57,7 @@ s3transfer==0.1.13 scandir==1.9.0 six==1.11.0 urllib3==1.23 -websocket-client==0.51.0 +websocket-client==0.52.0 Werkzeug==0.14.1 wrapt==1.10.11 xmltodict==0.11.0 diff --git a/test/upstream-requirements-py37.txt b/test/upstream-requirements-py37.txt index c607f207..28d1fa60 100644 --- a/test/upstream-requirements-py37.txt +++ b/test/upstream-requirements-py37.txt @@ -1,7 +1,7 @@ apipkg==1.5 asn1crypto==0.24.0 -atomicwrites==1.2.0 -attrs==18.1.0 +atomicwrites==1.2.1 +attrs==18.2.0 aws-xray-sdk==0.95 boto==2.49.0 boto3==1.7.84 @@ -34,8 +34,8 @@ py==1.6.0 pyaml==17.12.1 pycparser==2.18 pycryptodome==3.6.6 -pytest==3.7.4 -pytest-cov==2.5.1 +pytest==3.8.0 +pytest-cov==2.6.0 pytest-forked==0.2 pytest-mock==1.10.0 pytest-xdist==1.23.0 @@ -48,7 +48,7 @@ responses==0.9.0 s3transfer==0.1.13 six==1.11.0 urllib3==1.23 -websocket-client==0.51.0 +websocket-client==0.52.0 Werkzeug==0.14.1 wrapt==1.10.11 xmltodict==0.11.0 diff --git a/tox.ini b/tox.ini index ec66f5b9..3ed8d62d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,9 @@ [tox] envlist = - py{27,34,35,36}-{local,integ,examples}-fast, nocmk, sourcebuildcheck, + py{27,34,35,36,37}-{local,integ,ddb,examples}-fast, + nocmk, sourcebuildcheck, docs, bandit, doc8, readme, - flake8, pylint, - flake8-tests, pylint-tests, - flake8-examples, pylint-examples, + flake8{,-tests,-examples}, pylint{,-tests,-examples}, vulture, test-upstream-requirements-py{2,3}7 @@ -37,7 +36,7 @@ envlist = # release :: Builds dist files and uploads to pypi pypirc profile. [testenv:base-command] -commands = pytest --basetemp={envtmpdir} -l --cov dynamodb_encryption_sdk test/ {posargs} +commands = pytest --basetemp={envtmpdir} -l --cov dynamodb_encryption_sdk {posargs} [testenv] passenv = @@ -55,29 +54,33 @@ sitepackages = False deps = -rtest/requirements.txt commands = # Only run small test scenario sets - local-fast: {[testenv:base-command]commands} -m "local and not slow and not veryslow and not nope" - integ-fast: {[testenv:base-command]commands} -m "integ and not ddb_integ and not slow and not veryslow and not nope" - ddb-fast: {[testenv:base-command]commands} -m "ddb_integ and not slow and not veryslow and not nope" - all-fast: {[testenv:base-command]commands} -m "not slow and not veryslow and not nope" + local-fast: {[testenv:base-command]commands} test/ -m "local and not slow and not veryslow and not nope" + integ-fast: {[testenv:base-command]commands} test/ -m "integ and not ddb_integ and not slow and not veryslow and not nope" + ddb-fast: {[testenv:base-command]commands} test/ -m "ddb_integ and not slow and not veryslow and not nope" + all-fast: {[testenv:base-command]commands} test/ -m "not slow and not veryslow and not nope" # Also run moderately large test scenario sets - local-slow: {[testenv:base-command]commands} -m "local and not veryslow and not nope" - integ-slow: {[testenv:base-command]commands} -m "integ and not ddb_integ and not veryslow and not nope" - ddb-slow: {[testenv:base-command]commands} -m "ddb_integ and not veryslow and not nope" - all-slow: {[testenv:base-command]commands} -m "not veryslow and not nope" + local-slow: {[testenv:base-command]commands} test/ -m "local and not veryslow and not nope" + integ-slow: {[testenv:base-command]commands} test/ -m "integ and not ddb_integ and not veryslow and not nope" + ddb-slow: {[testenv:base-command]commands} test/ -m "ddb_integ and not veryslow and not nope" + all-slow: {[testenv:base-command]commands} test/ -m "not veryslow and not nope" + # Only run those tests that need to be isolated in Travis CI + travis-isolation: {[testenv:base-command]commands} test/ -m travis_isolation + travis-local-slow: {[testenv:base-command]commands} test/ -m "local and not veryslow and not nope and not travis_isolation" + travis-integ-slow: {[testenv:base-command]commands} test/ -m "integ and not ddb_integ and not veryslow and not nope and not travis_isolation" # Also run very large test scenario sets - local-full: {[testenv:base-command]commands} -m "local and not nope" - integ-full: {[testenv:base-command]commands} -m "integ and not ddb_integ and not nope" - ddb-full: {[testenv:base-command]commands} -m "ddb_integ and not nope" - all-full: {[testenv:base-command]commands} -m "not nope" + local-full: {[testenv:base-command]commands} test/ -m "local and not nope" + integ-full: {[testenv:base-command]commands} test/ -m "integ and not ddb_integ and not nope" + ddb-full: {[testenv:base-command]commands} test/ -m "ddb_integ and not nope" + all-full: {[testenv:base-command]commands} test/ -m "not nope" # Only run extremely large test scenario sets - local-nope: {[testenv:base-command]commands} -m "local and nope" - integ-nope: {[testenv:base-command]commands} -m "integ and not ddb_integ and nope" - ddb-nope: {[testenv:base-command]commands} -m "ddb_integ and nope" - all-nope: {[testenv:base-command]commands} -m "nope" + local-nope: {[testenv:base-command]commands} test/ -m "local and nope" + integ-nope: {[testenv:base-command]commands} test/ -m "integ and not ddb_integ and nope" + ddb-nope: {[testenv:base-command]commands} test/ -m "ddb_integ and nope" + all-nope: {[testenv:base-command]commands} test/ -m "nope" # Do not select any specific markers manual: {[testenv:base-command]commands} # Only run examples tests - examples: {[testenv:base-command]commands} -m "examples" + examples: {[testenv:base-command]commands} examples/test/ -m "examples" # Verify that local tests work without environment variables present [testenv:nocmk] @@ -292,13 +295,14 @@ commands = seed-isort-config [testenv:isort] basepython = python3 deps = isort -commands = isort -rc \ - src \ - test \ - # We do not include examples/test because of the need to modify sys.path for some imports - examples/src/ \ - doc \ - setup.py \ +commands = isort \ + -rc \ + src \ + test \ + examples/ \ + doc \ + setup.py \ + --skip examples/test/examples_test_utils.py \ {posargs} [testenv:isort-check]