diff --git a/Makefile b/Makefile index 2fc6aea96..0df12ac17 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ifeq ($(TEST_SERVER_MODE), true) # exclude test_kinesisvideoarchivedmedia # because testing with moto_server is difficult with data-endpoint - TEST_EXCLUDE := --exclude='test_iot.*' --exclude="test_kinesisvideoarchivedmedia.*" + TEST_EXCLUDE := -k 'not (test_iot or test_kinesisvideoarchivedmedia)' else TEST_EXCLUDE := endif @@ -23,13 +23,13 @@ lint: test-only: rm -f .coverage rm -rf cover - @nosetests -sv --with-coverage --cover-html ./tests/ $(TEST_EXCLUDE) + @pytest -sv --cov=moto --cov-report html ./tests/ $(TEST_EXCLUDE) test: lint test-only test_server: - @TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/ + @TEST_SERVER_MODE=true pytest -sv --cov=moto --cov-report html ./tests/ aws_managed_policies: scripts/update_managed_policies.py diff --git a/docs/conf.py b/docs/conf.py index a902d0ecf..7bba967b2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,12 +20,12 @@ import shlex # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -33,23 +33,23 @@ import shlex extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Moto' -copyright = '2015, Steve Pulec' -author = 'Steve Pulec' +project = "Moto" +copyright = "2015, Steve Pulec" +author = "Steve Pulec" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -57,6 +57,7 @@ author = 'Steve Pulec' # # The short X.Y version. import moto + version = moto.__version__ # The full version, including alpha/beta/rc tags. release = moto.__version__ @@ -70,37 +71,37 @@ language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -110,156 +111,149 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'Motodoc' +htmlhelp_basename = "Motodoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Latex figure (float) alignment + #'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Moto.tex', 'Moto Documentation', - 'Steve Pulec', 'manual'), + (master_doc, "Moto.tex", "Moto Documentation", "Steve Pulec", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'moto', 'Moto Documentation', - [author], 1) -] +man_pages = [(master_doc, "moto", "Moto Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -268,19 +262,25 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Moto', 'Moto Documentation', - author, 'Moto', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "Moto", + "Moto Documentation", + author, + "Moto", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False diff --git a/moto/applicationautoscaling/models.py b/moto/applicationautoscaling/models.py index 47a1adad8..40d1094fc 100644 --- a/moto/applicationautoscaling/models.py +++ b/moto/applicationautoscaling/models.py @@ -110,8 +110,8 @@ class ApplicationAutoscalingBackend(BaseBackend): return r_id in self.targets.get(dimension, []) def _ecs_service_exists_for_target(self, r_id): - """ Raises a ValidationException if an ECS service does not exist - for the specified resource ID. + """Raises a ValidationException if an ECS service does not exist + for the specified resource ID. """ resource_type, cluster, service = r_id.split("/") result = self.ecs_backend.describe_services(cluster, [service]) diff --git a/moto/applicationautoscaling/responses.py b/moto/applicationautoscaling/responses.py index 5bb0a4144..ad63af948 100644 --- a/moto/applicationautoscaling/responses.py +++ b/moto/applicationautoscaling/responses.py @@ -96,8 +96,8 @@ class ApplicationAutoScalingResponse(BaseResponse): return json.dumps({}) def _validate_params(self): - """ Validate parameters. - TODO Integrate this validation with the validation in models.py + """Validate parameters. + TODO Integrate this validation with the validation in models.py """ namespace = self._get_param("ServiceNamespace") dimension = self._get_param("ScalableDimension") diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py index 1a25a656d..ee5cd9acd 100644 --- a/moto/autoscaling/models.py +++ b/moto/autoscaling/models.py @@ -863,7 +863,7 @@ class AutoScalingBackend(BaseBackend): self.set_desired_capacity(group_name, desired_capacity) def change_capacity_percent(self, group_name, scaling_adjustment): - """ http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-scale-based-on-demand.html + """http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-scale-based-on-demand.html If PercentChangeInCapacity returns a value between 0 and 1, Auto Scaling will round it off to 1. If the PercentChangeInCapacity returns a value greater than 1, Auto Scaling will round it off to the diff --git a/moto/cloudformation/utils.py b/moto/cloudformation/utils.py index d025af5fd..c9e522efb 100644 --- a/moto/cloudformation/utils.py +++ b/moto/cloudformation/utils.py @@ -41,8 +41,7 @@ def random_suffix(): def yaml_tag_constructor(loader, tag, node): - """convert shorthand intrinsic function to full name - """ + """convert shorthand intrinsic function to full name""" def _f(loader, tag, node): if tag == "!GetAtt": diff --git a/moto/config/models.py b/moto/config/models.py index db2556343..99ae49e44 100644 --- a/moto/config/models.py +++ b/moto/config/models.py @@ -1006,9 +1006,9 @@ class ConfigBackend(BaseBackend): def get_resource_config_history(self, resource_type, id, backend_region): """Returns the configuration of an item in the AWS Config format of the resource for the current regional backend. - NOTE: This is --NOT-- returning history as it is not supported in moto at this time. (PR's welcome!) - As such, the later_time, earlier_time, limit, and next_token are ignored as this will only - return 1 item. (If no items, it raises an exception) + NOTE: This is --NOT-- returning history as it is not supported in moto at this time. (PR's welcome!) + As such, the later_time, earlier_time, limit, and next_token are ignored as this will only + return 1 item. (If no items, it raises an exception) """ # If the type isn't implemented then we won't find the item: if resource_type not in RESOURCE_MAP: @@ -1090,10 +1090,10 @@ class ConfigBackend(BaseBackend): ): """Returns the configuration of an item in the AWS Config format of the resource for the current regional backend. - As far a moto goes -- the only real difference between this function and the `batch_get_resource_config` function is that - this will require a Config Aggregator be set up a priori and can search based on resource regions. + As far a moto goes -- the only real difference between this function and the `batch_get_resource_config` function is that + this will require a Config Aggregator be set up a priori and can search based on resource regions. - Note: moto will IGNORE the resource account ID in the search query. + Note: moto will IGNORE the resource account ID in the search query. """ if not self.config_aggregators.get(aggregator_name): raise NoSuchConfigurationAggregatorException() diff --git a/moto/core/responses.py b/moto/core/responses.py index fdac22c18..1149ab0be 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -62,9 +62,9 @@ def _decode_dict(d): class DynamicDictLoader(DictLoader): """ - Note: There's a bug in jinja2 pre-2.7.3 DictLoader where caching does not work. - Including the fixed (current) method version here to ensure performance benefit - even for those using older jinja versions. + Note: There's a bug in jinja2 pre-2.7.3 DictLoader where caching does not work. + Including the fixed (current) method version here to ensure performance benefit + even for those using older jinja versions. """ def get_source(self, environment, template): diff --git a/moto/core/utils.py b/moto/core/utils.py index 5f35538de..97303a508 100644 --- a/moto/core/utils.py +++ b/moto/core/utils.py @@ -16,7 +16,7 @@ REQUEST_ID_LONG = string.digits + string.ascii_uppercase def camelcase_to_underscores(argument): - """ Converts a camelcase param like theNewAttribute to the equivalent + """Converts a camelcase param like theNewAttribute to the equivalent python underscore variable like the_new_attribute""" result = "" prev_char_title = True @@ -42,9 +42,9 @@ def camelcase_to_underscores(argument): def underscores_to_camelcase(argument): - """ Converts a camelcase param like the_new_attribute to the equivalent + """Converts a camelcase param like the_new_attribute to the equivalent camelcase version like theNewAttribute. Note that the first letter is - NOT capitalized by this function """ + NOT capitalized by this function""" result = "" previous_was_underscore = False for char in argument: diff --git a/moto/ec2/models.py b/moto/ec2/models.py index 7a0cef7a2..bdb1cb03a 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -1059,7 +1059,7 @@ class InstanceBackend(object): return instance def get_reservations_by_instance_ids(self, instance_ids, filters=None): - """ Go through all of the reservations and filter to only return those + """Go through all of the reservations and filter to only return those associated with the given instance_ids. """ reservations = [] @@ -1358,9 +1358,9 @@ class Ami(TaggedEC2Resource): elif source_ami: """ - http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html - "We don't copy launch permissions, user-defined tags, or Amazon S3 bucket permissions from the source AMI to the new AMI." - ~ 2014.09.29 + http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html + "We don't copy launch permissions, user-defined tags, or Amazon S3 bucket permissions from the source AMI to the new AMI." + ~ 2014.09.29 """ self.virtualization_type = source_ami.virtualization_type self.architecture = source_ami.architecture @@ -1518,9 +1518,9 @@ class AmiBackend(object): # If anything is invalid, nothing is added. (No partial success.) if user_ids: """ - AWS docs: - "The AWS account ID is a 12-digit number, such as 123456789012, that you use to construct Amazon Resource Names (ARNs)." - http://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html + AWS docs: + "The AWS account ID is a 12-digit number, such as 123456789012, that you use to construct Amazon Resource Names (ARNs)." + http://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html """ for user_id in user_ids: if len(user_id) != 12 or not user_id.isdigit(): diff --git a/moto/emr/utils.py b/moto/emr/utils.py index 4d9da8434..48f3232fa 100644 --- a/moto/emr/utils.py +++ b/moto/emr/utils.py @@ -43,14 +43,14 @@ def steps_from_query_string(querystring_dict): class Unflattener: @staticmethod def unflatten_complex_params(input_dict, param_name): - """ Function to unflatten (portions of) dicts with complex keys. The moto request parser flattens the incoming + """Function to unflatten (portions of) dicts with complex keys. The moto request parser flattens the incoming request bodies, which is generally helpful, but for nested dicts/lists can result in a hard-to-manage parameter exposion. This function allows one to selectively unflatten a set of dict keys, replacing them with a deep dist/list structure named identically to the root component in the complex name. Complex keys are composed of multiple components separated by periods. Components may be prefixed with _, which is stripped. Lists indexes are represented - with two components, 'member' and the index number. """ + with two components, 'member' and the index number.""" items_to_process = {} for k in input_dict.keys(): if k.startswith(param_name): diff --git a/moto/iotdata/models.py b/moto/iotdata/models.py index 41b69bc7f..f695fb3fc 100644 --- a/moto/iotdata/models.py +++ b/moto/iotdata/models.py @@ -114,8 +114,7 @@ class FakeShadow(BaseModel): } def to_dict(self, include_delta=True): - """returning nothing except for just top-level keys for now. - """ + """returning nothing except for just top-level keys for now.""" if self.deleted: return {"timestamp": self.timestamp, "version": self.version} delta = self.parse_payload(self.desired, self.reported) diff --git a/moto/packages/httpretty/core.py b/moto/packages/httpretty/core.py index 83bd19237..2f48ad567 100644 --- a/moto/packages/httpretty/core.py +++ b/moto/packages/httpretty/core.py @@ -269,13 +269,13 @@ class fakesock(object): _sock=None, ): """ - Matches both the Python 2 API: - def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): - https://github.com/python/cpython/blob/2.7/Lib/socket.py + Matches both the Python 2 API: + def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): + https://github.com/python/cpython/blob/2.7/Lib/socket.py - and the Python 3 API: - def __init__(self, family=-1, type=-1, proto=-1, fileno=None): - https://github.com/python/cpython/blob/3.5/Lib/socket.py + and the Python 3 API: + def __init__(self, family=-1, type=-1, proto=-1, fileno=None): + https://github.com/python/cpython/blob/3.5/Lib/socket.py """ if httpretty.allow_net_connect: if PY3: diff --git a/moto/s3/utils.py b/moto/s3/utils.py index 2cdb7e862..d02da3a60 100644 --- a/moto/s3/utils.py +++ b/moto/s3/utils.py @@ -98,7 +98,7 @@ def undo_clean_key_name(key_name): class _VersionedKeyStore(dict): - """ A simplified/modified version of Django's `MultiValueDict` taken from: + """A simplified/modified version of Django's `MultiValueDict` taken from: https://github.com/django/django/blob/70576740b0bb5289873f5a9a9a4e1a26b2c330e5/django/utils/datastructures.py#L282 """ diff --git a/moto/sagemaker/models.py b/moto/sagemaker/models.py index 8fef306b8..f53cc3eec 100644 --- a/moto/sagemaker/models.py +++ b/moto/sagemaker/models.py @@ -580,7 +580,9 @@ class SageMakerModelBackend(BaseBackend): message = "Could not find model '{}'.".format( Model.arn_for_model_name(model_name, self.region_name) ) - raise ValidationError(message=message) + raise RESTError( + error_type="ValidationException", message=message, template="error_json", + ) def list_models(self): models = [] diff --git a/requirements-tests.txt b/requirements-tests.txt index eaa8454c7..847ce539e 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -1,4 +1,4 @@ -nose +pytest +pytest-cov sure==1.4.11 freezegun -parameterized>=0.7.0 \ No newline at end of file diff --git a/scripts/get_amis.py b/scripts/get_amis.py index 687dab2d4..b694340bd 100644 --- a/scripts/get_amis.py +++ b/scripts/get_amis.py @@ -3,35 +3,64 @@ import json # Taken from free tier list when creating an instance instances = [ - 'ami-760aaa0f', 'ami-bb9a6bc2', 'ami-35e92e4c', 'ami-785db401', 'ami-b7e93bce', 'ami-dca37ea5', 'ami-999844e0', - 'ami-9b32e8e2', 'ami-f8e54081', 'ami-bceb39c5', 'ami-03cf127a', 'ami-1ecc1e67', 'ami-c2ff2dbb', 'ami-12c6146b', - 'ami-d1cb19a8', 'ami-61db0918', 'ami-56ec3e2f', 'ami-84ee3cfd', 'ami-86ee3cff', 'ami-f0e83a89', 'ami-1f12c066', - 'ami-afee3cd6', 'ami-1812c061', 'ami-77ed3f0e', 'ami-3bf32142', 'ami-6ef02217', 'ami-f4cf1d8d', 'ami-3df32144', - 'ami-c6f321bf', 'ami-24f3215d', 'ami-fa7cdd89', 'ami-1e749f67', 'ami-a9cc1ed0', 'ami-8104a4f8' + "ami-760aaa0f", + "ami-bb9a6bc2", + "ami-35e92e4c", + "ami-785db401", + "ami-b7e93bce", + "ami-dca37ea5", + "ami-999844e0", + "ami-9b32e8e2", + "ami-f8e54081", + "ami-bceb39c5", + "ami-03cf127a", + "ami-1ecc1e67", + "ami-c2ff2dbb", + "ami-12c6146b", + "ami-d1cb19a8", + "ami-61db0918", + "ami-56ec3e2f", + "ami-84ee3cfd", + "ami-86ee3cff", + "ami-f0e83a89", + "ami-1f12c066", + "ami-afee3cd6", + "ami-1812c061", + "ami-77ed3f0e", + "ami-3bf32142", + "ami-6ef02217", + "ami-f4cf1d8d", + "ami-3df32144", + "ami-c6f321bf", + "ami-24f3215d", + "ami-fa7cdd89", + "ami-1e749f67", + "ami-a9cc1ed0", + "ami-8104a4f8", ] -client = boto3.client('ec2', region_name='eu-west-1') +client = boto3.client("ec2", region_name="eu-west-1") test = client.describe_images(ImageIds=instances) result = [] -for image in test['Images']: +for image in test["Images"]: try: tmp = { - 'ami_id': image['ImageId'], - 'name': image['Name'], - 'description': image['Description'], - 'owner_id': image['OwnerId'], - 'public': image['Public'], - 'virtualization_type': image['VirtualizationType'], - 'architecture': image['Architecture'], - 'state': image['State'], - 'platform': image.get('Platform'), - 'image_type': image['ImageType'], - 'hypervisor': image['Hypervisor'], - 'root_device_name': image['RootDeviceName'], - 'root_device_type': image['RootDeviceType'], - 'sriov': image.get('SriovNetSupport', 'simple') + "ami_id": image["ImageId"], + "name": image["Name"], + "description": image["Description"], + "owner_id": image["OwnerId"], + "public": image["Public"], + "virtualization_type": image["VirtualizationType"], + "architecture": image["Architecture"], + "state": image["State"], + "platform": image.get("Platform"), + "image_type": image["ImageType"], + "hypervisor": image["Hypervisor"], + "root_device_name": image["RootDeviceName"], + "root_device_type": image["RootDeviceType"], + "sriov": image.get("SriovNetSupport", "simple"), } result.append(tmp) except Exception as err: diff --git a/scripts/implementation_coverage.py b/scripts/implementation_coverage.py index 57f978ff9..23def7700 100755 --- a/scripts/implementation_coverage.py +++ b/scripts/implementation_coverage.py @@ -7,12 +7,18 @@ import boto3 script_dir = os.path.dirname(os.path.abspath(__file__)) -alternative_service_names = {'lambda': 'awslambda', 'dynamodb': 'dynamodb2'} +alternative_service_names = {"lambda": "awslambda", "dynamodb": "dynamodb2"} def get_moto_implementation(service_name): - service_name = service_name.replace("-", "") if "-" in service_name else service_name - alt_service_name = alternative_service_names[service_name] if service_name in alternative_service_names else service_name + service_name = ( + service_name.replace("-", "") if "-" in service_name else service_name + ) + alt_service_name = ( + alternative_service_names[service_name] + if service_name in alternative_service_names + else service_name + ) if hasattr(moto, "mock_{}".format(alt_service_name)): mock = getattr(moto, "mock_{}".format(alt_service_name)) elif hasattr(moto, "mock_{}".format(service_name)): @@ -31,11 +37,13 @@ def calculate_implementation_coverage(): coverage = {} for service_name in service_names: moto_client = get_moto_implementation(service_name) - real_client = boto3.client(service_name, region_name='us-east-1') + real_client = boto3.client(service_name, region_name="us-east-1") implemented = [] not_implemented = [] - operation_names = [xform_name(op) for op in real_client.meta.service_model.operation_names] + operation_names = [ + xform_name(op) for op in real_client.meta.service_model.operation_names + ] for op in operation_names: if moto_client and op in dir(moto_client): implemented.append(op) @@ -43,20 +51,22 @@ def calculate_implementation_coverage(): not_implemented.append(op) coverage[service_name] = { - 'implemented': implemented, - 'not_implemented': not_implemented, + "implemented": implemented, + "not_implemented": not_implemented, } return coverage def print_implementation_coverage(coverage): for service_name in sorted(coverage): - implemented = coverage.get(service_name)['implemented'] - not_implemented = coverage.get(service_name)['not_implemented'] + implemented = coverage.get(service_name)["implemented"] + not_implemented = coverage.get(service_name)["not_implemented"] operations = sorted(implemented + not_implemented) if implemented and not_implemented: - percentage_implemented = int(100.0 * len(implemented) / (len(implemented) + len(not_implemented))) + percentage_implemented = int( + 100.0 * len(implemented) / (len(implemented) + len(not_implemented)) + ) elif implemented: percentage_implemented = 100 else: @@ -84,12 +94,14 @@ def write_implementation_coverage_to_file(coverage): print("Writing to {}".format(implementation_coverage_file)) with open(implementation_coverage_file, "w+") as file: for service_name in sorted(coverage): - implemented = coverage.get(service_name)['implemented'] - not_implemented = coverage.get(service_name)['not_implemented'] + implemented = coverage.get(service_name)["implemented"] + not_implemented = coverage.get(service_name)["not_implemented"] operations = sorted(implemented + not_implemented) if implemented and not_implemented: - percentage_implemented = int(100.0 * len(implemented) / (len(implemented) + len(not_implemented))) + percentage_implemented = int( + 100.0 * len(implemented) / (len(implemented) + len(not_implemented)) + ) elif implemented: percentage_implemented = 100 else: @@ -98,7 +110,9 @@ def write_implementation_coverage_to_file(coverage): file.write("\n") file.write("## {}\n".format(service_name)) file.write("
\n") - file.write("{}% implemented\n\n".format(percentage_implemented)) + file.write( + "{}% implemented\n\n".format(percentage_implemented) + ) for op in operations: if op in implemented: file.write("- [X] {}\n".format(op)) @@ -107,7 +121,7 @@ def write_implementation_coverage_to_file(coverage): file.write("
\n") -if __name__ == '__main__': +if __name__ == "__main__": cov = calculate_implementation_coverage() write_implementation_coverage_to_file(cov) print_implementation_coverage(cov) diff --git a/scripts/scaffold.py b/scripts/scaffold.py index de6781b3f..9255ac008 100755 --- a/scripts/scaffold.py +++ b/scripts/scaffold.py @@ -17,9 +17,7 @@ from lxml import etree import click import jinja2 -from prompt_toolkit import ( - prompt -) +from prompt_toolkit import prompt from prompt_toolkit.completion import WordCompleter from prompt_toolkit.shortcuts import print_formatted_text @@ -29,35 +27,35 @@ import boto3 from moto.core.responses import BaseResponse from moto.core import BaseBackend -from implementation_coverage import ( - get_moto_implementation -) +from implementation_coverage import get_moto_implementation from inflection import singularize -TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), './template') +TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "./template") -INPUT_IGNORED_IN_BACKEND = ['Marker', 'PageSize'] -OUTPUT_IGNORED_IN_BACKEND = ['NextMarker'] +INPUT_IGNORED_IN_BACKEND = ["Marker", "PageSize"] +OUTPUT_IGNORED_IN_BACKEND = ["NextMarker"] def print_progress(title, body, color): - click.secho(u'\t{}\t'.format(title), fg=color, nl=False) + click.secho(u"\t{}\t".format(title), fg=color, nl=False) click.echo(body) def select_service_and_operation(): service_names = Session().get_available_services() service_completer = WordCompleter(service_names) - service_name = prompt(u'Select service: ', completer=service_completer) + service_name = prompt(u"Select service: ", completer=service_completer) if service_name not in service_names: - click.secho(u'{} is not valid service'.format(service_name), fg='red') + click.secho(u"{} is not valid service".format(service_name), fg="red") raise click.Abort() moto_client = get_moto_implementation(service_name) - real_client = boto3.client(service_name, region_name='us-east-1') + real_client = boto3.client(service_name, region_name="us-east-1") implemented = [] not_implemented = [] - operation_names = [xform_name(op) for op in real_client.meta.service_model.operation_names] + operation_names = [ + xform_name(op) for op in real_client.meta.service_model.operation_names + ] for op in operation_names: if moto_client and op in dir(moto_client): implemented.append(op) @@ -65,133 +63,148 @@ def select_service_and_operation(): not_implemented.append(op) operation_completer = WordCompleter(operation_names) - click.echo('==Current Implementation Status==') + click.echo("==Current Implementation Status==") for operation_name in operation_names: - check = 'X' if operation_name in implemented else ' ' - click.secho('[{}] {}'.format(check, operation_name)) - click.echo('=================================') - operation_name = prompt(u'Select Operation: ', completer=operation_completer) + check = "X" if operation_name in implemented else " " + click.secho("[{}] {}".format(check, operation_name)) + click.echo("=================================") + operation_name = prompt(u"Select Operation: ", completer=operation_completer) if operation_name not in operation_names: - click.secho('{} is not valid operation'.format(operation_name), fg='red') + click.secho("{} is not valid operation".format(operation_name), fg="red") raise click.Abort() if operation_name in implemented: - click.secho('{} is already implemented'.format(operation_name), fg='red') + click.secho("{} is already implemented".format(operation_name), fg="red") raise click.Abort() return service_name, operation_name + def get_escaped_service(service): - return service.replace('-', '') + return service.replace("-", "") + def get_lib_dir(service): - return os.path.join('moto', get_escaped_service(service)) + return os.path.join("moto", get_escaped_service(service)) + def get_test_dir(service): - return os.path.join('tests', 'test_{}'.format(get_escaped_service(service))) + return os.path.join("tests", "test_{}".format(get_escaped_service(service))) def render_template(tmpl_dir, tmpl_filename, context, service, alt_filename=None): - is_test = True if 'test' in tmpl_dir else False - rendered = jinja2.Environment( - loader=jinja2.FileSystemLoader(tmpl_dir) - ).get_template(tmpl_filename).render(context) + is_test = True if "test" in tmpl_dir else False + rendered = ( + jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_dir)) + .get_template(tmpl_filename) + .render(context) + ) dirname = get_test_dir(service) if is_test else get_lib_dir(service) filename = alt_filename or os.path.splitext(tmpl_filename)[0] filepath = os.path.join(dirname, filename) if os.path.exists(filepath): - print_progress('skip creating', filepath, 'yellow') + print_progress("skip creating", filepath, "yellow") else: - print_progress('creating', filepath, 'green') - with open(filepath, 'w') as f: + print_progress("creating", filepath, "green") + with open(filepath, "w") as f: f.write(rendered) def append_mock_to_init_py(service): - path = os.path.join(os.path.dirname(__file__), '..', 'moto', '__init__.py') + path = os.path.join(os.path.dirname(__file__), "..", "moto", "__init__.py") with open(path) as f: - lines = [_.replace('\n', '') for _ in f.readlines()] + lines = [_.replace("\n", "") for _ in f.readlines()] - if any(_ for _ in lines if re.match('^mock_{}.*lazy_load(.*)$'.format(service), _)): + if any(_ for _ in lines if re.match("^mock_{}.*lazy_load(.*)$".format(service), _)): return - filtered_lines = [_ for _ in lines if re.match('^mock_.*lazy_load(.*)$', _)] + filtered_lines = [_ for _ in lines if re.match("^mock_.*lazy_load(.*)$", _)] last_import_line_index = lines.index(filtered_lines[-1]) - new_line = 'mock_{} = lazy_load(".{}", "mock_{}")'.format(get_escaped_service(service), get_escaped_service(service), get_escaped_service(service)) + new_line = 'mock_{} = lazy_load(".{}", "mock_{}")'.format( + get_escaped_service(service), + get_escaped_service(service), + get_escaped_service(service), + ) lines.insert(last_import_line_index + 1, new_line) - body = '\n'.join(lines) + '\n' - with open(path, 'w') as f: + body = "\n".join(lines) + "\n" + with open(path, "w") as f: f.write(body) def append_mock_dict_to_backends_py(service): - path = os.path.join(os.path.dirname(__file__), '..', 'moto', 'backends.py') + path = os.path.join(os.path.dirname(__file__), "..", "moto", "backends.py") with open(path) as f: - lines = [_.replace('\n', '') for _ in f.readlines()] + lines = [_.replace("\n", "") for _ in f.readlines()] - if any(_ for _ in lines if re.match(".*\"{}\": {}_backends.*".format(service, service), _)): + if any( + _ + for _ in lines + if re.match('.*"{}": {}_backends.*'.format(service, service), _) + ): return - filtered_lines = [_ for _ in lines if re.match(".*\".*\":.*_backends.*", _)] + filtered_lines = [_ for _ in lines if re.match('.*".*":.*_backends.*', _)] last_elem_line_index = lines.index(filtered_lines[-1]) - new_line = " \"{}\": (\"{}\", \"{}_backends\"),".format(service, get_escaped_service(service), get_escaped_service(service)) + new_line = ' "{}": ("{}", "{}_backends"),'.format( + service, get_escaped_service(service), get_escaped_service(service) + ) prev_line = lines[last_elem_line_index] - if not prev_line.endswith('{') and not prev_line.endswith(','): - lines[last_elem_line_index] += ',' + if not prev_line.endswith("{") and not prev_line.endswith(","): + lines[last_elem_line_index] += "," lines.insert(last_elem_line_index + 1, new_line) - body = '\n'.join(lines) + '\n' - with open(path, 'w') as f: + body = "\n".join(lines) + "\n" + with open(path, "w") as f: f.write(body) + def initialize_service(service, operation, api_protocol): - """create lib and test dirs if not exist - """ + """create lib and test dirs if not exist""" lib_dir = get_lib_dir(service) test_dir = get_test_dir(service) - print_progress('Initializing service', service, 'green') + print_progress("Initializing service", service, "green") client = boto3.client(service) service_class = client.__class__.__name__ endpoint_prefix = client._service_model.endpoint_prefix tmpl_context = { - 'service': service, - 'service_class': service_class, - 'endpoint_prefix': endpoint_prefix, - 'api_protocol': api_protocol, - 'escaped_service': get_escaped_service(service) + "service": service, + "service_class": service_class, + "endpoint_prefix": endpoint_prefix, + "api_protocol": api_protocol, + "escaped_service": get_escaped_service(service), } # initialize service directory if os.path.exists(lib_dir): - print_progress('skip creating', lib_dir, 'yellow') + print_progress("skip creating", lib_dir, "yellow") else: - print_progress('creating', lib_dir, 'green') + print_progress("creating", lib_dir, "green") os.makedirs(lib_dir) - tmpl_dir = os.path.join(TEMPLATE_DIR, 'lib') + tmpl_dir = os.path.join(TEMPLATE_DIR, "lib") for tmpl_filename in os.listdir(tmpl_dir): - render_template( - tmpl_dir, tmpl_filename, tmpl_context, service - ) + render_template(tmpl_dir, tmpl_filename, tmpl_context, service) # initialize test directory if os.path.exists(test_dir): - print_progress('skip creating', test_dir, 'yellow') + print_progress("skip creating", test_dir, "yellow") else: - print_progress('creating', test_dir, 'green') + print_progress("creating", test_dir, "green") os.makedirs(test_dir) - tmpl_dir = os.path.join(TEMPLATE_DIR, 'test') + tmpl_dir = os.path.join(TEMPLATE_DIR, "test") for tmpl_filename in os.listdir(tmpl_dir): - alt_filename = 'test_{}.py'.format(get_escaped_service(service)) if tmpl_filename == 'test_service.py.j2' else None - render_template( - tmpl_dir, tmpl_filename, tmpl_context, service, alt_filename + alt_filename = ( + "test_{}.py".format(get_escaped_service(service)) + if tmpl_filename == "test_service.py.j2" + else None ) + render_template(tmpl_dir, tmpl_filename, tmpl_context, service, alt_filename) # append mock to init files append_mock_to_init_py(service) @@ -199,22 +212,24 @@ def initialize_service(service, operation, api_protocol): def to_upper_camel_case(s): - return ''.join([_.title() for _ in s.split('_')]) + return "".join([_.title() for _ in s.split("_")]) def to_lower_camel_case(s): - words = s.split('_') - return ''.join(words[:1] + [_.title() for _ in words[1:]]) + words = s.split("_") + return "".join(words[:1] + [_.title() for _ in words[1:]]) def to_snake_case(s): - s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', s) - return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() + s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", s) + return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() + def get_operation_name_in_keys(operation_name, operation_keys): index = [_.lower() for _ in operation_keys].index(operation_name.lower()) return operation_keys[index] + def get_function_in_responses(service, operation, protocol): """refers to definition of API in botocore, and autogenerates function You can see example of elbv2 from link below. @@ -224,44 +239,56 @@ def get_function_in_responses(service, operation, protocol): aws_operation_name = get_operation_name_in_keys( to_upper_camel_case(operation), - list(client._service_model._service_description['operations'].keys()) + list(client._service_model._service_description["operations"].keys()), ) op_model = client._service_model.operation_model(aws_operation_name) - if not hasattr(op_model.output_shape, 'members'): + if not hasattr(op_model.output_shape, "members"): outputs = {} else: outputs = op_model.output_shape.members inputs = op_model.input_shape.members - input_names = [to_snake_case(_) for _ in inputs.keys() if _ not in INPUT_IGNORED_IN_BACKEND] - output_names = [to_snake_case(_) for _ in outputs.keys() if _ not in OUTPUT_IGNORED_IN_BACKEND] - body = '\ndef {}(self):\n'.format(operation) + input_names = [ + to_snake_case(_) for _ in inputs.keys() if _ not in INPUT_IGNORED_IN_BACKEND + ] + output_names = [ + to_snake_case(_) for _ in outputs.keys() if _ not in OUTPUT_IGNORED_IN_BACKEND + ] + body = "\ndef {}(self):\n".format(operation) for input_name, input_type in inputs.items(): type_name = input_type.type_name - if type_name == 'integer': + if type_name == "integer": arg_line_tmpl = ' {} = self._get_int_param("{}")\n' - elif type_name == 'list': + elif type_name == "list": arg_line_tmpl = ' {} = self._get_list_prefix("{}.member")\n' else: arg_line_tmpl = ' {} = self._get_param("{}")\n' body += arg_line_tmpl.format(to_snake_case(input_name), input_name) if output_names: - body += ' {} = self.{}_backend.{}(\n'.format(', '.join(output_names), get_escaped_service(service), operation) - else: - body += ' self.{}_backend.{}(\n'.format(get_escaped_service(service), operation) - for input_name in input_names: - body += ' {}={},\n'.format(input_name, input_name) - - body += ' )\n' - if protocol == 'query': - body += ' template = self.response_template({}_TEMPLATE)\n'.format(operation.upper()) - body += ' return template.render({})\n'.format( - ', '.join(['{}={}'.format(_, _) for _ in output_names]) + body += " {} = self.{}_backend.{}(\n".format( + ", ".join(output_names), get_escaped_service(service), operation + ) + else: + body += " self.{}_backend.{}(\n".format( + get_escaped_service(service), operation + ) + for input_name in input_names: + body += " {}={},\n".format(input_name, input_name) + + body += " )\n" + if protocol == "query": + body += " template = self.response_template({}_TEMPLATE)\n".format( + operation.upper() + ) + body += " return template.render({})\n".format( + ", ".join(["{}={}".format(_, _) for _ in output_names]) + ) + elif protocol in ["json", "rest-json"]: + body += " # TODO: adjust response\n" + body += " return json.dumps(dict({}))\n".format( + ", ".join(["{}={}".format(to_lower_camel_case(_), _) for _ in output_names]) ) - elif protocol in ['json', 'rest-json']: - body += ' # TODO: adjust response\n' - body += ' return json.dumps(dict({}))\n'.format(', '.join(['{}={}'.format(to_lower_camel_case(_), _) for _ in output_names])) return body @@ -273,44 +300,55 @@ def get_function_in_models(service, operation): client = boto3.client(service) aws_operation_name = get_operation_name_in_keys( to_upper_camel_case(operation), - list(client._service_model._service_description['operations'].keys()) + list(client._service_model._service_description["operations"].keys()), ) op_model = client._service_model.operation_model(aws_operation_name) inputs = op_model.input_shape.members - if not hasattr(op_model.output_shape, 'members'): + if not hasattr(op_model.output_shape, "members"): outputs = {} else: outputs = op_model.output_shape.members - input_names = [to_snake_case(_) for _ in inputs.keys() if _ not in INPUT_IGNORED_IN_BACKEND] - output_names = [to_snake_case(_) for _ in outputs.keys() if _ not in OUTPUT_IGNORED_IN_BACKEND] + input_names = [ + to_snake_case(_) for _ in inputs.keys() if _ not in INPUT_IGNORED_IN_BACKEND + ] + output_names = [ + to_snake_case(_) for _ in outputs.keys() if _ not in OUTPUT_IGNORED_IN_BACKEND + ] if input_names: - body = 'def {}(self, {}):\n'.format(operation, ', '.join(input_names)) + body = "def {}(self, {}):\n".format(operation, ", ".join(input_names)) else: - body = 'def {}(self)\n' - body += ' # implement here\n' - body += ' return {}\n\n'.format(', '.join(output_names)) + body = "def {}(self)\n" + body += " # implement here\n" + body += " return {}\n\n".format(", ".join(output_names)) return body def _get_subtree(name, shape, replace_list, name_prefix=[]): class_name = shape.__class__.__name__ - if class_name in ('StringShape', 'Shape'): + if class_name in ("StringShape", "Shape"): t = etree.Element(name) if name_prefix: - t.text = '{{ %s.%s }}' % (name_prefix[-1], to_snake_case(name)) + t.text = "{{ %s.%s }}" % (name_prefix[-1], to_snake_case(name)) else: - t.text = '{{ %s }}' % to_snake_case(name) + t.text = "{{ %s }}" % to_snake_case(name) return t - elif class_name in ('ListShape', ): + elif class_name in ("ListShape",): replace_list.append((name, name_prefix)) t = etree.Element(name) - t_member = etree.Element('member') + t_member = etree.Element("member") t.append(t_member) for nested_name, nested_shape in shape.member.members.items(): - t_member.append(_get_subtree(nested_name, nested_shape, replace_list, name_prefix + [singularize(name.lower())])) + t_member.append( + _get_subtree( + nested_name, + nested_shape, + replace_list, + name_prefix + [singularize(name.lower())], + ) + ) return t - raise ValueError('Not supported Shape') + raise ValueError("Not supported Shape") def get_response_query_template(service, operation): @@ -323,22 +361,22 @@ def get_response_query_template(service, operation): client = boto3.client(service) aws_operation_name = get_operation_name_in_keys( to_upper_camel_case(operation), - list(client._service_model._service_description['operations'].keys()) + list(client._service_model._service_description["operations"].keys()), ) op_model = client._service_model.operation_model(aws_operation_name) - result_wrapper = op_model.output_shape.serialization['resultWrapper'] - response_wrapper = result_wrapper.replace('Result', 'Response') + result_wrapper = op_model.output_shape.serialization["resultWrapper"] + response_wrapper = result_wrapper.replace("Result", "Response") metadata = op_model.metadata - xml_namespace = metadata['xmlNamespace'] + xml_namespace = metadata["xmlNamespace"] # build xml tree - t_root = etree.Element(response_wrapper, xmlns=xml_namespace) + t_root = etree.Element(response_wrapper, xmlns=xml_namespace) # build metadata - t_metadata = etree.Element('ResponseMetadata') - t_request_id = etree.Element('RequestId') - t_request_id.text = '1549581b-12b7-11e3-895e-1334aEXAMPLE' + t_metadata = etree.Element("ResponseMetadata") + t_request_id = etree.Element("RequestId") + t_request_id.text = "1549581b-12b7-11e3-895e-1334aEXAMPLE" t_metadata.append(t_request_id) t_root.append(t_metadata) @@ -349,68 +387,73 @@ def get_response_query_template(service, operation): for output_name, output_shape in outputs.items(): t_result.append(_get_subtree(output_name, output_shape, replace_list)) t_root.append(t_result) - xml_body = etree.tostring(t_root, pretty_print=True).decode('utf-8') + xml_body = etree.tostring(t_root, pretty_print=True).decode("utf-8") xml_body_lines = xml_body.splitlines() for replace in replace_list: name = replace[0] prefix = replace[1] singular_name = singularize(name) - start_tag = '<%s>' % name - iter_name = '{}.{}'.format(prefix[-1], name.lower())if prefix else name.lower() - loop_start = '{%% for %s in %s %%}' % (singular_name.lower(), iter_name) - end_tag = '' % name - loop_end = '{{ endfor }}' + start_tag = "<%s>" % name + iter_name = "{}.{}".format(prefix[-1], name.lower()) if prefix else name.lower() + loop_start = "{%% for %s in %s %%}" % (singular_name.lower(), iter_name) + end_tag = "" % name + loop_end = "{{ endfor }}" start_tag_indexes = [i for i, l in enumerate(xml_body_lines) if start_tag in l] if len(start_tag_indexes) != 1: - raise Exception('tag %s not found in response body' % start_tag) + raise Exception("tag %s not found in response body" % start_tag) start_tag_index = start_tag_indexes[0] xml_body_lines.insert(start_tag_index + 1, loop_start) end_tag_indexes = [i for i, l in enumerate(xml_body_lines) if end_tag in l] if len(end_tag_indexes) != 1: - raise Exception('tag %s not found in response body' % end_tag) + raise Exception("tag %s not found in response body" % end_tag) end_tag_index = end_tag_indexes[0] xml_body_lines.insert(end_tag_index, loop_end) - xml_body = '\n'.join(xml_body_lines) + xml_body = "\n".join(xml_body_lines) body = '\n{}_TEMPLATE = """{}"""'.format(operation.upper(), xml_body) return body def insert_code_to_class(path, base_class, new_code): with open(path) as f: - lines = [_.replace('\n', '') for _ in f.readlines()] - mod_path = os.path.splitext(path)[0].replace('/', '.') + lines = [_.replace("\n", "") for _ in f.readlines()] + mod_path = os.path.splitext(path)[0].replace("/", ".") mod = importlib.import_module(mod_path) clsmembers = inspect.getmembers(mod, inspect.isclass) - _response_cls = [_[1] for _ in clsmembers if issubclass(_[1], base_class) and _[1] != base_class] + _response_cls = [ + _[1] for _ in clsmembers if issubclass(_[1], base_class) and _[1] != base_class + ] if len(_response_cls) != 1: - raise Exception('unknown error, number of clsmembers is not 1') + raise Exception("unknown error, number of clsmembers is not 1") response_cls = _response_cls[0] code_lines, line_no = inspect.getsourcelines(response_cls) end_line_no = line_no + len(code_lines) - func_lines = [' ' * 4 + _ for _ in new_code.splitlines()] + func_lines = [" " * 4 + _ for _ in new_code.splitlines()] lines = lines[:end_line_no] + func_lines + lines[end_line_no:] - body = '\n'.join(lines) + '\n' - with open(path, 'w') as f: + body = "\n".join(lines) + "\n" + with open(path, "w") as f: f.write(body) + def insert_url(service, operation, api_protocol): client = boto3.client(service) service_class = client.__class__.__name__ aws_operation_name = get_operation_name_in_keys( to_upper_camel_case(operation), - list(client._service_model._service_description['operations'].keys()) + list(client._service_model._service_description["operations"].keys()), ) - uri = client._service_model.operation_model(aws_operation_name).http['requestUri'] + uri = client._service_model.operation_model(aws_operation_name).http["requestUri"] - path = os.path.join(os.path.dirname(__file__), '..', 'moto', get_escaped_service(service), 'urls.py') + path = os.path.join( + os.path.dirname(__file__), "..", "moto", get_escaped_service(service), "urls.py" + ) with open(path) as f: - lines = [_.replace('\n', '') for _ in f.readlines()] + lines = [_.replace("\n", "") for _ in f.readlines()] if any(_ for _ in lines if re.match(uri, _)): return @@ -418,50 +461,49 @@ def insert_url(service, operation, api_protocol): url_paths_found = False last_elem_line_index = -1 for i, line in enumerate(lines): - if line.startswith('url_paths'): + if line.startswith("url_paths"): url_paths_found = True - if url_paths_found and line.startswith('}'): + if url_paths_found and line.startswith("}"): last_elem_line_index = i - 1 prev_line = lines[last_elem_line_index] - if not prev_line.endswith('{') and not prev_line.endswith(','): - lines[last_elem_line_index] += ',' + if not prev_line.endswith("{") and not prev_line.endswith(","): + lines[last_elem_line_index] += "," # generate url pattern - if api_protocol == 'rest-json': + if api_protocol == "rest-json": new_line = " '{0}/.*$': response.dispatch," else: - new_line = " '{0}%s$': %sResponse.dispatch," % ( - uri, service_class - ) + new_line = " '{0}%s$': %sResponse.dispatch," % (uri, service_class) if new_line in lines: return lines.insert(last_elem_line_index + 1, new_line) - body = '\n'.join(lines) + '\n' - with open(path, 'w') as f: + body = "\n".join(lines) + "\n" + with open(path, "w") as f: f.write(body) + def insert_codes(service, operation, api_protocol): func_in_responses = get_function_in_responses(service, operation, api_protocol) func_in_models = get_function_in_models(service, operation) # edit responses.py - responses_path = 'moto/{}/responses.py'.format(get_escaped_service(service)) - print_progress('inserting code', responses_path, 'green') + responses_path = "moto/{}/responses.py".format(get_escaped_service(service)) + print_progress("inserting code", responses_path, "green") insert_code_to_class(responses_path, BaseResponse, func_in_responses) # insert template - if api_protocol == 'query': + if api_protocol == "query": template = get_response_query_template(service, operation) with open(responses_path) as f: lines = [_[:-1] for _ in f.readlines()] lines += template.splitlines() - with open(responses_path, 'w') as f: - f.write('\n'.join(lines)) + with open(responses_path, "w") as f: + f.write("\n".join(lines)) # edit models.py - models_path = 'moto/{}/models.py'.format(get_escaped_service(service)) - print_progress('inserting code', models_path, 'green') + models_path = "moto/{}/models.py".format(get_escaped_service(service)) + print_progress("inserting code", models_path, "green") insert_code_to_class(models_path, BaseBackend, func_in_models) # edit urls.py @@ -471,15 +513,20 @@ def insert_codes(service, operation, api_protocol): @click.command() def main(): service, operation = select_service_and_operation() - api_protocol = boto3.client(service)._service_model.metadata['protocol'] + api_protocol = boto3.client(service)._service_model.metadata["protocol"] initialize_service(service, operation, api_protocol) - if api_protocol in ['query', 'json', 'rest-json']: + if api_protocol in ["query", "json", "rest-json"]: insert_codes(service, operation, api_protocol) else: - print_progress('skip inserting code', 'api protocol "{}" is not supported'.format(api_protocol), 'yellow') + print_progress( + "skip inserting code", + 'api protocol "{}" is not supported'.format(api_protocol), + "yellow", + ) click.echo('You will still need to add the mock into "__init__.py"'.format(service)) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/scripts/update_managed_policies.py b/scripts/update_managed_policies.py index de7058fd7..2e227b752 100755 --- a/scripts/update_managed_policies.py +++ b/scripts/update_managed_policies.py @@ -23,42 +23,53 @@ def json_serial(obj): raise TypeError("Type not serializable") -client = boto3.client('iam') +client = boto3.client("iam") policies = {} -paginator = client.get_paginator('list_policies') +paginator = client.get_paginator("list_policies") try: - response_iterator = paginator.paginate(Scope='AWS') + response_iterator = paginator.paginate(Scope="AWS") for response in response_iterator: - for policy in response['Policies']: - policies[policy['PolicyName']] = policy + for policy in response["Policies"]: + policies[policy["PolicyName"]] = policy except NoCredentialsError: print("USAGE:") print("Put your AWS credentials into ~/.aws/credentials and run:") print(__file__) print("") print("Or specify them on the command line:") - print("AWS_ACCESS_KEY_ID=your_personal_access_key AWS_SECRET_ACCESS_KEY=your_personal_secret {}".format(__file__)) + print( + "AWS_ACCESS_KEY_ID=your_personal_access_key AWS_SECRET_ACCESS_KEY=your_personal_secret {}".format( + __file__ + ) + ) print("") sys.exit(1) for policy_name in policies: response = client.get_policy_version( - PolicyArn=policies[policy_name]['Arn'], - VersionId=policies[policy_name]['DefaultVersionId']) - for key in response['PolicyVersion']: - if key != "CreateDate": # the policy's CreateDate should not be overwritten by its version's CreateDate - policies[policy_name][key] = response['PolicyVersion'][key] + PolicyArn=policies[policy_name]["Arn"], + VersionId=policies[policy_name]["DefaultVersionId"], + ) + for key in response["PolicyVersion"]: + if ( + key != "CreateDate" + ): # the policy's CreateDate should not be overwritten by its version's CreateDate + policies[policy_name][key] = response["PolicyVersion"][key] -with open(output_file, 'w') as f: - triple_quote = '\"\"\"' +with open(output_file, "w") as f: + triple_quote = '"""' f.write("# Imported via `make aws_managed_policies`\n") - f.write('aws_managed_policies_data = {}\n'.format(triple_quote)) - f.write(json.dumps(policies, - sort_keys=True, - indent=4, - separators=(',', ': '), - default=json_serial)) - f.write('{}\n'.format(triple_quote)) + f.write("aws_managed_policies_data = {}\n".format(triple_quote)) + f.write( + json.dumps( + policies, + sort_keys=True, + indent=4, + separators=(",", ": "), + default=json_serial, + ) + ) + f.write("{}\n".format(triple_quote)) diff --git a/setup.cfg b/setup.cfg index fb04c16a8..1c247ef3d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,6 @@ -[nosetests] -verbosity=1 -detailed-errors=1 -with-coverage=1 -cover-package=moto - [bdist_wheel] universal=1 + +[tool:pytest] +markers = + network: marks tests which require network connection diff --git a/setup.py b/setup.py index bcbc88a20..a738feab6 100755 --- a/setup.py +++ b/setup.py @@ -13,20 +13,22 @@ PY2 = sys.version_info[0] == 2 # Borrowed from pip at https://github.com/pypa/pip/blob/62c27dee45625e1b63d1e023b0656310f276e050/setup.py#L11-L15 here = os.path.abspath(os.path.dirname(__file__)) + def read(*parts): # intentionally *not* adding an encoding option to open, See: # https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690 - with open(os.path.join(here, *parts), 'r') as fp: + with open(os.path.join(here, *parts), "r") as fp: return fp.read() def get_version(): - version_file = read('moto', '__init__.py') - version_match = re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', - version_file, re.MULTILINE) + version_file = read("moto", "__init__.py") + version_match = re.search( + r'^__version__ = [\'"]([^\'"]*)[\'"]', version_file, re.MULTILINE + ) if version_match: return version_match.group(1) - raise RuntimeError('Unable to find version string.') + raise RuntimeError("Unable to find version string.") install_requires = [ @@ -77,7 +79,9 @@ else: _dep_PyYAML = "PyYAML>=5.1" _dep_python_jose = "python-jose[cryptography]>=3.1.0,<4.0.0" -_dep_python_jose_ecdsa_pin = "ecdsa<0.15" # https://github.com/spulec/moto/pull/3263#discussion_r477404984 +_dep_python_jose_ecdsa_pin = ( + "ecdsa<0.15" # https://github.com/spulec/moto/pull/3263#discussion_r477404984 +) _dep_docker = "docker>=2.5.1" _dep_jsondiff = "jsondiff>=1.1.2" _dep_aws_xray_sdk = "aws-xray-sdk!=0.96,>=0.93" @@ -98,31 +102,31 @@ all_extra_deps = [ _dep_sshpubkeys_py2, _dep_sshpubkeys_py3, ] -all_server_deps = all_extra_deps + ['flask', 'flask-cors'] +all_server_deps = all_extra_deps + ["flask", "flask-cors"] # TODO: do we want to add ALL services here? # i.e. even those without extra dependencies. # Would be good for future-compatibility, I guess. extras_per_service = { - 'apigateway': [_dep_python_jose, _dep_python_jose_ecdsa_pin], - 'awslambda': [_dep_docker], - 'batch': [_dep_docker], - 'cloudformation': [_dep_docker, _dep_PyYAML, _dep_cfn_lint], - 'cognitoidp': [_dep_python_jose, _dep_python_jose_ecdsa_pin], - 'dynamodb2': [_dep_docker], - 'dynamodbstreams': [_dep_docker], + "apigateway": [_dep_python_jose, _dep_python_jose_ecdsa_pin], + "awslambda": [_dep_docker], + "batch": [_dep_docker], + "cloudformation": [_dep_docker, _dep_PyYAML, _dep_cfn_lint], + "cognitoidp": [_dep_python_jose, _dep_python_jose_ecdsa_pin], + "dynamodb2": [_dep_docker], + "dynamodbstreams": [_dep_docker], "ec2": [_dep_docker, _dep_sshpubkeys_py2, _dep_sshpubkeys_py3], - 'iotdata': [_dep_jsondiff], - 's3': [_dep_PyYAML], - 'ses': [_dep_docker], - 'sns': [_dep_docker], - 'sqs': [_dep_docker], - 'ssm': [_dep_docker, _dep_PyYAML, _dep_cfn_lint], - 'xray': [_dep_aws_xray_sdk], + "iotdata": [_dep_jsondiff], + "s3": [_dep_PyYAML], + "ses": [_dep_docker], + "sns": [_dep_docker], + "sqs": [_dep_docker], + "ssm": [_dep_docker, _dep_PyYAML, _dep_cfn_lint], + "xray": [_dep_aws_xray_sdk], } extras_require = { - 'all': all_extra_deps, - 'server': all_server_deps, + "all": all_extra_deps, + "server": all_server_deps, } extras_require.update(extras_per_service) @@ -136,18 +140,18 @@ else: setup( - name='moto', + name="moto", version=get_version(), - description='A library that allows your python tests to easily' - ' mock out the boto library', - long_description=read('README.md'), - long_description_content_type='text/markdown', - author='Steve Pulec', - author_email='spulec@gmail.com', - url='https://github.com/spulec/moto', + description="A library that allows your python tests to easily" + " mock out the boto library", + long_description=read("README.md"), + long_description_content_type="text/markdown", + author="Steve Pulec", + author_email="spulec@gmail.com", + url="https://github.com/spulec/moto", entry_points={ - 'console_scripts': [ - 'moto_server = moto.server:main', + "console_scripts": [ + "moto_server = moto.server:main", ], }, packages=find_packages(exclude=("tests", "tests.*")), diff --git a/tests/__init__.py b/tests/__init__.py index 05b1d476b..01fe5ab1f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -6,4 +6,3 @@ import logging logging.getLogger("boto").setLevel(logging.CRITICAL) logging.getLogger("boto3").setLevel(logging.CRITICAL) logging.getLogger("botocore").setLevel(logging.CRITICAL) -logging.getLogger("nose").setLevel(logging.CRITICAL) diff --git a/tests/backport_assert_raises.py b/tests/backport_assert_raises.py deleted file mode 100644 index bfed51308..000000000 --- a/tests/backport_assert_raises.py +++ /dev/null @@ -1,41 +0,0 @@ -from __future__ import unicode_literals - -""" -Patch courtesy of: -https://marmida.com/blog/index.php/2012/08/08/monkey-patching-assert_raises/ -""" - -# code for monkey-patching -import nose.tools - -# let's fix nose.tools.assert_raises (which is really unittest.assertRaises) -# so that it always supports context management - -# in order for these changes to be available to other modules, you'll need -# to guarantee this module is imported by your fixture before either nose or -# unittest are imported - -try: - nose.tools.assert_raises(Exception) -except TypeError: - # this version of assert_raises doesn't support the 1-arg version - class AssertRaisesContext(object): - def __init__(self, expected): - self.expected = expected - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, tb): - self.exception = exc_val - if issubclass(exc_type, self.expected): - return True - nose.tools.assert_equal(exc_type, self.expected) - # if you get to this line, the last assertion must have passed - # suppress the propagation of this exception - return True - - def assert_raises_context(exc_type): - return AssertRaisesContext(exc_type) - - nose.tools.assert_raises = assert_raises_context diff --git a/tests/helpers.py b/tests/helpers.py index ffe27103d..9293bcad9 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals import boto -from nose.plugins.skip import SkipTest +from unittest import SkipTest import six diff --git a/tests/test_acm/__init__.py b/tests/test_acm/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_acm/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_acm/resources/__init__.py b/tests/test_acm/resources/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_acm/resources/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_acm/test_acm.py b/tests/test_acm/test_acm.py index 5a1596a4d..b32fabeed 100644 --- a/tests/test_acm/test_acm.py +++ b/tests/test_acm/test_acm.py @@ -1,18 +1,16 @@ from __future__ import unicode_literals import os -import boto3 -from freezegun import freeze_time -import sure # noqa import uuid +import boto3 +import pytest +import sure # noqa from botocore.exceptions import ClientError - +from freezegun import freeze_time from moto import mock_acm, settings from moto.core import ACCOUNT_ID - -from nose import SkipTest -from nose.tools import assert_raises +from unittest import SkipTest RESOURCE_FOLDER = os.path.join(os.path.dirname(__file__), "resources") _GET_RESOURCE = lambda x: open(os.path.join(RESOURCE_FOLDER, x), "rb").read() @@ -396,17 +394,17 @@ def test_operations_with_invalid_tags(): client = boto3.client("acm", region_name="eu-central-1") # request certificate with invalid tags - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.request_certificate( DomainName="example.com", Tags=[{"Key": "X" * 200, "Value": "Valid"}], ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.contain( "Member must have length less than or equal to 128" ) # import certificate with invalid tags - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.import_certificate( Certificate=SERVER_CRT, PrivateKey=SERVER_KEY, @@ -417,31 +415,31 @@ def test_operations_with_invalid_tags(): ], ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.contain( "Member must have length less than or equal to 256" ) arn = _import_cert(client) # add invalid tags to existing certificate - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.add_tags_to_certificate( CertificateArn=arn, Tags=[{"Key": "aws:xxx", "Value": "Valid"}, {"Key": "key2"}], ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.contain( "AWS internal tags cannot be changed with this API" ) # try removing invalid tags from existing certificate - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.remove_tags_from_certificate( CertificateArn=arn, Tags=[{"Key": "aws:xxx", "Value": "Valid"}] ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.contain( "AWS internal tags cannot be changed with this API" ) @@ -452,13 +450,13 @@ def test_add_too_many_tags(): arn = _import_cert(client) # Add 51 tags - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.add_tags_to_certificate( CertificateArn=arn, Tags=[{"Key": "a-%d" % i, "Value": "abcd"} for i in range(1, 52)], ) - ex.exception.response["Error"]["Code"].should.equal("TooManyTagsException") - ex.exception.response["Error"]["Message"].should.contain("contains too many Tags") + ex.value.response["Error"]["Code"].should.equal("TooManyTagsException") + ex.value.response["Error"]["Message"].should.contain("contains too many Tags") client.list_tags_for_certificate(CertificateArn=arn)["Tags"].should.have.empty # Add 49 tags first, then try to add 2 more. @@ -469,15 +467,15 @@ def test_add_too_many_tags(): client.list_tags_for_certificate(CertificateArn=arn)["Tags"].should.have.length_of( 49 ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.add_tags_to_certificate( CertificateArn=arn, Tags=[{"Key": "x-1", "Value": "xyz"}, {"Key": "x-2", "Value": "xyz"}], ) - ex.exception.response["Error"]["Code"].should.equal("TooManyTagsException") - ex.exception.response["Error"]["Message"].should.contain("contains too many Tags") - ex.exception.response["Error"]["Message"].count("pqrs").should.equal(49) - ex.exception.response["Error"]["Message"].count("xyz").should.equal(2) + ex.value.response["Error"]["Code"].should.equal("TooManyTagsException") + ex.value.response["Error"]["Message"].should.contain("contains too many Tags") + ex.value.response["Error"]["Message"].count("pqrs").should.equal(49) + ex.value.response["Error"]["Message"].count("xyz").should.equal(2) client.list_tags_for_certificate(CertificateArn=arn)["Tags"].should.have.length_of( 49 ) @@ -495,20 +493,21 @@ def test_request_certificate_no_san(): # Also tests the SAN code -@freeze_time("2012-01-01 12:00:00", as_arg=True) @mock_acm -def test_request_certificate_issued_status(frozen_time): +def test_request_certificate_issued_status(): # After requesting a certificate, it should then auto-validate after 1 minute # Some sneaky programming for that ;-) client = boto3.client("acm", region_name="eu-central-1") - resp = client.request_certificate( - DomainName="google.com", - SubjectAlternativeNames=["google.com", "www.google.com", "mail.google.com"], - ) + with freeze_time("2012-01-01 12:00:00"): + resp = client.request_certificate( + DomainName="google.com", + SubjectAlternativeNames=["google.com", "www.google.com", "mail.google.com"], + ) arn = resp["CertificateArn"] - resp = client.describe_certificate(CertificateArn=arn) + with freeze_time("2012-01-01 12:00:00"): + resp = client.describe_certificate(CertificateArn=arn) resp["Certificate"]["CertificateArn"].should.equal(arn) resp["Certificate"]["DomainName"].should.equal("google.com") resp["Certificate"]["Issuer"].should.equal("Amazon") @@ -518,21 +517,21 @@ def test_request_certificate_issued_status(frozen_time): len(resp["Certificate"]["SubjectAlternativeNames"]).should.equal(3) # validation will be pending for 1 minute. - resp = client.describe_certificate(CertificateArn=arn) + with freeze_time("2012-01-01 12:00:00"): + resp = client.describe_certificate(CertificateArn=arn) resp["Certificate"]["CertificateArn"].should.equal(arn) resp["Certificate"]["Status"].should.equal("PENDING_VALIDATION") if not settings.TEST_SERVER_MODE: # Move time to get it issued. - frozen_time.move_to("2012-01-01 12:02:00") - resp = client.describe_certificate(CertificateArn=arn) + with freeze_time("2012-01-01 12:02:00"): + resp = client.describe_certificate(CertificateArn=arn) resp["Certificate"]["CertificateArn"].should.equal(arn) resp["Certificate"]["Status"].should.equal("ISSUED") -@freeze_time("2012-01-01 12:00:00", as_arg=True) @mock_acm -def test_request_certificate_with_mutiple_times(frozen_time): +def test_request_certificate_with_mutiple_times(): if settings.TEST_SERVER_MODE: raise SkipTest("Cant manipulate time in server mode") @@ -540,11 +539,12 @@ def test_request_certificate_with_mutiple_times(frozen_time): # Some sneaky programming for that ;-) client = boto3.client("acm", region_name="eu-central-1") - resp = client.request_certificate( - IdempotencyToken="test_token", - DomainName="google.com", - SubjectAlternativeNames=["google.com", "www.google.com", "mail.google.com"], - ) + with freeze_time("2012-01-01 12:00:00"): + resp = client.request_certificate( + IdempotencyToken="test_token", + DomainName="google.com", + SubjectAlternativeNames=["google.com", "www.google.com", "mail.google.com"], + ) original_arn = resp["CertificateArn"] # Should be able to request a certificate multiple times in an hour @@ -554,21 +554,25 @@ def test_request_certificate_with_mutiple_times(frozen_time): "2012-01-01 12:30:00", "2012-01-01 12:45:00", ): - frozen_time.move_to(time_intervals) + with freeze_time(time_intervals): + resp = client.request_certificate( + IdempotencyToken="test_token", + DomainName="google.com", + SubjectAlternativeNames=[ + "google.com", + "www.google.com", + "mail.google.com", + ], + ) + arn = resp["CertificateArn"] + arn.should.equal(original_arn) + + # Move time + with freeze_time("2012-01-01 13:01:00"): resp = client.request_certificate( IdempotencyToken="test_token", DomainName="google.com", SubjectAlternativeNames=["google.com", "www.google.com", "mail.google.com"], ) - arn = resp["CertificateArn"] - arn.should.equal(original_arn) - - # Move time - frozen_time.move_to("2012-01-01 13:01:00") - resp = client.request_certificate( - IdempotencyToken="test_token", - DomainName="google.com", - SubjectAlternativeNames=["google.com", "www.google.com", "mail.google.com"], - ) arn = resp["CertificateArn"] arn.should_not.equal(original_arn) diff --git a/tests/test_apigateway/__init__.py b/tests/test_apigateway/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_apigateway/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py index c58d644fa..f85fd4a02 100644 --- a/tests/test_apigateway/test_apigateway.py +++ b/tests/test_apigateway/test_apigateway.py @@ -11,7 +11,7 @@ from botocore.exceptions import ClientError import responses from moto import mock_apigateway, mock_cognitoidp, settings from moto.core import ACCOUNT_ID -from nose.tools import assert_raises +import pytest @freeze_time("2015-01-01") @@ -90,13 +90,13 @@ def test_create_rest_api_with_policy(): def test_create_rest_api_invalid_apikeysource(): client = boto3.client("apigateway", region_name="us-west-2") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_rest_api( name="my_api", description="this is my api", apiKeySource="not a valid api key source", ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Code"].should.equal("ValidationException") @mock_apigateway @@ -126,13 +126,13 @@ def test_create_rest_api_valid_apikeysources(): def test_create_rest_api_invalid_endpointconfiguration(): client = boto3.client("apigateway", region_name="us-west-2") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_rest_api( name="my_api", description="this is my api", endpointConfiguration={"types": ["INVALID"]}, ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Code"].should.equal("ValidationException") @mock_apigateway @@ -194,10 +194,10 @@ def test_create_resource__validate_name(): valid_names = ["users", "{user_id}", "{proxy+}", "user_09", "good-dog"] # All invalid names should throw an exception for name in invalid_names: - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_resource(restApiId=api_id, parentId=root_id, pathPart=name) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end and an optional plus sign before the closing brace." ) # All valid names should go through @@ -1194,10 +1194,10 @@ def test_create_deployment_requires_REST_methods(): response = client.create_rest_api(name="my_api", description="this is my api") api_id = response["id"] - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_deployment(restApiId=api_id, stageName=stage_name)["id"] - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "The REST API doesn't contain any methods" ) @@ -1217,10 +1217,10 @@ def test_create_deployment_requires_REST_method_integrations(): restApiId=api_id, resourceId=root_id, httpMethod="GET", authorizationType="NONE" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_deployment(restApiId=api_id, stageName=stage_name)["id"] - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "No integration defined for method" ) @@ -1273,12 +1273,12 @@ def test_put_integration_response_requires_responseTemplate(): integrationHttpMethod="POST", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration_response( restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200" ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal("Invalid request input") + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal("Invalid request input") # Works fine if responseTemplate is defined client.put_integration_response( restApiId=api_id, @@ -1314,13 +1314,13 @@ def test_put_integration_response_with_response_template(): integrationHttpMethod="POST", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration_response( restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200" ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal("Invalid request input") + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal("Invalid request input") client.put_integration_response( restApiId=api_id, @@ -1372,7 +1372,7 @@ def test_put_integration_validation(): for type in types_requiring_integration_method: # Ensure that integrations of these types fail if no integrationHttpMethod is provided - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1380,8 +1380,8 @@ def test_put_integration_validation(): type=type, uri="http://httpbin.org/robots.txt", ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "Enumeration value for HttpMethod must be non-empty" ) for type in types_not_requiring_integration_method: @@ -1428,7 +1428,7 @@ def test_put_integration_validation(): ) for type in ["AWS_PROXY"]: # Ensure that aws_proxy does not support S3 - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1440,13 +1440,13 @@ def test_put_integration_validation(): uri="arn:aws:apigateway:us-west-2:s3:path/b/k", integrationHttpMethod="POST", ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "Integrations of type 'AWS_PROXY' currently only supports Lambda function and Firehose stream invocations." ) for type in aws_types: # Ensure that the Role ARN is for the current account - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1456,13 +1456,13 @@ def test_put_integration_validation(): uri="arn:aws:apigateway:us-west-2:s3:path/b/k", integrationHttpMethod="POST", ) - ex.exception.response["Error"]["Code"].should.equal("AccessDeniedException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDeniedException") + ex.value.response["Error"]["Message"].should.equal( "Cross-account pass role is not allowed." ) for type in ["AWS"]: # Ensure that the Role ARN is specified for aws integrations - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1471,13 +1471,13 @@ def test_put_integration_validation(): uri="arn:aws:apigateway:us-west-2:s3:path/b/k", integrationHttpMethod="POST", ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "Role ARN must be specified for AWS integrations" ) for type in http_types: # Ensure that the URI is valid HTTP - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1486,13 +1486,13 @@ def test_put_integration_validation(): uri="non-valid-http", integrationHttpMethod="POST", ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "Invalid HTTP endpoint specified for URI" ) for type in aws_types: # Ensure that the URI is an ARN - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1501,13 +1501,13 @@ def test_put_integration_validation(): uri="non-valid-arn", integrationHttpMethod="POST", ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "Invalid ARN specified in the request" ) for type in aws_types: # Ensure that the URI is a valid ARN - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_integration( restApiId=api_id, resourceId=root_id, @@ -1516,8 +1516,8 @@ def test_put_integration_validation(): uri="arn:aws:iam::0000000000:role/service-role/asdf", integrationHttpMethod="POST", ) - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal( "AWS ARN for integration must contain path or action" ) @@ -1632,11 +1632,11 @@ def test_create_domain_names(): response["domainName"].should.equal(domain_name) response["certificateName"].should.equal(test_certificate_name) # without domain name it should throw BadRequestException - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_domain_name(domainName="") - ex.exception.response["Error"]["Message"].should.equal("No Domain Name specified") - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal("No Domain Name specified") + ex.value.response["Error"]["Code"].should.equal("BadRequestException") @mock_apigateway @@ -1666,13 +1666,11 @@ def test_get_domain_name(): client = boto3.client("apigateway", region_name="us-west-2") domain_name = "testDomain" # quering an invalid domain name which is not present - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_domain_name(domainName=domain_name) - ex.exception.response["Error"]["Message"].should.equal( - "Invalid Domain Name specified" - ) - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal("Invalid Domain Name specified") + ex.value.response["Error"]["Code"].should.equal("NotFoundException") # adding a domain name client.create_domain_name(domainName=domain_name) # retrieving the data of added domain name. @@ -1701,19 +1699,17 @@ def test_create_model(): response["description"].should.equal(description) # with an invalid rest_api_id it should throw NotFoundException - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_model( restApiId=dummy_rest_api_id, name=model_name, description=description, contentType=content_type, ) - ex.exception.response["Error"]["Message"].should.equal( - "Invalid Rest API Id specified" - ) - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal("Invalid Rest API Id specified") + ex.value.response["Error"]["Code"].should.equal("NotFoundException") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_model( restApiId=rest_api_id, name="", @@ -1721,8 +1717,8 @@ def test_create_model(): contentType=content_type, ) - ex.exception.response["Error"]["Message"].should.equal("No Model Name specified") - ex.exception.response["Error"]["Code"].should.equal("BadRequestException") + ex.value.response["Error"]["Message"].should.equal("No Model Name specified") + ex.value.response["Error"]["Code"].should.equal("BadRequestException") @mock_apigateway @@ -1770,12 +1766,10 @@ def test_get_model_by_name(): result["name"] = model_name result["description"] = description - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_model(restApiId=dummy_rest_api_id, modelName=model_name) - ex.exception.response["Error"]["Message"].should.equal( - "Invalid Rest API Id specified" - ) - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal("Invalid Rest API Id specified") + ex.value.response["Error"]["Code"].should.equal("NotFoundException") @mock_apigateway @@ -1784,12 +1778,10 @@ def test_get_model_with_invalid_name(): response = client.create_rest_api(name="my_api", description="this is my api") rest_api_id = response["id"] # test with an invalid model name - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_model(restApiId=rest_api_id, modelName="fake") - ex.exception.response["Error"]["Message"].should.equal( - "Invalid Model Name specified" - ) - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal("Invalid Model Name specified") + ex.value.response["Error"]["Code"].should.equal("NotFoundException") @mock_apigateway @@ -1868,11 +1860,11 @@ def test_create_api_headers(): payload = {"value": apikey_value, "name": apikey_name} client.create_api_key(**payload) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_api_key(**payload) - ex.exception.response["Error"]["Code"].should.equal("ConflictException") + ex.value.response["Error"]["Code"].should.equal("ConflictException") if not settings.TEST_SERVER_MODE: - ex.exception.response["ResponseMetadata"]["HTTPHeaders"].should.equal({}) + ex.value.response["ResponseMetadata"]["HTTPHeaders"].should.equal({}) @mock_apigateway @@ -1939,10 +1931,10 @@ def test_usage_plans(): len(response["items"]).should.equal(0) # # Try to get info about a non existing usage - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_usage_plan(usagePlanId="not_existing") - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal( "Invalid Usage Plan ID specified" ) @@ -2030,26 +2022,26 @@ def test_usage_plan_keys(): len(response["items"]).should.equal(0) # Try to get info about a non existing api key - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_usage_plan_key(usagePlanId=usage_plan_id, keyId="not_existing_key") - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal( "Invalid API Key identifier specified" ) # Try to get info about an existing api key that has not jet added to a valid usage plan - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_usage_plan_key(usagePlanId=usage_plan_id, keyId=key_id) - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal( "Invalid Usage Plan ID specified" ) # Try to get info about an existing api key that has not jet added to a valid usage plan - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_usage_plan_key(usagePlanId="not_existing_plan_id", keyId=key_id) - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Message"].should.equal( "Invalid Usage Plan ID specified" ) diff --git a/tests/test_applicationautoscaling/test_applicationautoscaling.py b/tests/test_applicationautoscaling/test_applicationautoscaling.py index 9b1c0b678..aed728ab6 100644 --- a/tests/test_applicationautoscaling/test_applicationautoscaling.py +++ b/tests/test_applicationautoscaling/test_applicationautoscaling.py @@ -1,10 +1,10 @@ from __future__ import unicode_literals -import botocore + import boto3 +import botocore +import pytest import sure # noqa -from nose.tools import assert_raises from moto import mock_applicationautoscaling, mock_ecs -from moto.applicationautoscaling.exceptions import AWSValidationException DEFAULT_REGION = "us-east-1" DEFAULT_ECS_CLUSTER = "default" @@ -334,7 +334,7 @@ def test_put_scaling_policy(): }, } - with assert_raises(client.exceptions.ValidationException) as e: + with pytest.raises(client.exceptions.ValidationException) as e: client.put_scaling_policy( PolicyName=policy_name, ServiceNamespace=namespace, @@ -343,7 +343,7 @@ def test_put_scaling_policy(): PolicyType="ABCDEFG", TargetTrackingScalingPolicyConfiguration=policy_body, ) - e.exception.response["Error"]["Message"].should.match( + e.value.response["Error"]["Message"].should.match( r"Unknown policy type .* specified." ) @@ -443,14 +443,14 @@ def test_delete_scaling_policies(): }, } - with assert_raises(client.exceptions.ValidationException) as e: + with pytest.raises(client.exceptions.ValidationException) as e: client.delete_scaling_policy( PolicyName=policy_name, ServiceNamespace=namespace, ResourceId=resource_id, ScalableDimension=scalable_dimension, ) - e.exception.response["Error"]["Message"].should.match(r"No scaling policy found .*") + e.value.response["Error"]["Message"].should.match(r"No scaling policy found .*") response = client.put_scaling_policy( PolicyName=policy_name, @@ -507,12 +507,10 @@ def test_deregister_scalable_target(): response = client.describe_scalable_targets(ServiceNamespace=namespace) len(response["ScalableTargets"]).should.equal(0) - with assert_raises(client.exceptions.ValidationException) as e: + with pytest.raises(client.exceptions.ValidationException) as e: client.deregister_scalable_target( ServiceNamespace=namespace, ResourceId=resource_id, ScalableDimension=scalable_dimension, ) - e.exception.response["Error"]["Message"].should.match( - r"No scalable target found .*" - ) + e.value.response["Error"]["Message"].should.match(r"No scalable target found .*") diff --git a/tests/test_applicationautoscaling/test_validation.py b/tests/test_applicationautoscaling/test_validation.py index 02281ab05..b074d3396 100644 --- a/tests/test_applicationautoscaling/test_validation.py +++ b/tests/test_applicationautoscaling/test_validation.py @@ -4,10 +4,9 @@ from moto import mock_applicationautoscaling, mock_ecs from moto.applicationautoscaling import models from moto.applicationautoscaling.exceptions import AWSValidationException from botocore.exceptions import ParamValidationError -from nose.tools import assert_raises +import pytest import sure # noqa from botocore.exceptions import ClientError -from parameterized import parameterized from .test_applicationautoscaling import register_scalable_target DEFAULT_REGION = "us-east-1" @@ -25,21 +24,21 @@ DEFAULT_ROLE_ARN = "test:arn" @mock_applicationautoscaling def test_describe_scalable_targets_no_params_should_raise_param_validation_errors(): client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) - with assert_raises(ParamValidationError): + with pytest.raises(ParamValidationError): client.describe_scalable_targets() @mock_applicationautoscaling def test_register_scalable_target_no_params_should_raise_param_validation_errors(): client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) - with assert_raises(ParamValidationError): + with pytest.raises(ParamValidationError): client.register_scalable_target() @mock_applicationautoscaling def test_register_scalable_target_with_none_service_namespace_should_raise_param_validation_errors(): client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) - with assert_raises(ParamValidationError): + with pytest.raises(ParamValidationError): register_scalable_target(client, ServiceNamespace=None) @@ -47,7 +46,7 @@ def test_register_scalable_target_with_none_service_namespace_should_raise_param def test_describe_scalable_targets_with_invalid_scalable_dimension_should_return_validation_exception(): client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: response = client.describe_scalable_targets( ServiceNamespace=DEFAULT_SERVICE_NAMESPACE, ScalableDimension="foo", ) @@ -62,7 +61,7 @@ def test_describe_scalable_targets_with_invalid_scalable_dimension_should_return def test_describe_scalable_targets_with_invalid_service_namespace_should_return_validation_exception(): client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: response = client.describe_scalable_targets( ServiceNamespace="foo", ScalableDimension=DEFAULT_SCALABLE_DIMENSION, ) @@ -77,7 +76,7 @@ def test_describe_scalable_targets_with_invalid_service_namespace_should_return_ def test_describe_scalable_targets_with_multiple_invalid_parameters_should_return_validation_exception(): client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: response = client.describe_scalable_targets( ServiceNamespace="foo", ScalableDimension="bar", ) @@ -94,7 +93,7 @@ def test_register_scalable_target_ecs_with_non_existent_service_should_return_va client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION) resource_id = "service/{}/foo".format(DEFAULT_ECS_CLUSTER) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: register_scalable_target(client, ServiceNamespace="ecs", ResourceId=resource_id) err.response["Error"]["Code"].should.equal("ValidationException") err.response["Error"]["Message"].should.equal( @@ -103,12 +102,13 @@ def test_register_scalable_target_ecs_with_non_existent_service_should_return_va err.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) -@parameterized( +@pytest.mark.parametrize( + "namespace,r_id,dimension,expected", [ ("ecs", "service/default/test-svc", "ecs:service:DesiredCount", True), ("ecs", "banana/default/test-svc", "ecs:service:DesiredCount", False), ("rds", "service/default/test-svc", "ecs:service:DesiredCount", False), - ] + ], ) def test_target_params_are_valid_success(namespace, r_id, dimension, expected): if expected is True: @@ -116,7 +116,7 @@ def test_target_params_are_valid_success(namespace, r_id, dimension, expected): expected ) else: - with assert_raises(AWSValidationException): + with pytest.raises(AWSValidationException): models._target_params_are_valid(namespace, r_id, dimension) diff --git a/tests/test_athena/__init__.py b/tests/test_athena/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_athena/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_athena/test_athena.py b/tests/test_athena/test_athena.py index 805a653e3..f667f2316 100644 --- a/tests/test_athena/test_athena.py +++ b/tests/test_athena/test_athena.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest import boto3 import sure # noqa @@ -104,15 +104,15 @@ def test_start_query_execution(): def test_start_query_validate_workgroup(): client = boto3.client("athena", region_name="us-east-1") - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.start_query_execution( QueryString="query1", QueryExecutionContext={"Database": "string"}, ResultConfiguration={"OutputLocation": "string"}, WorkGroup="unknown_workgroup", ) - err.exception.response["Error"]["Code"].should.equal("InvalidRequestException") - err.exception.response["Error"]["Message"].should.equal("WorkGroup does not exist") + err.value.response["Error"]["Code"].should.equal("InvalidRequestException") + err.value.response["Error"]["Message"].should.equal("WorkGroup does not exist") @mock_athena diff --git a/tests/test_autoscaling/__init__.py b/tests/test_autoscaling/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_autoscaling/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_autoscaling/test_autoscaling.py b/tests/test_autoscaling/test_autoscaling.py index 1e7121381..cbcd8eb20 100644 --- a/tests/test_autoscaling/test_autoscaling.py +++ b/tests/test_autoscaling/test_autoscaling.py @@ -8,7 +8,7 @@ from boto.ec2.autoscale import Tag import boto.ec2.elb import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import ( mock_autoscaling, @@ -21,7 +21,7 @@ from moto import ( ) from tests.helpers import requires_boto_gte -from utils import ( +from .utils import ( setup_networking, setup_networking_deprecated, setup_instance_with_networking, @@ -97,8 +97,8 @@ def test_create_autoscaling_group(): @mock_autoscaling_deprecated def test_create_autoscaling_groups_defaults(): - """ Test with the minimum inputs and check that all of the proper defaults - are assigned for the other attributes """ + """Test with the minimum inputs and check that all of the proper defaults + are assigned for the other attributes""" mocked_networking = setup_networking_deprecated() conn = boto.connect_autoscale() @@ -781,7 +781,7 @@ def test_create_autoscaling_group_from_invalid_instance_id(): mocked_networking = setup_networking() client = boto3.client("autoscaling", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_auto_scaling_group( AutoScalingGroupName="test_asg", InstanceId=invalid_instance_id, @@ -791,9 +791,9 @@ def test_create_autoscaling_group_from_invalid_instance_id(): VPCZoneIdentifier=mocked_networking["subnet1"], NewInstancesProtectedFromScaleIn=False, ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Code"].should.equal("ValidationError") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("ValidationError") + ex.value.response["Error"]["Message"].should.equal( "Instance [{0}] is invalid.".format(invalid_instance_id) ) @@ -842,7 +842,7 @@ def test_create_autoscaling_group_no_template_ref(): )["LaunchTemplate"] client = boto3.client("autoscaling", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_auto_scaling_group( AutoScalingGroupName="test_asg", LaunchTemplate={"Version": str(template["LatestVersionNumber"])}, @@ -852,9 +852,9 @@ def test_create_autoscaling_group_no_template_ref(): VPCZoneIdentifier=mocked_networking["subnet1"], NewInstancesProtectedFromScaleIn=False, ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Code"].should.equal("ValidationError") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("ValidationError") + ex.value.response["Error"]["Message"].should.equal( "Valid requests must contain either launchTemplateId or LaunchTemplateName" ) @@ -874,7 +874,7 @@ def test_create_autoscaling_group_multiple_template_ref(): )["LaunchTemplate"] client = boto3.client("autoscaling", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_auto_scaling_group( AutoScalingGroupName="test_asg", LaunchTemplate={ @@ -888,9 +888,9 @@ def test_create_autoscaling_group_multiple_template_ref(): VPCZoneIdentifier=mocked_networking["subnet1"], NewInstancesProtectedFromScaleIn=False, ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Code"].should.equal("ValidationError") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("ValidationError") + ex.value.response["Error"]["Message"].should.equal( "Valid requests must contain either launchTemplateId or LaunchTemplateName" ) @@ -899,7 +899,7 @@ def test_create_autoscaling_group_multiple_template_ref(): def test_create_autoscaling_group_boto3_no_launch_configuration(): mocked_networking = setup_networking() client = boto3.client("autoscaling", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_auto_scaling_group( AutoScalingGroupName="test_asg", MinSize=0, @@ -908,9 +908,9 @@ def test_create_autoscaling_group_boto3_no_launch_configuration(): VPCZoneIdentifier=mocked_networking["subnet1"], NewInstancesProtectedFromScaleIn=False, ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Code"].should.equal("ValidationError") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("ValidationError") + ex.value.response["Error"]["Message"].should.equal( "Valid requests must contain either LaunchTemplate, LaunchConfigurationName, " "InstanceId or MixedInstancesPolicy parameter." ) @@ -934,7 +934,7 @@ def test_create_autoscaling_group_boto3_multiple_launch_configurations(): LaunchConfigurationName="test_launch_configuration" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_auto_scaling_group( AutoScalingGroupName="test_asg", LaunchConfigurationName="test_launch_configuration", @@ -948,9 +948,9 @@ def test_create_autoscaling_group_boto3_multiple_launch_configurations(): VPCZoneIdentifier=mocked_networking["subnet1"], NewInstancesProtectedFromScaleIn=False, ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Code"].should.equal("ValidationError") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("ValidationError") + ex.value.response["Error"]["Message"].should.equal( "Valid requests must contain either LaunchTemplate, LaunchConfigurationName, " "InstanceId or MixedInstancesPolicy parameter." ) diff --git a/tests/test_autoscaling/test_autoscaling_cloudformation.py b/tests/test_autoscaling/test_autoscaling_cloudformation.py index 240ba66e0..24a5b5628 100644 --- a/tests/test_autoscaling/test_autoscaling_cloudformation.py +++ b/tests/test_autoscaling/test_autoscaling_cloudformation.py @@ -7,7 +7,7 @@ from moto import ( mock_ec2, ) -from utils import setup_networking +from .utils import setup_networking @mock_autoscaling diff --git a/tests/test_autoscaling/test_elbv2.py b/tests/test_autoscaling/test_elbv2.py index a3d3dba9f..d3b1cc5f8 100644 --- a/tests/test_autoscaling/test_elbv2.py +++ b/tests/test_autoscaling/test_elbv2.py @@ -4,7 +4,7 @@ import boto3 import sure # noqa from moto import mock_autoscaling, mock_ec2, mock_elbv2 -from utils import setup_networking +from .utils import setup_networking @mock_elbv2 diff --git a/tests/test_autoscaling/test_launch_configurations.py b/tests/test_autoscaling/test_launch_configurations.py index ab2743f54..3ed296f64 100644 --- a/tests/test_autoscaling/test_launch_configurations.py +++ b/tests/test_autoscaling/test_launch_configurations.py @@ -152,8 +152,8 @@ def test_create_launch_configuration_using_ip_association_should_default_to_fals @mock_autoscaling_deprecated def test_create_launch_configuration_defaults(): - """ Test with the minimum inputs and check that all of the proper defaults - are assigned for the other attributes """ + """Test with the minimum inputs and check that all of the proper defaults + are assigned for the other attributes""" conn = boto.connect_autoscale() config = LaunchConfiguration( name="tester", image_id="ami-abcd1234", instance_type="m1.small" diff --git a/tests/test_autoscaling/test_policies.py b/tests/test_autoscaling/test_policies.py index f44938eea..ca1009dbe 100644 --- a/tests/test_autoscaling/test_policies.py +++ b/tests/test_autoscaling/test_policies.py @@ -7,7 +7,7 @@ import sure # noqa from moto import mock_autoscaling_deprecated -from utils import setup_networking_deprecated +from .utils import setup_networking_deprecated def setup_autoscale_group(): @@ -170,7 +170,7 @@ def test_execute_policy_percent_change_in_capacity(): @mock_autoscaling_deprecated def test_execute_policy_small_percent_change_in_capacity(): - """ http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-scale-based-on-demand.html + """http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-scale-based-on-demand.html If PercentChangeInCapacity returns a value between 0 and 1, Auto Scaling will round it off to 1.""" setup_autoscale_group() diff --git a/tests/test_awslambda/__init__.py b/tests/test_awslambda/__init__.py index e69de29bb..08a1c1568 100644 --- a/tests/test_awslambda/__init__.py +++ b/tests/test_awslambda/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_awslambda/test_awslambda_cloudformation.py b/tests/test_awslambda/test_awslambda_cloudformation.py index c3061ff3a..6d998bfd4 100644 --- a/tests/test_awslambda/test_awslambda_cloudformation.py +++ b/tests/test_awslambda/test_awslambda_cloudformation.py @@ -4,7 +4,7 @@ import sure # noqa import zipfile from botocore.exceptions import ClientError from moto import mock_cloudformation, mock_iam, mock_lambda, mock_s3, mock_sqs -from nose.tools import assert_raises +import pytest from string import Template from uuid import uuid4 @@ -109,9 +109,9 @@ def test_lambda_can_be_deleted_by_cloudformation(): # Delete Stack cf.delete_stack(StackName=stack["StackId"]) # Verify function was deleted - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: lmbda.get_function(FunctionName=created_fn_name) - e.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") + e.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") @mock_cloudformation diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py index f7e7b3c7e..7e4fc22f5 100644 --- a/tests/test_awslambda/test_lambda.py +++ b/tests/test_awslambda/test_lambda.py @@ -24,7 +24,7 @@ from moto import ( mock_sqs, ) from moto.sts.models import ACCOUNT_ID -from nose.tools import assert_raises +import pytest from botocore.exceptions import ClientError _lambda_region = "us-west-2" @@ -93,6 +93,7 @@ def test_list_functions(): result["Functions"].should.have.length_of(0) +@pytest.mark.network @mock_lambda def test_invoke_requestresponse_function(): conn = boto3.client("lambda", _lambda_region) @@ -137,6 +138,7 @@ def test_invoke_requestresponse_function(): assert "LogResult" not in success_result +@pytest.mark.network @mock_lambda def test_invoke_requestresponse_function_with_arn(): from moto.awslambda.models import ACCOUNT_ID @@ -169,6 +171,7 @@ def test_invoke_requestresponse_function_with_arn(): json.loads(payload).should.equal(in_data) +@pytest.mark.network @mock_lambda def test_invoke_event_function(): conn = boto3.client("lambda", _lambda_region) @@ -196,6 +199,7 @@ def test_invoke_event_function(): json.loads(success_result["Payload"].read().decode("utf-8")).should.equal(in_data) +@pytest.mark.network @mock_lambda def test_invoke_dryrun_function(): conn = boto3.client("lambda", _lambda_region) @@ -258,6 +262,7 @@ if settings.TEST_SERVER_MODE: actual_payload.should.equal(expected_payload) +@pytest.mark.network @mock_logs @mock_sns @mock_ec2 @@ -497,7 +502,7 @@ def test_get_function(): ) # Test get function when can't find function name - with assert_raises(conn.exceptions.ResourceNotFoundException): + with pytest.raises(conn.exceptions.ResourceNotFoundException): conn.get_function(FunctionName="junk", Qualifier="$LATEST") @@ -729,6 +734,7 @@ def test_list_create_list_get_delete_list(): conn.list_functions()["Functions"].should.have.length_of(0) +@pytest.mark.network @mock_lambda def test_invoke_lambda_error(): lambda_fx = """ @@ -844,6 +850,7 @@ def test_tags_not_found(): ).should.throw(botocore.client.ClientError) +@pytest.mark.network @mock_lambda def test_invoke_async_function(): conn = boto3.client("lambda", _lambda_region) @@ -1115,6 +1122,7 @@ def test_create_event_source_mapping(): assert response["State"] == "Enabled" +@pytest.mark.network @mock_logs @mock_lambda @mock_sqs @@ -1156,6 +1164,7 @@ def test_invoke_function_from_sqs(): ) +@pytest.mark.network @mock_logs @mock_lambda @mock_dynamodb2 @@ -1204,6 +1213,7 @@ def test_invoke_function_from_dynamodb_put(): ) +@pytest.mark.network @mock_logs @mock_lambda @mock_dynamodb2 @@ -1286,6 +1296,7 @@ def wait_for_log_msg(expected_msg, log_group): return False, received_messages +@pytest.mark.network @mock_logs @mock_lambda @mock_sqs @@ -1662,7 +1673,7 @@ def test_update_function_s3(): @mock_lambda def test_create_function_with_invalid_arn(): err = create_invalid_lambda("test-iam-role") - err.exception.response["Error"]["Message"].should.equal( + err.value.response["Error"]["Message"].should.equal( r"1 validation error detected: Value 'test-iam-role' at 'role' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:(aws[a-zA-Z-]*)?:iam::(\d{12}):role/?[a-zA-Z_0-9+=,.@\-_/]+" ) @@ -1670,7 +1681,7 @@ def test_create_function_with_invalid_arn(): @mock_lambda def test_create_function_with_arn_from_different_account(): err = create_invalid_lambda("arn:aws:iam::000000000000:role/example_role") - err.exception.response["Error"]["Message"].should.equal( + err.value.response["Error"]["Message"].should.equal( "Cross-account pass role is not allowed." ) @@ -1680,7 +1691,7 @@ def test_create_function_with_unknown_arn(): err = create_invalid_lambda( "arn:aws:iam::" + str(ACCOUNT_ID) + ":role/service-role/unknown_role" ) - err.exception.response["Error"]["Message"].should.equal( + err.value.response["Error"]["Message"].should.equal( "The role defined for the function cannot be assumed by Lambda." ) @@ -1800,7 +1811,7 @@ def test_get_function_concurrency(): def create_invalid_lambda(role): conn = boto3.client("lambda", _lambda_region) zip_content = get_test_zip_file1() - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: conn.create_function( FunctionName="testFunction", Runtime="python2.7", diff --git a/tests/test_batch/__init__.py b/tests/test_batch/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_batch/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_batch/test_batch.py b/tests/test_batch/test_batch.py index 566be6aca..5a7757777 100644 --- a/tests/test_batch/test_batch.py +++ b/tests/test_batch/test_batch.py @@ -6,10 +6,7 @@ import boto3 from botocore.exceptions import ClientError import sure # noqa from moto import mock_batch, mock_iam, mock_ec2, mock_ecs, mock_logs - -import functools -import nose - +import pytest DEFAULT_REGION = "eu-central-1" @@ -689,6 +686,7 @@ def test_submit_job_by_name(): @mock_ecs @mock_iam @mock_batch +@pytest.mark.network def test_submit_job(): ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) @@ -740,7 +738,9 @@ def test_submit_job(): else: raise RuntimeError("Batch job timed out") - resp = logs_client.describe_log_streams(logGroupName="/aws/batch/job") + resp = logs_client.describe_log_streams( + logGroupName="/aws/batch/job", logStreamNamePrefix="sayhellotomylittlefriend" + ) len(resp["logStreams"]).should.equal(1) ls_name = resp["logStreams"][0]["logStreamName"] @@ -755,6 +755,7 @@ def test_submit_job(): @mock_ecs @mock_iam @mock_batch +@pytest.mark.network def test_list_jobs(): ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) diff --git a/tests/test_batch/test_batch_cloudformation.py b/tests/test_batch/test_batch_cloudformation.py index cc51b79f3..7935f3fe9 100644 --- a/tests/test_batch/test_batch_cloudformation.py +++ b/tests/test_batch/test_batch_cloudformation.py @@ -14,7 +14,6 @@ from moto import ( mock_cloudformation, ) import functools -import nose import json DEFAULT_REGION = "eu-central-1" diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud.py b/tests/test_cloudformation/test_cloudformation_stack_crud.py index d7e26e85d..40004f805 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud.py @@ -12,9 +12,7 @@ import boto.cloudformation from boto.exception import BotoServerError import sure # noqa -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises # noqa -from nose.tools import assert_raises +import pytest from moto.core import ACCOUNT_ID from moto import ( @@ -319,7 +317,7 @@ def test_delete_stack_by_id(): conn.describe_stacks().should.have.length_of(1) conn.delete_stack(stack_id) conn.describe_stacks().should.have.length_of(0) - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.describe_stacks("test_stack") conn.describe_stacks(stack_id).should.have.length_of(1) @@ -338,7 +336,7 @@ def test_delete_stack_with_resource_missing_delete_attr(): @mock_cloudformation_deprecated def test_bad_describe_stack(): conn = boto.connect_cloudformation() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.describe_stacks("bad_stack") @@ -519,10 +517,10 @@ def test_update_stack_when_rolled_back(): stack_id ].status = "ROLLBACK_COMPLETE" - with assert_raises(BotoServerError) as err: + with pytest.raises(BotoServerError) as err: conn.update_stack("test_stack", dummy_template_json) - ex = err.exception + ex = err.value ex.body.should.match(r"is in ROLLBACK_COMPLETE state and can not be updated") ex.error_code.should.equal("ValidationError") ex.reason.should.equal("Bad Request") diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py index 65469f1b3..86b6f1a94 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py @@ -9,8 +9,7 @@ import boto3 from botocore.exceptions import ClientError import sure # noqa -# Ensure 'assert_raises' context manager support for Python 2.6 -from nose.tools import assert_raises +import pytest from moto import mock_cloudformation, mock_s3, mock_sqs, mock_ec2 from moto.core import ACCOUNT_ID @@ -548,7 +547,7 @@ def test_boto3_list_stack_set_operations(): @mock_cloudformation def test_boto3_bad_list_stack_resources(): cf_conn = boto3.client("cloudformation", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): cf_conn.list_stack_resources(StackName="test_stack_set") @@ -1180,7 +1179,7 @@ def test_describe_updated_stack(): @mock_cloudformation def test_bad_describe_stack(): cf_conn = boto3.client("cloudformation", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): cf_conn.describe_stacks(StackName="non_existent_stack") @@ -1332,7 +1331,7 @@ def test_delete_stack_with_export(): def test_export_names_must_be_unique(): cf = boto3.resource("cloudformation", region_name="us-east-1") cf.create_stack(StackName="test_stack", TemplateBody=dummy_output_template_json) - with assert_raises(ClientError): + with pytest.raises(ClientError): cf.create_stack(StackName="test_stack", TemplateBody=dummy_output_template_json) @@ -1373,7 +1372,7 @@ def test_boto3_create_duplicate_stack(): StackName="test_stack", TemplateBody=dummy_template_json, ) - with assert_raises(ClientError): + with pytest.raises(ClientError): cf_conn.create_stack( StackName="test_stack", TemplateBody=dummy_template_json, ) diff --git a/tests/test_cloudformation/test_validate.py b/tests/test_cloudformation/test_validate.py index ea14fceea..a4c65a4c7 100644 --- a/tests/test_cloudformation/test_validate.py +++ b/tests/test_cloudformation/test_validate.py @@ -3,7 +3,6 @@ import json import yaml import os import boto3 -from nose.tools import raises import botocore import sure # noqa diff --git a/tests/test_cloudwatch/__init__.py b/tests/test_cloudwatch/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_cloudwatch/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_cloudwatch/test_cloudwatch_boto3.py b/tests/test_cloudwatch/test_cloudwatch_boto3.py index 9c4757d60..d448b0c58 100644 --- a/tests/test_cloudwatch/test_cloudwatch_boto3.py +++ b/tests/test_cloudwatch/test_cloudwatch_boto3.py @@ -4,7 +4,7 @@ import boto3 from botocore.exceptions import ClientError from datetime import datetime, timedelta from freezegun import freeze_time -from nose.tools import assert_raises +import pytest from uuid import uuid4 import pytz import sure # noqa @@ -111,18 +111,18 @@ def test_delete_invalid_alarm(): ) # trying to delete an alarm which is not created along with valid alarm. - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: cloudwatch.delete_alarms(AlarmNames=["InvalidAlarmName", "testalarm1"]) - e.exception.response["Error"]["Code"].should.equal("ResourceNotFound") + e.value.response["Error"]["Code"].should.equal("ResourceNotFound") resp = cloudwatch.describe_alarms(AlarmNames=["testalarm1"]) # making sure other alarms are not deleted in case of an error. len(resp["MetricAlarms"]).should.equal(1) # test to check if the error raises if only one invalid alarm is tried to delete. - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: cloudwatch.delete_alarms(AlarmNames=["InvalidAlarmName"]) - e.exception.response["Error"]["Code"].should.equal("ResourceNotFound") + e.value.response["Error"]["Code"].should.equal("ResourceNotFound") @mock_cloudwatch @@ -423,9 +423,9 @@ def test_list_metrics_paginated(): # Verify that only a single page of metrics is returned cloudwatch.list_metrics()["Metrics"].should.be.empty # Verify we can't pass a random NextToken - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: cloudwatch.list_metrics(NextToken=str(uuid4())) - e.exception.response["Error"]["Message"].should.equal( + e.value.response["Error"]["Message"].should.equal( "Request parameter NextToken is invalid" ) # Add a boatload of metrics @@ -452,9 +452,9 @@ def test_list_metrics_paginated(): len(third_page["Metrics"]).should.equal(100) third_page.shouldnt.contain("NextToken") # Verify that we can't reuse an existing token - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: cloudwatch.list_metrics(NextToken=first_page["NextToken"]) - e.exception.response["Error"]["Message"].should.equal( + e.value.response["Error"]["Message"].should.equal( "Request parameter NextToken is invalid" ) diff --git a/tests/test_codecommit/test_codecommit.py b/tests/test_codecommit/test_codecommit.py index 69021372a..4c38252ff 100644 --- a/tests/test_codecommit/test_codecommit.py +++ b/tests/test_codecommit/test_codecommit.py @@ -4,7 +4,7 @@ import sure # noqa from moto import mock_codecommit from moto.core import ACCOUNT_ID from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest @mock_codecommit @@ -81,12 +81,12 @@ def test_create_repository_repository_name_exists(): client.create_repository(repositoryName="repository_two") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_repository( repositoryName="repository_two", repositoryDescription="description repo two", ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateRepository") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("RepositoryNameExistsException") @@ -99,9 +99,9 @@ def test_create_repository_repository_name_exists(): def test_create_repository_invalid_repository_name(): client = boto3.client("codecommit", region_name="eu-central-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_repository(repositoryName="in_123_valid_@#$_characters") - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateRepository") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidRepositoryNameException") @@ -156,9 +156,9 @@ def test_get_repository(): client = boto3.client("codecommit", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_repository(repositoryName=repository_name) - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetRepository") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("RepositoryDoesNotExistException") @@ -171,9 +171,9 @@ def test_get_repository(): def test_get_repository_invalid_repository_name(): client = boto3.client("codecommit", region_name="eu-central-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_repository(repositoryName="repository_one-@#@") - ex = e.exception + ex = e.value ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidRepositoryNameException") ex.response["Error"]["Message"].should.equal( @@ -207,9 +207,9 @@ def test_delete_repository(): def test_delete_repository_invalid_repository_name(): client = boto3.client("codecommit", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_repository(repositoryName="_rep@ository_one") - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeleteRepository") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidRepositoryNameException") diff --git a/tests/test_codepipeline/test_codepipeline.py b/tests/test_codepipeline/test_codepipeline.py index a40efa05c..ca1094582 100644 --- a/tests/test_codepipeline/test_codepipeline.py +++ b/tests/test_codepipeline/test_codepipeline.py @@ -4,7 +4,7 @@ from datetime import datetime import boto3 import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_codepipeline, mock_iam @@ -77,9 +77,9 @@ def test_create_pipeline_errors(): client_iam = boto3.client("iam", region_name="us-east-1") create_basic_codepipeline(client, "test-pipeline") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: create_basic_codepipeline(client, "test-pipeline") - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreatePipeline") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidStructureException") @@ -87,7 +87,7 @@ def test_create_pipeline_errors(): "A pipeline with the name 'test-pipeline' already exists in account '123456789012'" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_pipeline( pipeline={ "name": "invalid-pipeline", @@ -115,7 +115,7 @@ def test_create_pipeline_errors(): ], } ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreatePipeline") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidStructureException") @@ -139,7 +139,7 @@ def test_create_pipeline_errors(): ), )["Role"]["Arn"] - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_pipeline( pipeline={ "name": "invalid-pipeline", @@ -167,7 +167,7 @@ def test_create_pipeline_errors(): ], } ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreatePipeline") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidStructureException") @@ -175,7 +175,7 @@ def test_create_pipeline_errors(): "CodePipeline is not authorized to perform AssumeRole on role arn:aws:iam::123456789012:role/wrong-role" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_pipeline( pipeline={ "name": "invalid-pipeline", @@ -203,7 +203,7 @@ def test_create_pipeline_errors(): ], } ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreatePipeline") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidStructureException") @@ -282,9 +282,9 @@ def test_get_pipeline(): def test_get_pipeline_errors(): client = boto3.client("codepipeline", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_pipeline(name="not-existing") - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetPipeline") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("PipelineNotFoundException") @@ -410,7 +410,7 @@ def test_update_pipeline(): def test_update_pipeline_errors(): client = boto3.client("codepipeline", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.update_pipeline( pipeline={ "name": "not-existing", @@ -456,7 +456,7 @@ def test_update_pipeline_errors(): ], } ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("UpdatePipeline") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") @@ -517,11 +517,11 @@ def test_list_tags_for_resource(): def test_list_tags_for_resource_errors(): client = boto3.client("codepipeline", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_tags_for_resource( resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListTagsForResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") @@ -555,12 +555,12 @@ def test_tag_resource_errors(): name = "test-pipeline" create_basic_codepipeline(client, name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.tag_resource( resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing", tags=[{"key": "key-2", "value": "value-2"}], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("TagResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") @@ -568,12 +568,12 @@ def test_tag_resource_errors(): "The account with id '123456789012' does not include a pipeline with the name 'not-existing'" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.tag_resource( resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name), tags=[{"key": "aws:key", "value": "value"}], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("TagResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidTagsException") @@ -583,7 +583,7 @@ def test_tag_resource_errors(): "msg=[Caller is an end user and not allowed to mutate system tags]" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.tag_resource( resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name), tags=[ @@ -591,7 +591,7 @@ def test_tag_resource_errors(): for i in range(50) ], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("TagResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("TooManyTagsException") @@ -634,12 +634,12 @@ def test_untag_resource(): def test_untag_resource_errors(): client = boto3.client("codepipeline", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.untag_resource( resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing", tagKeys=["key"], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("UntagResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") diff --git a/tests/test_cognitoidentity/__init__.py b/tests/test_cognitoidentity/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_cognitoidentity/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_cognitoidentity/test_cognitoidentity.py b/tests/test_cognitoidentity/test_cognitoidentity.py index 164cb023c..cfe673cdf 100644 --- a/tests/test_cognitoidentity/test_cognitoidentity.py +++ b/tests/test_cognitoidentity/test_cognitoidentity.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import boto3 import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_cognitoidentity from moto.cognitoidentity.utils import get_random_identity_id @@ -75,12 +75,12 @@ def test_describe_identity_pool(): def test_describe_identity_pool_with_invalid_id_raises_error(): conn = boto3.client("cognito-identity", "us-west-2") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: conn.describe_identity_pool(IdentityPoolId="us-west-2_non-existent") - cm.exception.operation_name.should.equal("DescribeIdentityPool") - cm.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.operation_name.should.equal("DescribeIdentityPool") + cm.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # testing a helper function diff --git a/tests/test_cognitoidp/__init__.py b/tests/test_cognitoidp/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_cognitoidp/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_cognitoidp/test_cognitoidp.py b/tests/test_cognitoidp/test_cognitoidp.py index a5212b82e..54ee9528f 100644 --- a/tests/test_cognitoidp/test_cognitoidp.py +++ b/tests/test_cognitoidp/test_cognitoidp.py @@ -17,7 +17,7 @@ import boto3 import sure # noqa from botocore.exceptions import ClientError from jose import jws, jwk, jwt -from nose.tools import assert_raises +import pytest from moto import mock_cognitoidp, settings from moto.cognitoidp.utils import create_id @@ -603,14 +603,14 @@ def test_update_identity_provider_no_user_pool(): new_value = str(uuid.uuid4()) - with assert_raises(conn.exceptions.ResourceNotFoundException) as cm: + with pytest.raises(conn.exceptions.ResourceNotFoundException) as cm: conn.update_identity_provider( UserPoolId="foo", ProviderName="bar", ProviderDetails={"thing": new_value} ) - cm.exception.operation_name.should.equal("UpdateIdentityProvider") - cm.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.operation_name.should.equal("UpdateIdentityProvider") + cm.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) @mock_cognitoidp @@ -623,16 +623,16 @@ def test_update_identity_provider_no_identity_provider(): new_value = str(uuid.uuid4()) user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"] - with assert_raises(conn.exceptions.ResourceNotFoundException) as cm: + with pytest.raises(conn.exceptions.ResourceNotFoundException) as cm: conn.update_identity_provider( UserPoolId=user_pool_id, ProviderName="foo", ProviderDetails={"thing": new_value}, ) - cm.exception.operation_name.should.equal("UpdateIdentityProvider") - cm.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.operation_name.should.equal("UpdateIdentityProvider") + cm.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) @mock_cognitoidp @@ -699,11 +699,11 @@ def test_create_group_with_duplicate_name_raises_error(): conn.create_group(GroupName=group_name, UserPoolId=user_pool_id) - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: conn.create_group(GroupName=group_name, UserPoolId=user_pool_id) - cm.exception.operation_name.should.equal("CreateGroup") - cm.exception.response["Error"]["Code"].should.equal("GroupExistsException") - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.operation_name.should.equal("CreateGroup") + cm.value.response["Error"]["Code"].should.equal("GroupExistsException") + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) @mock_cognitoidp @@ -747,9 +747,9 @@ def test_delete_group(): result = conn.delete_group(GroupName=group_name, UserPoolId=user_pool_id) list(result.keys()).should.equal(["ResponseMetadata"]) # No response expected - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: conn.get_group(GroupName=group_name, UserPoolId=user_pool_id) - cm.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") + cm.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") @mock_cognitoidp @@ -1565,17 +1565,17 @@ def test_resource_server(): res["ResourceServer"]["Name"].should.equal(name) res["ResourceServer"]["Scopes"].should.equal(scopes) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_resource_server( UserPoolId=user_pool_id, Identifier=identifier, Name=name, Scopes=scopes ) - ex.exception.operation_name.should.equal("CreateResourceServer") - ex.exception.response["Error"]["Code"].should.equal("InvalidParameterException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.operation_name.should.equal("CreateResourceServer") + ex.value.response["Error"]["Code"].should.equal("InvalidParameterException") + ex.value.response["Error"]["Message"].should.equal( "%s already exists in user pool %s." % (identifier, user_pool_id) ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) @mock_cognitoidp diff --git a/tests/test_config/__init__.py b/tests/test_config/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_config/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_config/test_config.py b/tests/test_config/test_config.py index 344622221..41774c2fa 100644 --- a/tests/test_config/test_config.py +++ b/tests/test_config/test_config.py @@ -5,8 +5,8 @@ from datetime import datetime, timedelta import boto3 from botocore.exceptions import ClientError -from nose import SkipTest -from nose.tools import assert_raises +from unittest import SkipTest +import pytest from moto import mock_s3 from moto.config import mock_config @@ -20,23 +20,23 @@ def test_put_configuration_recorder(): client = boto3.client("config", region_name="us-west-2") # Try without a name supplied: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_recorder(ConfigurationRecorder={"roleARN": "somearn"}) assert ( - ce.exception.response["Error"]["Code"] + ce.value.response["Error"]["Code"] == "InvalidConfigurationRecorderNameException" ) - assert "is not valid, blank string." in ce.exception.response["Error"]["Message"] + assert "is not valid, blank string." in ce.value.response["Error"]["Message"] # Try with a really long name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_recorder( ConfigurationRecorder={"name": "a" * 257, "roleARN": "somearn"} ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" assert ( "Member must have length less than or equal to 256" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With resource types and flags set to True: @@ -68,7 +68,7 @@ def test_put_configuration_recorder(): ] for bg in bad_groups: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_recorder( ConfigurationRecorder={ "name": "default", @@ -76,16 +76,14 @@ def test_put_configuration_recorder(): "recordingGroup": bg, } ) + assert ce.value.response["Error"]["Code"] == "InvalidRecordingGroupException" assert ( - ce.exception.response["Error"]["Code"] == "InvalidRecordingGroupException" - ) - assert ( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] == "The recording group provided is not valid" ) # With an invalid Resource Type: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_recorder( ConfigurationRecorder={ "name": "default", @@ -103,11 +101,11 @@ def test_put_configuration_recorder(): }, } ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" assert "2 validation error detected: Value '['LOLNO', 'LOLSTILLNO']" in str( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] ) - assert "AWS::EC2::Instance" in ce.exception.response["Error"]["Message"] + assert "AWS::EC2::Instance" in ce.value.response["Error"]["Message"] # Create a proper one: client.put_configuration_recorder( @@ -166,7 +164,7 @@ def test_put_configuration_recorder(): assert not result[0]["recordingGroup"].get("resourceTypes") # Can currently only have exactly 1 Config Recorder in an account/region: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_recorder( ConfigurationRecorder={ "name": "someotherrecorder", @@ -178,12 +176,12 @@ def test_put_configuration_recorder(): } ) assert ( - ce.exception.response["Error"]["Code"] + ce.value.response["Error"]["Code"] == "MaxNumberOfConfigurationRecordersExceededException" ) assert ( "maximum number of configuration recorders: 1 is reached." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) @@ -192,7 +190,7 @@ def test_put_configuration_aggregator(): client = boto3.client("config", region_name="us-west-2") # With too many aggregation sources: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -208,12 +206,12 @@ def test_put_configuration_aggregator(): ) assert ( "Member must have length less than or equal to 1" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # With an invalid region config (no regions defined): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -225,11 +223,11 @@ def test_put_configuration_aggregator(): ) assert ( "Your request does not specify any regions" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", OrganizationAggregationSource={ @@ -238,12 +236,12 @@ def test_put_configuration_aggregator(): ) assert ( "Your request does not specify any regions" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" # With both region flags defined: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -255,12 +253,11 @@ def test_put_configuration_aggregator(): ], ) assert ( - "You must choose one of these options" - in ce.exception.response["Error"]["Message"] + "You must choose one of these options" in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", OrganizationAggregationSource={ @@ -270,24 +267,23 @@ def test_put_configuration_aggregator(): }, ) assert ( - "You must choose one of these options" - in ce.exception.response["Error"]["Message"] + "You must choose one of these options" in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" # Name too long: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="a" * 257, AccountAggregationSources=[ {"AccountIds": ["012345678910"], "AllAwsRegions": True} ], ) - assert "configurationAggregatorName" in ce.exception.response["Error"]["Message"] - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert "configurationAggregatorName" in ce.value.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "ValidationException" # Too many tags (>50): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -299,12 +295,12 @@ def test_put_configuration_aggregator(): ) assert ( "Member must have length less than or equal to 50" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Tag key is too big (>128 chars): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -314,12 +310,12 @@ def test_put_configuration_aggregator(): ) assert ( "Member must have length less than or equal to 128" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Tag value is too big (>256 chars): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -329,12 +325,12 @@ def test_put_configuration_aggregator(): ) assert ( "Member must have length less than or equal to 256" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Duplicate Tags: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -342,11 +338,11 @@ def test_put_configuration_aggregator(): ], Tags=[{"Key": "a", "Value": "a"}, {"Key": "a", "Value": "a"}], ) - assert "Duplicate tag keys found." in ce.exception.response["Error"]["Message"] - assert ce.exception.response["Error"]["Code"] == "InvalidInput" + assert "Duplicate tag keys found." in ce.value.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidInput" # Invalid characters in the tag key: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -356,12 +352,12 @@ def test_put_configuration_aggregator(): ) assert ( "Member must satisfy regular expression pattern:" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # If it contains both the AccountAggregationSources and the OrganizationAggregationSource - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator( ConfigurationAggregatorName="testing", AccountAggregationSources=[ @@ -374,18 +370,18 @@ def test_put_configuration_aggregator(): ) assert ( "AccountAggregationSource and the OrganizationAggregationSource" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" # If it contains neither: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_configuration_aggregator(ConfigurationAggregatorName="testing") assert ( "AccountAggregationSource or the OrganizationAggregationSource" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" # Just make one: account_aggregation_source = { @@ -466,31 +462,29 @@ def test_describe_configuration_aggregators(): ) # Describe with an incorrect name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_configuration_aggregators( ConfigurationAggregatorNames=["DoesNotExist"] ) assert ( "The configuration aggregator does not exist." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) assert ( - ce.exception.response["Error"]["Code"] - == "NoSuchConfigurationAggregatorException" + ce.value.response["Error"]["Code"] == "NoSuchConfigurationAggregatorException" ) # Error describe with more than 1 item in the list: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_configuration_aggregators( ConfigurationAggregatorNames=["testing0", "DoesNotExist"] ) assert ( "At least one of the configuration aggregators does not exist." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) assert ( - ce.exception.response["Error"]["Code"] - == "NoSuchConfigurationAggregatorException" + ce.value.response["Error"]["Code"] == "NoSuchConfigurationAggregatorException" ) # Get the normal list: @@ -551,12 +545,10 @@ def test_describe_configuration_aggregators(): ) # Test with an invalid filter: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_configuration_aggregators(NextToken="WRONG") - assert ( - "The nextToken provided is invalid" == ce.exception.response["Error"]["Message"] - ) - assert ce.exception.response["Error"]["Code"] == "InvalidNextTokenException" + assert "The nextToken provided is invalid" == ce.value.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidNextTokenException" @mock_config @@ -564,7 +556,7 @@ def test_put_aggregation_authorization(): client = boto3.client("config", region_name="us-west-2") # Too many tags (>50): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_aggregation_authorization( AuthorizedAccountId="012345678910", AuthorizedAwsRegion="us-west-2", @@ -574,12 +566,12 @@ def test_put_aggregation_authorization(): ) assert ( "Member must have length less than or equal to 50" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Tag key is too big (>128 chars): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_aggregation_authorization( AuthorizedAccountId="012345678910", AuthorizedAwsRegion="us-west-2", @@ -587,12 +579,12 @@ def test_put_aggregation_authorization(): ) assert ( "Member must have length less than or equal to 128" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Tag value is too big (>256 chars): - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_aggregation_authorization( AuthorizedAccountId="012345678910", AuthorizedAwsRegion="us-west-2", @@ -600,22 +592,22 @@ def test_put_aggregation_authorization(): ) assert ( "Member must have length less than or equal to 256" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Duplicate Tags: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_aggregation_authorization( AuthorizedAccountId="012345678910", AuthorizedAwsRegion="us-west-2", Tags=[{"Key": "a", "Value": "a"}, {"Key": "a", "Value": "a"}], ) - assert "Duplicate tag keys found." in ce.exception.response["Error"]["Message"] - assert ce.exception.response["Error"]["Code"] == "InvalidInput" + assert "Duplicate tag keys found." in ce.value.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidInput" # Invalid characters in the tag key: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_aggregation_authorization( AuthorizedAccountId="012345678910", AuthorizedAwsRegion="us-west-2", @@ -623,9 +615,9 @@ def test_put_aggregation_authorization(): ) assert ( "Member must satisfy regular expression pattern:" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" # Put a normal one there: result = client.put_aggregation_authorization( @@ -708,12 +700,10 @@ def test_describe_aggregation_authorizations(): ] == ["{}".format(str(x) * 12) for x in range(8, 10)] # Test with an invalid filter: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_aggregation_authorizations(NextToken="WRONG") - assert ( - "The nextToken provided is invalid" == ce.exception.response["Error"]["Message"] - ) - assert ce.exception.response["Error"]["Code"] == "InvalidNextTokenException" + assert "The nextToken provided is invalid" == ce.value.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidNextTokenException" @mock_config @@ -751,15 +741,14 @@ def test_delete_configuration_aggregator(): client.delete_configuration_aggregator(ConfigurationAggregatorName="testing") # And again to confirm that it's deleted: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.delete_configuration_aggregator(ConfigurationAggregatorName="testing") assert ( "The configuration aggregator does not exist." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) assert ( - ce.exception.response["Error"]["Code"] - == "NoSuchConfigurationAggregatorException" + ce.value.response["Error"]["Code"] == "NoSuchConfigurationAggregatorException" ) @@ -796,22 +785,18 @@ def test_describe_configurations(): ) # Specify an incorrect name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_configuration_recorders(ConfigurationRecorderNames=["wrong"]) - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" - ) - assert "wrong" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" + assert "wrong" in ce.value.response["Error"]["Message"] # And with both a good and wrong name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_configuration_recorders( ConfigurationRecorderNames=["testrecorder", "wrong"] ) - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" - ) - assert "wrong" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" + assert "wrong" in ce.value.response["Error"]["Message"] @mock_config @@ -819,14 +804,14 @@ def test_delivery_channels(): client = boto3.client("config", region_name="us-west-2") # Try without a config recorder: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel(DeliveryChannel={}) assert ( - ce.exception.response["Error"]["Code"] + ce.value.response["Error"]["Code"] == "NoAvailableConfigurationRecorderException" ) assert ( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] == "Configuration recorder is not available to " "put delivery channel." ) @@ -845,43 +830,41 @@ def test_delivery_channels(): ) # Try without a name supplied: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel(DeliveryChannel={}) - assert ( - ce.exception.response["Error"]["Code"] == "InvalidDeliveryChannelNameException" - ) - assert "is not valid, blank string." in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidDeliveryChannelNameException" + assert "is not valid, blank string." in ce.value.response["Error"]["Message"] # Try with a really long name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel(DeliveryChannel={"name": "a" * 257}) - assert ce.exception.response["Error"]["Code"] == "ValidationException" + assert ce.value.response["Error"]["Code"] == "ValidationException" assert ( "Member must have length less than or equal to 256" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Without specifying a bucket name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel(DeliveryChannel={"name": "testchannel"}) - assert ce.exception.response["Error"]["Code"] == "NoSuchBucketException" + assert ce.value.response["Error"]["Code"] == "NoSuchBucketException" assert ( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] == "Cannot find a S3 bucket with an empty bucket name." ) - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel( DeliveryChannel={"name": "testchannel", "s3BucketName": ""} ) - assert ce.exception.response["Error"]["Code"] == "NoSuchBucketException" + assert ce.value.response["Error"]["Code"] == "NoSuchBucketException" assert ( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] == "Cannot find a S3 bucket with an empty bucket name." ) # With an empty string for the S3 key prefix: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel( DeliveryChannel={ "name": "testchannel", @@ -889,11 +872,11 @@ def test_delivery_channels(): "s3KeyPrefix": "", } ) - assert ce.exception.response["Error"]["Code"] == "InvalidS3KeyPrefixException" - assert "empty s3 key prefix." in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidS3KeyPrefixException" + assert "empty s3 key prefix." in ce.value.response["Error"]["Message"] # With an empty string for the SNS ARN: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel( DeliveryChannel={ "name": "testchannel", @@ -901,11 +884,11 @@ def test_delivery_channels(): "snsTopicARN": "", } ) - assert ce.exception.response["Error"]["Code"] == "InvalidSNSTopicARNException" - assert "The sns topic arn" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidSNSTopicARNException" + assert "The sns topic arn" in ce.value.response["Error"]["Message"] # With an invalid delivery frequency: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel( DeliveryChannel={ "name": "testchannel", @@ -913,9 +896,9 @@ def test_delivery_channels(): "configSnapshotDeliveryProperties": {"deliveryFrequency": "WRONG"}, } ) - assert ce.exception.response["Error"]["Code"] == "InvalidDeliveryFrequency" - assert "WRONG" in ce.exception.response["Error"]["Message"] - assert "TwentyFour_Hours" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "InvalidDeliveryFrequency" + assert "WRONG" in ce.value.response["Error"]["Message"] + assert "TwentyFour_Hours" in ce.value.response["Error"]["Message"] # Create a proper one: client.put_delivery_channel( @@ -950,17 +933,17 @@ def test_delivery_channels(): ) # Can only have 1: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_delivery_channel( DeliveryChannel={"name": "testchannel2", "s3BucketName": "somebucket"} ) assert ( - ce.exception.response["Error"]["Code"] + ce.value.response["Error"]["Code"] == "MaxNumberOfDeliveryChannelsExceededException" ) assert ( "because the maximum number of delivery channels: 1 is reached." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) @@ -1015,16 +998,16 @@ def test_describe_delivery_channels(): ) # Specify an incorrect name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_delivery_channels(DeliveryChannelNames=["wrong"]) - assert ce.exception.response["Error"]["Code"] == "NoSuchDeliveryChannelException" - assert "wrong" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "NoSuchDeliveryChannelException" + assert "wrong" in ce.value.response["Error"]["Message"] # And with both a good and wrong name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_delivery_channels(DeliveryChannelNames=["testchannel", "wrong"]) - assert ce.exception.response["Error"]["Code"] == "NoSuchDeliveryChannelException" - assert "wrong" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "NoSuchDeliveryChannelException" + assert "wrong" in ce.value.response["Error"]["Message"] @mock_config @@ -1032,11 +1015,9 @@ def test_start_configuration_recorder(): client = boto3.client("config", region_name="us-west-2") # Without a config recorder: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.start_configuration_recorder(ConfigurationRecorderName="testrecorder") - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" - ) + assert ce.value.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" # Make the config recorder; client.put_configuration_recorder( @@ -1052,11 +1033,9 @@ def test_start_configuration_recorder(): ) # Without a delivery channel: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.start_configuration_recorder(ConfigurationRecorderName="testrecorder") - assert ( - ce.exception.response["Error"]["Code"] == "NoAvailableDeliveryChannelException" - ) + assert ce.value.response["Error"]["Code"] == "NoAvailableDeliveryChannelException" # Make the delivery channel: client.put_delivery_channel( @@ -1090,11 +1069,9 @@ def test_stop_configuration_recorder(): client = boto3.client("config", region_name="us-west-2") # Without a config recorder: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.stop_configuration_recorder(ConfigurationRecorderName="testrecorder") - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" - ) + assert ce.value.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" # Make the config recorder; client.put_configuration_recorder( @@ -1180,14 +1157,12 @@ def test_describe_configuration_recorder_status(): assert not result[0]["recording"] # Invalid name: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.describe_configuration_recorder_status( ConfigurationRecorderNames=["testrecorder", "wrong"] ) - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" - ) - assert "wrong" in ce.exception.response["Error"]["Message"] + assert ce.value.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" + assert "wrong" in ce.value.response["Error"]["Message"] @mock_config @@ -1211,11 +1186,9 @@ def test_delete_configuration_recorder(): client.delete_configuration_recorder(ConfigurationRecorderName="testrecorder") # Try again -- it should be deleted: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.delete_configuration_recorder(ConfigurationRecorderName="testrecorder") - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" - ) + assert ce.value.response["Error"]["Code"] == "NoSuchConfigurationRecorderException" @mock_config @@ -1240,15 +1213,14 @@ def test_delete_delivery_channel(): client.start_configuration_recorder(ConfigurationRecorderName="testrecorder") # With the recorder enabled: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.delete_delivery_channel(DeliveryChannelName="testchannel") assert ( - ce.exception.response["Error"]["Code"] - == "LastDeliveryChannelDeleteFailedException" + ce.value.response["Error"]["Code"] == "LastDeliveryChannelDeleteFailedException" ) assert ( "because there is a running configuration recorder." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Stop recording: @@ -1258,16 +1230,16 @@ def test_delete_delivery_channel(): client.delete_delivery_channel(DeliveryChannelName="testchannel") # Verify: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.delete_delivery_channel(DeliveryChannelName="testchannel") - assert ce.exception.response["Error"]["Code"] == "NoSuchDeliveryChannelException" + assert ce.value.response["Error"]["Code"] == "NoSuchDeliveryChannelException" @mock_config @mock_s3 def test_list_discovered_resource(): """NOTE: We are only really testing the Config part. For each individual service, please add tests - for that individual service's "list_config_service_resources" function. + for that individual service's "list_config_service_resources" function. """ client = boto3.client("config", region_name="us-west-2") @@ -1341,12 +1313,12 @@ def test_list_discovered_resource(): )["resourceIdentifiers"] # Test with an invalid page num > 100: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.list_discovered_resources(resourceType="AWS::S3::Bucket", limit=101) - assert "101" in ce.exception.response["Error"]["Message"] + assert "101" in ce.value.response["Error"]["Message"] # Test by supplying both resourceName and also resourceIds: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.list_discovered_resources( resourceType="AWS::S3::Bucket", resourceName="whats", @@ -1354,18 +1326,18 @@ def test_list_discovered_resource(): ) assert ( "Both Resource ID and Resource Name cannot be specified in the request" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # More than 20 resourceIds: resource_ids = ["{}".format(x) for x in range(0, 21)] - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.list_discovered_resources( resourceType="AWS::S3::Bucket", resourceIds=resource_ids ) assert ( "The specified list had more than 20 resource ID's." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) @@ -1373,18 +1345,18 @@ def test_list_discovered_resource(): @mock_s3 def test_list_aggregate_discovered_resource(): """NOTE: We are only really testing the Config part. For each individual service, please add tests - for that individual service's "list_config_service_resources" function. + for that individual service's "list_config_service_resources" function. """ client = boto3.client("config", region_name="us-west-2") # Without an aggregator: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.list_aggregate_discovered_resources( ConfigurationAggregatorName="lolno", ResourceType="AWS::S3::Bucket" ) assert ( "The configuration aggregator does not exist" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Create the aggregator: @@ -1504,40 +1476,40 @@ def test_list_aggregate_discovered_resource(): )["ResourceIdentifiers"] # Test with an invalid page num > 100: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.list_aggregate_discovered_resources( ConfigurationAggregatorName="testing", ResourceType="AWS::S3::Bucket", Limit=101, ) - assert "101" in ce.exception.response["Error"]["Message"] + assert "101" in ce.value.response["Error"]["Message"] @mock_config @mock_s3 def test_get_resource_config_history(): """NOTE: We are only really testing the Config part. For each individual service, please add tests - for that individual service's "get_config_resource" function. + for that individual service's "get_config_resource" function. """ client = boto3.client("config", region_name="us-west-2") # With an invalid resource type: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_resource_config_history( resourceType="NOT::A::RESOURCE", resourceId="notcreatedyet" ) - assert ce.exception.response["Error"] == { + assert ce.value.response["Error"] == { "Message": "Resource notcreatedyet of resourceType:NOT::A::RESOURCE is unknown or has " "not been discovered", "Code": "ResourceNotDiscoveredException", } # With nothing created yet: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_resource_config_history( resourceType="AWS::S3::Bucket", resourceId="notcreatedyet" ) - assert ce.exception.response["Error"] == { + assert ce.value.response["Error"] == { "Message": "Resource notcreatedyet of resourceType:AWS::S3::Bucket is unknown or has " "not been discovered", "Code": "ResourceNotDiscoveredException", @@ -1565,23 +1537,23 @@ def test_get_resource_config_history(): Bucket="eu-bucket", CreateBucketConfiguration={"LocationConstraint": "eu-west-1"}, ) - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_resource_config_history( resourceType="AWS::S3::Bucket", resourceId="eu-bucket" ) - assert ce.exception.response["Error"]["Code"] == "ResourceNotDiscoveredException" + assert ce.value.response["Error"]["Code"] == "ResourceNotDiscoveredException" @mock_config @mock_s3 def test_batch_get_resource_config(): """NOTE: We are only really testing the Config part. For each individual service, please add tests - for that individual service's "get_config_resource" function. + for that individual service's "get_config_resource" function. """ client = boto3.client("config", region_name="us-west-2") # With more than 100 resourceKeys: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.batch_get_resource_config( resourceKeys=[ {"resourceType": "AWS::S3::Bucket", "resourceId": "someBucket"} @@ -1590,7 +1562,7 @@ def test_batch_get_resource_config(): ) assert ( "Member must have length less than or equal to 100" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With invalid resource types and resources that don't exist: @@ -1640,7 +1612,7 @@ def test_batch_get_resource_config(): @mock_s3 def test_batch_get_aggregate_resource_config(): """NOTE: We are only really testing the Config part. For each individual service, please add tests - for that individual service's "get_config_resource" function. + for that individual service's "get_config_resource" function. """ from moto.config.models import DEFAULT_ACCOUNT_ID @@ -1653,13 +1625,13 @@ def test_batch_get_aggregate_resource_config(): "ResourceType": "NOT::A::RESOURCE", "ResourceId": "nope", } - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.batch_get_aggregate_resource_config( ConfigurationAggregatorName="lolno", ResourceIdentifiers=[bad_ri] ) assert ( "The configuration aggregator does not exist" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Create the aggregator: @@ -1673,13 +1645,13 @@ def test_batch_get_aggregate_resource_config(): ) # With more than 100 items: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.batch_get_aggregate_resource_config( ConfigurationAggregatorName="testing", ResourceIdentifiers=[bad_ri] * 101 ) assert ( "Member must have length less than or equal to 100" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Create some S3 buckets: @@ -1814,16 +1786,16 @@ def test_put_evaluations(): client = boto3.client("config", region_name="us-west-2") # Try without Evaluations supplied: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_evaluations(Evaluations=[], ResultToken="test", TestMode=True) - assert ce.exception.response["Error"]["Code"] == "InvalidParameterValueException" + assert ce.value.response["Error"]["Code"] == "InvalidParameterValueException" assert ( "The Evaluations object in your request cannot be null" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Try without a ResultToken supplied: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_evaluations( Evaluations=[ { @@ -1836,13 +1808,13 @@ def test_put_evaluations(): ResultToken="", TestMode=True, ) - assert ce.exception.response["Error"]["Code"] == "InvalidResultTokenException" + assert ce.value.response["Error"]["Code"] == "InvalidResultTokenException" if os.environ.get("TEST_SERVER_MODE", "false").lower() == "true": raise SkipTest("Does not work in server mode due to error in Workzeug") else: # Try without TestMode supplied: - with assert_raises(NotImplementedError): + with pytest.raises(NotImplementedError): client.put_evaluations( Evaluations=[ { @@ -1913,21 +1885,21 @@ def test_put_organization_conformance_pack_errors(): client = boto3.client("config", region_name="us-east-1") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.put_organization_conformance_pack( DeliveryS3Bucket="awsconfigconforms-test-bucket", OrganizationConformancePackName="test-pack", ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("PutOrganizationConformancePack") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ValidationException") ex.response["Error"]["Message"].should.equal("Template body is invalid") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.put_organization_conformance_pack( DeliveryS3Bucket="awsconfigconforms-test-bucket", OrganizationConformancePackName="test-pack", @@ -1935,7 +1907,7 @@ def test_put_organization_conformance_pack_errors(): ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("PutOrganizationConformancePack") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ValidationException") @@ -1979,13 +1951,13 @@ def test_describe_organization_conformance_packs_errors(): client = boto3.client("config", region_name="us-east-1") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.describe_organization_conformance_packs( OrganizationConformancePackNames=["not-existing"] ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeOrganizationConformancePacks") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain( @@ -2055,13 +2027,13 @@ def test_describe_organization_conformance_pack_statuses_errors(): client = boto3.client("config", region_name="us-east-1") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.describe_organization_conformance_pack_statuses( OrganizationConformancePackNames=["not-existing"] ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeOrganizationConformancePackStatuses") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain( @@ -2127,13 +2099,13 @@ def test_get_organization_conformance_pack_detailed_status_errors(): client = boto3.client("config", region_name="us-east-1") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_organization_conformance_pack_detailed_status( OrganizationConformancePackName="not-existing" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetOrganizationConformancePackDetailedStatus") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain( @@ -2171,13 +2143,13 @@ def test_delete_organization_conformance_pack_errors(): client = boto3.client("config", region_name="us-east-1") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_organization_conformance_pack( OrganizationConformancePackName="not-existing" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeleteOrganizationConformancePack") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain( diff --git a/tests/test_core/__init__.py b/tests/test_core/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_core/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_core/test_auth.py b/tests/test_core/test_auth.py index b391d82c8..b6fc8a135 100644 --- a/tests/test_core/test_auth.py +++ b/tests/test_core/test_auth.py @@ -4,9 +4,7 @@ import boto3 import sure # noqa from botocore.exceptions import ClientError -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +import pytest from moto import mock_iam, mock_ec2, mock_s3, mock_sts, mock_elbv2, mock_rds2 from moto.core import set_initial_no_auth_action_count @@ -179,11 +177,11 @@ def test_invalid_client_token_id(): aws_access_key_id="invalid", aws_secret_access_key="invalid", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_user() - ex.exception.response["Error"]["Code"].should.equal("InvalidClientTokenId") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidClientTokenId") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "The security token included in the request is invalid." ) @@ -197,11 +195,11 @@ def test_auth_failure(): aws_access_key_id="invalid", aws_secret_access_key="invalid", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.describe_instances() - ex.exception.response["Error"]["Code"].should.equal("AuthFailure") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(401) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AuthFailure") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(401) + ex.value.response["Error"]["Message"].should.equal( "AWS was not able to validate the provided access credentials" ) @@ -216,11 +214,11 @@ def test_signature_does_not_match(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key="invalid", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_user() - ex.exception.response["Error"]["Code"].should.equal("SignatureDoesNotMatch") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("SignatureDoesNotMatch") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details." ) @@ -235,11 +233,11 @@ def test_auth_failure_with_valid_access_key_id(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key="invalid", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.describe_instances() - ex.exception.response["Error"]["Code"].should.equal("AuthFailure") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(401) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AuthFailure") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(401) + ex.value.response["Error"]["Message"].should.equal( "AWS was not able to validate the provided access credentials" ) @@ -255,11 +253,11 @@ def test_access_denied_with_no_policy(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.describe_instances() - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "User: arn:aws:iam::{account_id}:user/{user_name} is not authorized to perform: {operation}".format( account_id=ACCOUNT_ID, user_name=user_name, @@ -285,11 +283,11 @@ def test_access_denied_with_not_allowing_policy(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.describe_instances() - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "User: arn:aws:iam::{account_id}:user/{user_name} is not authorized to perform: {operation}".format( account_id=ACCOUNT_ID, user_name=user_name, @@ -321,11 +319,11 @@ def test_access_denied_for_run_instances(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.run_instances(MaxCount=1, MinCount=1) - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "User: arn:aws:iam::{account_id}:user/{user_name} is not authorized to perform: {operation}".format( account_id=ACCOUNT_ID, user_name=user_name, operation="ec2:RunInstances", ) @@ -352,11 +350,11 @@ def test_access_denied_with_denying_policy(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_vpc(CidrBlock="10.0.0.0/16") - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "User: arn:aws:iam::{account_id}:user/{user_name} is not authorized to perform: {operation}".format( account_id=ACCOUNT_ID, user_name=user_name, operation="ec2:CreateVpc" ) @@ -452,11 +450,11 @@ def test_s3_access_denied_with_denying_attached_group_policy(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.list_buckets() - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal("Access Denied") + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal("Access Denied") @set_initial_no_auth_action_count(6) @@ -486,11 +484,11 @@ def test_s3_access_denied_with_denying_inline_group_policy(): aws_secret_access_key=access_key["SecretAccessKey"], ) client.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_object(Bucket=bucket_name, Key="sdfsdf") - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal("Access Denied") + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal("Access Denied") @set_initial_no_auth_action_count(10) @@ -532,11 +530,11 @@ def test_access_denied_with_many_irrelevant_policies(): aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_key_pair(KeyName="TestKey") - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "User: arn:aws:iam::{account_id}:user/{user_name} is not authorized to perform: {operation}".format( account_id=ACCOUNT_ID, user_name=user_name, operation="ec2:CreateKeyPair" ) @@ -631,15 +629,15 @@ def test_access_denied_with_temporary_credentials(): aws_secret_access_key=credentials["SecretAccessKey"], aws_session_token=credentials["SessionToken"], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_db_instance( DBInstanceIdentifier="test-db-instance", DBInstanceClass="db.t3", Engine="aurora-postgresql", ) - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "User: arn:aws:sts::{account_id}:assumed-role/{role_name}/{session_name} is not authorized to perform: {operation}".format( account_id=ACCOUNT_ID, role_name=role_name, @@ -678,11 +676,11 @@ def test_s3_invalid_access_key_id(): aws_access_key_id="invalid", aws_secret_access_key="invalid", ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.list_buckets() - ex.exception.response["Error"]["Code"].should.equal("InvalidAccessKeyId") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidAccessKeyId") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "The AWS Access Key Id you provided does not exist in our records." ) @@ -700,11 +698,11 @@ def test_s3_signature_does_not_match(): aws_secret_access_key="invalid", ) client.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.put_object(Bucket=bucket_name, Key="abc") - ex.exception.response["Error"]["Code"].should.equal("SignatureDoesNotMatch") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("SignatureDoesNotMatch") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal( "The request signature we calculated does not match the signature you provided. Check your key and signing method." ) @@ -736,11 +734,11 @@ def test_s3_access_denied_not_action(): aws_secret_access_key=access_key["SecretAccessKey"], ) client.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.delete_object(Bucket=bucket_name, Key="sdfsdf") - ex.exception.response["Error"]["Code"].should.equal("AccessDenied") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) - ex.exception.response["Error"]["Message"].should.equal("Access Denied") + ex.value.response["Error"]["Code"].should.equal("AccessDenied") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) + ex.value.response["Error"]["Message"].should.equal("Access Denied") @set_initial_no_auth_action_count(4) @@ -776,10 +774,10 @@ def test_s3_invalid_token_with_temporary_credentials(): aws_session_token="invalid", ) client.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.list_bucket_metrics_configurations(Bucket=bucket_name) - ex.exception.response["Error"]["Code"].should.equal("InvalidToken") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidToken") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "The provided token is malformed or otherwise invalid." ) diff --git a/tests/test_core/test_decorator_calls.py b/tests/test_core/test_decorator_calls.py index 408ca6819..c57d62485 100644 --- a/tests/test_core/test_decorator_calls.py +++ b/tests/test_core/test_decorator_calls.py @@ -4,8 +4,7 @@ from boto.exception import EC2ResponseError import sure # noqa import unittest -import tests.backport_assert_raises # noqa -from nose.tools import assert_raises +import pytest from moto import mock_ec2_deprecated, mock_s3_deprecated @@ -25,23 +24,25 @@ def test_basic_decorator(): list(conn.get_all_instances()).should.equal([]) +@pytest.mark.network def test_context_manager(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError): + with pytest.raises(EC2ResponseError): conn.get_all_instances() with mock_ec2_deprecated(): conn = boto.connect_ec2("the_key", "the_secret") list(conn.get_all_instances()).should.equal([]) - with assert_raises(EC2ResponseError): + with pytest.raises(EC2ResponseError): conn = boto.connect_ec2("the_key", "the_secret") conn.get_all_instances() +@pytest.mark.network def test_decorator_start_and_stop(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError): + with pytest.raises(EC2ResponseError): conn.get_all_instances() mock = mock_ec2_deprecated() @@ -50,7 +51,7 @@ def test_decorator_start_and_stop(): list(conn.get_all_instances()).should.equal([]) mock.stop() - with assert_raises(EC2ResponseError): + with pytest.raises(EC2ResponseError): conn.get_all_instances() diff --git a/tests/test_core/test_instance_metadata.py b/tests/test_core/test_instance_metadata.py index d30138d5d..9870f0df5 100644 --- a/tests/test_core/test_instance_metadata.py +++ b/tests/test_core/test_instance_metadata.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals import sure # noqa -from nose.tools import assert_raises +import pytest import requests from moto import mock_ec2, settings diff --git a/tests/test_core/test_moto_api.py b/tests/test_core/test_moto_api.py index 6482d903e..648510475 100644 --- a/tests/test_core/test_moto_api.py +++ b/tests/test_core/test_moto_api.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals import sure # noqa -from nose.tools import assert_raises +import pytest import requests import boto3 diff --git a/tests/test_core/test_request_mocking.py b/tests/test_core/test_request_mocking.py index 2c44d52ce..3c56c7242 100644 --- a/tests/test_core/test_request_mocking.py +++ b/tests/test_core/test_request_mocking.py @@ -1,4 +1,5 @@ import requests +import pytest import sure # noqa import boto3 @@ -6,6 +7,7 @@ from moto import mock_sqs, settings @mock_sqs +@pytest.mark.network def test_passthrough_requests(): conn = boto3.client("sqs", region_name="us-west-1") conn.create_queue(QueueName="queue1") diff --git a/tests/test_datapipeline/__init__.py b/tests/test_datapipeline/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_datapipeline/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_datasync/test_datasync.py b/tests/test_datasync/test_datasync.py index e3ea87675..2214032c9 100644 --- a/tests/test_datasync/test_datasync.py +++ b/tests/test_datasync/test_datasync.py @@ -4,11 +4,11 @@ import boto import boto3 from botocore.exceptions import ClientError from moto import mock_datasync -from nose.tools import assert_raises +import pytest def create_locations(client, create_smb=False, create_s3=False): - """ + """ Convenience function for creating locations. Locations must exist before tasks can be created. """ @@ -101,7 +101,7 @@ def test_describe_location_wrong(): Password="", AgentArns=agent_arns, ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.describe_location_s3(LocationArn=response["LocationArn"]) @@ -139,7 +139,7 @@ def test_delete_location(): response = client.list_locations() assert len(response["Locations"]) == 0 - with assert_raises(ClientError) as e: + with pytest.raises(ClientError): response = client.delete_location(LocationArn=location_arn) @@ -159,11 +159,11 @@ def test_create_task_fail(): """ Test that Locations must exist before a Task can be created """ client = boto3.client("datasync", region_name="us-east-1") locations = create_locations(client, create_smb=True, create_s3=True) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.create_task( SourceLocationArn="1", DestinationLocationArn=locations["s3_arn"] ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.create_task( SourceLocationArn=locations["smb_arn"], DestinationLocationArn="2" ) @@ -220,7 +220,7 @@ def test_describe_task(): def test_describe_task_not_exist(): client = boto3.client("datasync", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.describe_task(TaskArn="abc") @@ -262,7 +262,7 @@ def test_update_task(): assert response["Name"] == updated_name assert response["Options"] == updated_options - with assert_raises(ClientError) as e: + with pytest.raises(ClientError): client.update_task(TaskArn="doesnt_exist") @@ -286,7 +286,7 @@ def test_delete_task(): response = client.list_tasks() assert len(response["Tasks"]) == 0 - with assert_raises(ClientError) as e: + with pytest.raises(ClientError): response = client.delete_task(TaskArn=task_arn) @@ -328,7 +328,7 @@ def test_start_task_execution_twice(): assert "TaskExecutionArn" in response task_execution_arn = response["TaskExecutionArn"] - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.start_task_execution(TaskArn=task_arn) @@ -392,7 +392,7 @@ def test_describe_task_execution(): def test_describe_task_execution_not_exist(): client = boto3.client("datasync", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.describe_task_execution(TaskExecutionArn="abc") diff --git a/tests/test_dynamodb/__init__.py b/tests/test_dynamodb/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_dynamodb/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_dynamodb/test_dynamodb.py b/tests/test_dynamodb/test_dynamodb.py index 931e57e06..3e1092025 100644 --- a/tests/test_dynamodb/test_dynamodb.py +++ b/tests/test_dynamodb/test_dynamodb.py @@ -4,8 +4,7 @@ import boto import boto.dynamodb import sure # noqa import requests -import tests.backport_assert_raises -from nose.tools import assert_raises +import pytest from moto import mock_dynamodb, mock_dynamodb_deprecated from moto.dynamodb import dynamodb_backend @@ -38,7 +37,7 @@ def test_list_tables_layer_1(): @mock_dynamodb_deprecated def test_describe_missing_table(): conn = boto.connect_dynamodb("the_key", "the_secret") - with assert_raises(DynamoDBResponseError): + with pytest.raises(DynamoDBResponseError): conn.describe_table("messages") diff --git a/tests/test_dynamodb2/__init__.py b/tests/test_dynamodb2/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_dynamodb2/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index 41baddc79..7a2ed32cb 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -17,7 +17,7 @@ from tests.helpers import requires_boto_gte import moto.dynamodb2.comparisons import moto.dynamodb2.models -from nose.tools import assert_raises +import pytest try: import boto.dynamodb2 @@ -72,7 +72,7 @@ def test_describe_missing_table(): conn = boto.dynamodb2.connect_to_region( "us-west-2", aws_access_key_id="ak", aws_secret_access_key="sk" ) - with assert_raises(JSONResponseError): + with pytest.raises(JSONResponseError): conn.describe_table("messages") @@ -201,7 +201,7 @@ def test_item_add_empty_string_exception(): ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.put_item( TableName=name, Item={ @@ -213,9 +213,9 @@ def test_item_add_empty_string_exception(): }, ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "One or more parameter values were invalid: An AttributeValue may not contain an empty string" ) @@ -248,7 +248,7 @@ def test_update_item_with_empty_string_exception(): }, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.update_item( TableName=name, Key={"forum_name": {"S": "LOLCat Forum"}}, @@ -256,9 +256,9 @@ def test_update_item_with_empty_string_exception(): ExpressionAttributeValues={":Body": {"S": ""}}, ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "One or more parameter values were invalid: An AttributeValue may not contain an empty string" ) @@ -1354,12 +1354,12 @@ def test_put_empty_item(): ) table = dynamodb.Table("test") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: table.put_item(Item={}) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Message"].should.equal( "One or more parameter values were invalid: Missing the key structure_id in the item" ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Code"].should.equal("ValidationException") @mock_dynamodb2 @@ -1373,12 +1373,12 @@ def test_put_item_nonexisting_hash_key(): ) table = dynamodb.Table("test") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: table.put_item(Item={"a_terribly_misguided_id_attribute": "abcdef"}) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Message"].should.equal( "One or more parameter values were invalid: Missing the key structure_id in the item" ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Code"].should.equal("ValidationException") @mock_dynamodb2 @@ -1398,12 +1398,12 @@ def test_put_item_nonexisting_range_key(): ) table = dynamodb.Table("test") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: table.put_item(Item={"structure_id": "abcdef"}) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Message"].should.equal( "One or more parameter values were invalid: Missing the key added_at in the item" ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Code"].should.equal("ValidationException") def test_filter_expression(): @@ -1980,7 +1980,7 @@ def test_delete_item(): assert response["Count"] == 2 # Test ReturnValues validation - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: table.delete_item( Key={"client": "client1", "app": "app1"}, ReturnValues="ALL_NEW" ) @@ -2085,11 +2085,11 @@ def test_describe_continuous_backups_errors(): client = boto3.client("dynamodb", region_name="us-east-1") # when - with assert_raises(Exception) as e: + with pytest.raises(Exception) as e: client.describe_continuous_backups(TableName="not-existing-table") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeContinuousBackups") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("TableNotFoundException") @@ -2171,14 +2171,14 @@ def test_update_continuous_backups_errors(): client = boto3.client("dynamodb", region_name="us-east-1") # when - with assert_raises(Exception) as e: + with pytest.raises(Exception) as e: client.update_continuous_backups( TableName="not-existing-table", PointInTimeRecoverySpecification={"PointInTimeRecoveryEnabled": True}, ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("UpdateContinuousBackups") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("TableNotFoundException") @@ -2291,7 +2291,7 @@ def test_update_item_on_map(): ExpressionAttributeValues={":tb": "new_value"}, ) # Running this against AWS DDB gives an exception so make sure it also fails.: - with assert_raises(client.exceptions.ClientError): + with pytest.raises(client.exceptions.ClientError): # botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the UpdateItem # operation: The document path provided in the update expression is invalid for update table.update_item( @@ -2321,7 +2321,7 @@ def test_update_item_on_map(): ) # Test nested value for a nonexistent attribute throws a ClientError. - with assert_raises(client.exceptions.ClientError): + with pytest.raises(client.exceptions.ClientError): table.update_item( Key={"forum_name": "the-key", "subject": "123"}, UpdateExpression="SET nonexistent.#nested = :tb", @@ -2409,7 +2409,7 @@ def test_update_return_attributes(): r = update("col1", "val5", "NONE") assert r["Attributes"] == {} - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: r = update("col1", "val6", "WRONG") @@ -2438,15 +2438,15 @@ def test_put_return_attributes(): ) assert r["Attributes"] == {"id": {"S": "foo"}, "col1": {"S": "val1"}} - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.put_item( TableName="moto-test", Item={"id": {"S": "foo"}, "col1": {"S": "val3"}}, ReturnValues="ALL_NEW", ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "Return values set to invalid value" ) @@ -2675,7 +2675,7 @@ def test_condition_expressions(): }, ) - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): client.put_item( TableName="test1", Item={ @@ -2691,7 +2691,7 @@ def test_condition_expressions(): }, ) - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): client.put_item( TableName="test1", Item={ @@ -2707,7 +2707,7 @@ def test_condition_expressions(): }, ) - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): client.put_item( TableName="test1", Item={ @@ -2735,7 +2735,7 @@ def test_condition_expressions(): ExpressionAttributeValues={":match": {"S": "match"}}, ) - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): client.update_item( TableName="test1", Key={"client": {"S": "client1"}, "app": {"S": "app1"}}, @@ -2745,7 +2745,7 @@ def test_condition_expressions(): ExpressionAttributeNames={"#existing": "existing", "#match": "match"}, ) - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): client.delete_item( TableName="test1", Key={"client": {"S": "client1"}, "app": {"S": "app1"}}, @@ -2830,7 +2830,7 @@ def test_condition_expression__attr_doesnt_exist(): update_if_attr_doesnt_exist() # Second time should fail - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): update_if_attr_doesnt_exist() @@ -2870,7 +2870,7 @@ def test_condition_expression__and_order(): # ensure that the RHS of the AND expression is not evaluated if the LHS # returns true (as it would result an error) - with assert_raises(client.exceptions.ConditionalCheckFailedException): + with pytest.raises(client.exceptions.ConditionalCheckFailedException): client.update_item( TableName="test", Key={"forum_name": {"S": "the-key"}}, @@ -2966,12 +2966,12 @@ def test_scan_by_non_exists_index(): ], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.scan(TableName="test", IndexName="non_exists_index") - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "The table does not have the specified index: non_exists_index" ) @@ -3001,15 +3001,15 @@ def test_query_by_non_exists_index(): ], ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.query( TableName="test", IndexName="non_exists_index", KeyConditionExpression="CarModel=M", ) - ex.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + ex.value.response["Error"]["Message"].should.equal( "Invalid index: non_exists_index for table: test. Available indexes are: test_gsi" ) @@ -3041,7 +3041,7 @@ def test_batch_items_returns_all(): @mock_dynamodb2 def test_batch_items_throws_exception_when_requesting_100_items_for_single_table(): dynamodb = _create_user_table() - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.batch_get_item( RequestItems={ "users": { @@ -3052,8 +3052,8 @@ def test_batch_items_throws_exception_when_requesting_100_items_for_single_table } } ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - msg = ex.exception.response["Error"]["Message"] + ex.value.response["Error"]["Code"].should.equal("ValidationException") + msg = ex.value.response["Error"]["Message"] msg.should.contain("1 validation error detected: Value") msg.should.contain( "at 'requestItems.users.member.keys' failed to satisfy constraint: Member must have length less than or equal to 100" @@ -3063,7 +3063,7 @@ def test_batch_items_throws_exception_when_requesting_100_items_for_single_table @mock_dynamodb2 def test_batch_items_throws_exception_when_requesting_100_items_across_all_tables(): dynamodb = _create_user_table() - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.batch_get_item( RequestItems={ "users": { @@ -3080,8 +3080,8 @@ def test_batch_items_throws_exception_when_requesting_100_items_across_all_table }, } ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "Too many items requested for the BatchGetItem call" ) @@ -3160,7 +3160,7 @@ def test_batch_items_with_basic_projection_expression_and_attr_expression_names( @mock_dynamodb2 def test_batch_items_should_throw_exception_for_duplicate_request(): client = _create_user_table() - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.batch_get_item( RequestItems={ "users": { @@ -3172,8 +3172,8 @@ def test_batch_items_should_throw_exception_for_duplicate_request(): } } ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "Provided list of item keys contains duplicates" ) @@ -3186,7 +3186,7 @@ def test_index_with_unknown_attributes_should_fail(): "Some index key attributes are not defined in AttributeDefinitions." ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.create_table( AttributeDefinitions=[ {"AttributeName": "customer_nr", "AttributeType": "S"}, @@ -3210,8 +3210,8 @@ def test_index_with_unknown_attributes_should_fail(): BillingMode="PAY_PER_REQUEST", ) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.contain(expected_exception) + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.contain(expected_exception) @mock_dynamodb2 @@ -3366,7 +3366,7 @@ def test_update_list_index__set_index_of_a_string(): client.put_item( TableName=table_name, Item={"id": {"S": "foo2"}, "itemstr": {"S": "somestring"}} ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.update_item( TableName=table_name, Key={"id": {"S": "foo2"}}, @@ -3377,8 +3377,8 @@ def test_update_list_index__set_index_of_a_string(): "Item" ] - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "The document path provided in the update expression is invalid for update" ) @@ -3615,19 +3615,19 @@ def test_item_size_is_under_400KB(): def assert_failure_due_to_item_size(func, **kwargs): - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: func(**kwargs) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "Item size has exceeded the maximum allowed size" ) def assert_failure_due_to_item_size_to_update(func, **kwargs): - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: func(**kwargs) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "Item size to update has exceeded the maximum allowed size" ) @@ -3654,10 +3654,10 @@ def test_hash_key_cannot_use_begins_with_operations(): batch.put_item(Item=item) table = dynamodb.Table("test-table") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: table.query(KeyConditionExpression=Key("key").begins_with("prefix-")) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "Query key condition not supported" ) @@ -4047,7 +4047,7 @@ def test_update_catches_invalid_list_append_operation(): ) # Update item using invalid list_append expression - with assert_raises(ParamValidationError) as ex: + with pytest.raises(ParamValidationError) as ex: client.update_item( TableName="TestTable", Key={"SHA256": {"S": "sha-of-file"}}, @@ -4056,10 +4056,8 @@ def test_update_catches_invalid_list_append_operation(): ) # Verify correct error is returned - str(ex.exception).should.match("Parameter validation failed:") - str(ex.exception).should.match( - "Invalid type for parameter ExpressionAttributeValues." - ) + str(ex.value).should.match("Parameter validation failed:") + str(ex.value).should.match("Invalid type for parameter ExpressionAttributeValues.") def _create_user_table(): @@ -4166,12 +4164,12 @@ def test_query_catches_when_no_filters(): ) table = dynamo.Table("origin-rbu-dev") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: table.query(TableName="original-rbu-dev") - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "Either KeyConditions or QueryFilter should be present" ) @@ -4197,7 +4195,7 @@ def test_invalid_transact_get_items(): client = boto3.client("dynamodb", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.transact_get_items( TransactItems=[ {"Get": {"Key": {"id": {"S": "1"}}, "TableName": "test1"}} @@ -4205,25 +4203,23 @@ def test_invalid_transact_get_items(): ] ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.match( + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.match( r"failed to satisfy constraint: Member must have length less than or equal to 25", re.I, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.transact_get_items( TransactItems=[ - {"Get": {"Key": {"id": {"S": "1"},}, "TableName": "test1"}}, - {"Get": {"Key": {"id": {"S": "1"},}, "TableName": "non_exists_table"}}, + {"Get": {"Key": {"id": {"S": "1"},}, "TableName": "test1",}}, + {"Get": {"Key": {"id": {"S": "1"},}, "TableName": "non_exists_table",}}, ] ) - ex.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( - "Requested resource not found" - ) + ex.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal("Requested resource not found") @mock_dynamodb2 @@ -4491,7 +4487,7 @@ def test_transact_write_items_put_conditional_expressions(): TableName="test-table", Item={"id": {"S": "foo2"},}, ) # Put multiple items - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.transact_write_items( TransactItems=[ { @@ -4514,8 +4510,8 @@ def test_transact_write_items_put_conditional_expressions(): ] ) # Assert the exception is correct - ex.exception.response["Error"]["Code"].should.equal("TransactionCanceledException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("TransactionCanceledException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Assert all are present items = dynamodb.scan(TableName="test-table")["Items"] items.should.have.length_of(1) @@ -4581,7 +4577,7 @@ def test_transact_write_items_conditioncheck_fails(): ) # Try to put an email address, but verify whether it exists # ConditionCheck should fail - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.transact_write_items( TransactItems=[ { @@ -4604,8 +4600,8 @@ def test_transact_write_items_conditioncheck_fails(): ] ) # Assert the exception is correct - ex.exception.response["Error"]["Code"].should.equal("TransactionCanceledException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("TransactionCanceledException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Assert the original email address is still present items = dynamodb.scan(TableName="test-table")["Items"] @@ -4687,7 +4683,7 @@ def test_transact_write_items_delete_with_failed_condition_expression(): ) # Try to delete an item that does not have an email address # ConditionCheck should fail - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.transact_write_items( TransactItems=[ { @@ -4701,8 +4697,8 @@ def test_transact_write_items_delete_with_failed_condition_expression(): ] ) # Assert the exception is correct - ex.exception.response["Error"]["Code"].should.equal("TransactionCanceledException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("TransactionCanceledException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Assert the original item is still present items = dynamodb.scan(TableName="test-table")["Items"] items.should.have.length_of(1) @@ -4758,7 +4754,7 @@ def test_transact_write_items_update_with_failed_condition_expression(): ) # Try to update an item that does not have an email address # ConditionCheck should fail - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.transact_write_items( TransactItems=[ { @@ -4774,8 +4770,8 @@ def test_transact_write_items_update_with_failed_condition_expression(): ] ) # Assert the exception is correct - ex.exception.response["Error"]["Code"].should.equal("TransactionCanceledException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("TransactionCanceledException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Assert the original item is still present items = dynamodb.scan(TableName="test-table")["Items"] items.should.have.length_of(1) @@ -5318,7 +5314,7 @@ def test_transact_write_items_fails_with_transaction_canceled_exception(): # Insert one item dynamodb.put_item(TableName="test-table", Item={"id": {"S": "foo"}}) # Update two items, the one that exists and another that doesn't - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: dynamodb.transact_write_items( TransactItems=[ { @@ -5343,9 +5339,9 @@ def test_transact_write_items_fails_with_transaction_canceled_exception(): }, ] ) - ex.exception.response["Error"]["Code"].should.equal("TransactionCanceledException") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("TransactionCanceledException") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "Transaction cancelled, please refer cancellation reasons for specific reasons [None, ConditionalCheckFailed]" ) diff --git a/tests/test_dynamodb2/test_dynamodb_executor.py b/tests/test_dynamodb2/test_dynamodb_executor.py index 4ef0bb423..892d2715c 100644 --- a/tests/test_dynamodb2/test_dynamodb_executor.py +++ b/tests/test_dynamodb2/test_dynamodb_executor.py @@ -1,9 +1,10 @@ +import pytest + from moto.dynamodb2.exceptions import IncorrectOperandType, IncorrectDataType from moto.dynamodb2.models import Item, DynamoType from moto.dynamodb2.parsing.executors import UpdateExpressionExecutor from moto.dynamodb2.parsing.expressions import UpdateExpressionParser from moto.dynamodb2.parsing.validators import UpdateExpressionValidator -from parameterized import parameterized def test_execution_of_if_not_exists_not_existing_value(): @@ -384,7 +385,8 @@ def test_execution_of_add_to_a_set(): assert expected_item == item -@parameterized( +@pytest.mark.parametrize( + "expression_attribute_values,unexpected_data_type", [ ({":value": {"S": "10"}}, "STRING",), ({":value": {"N": "10"}}, "NUMBER",), @@ -393,7 +395,7 @@ def test_execution_of_add_to_a_set(): ({":value": {"NULL": True}}, "NULL",), ({":value": {"M": {"el0": {"S": "10"}}}}, "MAP",), ({":value": {"L": []}}, "LIST",), - ] + ], ) def test_execution_of__delete_element_from_set_invalid_value( expression_attribute_values, unexpected_data_type diff --git a/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py b/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py index 12e75a73e..1c8c12110 100644 --- a/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py +++ b/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py @@ -8,7 +8,7 @@ from boto3.dynamodb.conditions import Key from botocore.exceptions import ClientError import sure # noqa from freezegun import freeze_time -from nose.tools import assert_raises +import pytest from moto import mock_dynamodb2, mock_dynamodb2_deprecated from boto.exception import JSONResponseError @@ -1353,10 +1353,10 @@ def test_update_item_with_expression(): def assert_failure_due_to_key_not_in_schema(func, **kwargs): - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: func(**kwargs) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "The provided key element does not match the schema" ) diff --git a/tests/test_dynamodb2/test_dynamodb_validation.py b/tests/test_dynamodb2/test_dynamodb_validation.py index d60dd48f6..8761d2cd2 100644 --- a/tests/test_dynamodb2/test_dynamodb_validation.py +++ b/tests/test_dynamodb2/test_dynamodb_validation.py @@ -1,3 +1,5 @@ +import pytest + from moto.dynamodb2.exceptions import ( AttributeIsReservedKeyword, ExpressionAttributeValueNotDefined, @@ -10,12 +12,10 @@ from moto.dynamodb2.models import Item, DynamoType from moto.dynamodb2.parsing.ast_nodes import ( NodeDepthLeftTypeFetcher, UpdateExpressionSetAction, - UpdateExpressionValue, DDBTypedValue, ) from moto.dynamodb2.parsing.expressions import UpdateExpressionParser from moto.dynamodb2.parsing.validators import UpdateExpressionValidator -from parameterized import parameterized def test_validation_of_update_expression_with_keyword(): @@ -41,8 +41,8 @@ def test_validation_of_update_expression_with_keyword(): assert e.keyword == "path" -@parameterized( - ["SET a = #b + :val2", "SET a = :val2 + #b",] +@pytest.mark.parametrize( + "update_expression", ["SET a = #b + :val2", "SET a = :val2 + #b",] ) def test_validation_of_a_set_statement_with_incorrect_passed_value(update_expression): """ @@ -98,9 +98,7 @@ def test_validation_of_update_expression_with_attribute_that_does_not_exist_in_i assert True -@parameterized( - ["SET a = #c", "SET a = #c + #d",] -) +@pytest.mark.parametrize("update_expression", ["SET a = #c", "SET a = #c + #d",]) def test_validation_of_update_expression_with_attribute_name_that_is_not_defined( update_expression, ): diff --git a/tests/test_dynamodbstreams/__init__.py b/tests/test_dynamodbstreams/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_dynamodbstreams/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_dynamodbstreams/test_dynamodbstreams.py b/tests/test_dynamodbstreams/test_dynamodbstreams.py index 6f66e304d..70efc5289 100644 --- a/tests/test_dynamodbstreams/test_dynamodbstreams.py +++ b/tests/test_dynamodbstreams/test_dynamodbstreams.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals, print_function -from nose.tools import assert_raises +import pytest import boto3 from moto import mock_dynamodb2, mock_dynamodbstreams @@ -224,7 +224,7 @@ class TestEdges: assert "LatestStreamLabel" in resp["TableDescription"] # now try to enable it again - with assert_raises(conn.exceptions.ResourceInUseException): + with pytest.raises(conn.exceptions.ResourceInUseException): resp = conn.update_table( TableName="test-streams", StreamSpecification={ diff --git a/tests/test_ec2/test_amis.py b/tests/test_ec2/test_amis.py index 5b26acf6f..db1e263b3 100644 --- a/tests/test_ec2/test_amis.py +++ b/tests/test_ec2/test_amis.py @@ -6,8 +6,8 @@ import boto3 from boto.exception import EC2ResponseError from botocore.exceptions import ClientError -# Ensure 'assert_raises' context manager support for Python 2.6 -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import sure # noqa from moto import mock_ec2_deprecated, mock_ec2 @@ -27,13 +27,13 @@ def test_ami_create_and_delete(): reservation = conn.run_instances("ami-1234abcd") instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: image_id = conn.create_image( instance.id, "test-ami", "this is a test ami", dry_run=True ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set" ) @@ -76,22 +76,22 @@ def test_ami_create_and_delete(): root_mapping.should_not.be.none # Deregister - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: success = conn.deregister_image(image_id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set" ) success = conn.deregister_image(image_id) success.should.be.true - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.deregister_image(image_id) - cm.exception.code.should.equal("InvalidAMIID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @requires_boto_gte("2.14.0") @@ -112,7 +112,7 @@ def test_ami_copy(): # Boto returns a 'CopyImage' object with an image_id attribute here. Use # the image_id to fetch the full info. - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: copy_image_ref = conn.copy_image( source_image.region.name, source_image.id, @@ -120,9 +120,9 @@ def test_ami_copy(): "this is a test copy ami", dry_run=True, ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set" ) @@ -152,28 +152,28 @@ def test_ami_copy(): ) # Copy from non-existent source ID. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.copy_image( source_image.region.name, "ami-abcd1234", "test-copy-ami", "this is a test copy ami", ) - cm.exception.code.should.equal("InvalidAMIID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Copy from non-existent source region. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: invalid_region = ( "us-east-1" if (source_image.region.name != "us-east-1") else "us-west-1" ) conn.copy_image( invalid_region, source_image.id, "test-copy-ami", "this is a test copy ami" ) - cm.exception.code.should.equal("InvalidAMIID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 @@ -208,11 +208,11 @@ def test_ami_tagging(): conn.create_image(instance.id, "test-ami", "this is a test ami") image = conn.get_all_images()[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: image.add_tag("a key", "some value", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) @@ -233,11 +233,11 @@ def test_ami_create_from_missing_instance(): conn = boto.connect_ec2("the_key", "the_secret") args = ["i-abcdefg", "test-ami", "this is a test ami"] - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_image(*args) - cm.exception.code.should.equal("InvalidInstanceID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidInstanceID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -353,22 +353,22 @@ def test_ami_filtering_via_tag(): def test_getting_missing_ami(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_image("ami-missing") - cm.exception.code.should.equal("InvalidAMIID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated def test_getting_malformed_ami(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_image("foo-missing") - cm.exception.code.should.equal("InvalidAMIID.Malformed") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.Malformed") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -399,11 +399,11 @@ def test_ami_attribute_group_permissions(): } # Add 'all' group and confirm - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.modify_image_attribute(**dict(ADD_GROUP_ARGS, **{"dry_run": True})) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set" ) @@ -616,9 +616,9 @@ def test_ami_describe_executable_users_and_filter(): @mock_ec2_deprecated def test_ami_attribute_user_and_group_permissions(): """ - Boto supports adding/removing both users and groups at the same time. - Just spot-check this -- input variations, idempotency, etc are validated - via user-specific and group-specific tests above. + Boto supports adding/removing both users and groups at the same time. + Just spot-check this -- input variations, idempotency, etc are validated + via user-specific and group-specific tests above. """ conn = boto.connect_ec2("the_key", "the_secret") reservation = conn.run_instances("ami-1234abcd") @@ -678,86 +678,86 @@ def test_ami_attribute_error_cases(): image = conn.get_image(image_id) # Error: Add with group != 'all' - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( image.id, attribute="launchPermission", operation="add", groups="everyone" ) - cm.exception.code.should.equal("InvalidAMIAttributeItemValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIAttributeItemValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Add with user ID that isn't an integer. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( image.id, attribute="launchPermission", operation="add", user_ids="12345678901A", ) - cm.exception.code.should.equal("InvalidAMIAttributeItemValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIAttributeItemValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Add with user ID that is > length 12. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( image.id, attribute="launchPermission", operation="add", user_ids="1234567890123", ) - cm.exception.code.should.equal("InvalidAMIAttributeItemValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIAttributeItemValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Add with user ID that is < length 12. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( image.id, attribute="launchPermission", operation="add", user_ids="12345678901", ) - cm.exception.code.should.equal("InvalidAMIAttributeItemValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIAttributeItemValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Add with one invalid user ID among other valid IDs, ensure no # partial changes. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( image.id, attribute="launchPermission", operation="add", user_ids=["123456789011", "foo", "123456789022"], ) - cm.exception.code.should.equal("InvalidAMIAttributeItemValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIAttributeItemValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none attributes = conn.get_image_attribute(image.id, attribute="launchPermission") attributes.attrs.should.have.length_of(0) # Error: Add with invalid image ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( "ami-abcd1234", attribute="launchPermission", operation="add", groups="all" ) - cm.exception.code.should.equal("InvalidAMIID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Remove with invalid image ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_image_attribute( "ami-abcd1234", attribute="launchPermission", operation="remove", groups="all", ) - cm.exception.code.should.equal("InvalidAMIID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 @@ -765,11 +765,11 @@ def test_ami_describe_non_existent(): ec2 = boto3.resource("ec2", region_name="us-west-1") # Valid pattern but non-existent id img = ec2.Image("ami-abcd1234") - with assert_raises(ClientError): + with pytest.raises(ClientError): img.load() # Invalid ami pattern img = ec2.Image("not_an_ami_id") - with assert_raises(ClientError): + with pytest.raises(ClientError): img.load() diff --git a/tests/test_ec2/test_customer_gateways.py b/tests/test_ec2/test_customer_gateways.py index a676a2b5d..8d94a9a94 100644 --- a/tests/test_ec2/test_customer_gateways.py +++ b/tests/test_ec2/test_customer_gateways.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals import boto import sure # noqa -from nose.tools import assert_raises -from nose.tools import assert_false +import pytest from boto.exception import EC2ResponseError from moto import mock_ec2_deprecated @@ -45,5 +44,5 @@ def test_delete_customer_gateways(): @mock_ec2_deprecated def test_delete_customer_gateways_bad_id(): conn = boto.connect_vpc("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_customer_gateway("cgw-0123abcd") diff --git a/tests/test_ec2/test_dhcp_options.py b/tests/test_ec2/test_dhcp_options.py index 4aaceaa07..85bc7f244 100644 --- a/tests/test_ec2/test_dhcp_options.py +++ b/tests/test_ec2/test_dhcp_options.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto3 import boto @@ -33,11 +32,11 @@ def test_dhcp_options_associate_invalid_dhcp_id(): conn = boto.connect_vpc("the_key", "the_secret") vpc = conn.create_vpc("10.0.0.0/16") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_dhcp_options("foo", vpc.id) - cm.exception.code.should.equal("InvalidDhcpOptionID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidDhcpOptionID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -46,11 +45,11 @@ def test_dhcp_options_associate_invalid_vpc_id(): conn = boto.connect_vpc("the_key", "the_secret") dhcp_options = conn.create_dhcp_options(SAMPLE_DOMAIN_NAME, SAMPLE_NAME_SERVERS) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_dhcp_options(dhcp_options.id, "foo") - cm.exception.code.should.equal("InvalidVpcID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVpcID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -64,19 +63,19 @@ def test_dhcp_options_delete_with_vpc(): rval = conn.associate_dhcp_options(dhcp_options_id, vpc.id) rval.should.be.equal(True) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_dhcp_options(dhcp_options_id) - cm.exception.code.should.equal("DependencyViolation") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("DependencyViolation") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none vpc.delete() - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_dhcp_options([dhcp_options_id]) - cm.exception.code.should.equal("InvalidDhcpOptionID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidDhcpOptionID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -100,17 +99,17 @@ def test_create_dhcp_options_invalid_options(): conn = boto.connect_vpc("the_key", "the_secret") servers = ["f", "f", "f", "f", "f"] - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_dhcp_options(ntp_servers=servers) - cm.exception.code.should.equal("InvalidParameterValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidParameterValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_dhcp_options(netbios_node_type="0") - cm.exception.code.should.equal("InvalidParameterValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidParameterValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -131,11 +130,11 @@ def test_describe_dhcp_options_invalid_id(): """get error on invalid dhcp_option_id lookup""" conn = boto.connect_vpc("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_dhcp_options(["1"]) - cm.exception.code.should.equal("InvalidDhcpOptionID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidDhcpOptionID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -149,11 +148,11 @@ def test_delete_dhcp_options(): conn.delete_dhcp_options(dhcp_option.id) # .should.be.equal(True) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_dhcp_options([dhcp_option.id]) - cm.exception.code.should.equal("InvalidDhcpOptionID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidDhcpOptionID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -162,11 +161,11 @@ def test_delete_dhcp_options_invalid_id(): conn.create_dhcp_options() - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_dhcp_options("dopt-abcd1234") - cm.exception.code.should.equal("InvalidDhcpOptionID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidDhcpOptionID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -175,11 +174,11 @@ def test_delete_dhcp_options_malformed_id(): conn.create_dhcp_options() - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_dhcp_options("foo-abcd1234") - cm.exception.code.should.equal("InvalidDhcpOptionsId.Malformed") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidDhcpOptionsId.Malformed") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated diff --git a/tests/test_ec2/test_elastic_block_store.py b/tests/test_ec2/test_elastic_block_store.py index 2a5dfbf2a..d0b1dee2d 100644 --- a/tests/test_ec2/test_elastic_block_store.py +++ b/tests/test_ec2/test_elastic_block_store.py @@ -1,17 +1,15 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises - -from moto.ec2 import ec2_backends import boto import boto3 -from botocore.exceptions import ClientError -from boto.exception import EC2ResponseError -import sure # noqa -from moto import mock_ec2_deprecated, mock_ec2 +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest +import sure # noqa +from boto.exception import EC2ResponseError +from botocore.exceptions import ClientError +from moto import mock_ec2, mock_ec2_deprecated +from moto.ec2 import ec2_backends from moto.ec2.models import OWNER_ID from moto.kms import mock_kms @@ -31,11 +29,11 @@ def test_create_and_delete_volume(): volume = current_volume[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: volume.delete(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeleteVolume operation: Request would have succeeded, but DryRun flag is set" ) @@ -46,11 +44,11 @@ def test_create_and_delete_volume(): my_volume.should.have.length_of(0) # Deleting something that was already deleted should throw an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: volume.delete() - cm.exception.code.should.equal("InvalidVolume.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVolume.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -72,11 +70,11 @@ def test_delete_attached_volume(): # attempt to delete volume # assert raises VolumeInUseError - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: volume.delete() - ex.exception.error_code.should.equal("VolumeInUse") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("VolumeInUse") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "Volume {0} is currently attached to {1}".format(volume.id, instance.id) ) @@ -95,11 +93,11 @@ def test_delete_attached_volume(): @mock_ec2_deprecated def test_create_encrypted_volume_dryrun(): conn = boto.ec2.connect_to_region("us-east-1") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set" ) @@ -109,11 +107,11 @@ def test_create_encrypted_volume(): conn = boto.ec2.connect_to_region("us-east-1") volume = conn.create_volume(80, "us-east-1a", encrypted=True) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set" ) @@ -134,11 +132,11 @@ def test_filter_volume_by_id(): vol2 = conn.get_all_volumes(volume_ids=[volume1.id, volume2.id]) vol2.should.have.length_of(2) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_volumes(volume_ids=["vol-does_not_exist"]) - cm.exception.code.should.equal("InvalidVolume.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVolume.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -259,11 +257,11 @@ def test_volume_attach_and_detach(): volume.update() volume.volume_state().should.equal("available") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: volume.attach(instance.id, "/dev/sdh", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the AttachVolume operation: Request would have succeeded, but DryRun flag is set" ) @@ -275,11 +273,11 @@ def test_volume_attach_and_detach(): volume.attach_data.instance_id.should.equal(instance.id) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: volume.detach(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DetachVolume operation: Request would have succeeded, but DryRun flag is set" ) @@ -288,23 +286,23 @@ def test_volume_attach_and_detach(): volume.update() volume.volume_state().should.equal("available") - with assert_raises(EC2ResponseError) as cm1: + with pytest.raises(EC2ResponseError) as cm1: volume.attach("i-1234abcd", "/dev/sdh") - cm1.exception.code.should.equal("InvalidInstanceID.NotFound") - cm1.exception.status.should.equal(400) - cm1.exception.request_id.should_not.be.none + cm1.value.code.should.equal("InvalidInstanceID.NotFound") + cm1.value.status.should.equal(400) + cm1.value.request_id.should_not.be.none - with assert_raises(EC2ResponseError) as cm2: + with pytest.raises(EC2ResponseError) as cm2: conn.detach_volume(volume.id, instance.id, "/dev/sdh") - cm2.exception.code.should.equal("InvalidAttachment.NotFound") - cm2.exception.status.should.equal(400) - cm2.exception.request_id.should_not.be.none + cm2.value.code.should.equal("InvalidAttachment.NotFound") + cm2.value.status.should.equal(400) + cm2.value.request_id.should_not.be.none - with assert_raises(EC2ResponseError) as cm3: + with pytest.raises(EC2ResponseError) as cm3: conn.detach_volume(volume.id, "i-1234abcd", "/dev/sdh") - cm3.exception.code.should.equal("InvalidInstanceID.NotFound") - cm3.exception.status.should.equal(400) - cm3.exception.request_id.should_not.be.none + cm3.value.code.should.equal("InvalidInstanceID.NotFound") + cm3.value.status.should.equal(400) + cm3.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -312,11 +310,11 @@ def test_create_snapshot(): conn = boto.ec2.connect_to_region("us-east-1") volume = conn.create_volume(80, "us-east-1a") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: snapshot = volume.create_snapshot("a dryrun snapshot", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set" ) @@ -340,11 +338,11 @@ def test_create_snapshot(): conn.get_all_snapshots().should.have.length_of(num_snapshots) # Deleting something that was already deleted should throw an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: snapshot.delete() - cm.exception.code.should.equal("InvalidSnapshot.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSnapshot.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -382,11 +380,11 @@ def test_filter_snapshot_by_id(): s.volume_id.should.be.within([volume2.id, volume3.id]) s.region.name.should.equal(conn.region.name) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_snapshots(snapshot_ids=["snap-does_not_exist"]) - cm.exception.code.should.equal("InvalidSnapshot.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSnapshot.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -484,11 +482,11 @@ def test_snapshot_attribute(): # Add 'all' group and confirm - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.modify_snapshot_attribute(**dict(ADD_GROUP_ARGS, **{"dry_run": True})) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set" ) @@ -506,11 +504,11 @@ def test_snapshot_attribute(): ) # Remove 'all' group and confirm - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.modify_snapshot_attribute(**dict(REMOVE_GROUP_ARGS, **{"dry_run": True})) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set" ) @@ -527,40 +525,40 @@ def test_snapshot_attribute(): ).should_not.throw(EC2ResponseError) # Error: Add with group != 'all' - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_snapshot_attribute( snapshot.id, attribute="createVolumePermission", operation="add", groups="everyone", ) - cm.exception.code.should.equal("InvalidAMIAttributeItemValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAMIAttributeItemValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Add with invalid snapshot ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_snapshot_attribute( "snapshot-abcd1234", attribute="createVolumePermission", operation="add", groups="all", ) - cm.exception.code.should.equal("InvalidSnapshot.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSnapshot.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Remove with invalid snapshot ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.modify_snapshot_attribute( "snapshot-abcd1234", attribute="createVolumePermission", operation="remove", groups="all", ) - cm.exception.code.should.equal("InvalidSnapshot.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSnapshot.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 @@ -595,12 +593,12 @@ def test_modify_snapshot_attribute(): } # Add 'all' group and confirm - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_client.modify_snapshot_attribute(**dict(ADD_GROUP_ARGS, **{"DryRun": True})) - cm.exception.response["Error"]["Code"].should.equal("DryRunOperation") - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("DryRunOperation") + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ec2_client.modify_snapshot_attribute(**ADD_GROUP_ARGS) @@ -620,13 +618,13 @@ def test_modify_snapshot_attribute(): ], "This snapshot should have public group permissions." # Remove 'all' group and confirm - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: ec2_client.modify_snapshot_attribute( **dict(REMOVE_GROUP_ARGS, **{"DryRun": True}) ) - cm.exception.response["Error"]["Code"].should.equal("DryRunOperation") - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("DryRunOperation") + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ec2_client.modify_snapshot_attribute(**REMOVE_GROUP_ARGS) @@ -646,40 +644,40 @@ def test_modify_snapshot_attribute(): ], "This snapshot should have no permissions." # Error: Add with group != 'all' - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_client.modify_snapshot_attribute( SnapshotId=snapshot.id, Attribute="createVolumePermission", OperationType="add", GroupNames=["everyone"], ) - cm.exception.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Error: Add with invalid snapshot ID - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_client.modify_snapshot_attribute( SnapshotId="snapshot-abcd1234", Attribute="createVolumePermission", OperationType="add", GroupNames=["all"], ) - cm.exception.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Error: Remove with invalid snapshot ID - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_client.modify_snapshot_attribute( SnapshotId="snapshot-abcd1234", Attribute="createVolumePermission", OperationType="remove", GroupNames=["all"], ) - cm.exception.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Test adding user id ec2_client.modify_snapshot_attribute( @@ -740,11 +738,11 @@ def test_create_volume_from_snapshot(): volume = conn.create_volume(80, "us-east-1a") snapshot = volume.create_snapshot("a test snapshot") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: snapshot = volume.create_snapshot("a test snapshot", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set" ) @@ -786,13 +784,13 @@ def test_modify_attribute_blockDeviceMapping(): instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.modify_attribute( "blockDeviceMapping", {"/dev/sda1": True}, dry_run=True ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyInstanceAttribute operation: Request would have succeeded, but DryRun flag is set" ) @@ -809,11 +807,11 @@ def test_volume_tag_escaping(): vol = conn.create_volume(10, "us-east-1a") snapshot = conn.create_snapshot(vol.id, "Desc") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: snapshot.add_tags({"key": ""}, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) snaps = [snap for snap in conn.get_all_snapshots() if snap.id == snapshot.id] @@ -879,25 +877,25 @@ def test_copy_snapshot(): getattr(source, attrib).should.equal(getattr(dest, attrib)) # Copy from non-existent source ID. - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: create_snapshot_error = ec2_client.create_snapshot(VolumeId="vol-abcd1234") - cm.exception.response["Error"]["Code"].should.equal("InvalidVolume.NotFound") - cm.exception.response["Error"]["Message"].should.equal( - "The volume 'vol-abcd1234' does not exist." - ) - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("InvalidVolume.NotFound") + cm.value.response["Error"]["Message"].should.equal( + "The volume 'vol-abcd1234' does not exist." + ) + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) # Copy from non-existent source region. - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: copy_snapshot_response = dest_ec2_client.copy_snapshot( SourceSnapshotId=create_snapshot_response["SnapshotId"], SourceRegion="eu-west-2", ) - cm.exception.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") - cm.exception.response["Error"]["Message"].should.be.none - cm.exception.response["ResponseMetadata"]["RequestId"].should_not.be.none - cm.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + cm.value.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") + cm.value.response["Error"]["Message"].should.be.none + cm.value.response["ResponseMetadata"]["RequestId"].should_not.be.none + cm.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) @mock_ec2 @@ -921,12 +919,12 @@ def test_search_for_many_snapshots(): @mock_ec2 def test_create_unencrypted_volume_with_kms_key_fails(): resource = boto3.resource("ec2", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: resource.create_volume( AvailabilityZone="us-east-1a", Encrypted=False, KmsKeyId="key", Size=10 ) - ex.exception.response["Error"]["Code"].should.equal("InvalidParameterDependency") - ex.exception.response["Error"]["Message"].should.contain("KmsKeyId") + ex.value.response["Error"]["Code"].should.equal("InvalidParameterDependency") + ex.value.response["Error"]["Message"].should.contain("KmsKeyId") @mock_kms @@ -934,9 +932,9 @@ def test_create_unencrypted_volume_with_kms_key_fails(): def test_create_encrypted_volume_without_kms_key_should_use_default_key(): kms = boto3.client("kms", region_name="us-east-1") # Default master key for EBS does not exist until needed. - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: kms.describe_key(KeyId="alias/aws/ebs") - ex.exception.response["Error"]["Code"].should.equal("NotFoundException") + ex.value.response["Error"]["Code"].should.equal("NotFoundException") # Creating an encrypted volume should create (and use) the default key. resource = boto3.resource("ec2", region_name="us-east-1") volume = resource.create_volume( diff --git a/tests/test_ec2/test_elastic_ip_addresses.py b/tests/test_ec2/test_elastic_ip_addresses.py index baecb94d6..8edd92e65 100644 --- a/tests/test_ec2/test_elastic_ip_addresses.py +++ b/tests/test_ec2/test_elastic_ip_addresses.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto import boto3 @@ -21,11 +20,11 @@ def test_eip_allocate_classic(): """Allocate/release Classic EIP""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: standard = conn.allocate_address(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set" ) @@ -35,11 +34,11 @@ def test_eip_allocate_classic(): standard.instance_id.should.be.none standard.domain.should.be.equal("standard") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: standard.release(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set" ) @@ -52,11 +51,11 @@ def test_eip_allocate_vpc(): """Allocate/release VPC EIP""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: vpc = conn.allocate_address(domain="vpc", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set" ) @@ -84,11 +83,11 @@ def test_eip_allocate_invalid_domain(): """Allocate EIP invalid domain""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.allocate_address(domain="bogus") - cm.exception.code.should.equal("InvalidParameterValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidParameterValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -102,19 +101,19 @@ def test_eip_associate_classic(): eip = conn.allocate_address() eip.instance_id.should.be.none - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_address(public_ip=eip.public_ip) - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.associate_address( instance_id=instance.id, public_ip=eip.public_ip, dry_run=True ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the AssociateAddress operation: Request would have succeeded, but DryRun flag is set" ) @@ -123,11 +122,11 @@ def test_eip_associate_classic(): eip = conn.get_all_addresses(addresses=[eip.public_ip])[0] eip.instance_id.should.be.equal(instance.id) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.disassociate_address(public_ip=eip.public_ip, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DisAssociateAddress operation: Request would have succeeded, but DryRun flag is set" ) @@ -153,11 +152,11 @@ def test_eip_associate_vpc(): eip = conn.allocate_address(domain="vpc") eip.instance_id.should.be.none - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_address(allocation_id=eip.allocation_id) - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none conn.associate_address(instance_id=instance.id, allocation_id=eip.allocation_id) # no .update() on address ): @@ -169,11 +168,11 @@ def test_eip_associate_vpc(): eip.instance_id.should.be.equal("") eip.association_id.should.be.none - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: eip.release(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set" ) @@ -241,11 +240,11 @@ def test_eip_associate_network_interface(): eip = conn.allocate_address(domain="vpc") eip.network_interface_id.should.be.none - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_address(network_interface_id=eni.id) - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none conn.associate_address(network_interface_id=eni.id, allocation_id=eip.allocation_id) # no .update() on address ): @@ -276,13 +275,13 @@ def test_eip_reassociate(): conn.associate_address(instance_id=instance1.id, public_ip=eip.public_ip) # Different ID detects resource association - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_address( instance_id=instance2.id, public_ip=eip.public_ip, allow_reassociation=False ) - cm.exception.code.should.equal("Resource.AlreadyAssociated") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("Resource.AlreadyAssociated") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none conn.associate_address.when.called_with( instance_id=instance2.id, public_ip=eip.public_ip, allow_reassociation=True @@ -312,11 +311,11 @@ def test_eip_reassociate_nic(): conn.associate_address(network_interface_id=eni1.id, public_ip=eip.public_ip) # Different ID detects resource association - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_address(network_interface_id=eni2.id, public_ip=eip.public_ip) - cm.exception.code.should.equal("Resource.AlreadyAssociated") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("Resource.AlreadyAssociated") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none conn.associate_address.when.called_with( network_interface_id=eni2.id, public_ip=eip.public_ip, allow_reassociation=True @@ -336,11 +335,11 @@ def test_eip_associate_invalid_args(): eip = conn.allocate_address() - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_address(instance_id=instance.id) - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none instance.terminate() @@ -350,11 +349,11 @@ def test_eip_disassociate_bogus_association(): """Disassociate bogus EIP""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.disassociate_address(association_id="bogus") - cm.exception.code.should.equal("InvalidAssociationID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAssociationID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -362,11 +361,11 @@ def test_eip_release_bogus_eip(): """Release bogus EIP""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.release_address(allocation_id="bogus") - cm.exception.code.should.equal("InvalidAllocationID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAllocationID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -374,11 +373,11 @@ def test_eip_disassociate_arg_error(): """Invalid arguments disassociate address""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.disassociate_address() - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -386,11 +385,11 @@ def test_eip_release_arg_error(): """Invalid arguments release address""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.release_address() - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -438,11 +437,11 @@ def test_eip_describe_none(): """Error when search for bogus IP""" conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_addresses(addresses=["256.256.256.256"]) - cm.exception.code.should.equal("InvalidAddress.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAddress.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 diff --git a/tests/test_ec2/test_elastic_network_interfaces.py b/tests/test_ec2/test_elastic_network_interfaces.py index e7fd878a6..a5bb019b0 100644 --- a/tests/test_ec2/test_elastic_network_interfaces.py +++ b/tests/test_ec2/test_elastic_network_interfaces.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto3 from botocore.exceptions import ClientError @@ -21,11 +20,11 @@ def test_elastic_network_interfaces(): vpc = conn.create_vpc("10.0.0.0/16") subnet = conn.create_subnet(vpc.id, "10.0.0.0/18") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: eni = conn.create_network_interface(subnet.id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set" ) @@ -38,11 +37,11 @@ def test_elastic_network_interfaces(): eni.private_ip_addresses.should.have.length_of(1) eni.private_ip_addresses[0].private_ip_address.startswith("10.").should.be.true - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.delete_network_interface(eni.id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set" ) @@ -51,22 +50,22 @@ def test_elastic_network_interfaces(): all_enis = conn.get_all_network_interfaces() all_enis.should.have.length_of(0) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_network_interface(eni.id) - cm.exception.error_code.should.equal("InvalidNetworkInterfaceID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.error_code.should.equal("InvalidNetworkInterfaceID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated def test_elastic_network_interfaces_subnet_validation(): conn = boto.connect_vpc("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_network_interface("subnet-abcd1234") - cm.exception.error_code.should.equal("InvalidSubnetID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.error_code.should.equal("InvalidSubnetID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -133,13 +132,13 @@ def test_elastic_network_interfaces_modify_attribute(): eni.groups.should.have.length_of(1) eni.groups[0].id.should.equal(security_group1.id) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.modify_network_interface_attribute( eni.id, "groupset", [security_group2.id], dry_run=True ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set" ) @@ -228,11 +227,11 @@ def test_elastic_network_interfaces_get_by_tag_name(): SubnetId=subnet.id, PrivateIpAddress="10.0.10.5" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: eni1.create_tags(Tags=[{"Key": "Name", "Value": "eni1"}], DryRun=True) - ex.exception.response["Error"]["Code"].should.equal("DryRunOperation") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("DryRunOperation") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) diff --git a/tests/test_ec2/test_flow_logs.py b/tests/test_ec2/test_flow_logs.py index 044e6c31d..743466eaa 100644 --- a/tests/test_ec2/test_flow_logs.py +++ b/tests/test_ec2/test_flow_logs.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals -import tests.backport_assert_raises # noqa -from nose.tools import assert_raises +import pytest import boto3 @@ -36,7 +35,7 @@ def test_create_flow_logs_s3(): CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], @@ -45,9 +44,9 @@ def test_create_flow_logs_s3(): LogDestination="arn:aws:s3:::" + bucket.name, DryRun=True, ) - ex.exception.response["Error"]["Code"].should.equal("DryRunOperation") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("DryRunOperation") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "An error occurred (DryRunOperation) when calling the CreateFlowLogs operation: Request would have succeeded, but DryRun flag is set" ) @@ -87,7 +86,7 @@ def test_create_flow_logs_cloud_watch(): vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] logs_client.create_log_group(logGroupName="test-group") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], @@ -97,9 +96,9 @@ def test_create_flow_logs_cloud_watch(): DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DryRun=True, ) - ex.exception.response["Error"]["Code"].should.equal("DryRunOperation") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("DryRunOperation") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "An error occurred (DryRunOperation) when calling the CreateFlowLogs operation: Request would have succeeded, but DryRun flag is set" ) @@ -243,19 +242,19 @@ def test_delete_flow_logs_delete_many(): def test_delete_flow_logs_non_existing(): client = boto3.client("ec2", region_name="us-west-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.delete_flow_logs(FlowLogIds=["fl-1a2b3c4d"]) - ex.exception.response["Error"]["Code"].should.equal("InvalidFlowLogId.NotFound") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidFlowLogId.NotFound") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "These flow log ids in the input list are not found: [TotalCount: 1] fl-1a2b3c4d" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.delete_flow_logs(FlowLogIds=["fl-1a2b3c4d", "fl-2b3c4d5e"]) - ex.exception.response["Error"]["Code"].should.equal("InvalidFlowLogId.NotFound") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidFlowLogId.NotFound") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "These flow log ids in the input list are not found: [TotalCount: 2] fl-1a2b3c4d fl-2b3c4d5e" ) @@ -304,7 +303,7 @@ def test_create_flow_logs_invalid_parameters(): CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], @@ -313,26 +312,26 @@ def test_create_flow_logs_invalid_parameters(): LogDestination="arn:aws:s3:::" + bucket.name, MaxAggregationInterval=10, ) - ex.exception.response["Error"]["Code"].should.equal("InvalidParameter") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidParameter") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "Invalid Flow Log Max Aggregation Interval" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], TrafficType="ALL", LogDestinationType="s3", ) - ex.exception.response["Error"]["Code"].should.equal("InvalidParameter") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidParameter") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "LogDestination can't be empty if LogGroupName is not provided." ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], @@ -340,22 +339,22 @@ def test_create_flow_logs_invalid_parameters(): LogDestinationType="s3", LogGroupName="test", ) - ex.exception.response["Error"]["Code"].should.equal("InvalidParameter") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidParameter") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "LogDestination type must be cloud-watch-logs if LogGroupName is provided." ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], TrafficType="ALL", LogGroupName="test", ) - ex.exception.response["Error"]["Code"].should.equal("InvalidParameter") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidParameter") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "DeliverLogsPermissionArn can't be empty if LogDestinationType is cloud-watch-logs." ) @@ -368,7 +367,7 @@ def test_create_flow_logs_invalid_parameters(): )["FlowLogIds"] response.should.have.length_of(1) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], @@ -376,9 +375,9 @@ def test_create_flow_logs_invalid_parameters(): LogDestinationType="s3", LogDestination="arn:aws:s3:::" + bucket.name, ) - ex.exception.response["Error"]["Code"].should.equal("FlowLogAlreadyExists") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("FlowLogAlreadyExists") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "Error. There is an existing Flow Log with the same configuration and log destination." ) @@ -391,7 +390,7 @@ def test_create_flow_logs_invalid_parameters(): )["FlowLogIds"] response.should.have.length_of(1) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_flow_logs( ResourceType="VPC", ResourceIds=[vpc["VpcId"]], @@ -399,9 +398,9 @@ def test_create_flow_logs_invalid_parameters(): LogGroupName="test-group", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", ) - ex.exception.response["Error"]["Code"].should.equal("FlowLogAlreadyExists") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("FlowLogAlreadyExists") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "Error. There is an existing Flow Log with the same configuration and log destination." ) diff --git a/tests/test_ec2/test_general.py b/tests/test_ec2/test_general.py index 7b8f3bd53..c2b578929 100644 --- a/tests/test_ec2/test_general.py +++ b/tests/test_ec2/test_general.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto import boto3 @@ -25,11 +24,11 @@ def test_console_output(): def test_console_output_without_instance(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_console_output("i-1234abcd") - cm.exception.code.should.equal("InvalidInstanceID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidInstanceID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 diff --git a/tests/test_ec2/test_instances.py b/tests/test_ec2/test_instances.py index d7a2ff3f3..146e3c696 100644 --- a/tests/test_ec2/test_instances.py +++ b/tests/test_ec2/test_instances.py @@ -1,10 +1,9 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 +# Ensure 'pytest.raises' context manager support for Python 2.6 from botocore.exceptions import ClientError -import tests.backport_assert_raises -from nose.tools import assert_raises +import pytest import base64 import ipaddress @@ -52,11 +51,11 @@ def test_add_servers(): def test_instance_launch_and_terminate(): conn = boto.ec2.connect_to_region("us-east-1") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: reservation = conn.run_instances("ami-1234abcd", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the RunInstance operation: Request would have succeeded, but DryRun flag is set" ) @@ -87,11 +86,11 @@ def test_instance_launch_and_terminate(): volume.attach_data.instance_id.should.equal(instance.id) volume.status.should.equal("in-use") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.terminate_instances([instance.id], dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the TerminateInstance operation: Request would have succeeded, but DryRun flag is set" ) @@ -216,14 +215,12 @@ def test_instance_detach_volume_wrong_path(): ) instance = result[0] for volume in instance.volumes.all(): - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: instance.detach_volume(VolumeId=volume.volume_id, Device="/dev/sdf") - ex.exception.response["Error"]["Code"].should.equal( - "InvalidAttachment.NotFound" - ) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("InvalidAttachment.NotFound") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "The volume {0} is not attached to instance {1} as device {2}".format( volume.volume_id, instance.instance_id, "/dev/sdf" ) @@ -290,11 +287,11 @@ def test_get_instances_by_id(): instance_ids.should.equal([instance1.id, instance2.id]) # Call get_all_instances with a bad id should raise an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_instances(instance_ids=[instance1.id, "i-1234abcd"]) - cm.exception.code.should.equal("InvalidInstanceID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidInstanceID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 @@ -743,11 +740,11 @@ def test_instance_start_and_stop(): instance_ids = [instance.id for instance in instances] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: stopped_instances = conn.stop_instances(instance_ids, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the StopInstance operation: Request would have succeeded, but DryRun flag is set" ) @@ -756,11 +753,11 @@ def test_instance_start_and_stop(): for instance in stopped_instances: instance.state.should.equal("stopping") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: started_instances = conn.start_instances([instances[0].id], dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the StartInstance operation: Request would have succeeded, but DryRun flag is set" ) @@ -774,11 +771,11 @@ def test_instance_reboot(): reservation = conn.run_instances("ami-1234abcd") instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.reboot(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the RebootInstance operation: Request would have succeeded, but DryRun flag is set" ) @@ -792,11 +789,11 @@ def test_instance_attribute_instance_type(): reservation = conn.run_instances("ami-1234abcd") instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.modify_attribute("instanceType", "m1.small", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyInstanceType operation: Request would have succeeded, but DryRun flag is set" ) @@ -820,11 +817,11 @@ def test_modify_instance_attribute_security_groups(): "test security group 2", "this is a test security group 2" ).id - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.modify_attribute("groupSet", [sg_id, sg_id2], dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set" ) @@ -843,11 +840,11 @@ def test_instance_attribute_user_data(): reservation = conn.run_instances("ami-1234abcd") instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.modify_attribute("userData", "this is my user data", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyUserData operation: Request would have succeeded, but DryRun flag is set" ) @@ -873,11 +870,11 @@ def test_instance_attribute_source_dest_check(): # Set to false (note: Boto converts bool to string, eg 'false') - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.modify_attribute("sourceDestCheck", False, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifySourceDestCheck operation: Request would have succeeded, but DryRun flag is set" ) @@ -919,11 +916,11 @@ def test_user_data_with_run_instance(): def test_run_instance_with_security_group_name(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: group = conn.create_security_group("group1", "some description", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set" ) @@ -1196,11 +1193,11 @@ def test_instance_with_nic_attach_detach(): set([group.id for group in eni.groups]).should.equal(set([security_group2.id])) # Attach - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.attach_network_interface(eni.id, instance.id, device_index=1, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the AttachNetworkInterface operation: Request would have succeeded, but DryRun flag is set" ) @@ -1223,11 +1220,11 @@ def test_instance_with_nic_attach_detach(): ) # Detach - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.detach_network_interface(instance_eni.attachment.id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DetachNetworkInterface operation: Request would have succeeded, but DryRun flag is set" ) @@ -1242,11 +1239,11 @@ def test_instance_with_nic_attach_detach(): set([group.id for group in eni.groups]).should.equal(set([security_group2.id])) # Detach with invalid attachment ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.detach_network_interface("eni-attach-1234abcd") - cm.exception.code.should.equal("InvalidAttachmentID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAttachmentID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -1307,12 +1304,12 @@ def test_run_instance_with_block_device_mappings_missing_ebs(): "InstanceType": "t1.micro", "BlockDeviceMappings": [{"DeviceName": "/dev/sda2"}], } - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: ec2_client.run_instances(**kwargs) - ex.exception.response["Error"]["Code"].should.equal("MissingParameter") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("MissingParameter") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "The request must contain the parameter ebs" ) @@ -1331,12 +1328,12 @@ def test_run_instance_with_block_device_mappings_missing_size(): {"DeviceName": "/dev/sda2", "Ebs": {"VolumeType": "standard"}} ], } - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: ec2_client.run_instances(**kwargs) - ex.exception.response["Error"]["Code"].should.equal("MissingParameter") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("MissingParameter") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "The request must contain the parameter size or snapshotId" ) @@ -1410,11 +1407,11 @@ def test_describe_instance_status_with_instance_filter_deprecated(): all_status[0].id.should.equal(instance.id) # Call get_all_instance_status with a bad id should raise an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_instance_status(instance_ids=[instance.id, "i-1234abcd"]) - cm.exception.code.should.equal("InvalidInstanceID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidInstanceID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 @@ -1537,13 +1534,13 @@ def test_get_instance_by_security_group(): security_group = conn.create_security_group("test", "test") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.modify_instance_attribute( instance.id, "groupSet", [security_group.id], dry_run=True ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set" ) @@ -1661,13 +1658,13 @@ def test_describe_instance_attribute(): ] for invalid_instance_attribute in invalid_instance_attributes: - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.describe_instance_attribute( InstanceId=instance_id, Attribute=invalid_instance_attribute ) - ex.exception.response["Error"]["Code"].should.equal("InvalidParameterValue") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Code"].should.equal("InvalidParameterValue") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) message = "Value ({invalid_instance_attribute}) for parameter attribute is invalid. Unknown attribute.".format( invalid_instance_attribute=invalid_instance_attribute ) - ex.exception.response["Error"]["Message"].should.equal(message) + ex.value.response["Error"]["Message"].should.equal(message) diff --git a/tests/test_ec2/test_internet_gateways.py b/tests/test_ec2/test_internet_gateways.py index 2319bf062..49cc6e38c 100644 --- a/tests/test_ec2/test_internet_gateways.py +++ b/tests/test_ec2/test_internet_gateways.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import re @@ -28,11 +27,11 @@ def test_igw_create(): conn.get_all_internet_gateways().should.have.length_of(0) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: igw = conn.create_internet_gateway(dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateInternetGateway operation: Request would have succeeded, but DryRun flag is set" ) @@ -51,11 +50,11 @@ def test_igw_attach(): igw = conn.create_internet_gateway() vpc = conn.create_vpc(VPC_CIDR) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.attach_internet_gateway(igw.id, vpc.id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the AttachInternetGateway operation: Request would have succeeded, but DryRun flag is set" ) @@ -71,11 +70,11 @@ def test_igw_attach_bad_vpc(): conn = boto.connect_vpc("the_key", "the_secret") igw = conn.create_internet_gateway() - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.attach_internet_gateway(igw.id, BAD_VPC) - cm.exception.code.should.equal("InvalidVpcID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVpcID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -87,11 +86,11 @@ def test_igw_attach_twice(): vpc2 = conn.create_vpc(VPC_CIDR) conn.attach_internet_gateway(igw.id, vpc1.id) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.attach_internet_gateway(igw.id, vpc2.id) - cm.exception.code.should.equal("Resource.AlreadyAssociated") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("Resource.AlreadyAssociated") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -102,11 +101,11 @@ def test_igw_detach(): vpc = conn.create_vpc(VPC_CIDR) conn.attach_internet_gateway(igw.id, vpc.id) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.detach_internet_gateway(igw.id, vpc.id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DetachInternetGateway operation: Request would have succeeded, but DryRun flag is set" ) @@ -124,11 +123,11 @@ def test_igw_detach_wrong_vpc(): vpc2 = conn.create_vpc(VPC_CIDR) conn.attach_internet_gateway(igw.id, vpc1.id) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.detach_internet_gateway(igw.id, vpc2.id) - cm.exception.code.should.equal("Gateway.NotAttached") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("Gateway.NotAttached") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -139,11 +138,11 @@ def test_igw_detach_invalid_vpc(): vpc = conn.create_vpc(VPC_CIDR) conn.attach_internet_gateway(igw.id, vpc.id) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.detach_internet_gateway(igw.id, BAD_VPC) - cm.exception.code.should.equal("Gateway.NotAttached") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("Gateway.NotAttached") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -153,11 +152,11 @@ def test_igw_detach_unattached(): igw = conn.create_internet_gateway() vpc = conn.create_vpc(VPC_CIDR) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.detach_internet_gateway(igw.id, vpc.id) - cm.exception.code.should.equal("Gateway.NotAttached") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("Gateway.NotAttached") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -169,11 +168,11 @@ def test_igw_delete(): igw = conn.create_internet_gateway() conn.get_all_internet_gateways().should.have.length_of(1) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.delete_internet_gateway(igw.id, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeleteInternetGateway operation: Request would have succeeded, but DryRun flag is set" ) @@ -189,11 +188,11 @@ def test_igw_delete_attached(): vpc = conn.create_vpc(VPC_CIDR) conn.attach_internet_gateway(igw.id, vpc.id) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_internet_gateway(igw.id) - cm.exception.code.should.equal("DependencyViolation") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("DependencyViolation") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -209,11 +208,11 @@ def test_igw_desribe(): def test_igw_describe_bad_id(): """ internet gateway fail to fetch by bad id """ conn = boto.connect_vpc("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_internet_gateways([BAD_IGW]) - cm.exception.code.should.equal("InvalidInternetGatewayID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidInternetGatewayID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated diff --git a/tests/test_ec2/test_key_pairs.py b/tests/test_ec2/test_key_pairs.py index 09982ac7a..dcca8b116 100644 --- a/tests/test_ec2/test_key_pairs.py +++ b/tests/test_ec2/test_key_pairs.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto import sure # noqa @@ -56,22 +55,22 @@ def test_key_pairs_empty(): def test_key_pairs_invalid_id(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_key_pairs("foo") - cm.exception.code.should.equal("InvalidKeyPair.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidKeyPair.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated def test_key_pairs_create(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.create_key_pair("foo", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateKeyPair operation: Request would have succeeded, but DryRun flag is set" ) @@ -110,11 +109,11 @@ def test_key_pairs_create_exist(): conn.create_key_pair("foo") assert len(conn.get_all_key_pairs()) == 1 - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_key_pair("foo") - cm.exception.code.should.equal("InvalidKeyPair.Duplicate") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidKeyPair.Duplicate") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -130,11 +129,11 @@ def test_key_pairs_delete_exist(): conn = boto.connect_ec2("the_key", "the_secret") conn.create_key_pair("foo") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: r = conn.delete_key_pair("foo", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set" ) @@ -147,11 +146,11 @@ def test_key_pairs_delete_exist(): def test_key_pairs_import(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.import_key_pair("foo", RSA_PUBLIC_KEY_OPENSSH, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the ImportKeyPair operation: Request would have succeeded, but DryRun flag is set" ) @@ -176,34 +175,34 @@ def test_key_pairs_import_exist(): assert kp.name == "foo" assert len(conn.get_all_key_pairs()) == 1 - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_key_pair("foo") - cm.exception.code.should.equal("InvalidKeyPair.Duplicate") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidKeyPair.Duplicate") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated def test_key_pairs_invalid(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.import_key_pair("foo", b"") - ex.exception.error_code.should.equal("InvalidKeyPair.Format") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal("Key is not in valid OpenSSH public key format") + ex.value.error_code.should.equal("InvalidKeyPair.Format") + ex.value.status.should.equal(400) + ex.value.message.should.equal("Key is not in valid OpenSSH public key format") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.import_key_pair("foo", b"garbage") - ex.exception.error_code.should.equal("InvalidKeyPair.Format") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal("Key is not in valid OpenSSH public key format") + ex.value.error_code.should.equal("InvalidKeyPair.Format") + ex.value.status.should.equal(400) + ex.value.message.should.equal("Key is not in valid OpenSSH public key format") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.import_key_pair("foo", DSA_PUBLIC_KEY_OPENSSH) - ex.exception.error_code.should.equal("InvalidKeyPair.Format") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal("Key is not in valid OpenSSH public key format") + ex.value.error_code.should.equal("InvalidKeyPair.Format") + ex.value.status.should.equal(400) + ex.value.message.should.equal("Key is not in valid OpenSSH public key format") @mock_ec2_deprecated diff --git a/tests/test_ec2/test_launch_templates.py b/tests/test_ec2/test_launch_templates.py index 4c37818d1..41896be96 100644 --- a/tests/test_ec2/test_launch_templates.py +++ b/tests/test_ec2/test_launch_templates.py @@ -1,7 +1,7 @@ import boto3 import sure # noqa -from nose.tools import assert_raises +import pytest from botocore.client import ClientError from moto import mock_ec2 @@ -30,7 +30,7 @@ def test_launch_template_create(): lt["DefaultVersionNumber"].should.equal(1) lt["LatestVersionNumber"].should.equal(1) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: cli.create_launch_template( LaunchTemplateName="test-template", LaunchTemplateData={ @@ -43,7 +43,7 @@ def test_launch_template_create(): }, ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidLaunchTemplateName.AlreadyExistsException) when calling the CreateLaunchTemplate operation: Launch template name already in use." ) diff --git a/tests/test_ec2/test_network_acls.py b/tests/test_ec2/test_network_acls.py index c20bf75c6..c2a790ed7 100644 --- a/tests/test_ec2/test_network_acls.py +++ b/tests/test_ec2/test_network_acls.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import boto import boto3 import sure # noqa -from nose.tools import assert_raises +import pytest from botocore.exceptions import ClientError from moto import mock_ec2_deprecated, mock_ec2 @@ -261,7 +261,7 @@ def test_duplicate_network_acl_entry(): RuleNumber=rule_number, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: default_network_acl.create_entry( CidrBlock="10.0.0.0/0", Egress=egress, @@ -269,7 +269,7 @@ def test_duplicate_network_acl_entry(): RuleAction="deny", RuleNumber=rule_number, ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (NetworkAclEntryAlreadyExists) when calling the CreateNetworkAclEntry " "operation: The network acl entry identified by {} already exists.".format( rule_number @@ -297,10 +297,10 @@ def test_describe_network_acls(): resp2 = conn.describe_network_acls()["NetworkAcls"] resp2.should.have.length_of(3) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.describe_network_acls(NetworkAclIds=["1"]) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidRouteTableID.NotFound) when calling the " "DescribeNetworkAcls operation: The routeTable ID '1' does not exist" ) diff --git a/tests/test_ec2/test_route_tables.py b/tests/test_ec2/test_route_tables.py index a652bd1cf..889515962 100644 --- a/tests/test_ec2/test_route_tables.py +++ b/tests/test_ec2/test_route_tables.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto import boto3 @@ -61,22 +60,22 @@ def test_route_tables_additional(): local_route.state.should.equal("active") local_route.destination_cidr_block.should.equal(vpc.cidr_block) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_vpc(vpc.id) - cm.exception.code.should.equal("DependencyViolation") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("DependencyViolation") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none conn.delete_route_table(route_table.id) all_route_tables = conn.get_all_route_tables(filters={"vpc-id": vpc.id}) all_route_tables.should.have.length_of(1) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_route_table("rtb-1234abcd") - cm.exception.code.should.equal("InvalidRouteTableID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidRouteTableID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -197,11 +196,11 @@ def test_route_table_associations(): association_id_idempotent.should.equal(association_id) # Error: Attempt delete associated route table. - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_route_table(route_table.id) - cm.exception.code.should.equal("DependencyViolation") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("DependencyViolation") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Disassociate conn.disassociate_route_table(association_id) @@ -211,33 +210,33 @@ def test_route_table_associations(): route_table.associations.should.have.length_of(0) # Error: Disassociate with invalid association ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.disassociate_route_table(association_id) - cm.exception.code.should.equal("InvalidAssociationID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAssociationID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Associate with invalid subnet ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_route_table(route_table.id, "subnet-1234abcd") - cm.exception.code.should.equal("InvalidSubnetID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSubnetID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Associate with invalid route table ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.associate_route_table("rtb-1234abcd", subnet.id) - cm.exception.code.should.equal("InvalidRouteTableID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidRouteTableID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @requires_boto_gte("2.16.0") @mock_ec2_deprecated def test_route_table_replace_route_table_association(): """ - Note: Boto has deprecated replace_route_table_association (which returns status) - and now uses replace_route_table_association_with_assoc (which returns association ID). + Note: Boto has deprecated replace_route_table_association (which returns status) + and now uses replace_route_table_association_with_assoc (which returns association ID). """ conn = boto.connect_vpc("the_key", "the_secret") vpc = conn.create_vpc("10.0.0.0/16") @@ -293,20 +292,20 @@ def test_route_table_replace_route_table_association(): association_id_idempotent.should.equal(association_id2) # Error: Replace association with invalid association ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.replace_route_table_association_with_assoc( "rtbassoc-1234abcd", route_table1.id ) - cm.exception.code.should.equal("InvalidAssociationID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidAssociationID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Error: Replace association with invalid route table ID - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.replace_route_table_association_with_assoc(association_id2, "rtb-1234abcd") - cm.exception.code.should.equal("InvalidRouteTableID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidRouteTableID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -389,11 +388,11 @@ def test_routes_additional(): ] new_routes.should.have.length_of(0) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_route(main_route_table.id, ROUTE_CIDR) - cm.exception.code.should.equal("InvalidRoute.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidRoute.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -442,11 +441,11 @@ def test_routes_replace(): target_route.state.should.equal("active") target_route.destination_cidr_block.should.equal(ROUTE_CIDR) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.replace_route("rtb-1234abcd", ROUTE_CIDR, gateway_id=igw.id) - cm.exception.code.should.equal("InvalidRouteTableID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidRouteTableID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @requires_boto_gte("2.19.0") @@ -571,11 +570,11 @@ def test_create_route_with_invalid_destination_cidr_block_parameter(): internet_gateway.reload() destination_cidr_block = "1000.1.0.0/20" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: route = route_table.create_route( DestinationCidrBlock=destination_cidr_block, GatewayId=internet_gateway.id ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidParameterValue) when calling the CreateRoute " "operation: Value ({}) for parameter destinationCidrBlock is invalid. This is not a valid CIDR block.".format( destination_cidr_block diff --git a/tests/test_ec2/test_security_groups.py b/tests/test_ec2/test_security_groups.py index 10885df18..7ce9f3c5c 100644 --- a/tests/test_ec2/test_security_groups.py +++ b/tests/test_ec2/test_security_groups.py @@ -3,9 +3,8 @@ from __future__ import unicode_literals import copy import json -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises # noqa -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest import boto3 import boto @@ -20,13 +19,13 @@ from moto import mock_ec2, mock_ec2_deprecated def test_create_and_describe_security_group(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: security_group = conn.create_security_group( "test security group", "this is a test security group", dry_run=True ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set" ) @@ -38,13 +37,13 @@ def test_create_and_describe_security_group(): security_group.description.should.equal("this is a test security group") # Trying to create another group with the same name should throw an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_security_group( "test security group", "this is a test security group" ) - cm.exception.code.should.equal("InvalidGroup.Duplicate") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidGroup.Duplicate") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none all_groups = conn.get_all_security_groups() # The default group gets created automatically @@ -57,11 +56,11 @@ def test_create_and_describe_security_group(): def test_create_security_group_without_description_raises_error(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_security_group("test security group", "") - cm.exception.code.should.equal("MissingParameter") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("MissingParameter") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -87,13 +86,13 @@ def test_create_and_describe_vpc_security_group(): # Trying to create another group with the same name in the same VPC should # throw an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_security_group( "test security group", "this is a test security group", vpc_id ) - cm.exception.code.should.equal("InvalidGroup.Duplicate") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidGroup.Duplicate") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none all_groups = conn.get_all_security_groups(filters={"vpc_id": [vpc_id]}) @@ -146,18 +145,18 @@ def test_deleting_security_groups(): conn.get_all_security_groups().should.have.length_of(4) # Deleting a group that doesn't exist should throw an error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_security_group("foobar") - cm.exception.code.should.equal("InvalidGroup.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidGroup.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Delete by name - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.delete_security_group("test2", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set" ) @@ -184,7 +183,7 @@ def test_authorize_ip_range_and_revoke(): conn = boto.connect_ec2("the_key", "the_secret") security_group = conn.create_security_group("test", "test") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: success = security_group.authorize( ip_protocol="tcp", from_port="22", @@ -192,9 +191,9 @@ def test_authorize_ip_range_and_revoke(): cidr_ip="123.123.123.123/32", dry_run=True, ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the GrantSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set" ) @@ -208,19 +207,19 @@ def test_authorize_ip_range_and_revoke(): security_group.rules[0].grants[0].cidr_ip.should.equal("123.123.123.123/32") # Wrong Cidr should throw error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: security_group.revoke( ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.122/32", ) - cm.exception.code.should.equal("InvalidPermission.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidPermission.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Actually revoke - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: security_group.revoke( ip_protocol="tcp", from_port="22", @@ -228,9 +227,9 @@ def test_authorize_ip_range_and_revoke(): cidr_ip="123.123.123.123/32", dry_run=True, ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the RevokeSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set" ) @@ -246,7 +245,7 @@ def test_authorize_ip_range_and_revoke(): "testegress", "testegress", vpc_id="vpc-3432589" ) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: success = conn.authorize_security_group_egress( egress_security_group.id, "tcp", @@ -255,9 +254,9 @@ def test_authorize_ip_range_and_revoke(): cidr_ip="123.123.123.123/32", dry_run=True, ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the GrantSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set" ) @@ -285,7 +284,7 @@ def test_authorize_ip_range_and_revoke(): ).should.throw(EC2ResponseError) # Actually revoke - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.revoke_security_group_egress( egress_security_group.id, "tcp", @@ -294,9 +293,9 @@ def test_authorize_ip_range_and_revoke(): cidr_ip="123.123.123.123/32", dry_run=True, ) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the RevokeSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set" ) @@ -335,13 +334,13 @@ def test_authorize_other_group_and_revoke(): security_group.rules[0].grants[0].group_id.should.equal(other_security_group.id) # Wrong source group should throw error - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: security_group.revoke( ip_protocol="tcp", from_port="22", to_port="2222", src_group=wrong_group ) - cm.exception.code.should.equal("InvalidPermission.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidPermission.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none # Actually revoke security_group.revoke( @@ -440,11 +439,11 @@ def test_get_all_security_groups(): resp.should.have.length_of(1) resp[0].id.should.equal(sg1.id) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_security_groups(groupnames=["does_not_exist"]) - cm.exception.code.should.equal("InvalidGroup.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidGroup.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none resp.should.have.length_of(1) resp[0].id.should.equal(sg1.id) @@ -469,13 +468,13 @@ def test_get_all_security_groups(): def test_authorize_bad_cidr_throws_invalid_parameter_value(): conn = boto.connect_ec2("the_key", "the_secret") security_group = conn.create_security_group("test", "test") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: security_group.authorize( ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123" ) - cm.exception.code.should.equal("InvalidParameterValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidParameterValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -485,11 +484,11 @@ def test_security_group_tagging(): sg = conn.create_security_group("test-sg", "Test SG", vpc.id) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: sg.add_tag("Test", "Tag", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) @@ -534,13 +533,13 @@ def test_sec_group_rule_limit(): other_sg = ec2_conn.create_security_group("test_2", "test_other") # INGRESS - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group( group_id=sg.id, ip_protocol="-1", cidr_ip=["{0}.0.0.0/0".format(i) for i in range(110)], ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") sg.rules.should.be.empty # authorize a rule targeting a different sec group (because this count too) @@ -556,17 +555,17 @@ def test_sec_group_rule_limit(): ) success.should.be.true # verify that we cannot authorize past the limit for a CIDR IP - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group( group_id=sg.id, ip_protocol="-1", cidr_ip=["100.0.0.0/0"] ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") # verify that we cannot authorize past the limit for a different sec group - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group( group_id=sg.id, ip_protocol="-1", src_security_group_group_id=other_sg.id ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") # EGRESS # authorize a rule targeting a different sec group (because this count too) @@ -581,17 +580,17 @@ def test_sec_group_rule_limit(): group_id=sg.id, ip_protocol="-1", cidr_ip="{0}.0.0.0/0".format(i) ) # verify that we cannot authorize past the limit for a CIDR IP - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group_egress( group_id=sg.id, ip_protocol="-1", cidr_ip="101.0.0.0/0" ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") # verify that we cannot authorize past the limit for a different sec group - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group_egress( group_id=sg.id, ip_protocol="-1", src_group_id=other_sg.id ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") @mock_ec2_deprecated @@ -605,13 +604,13 @@ def test_sec_group_rule_limit_vpc(): other_sg = ec2_conn.create_security_group("test_2", "test", vpc_id=vpc.id) # INGRESS - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group( group_id=sg.id, ip_protocol="-1", cidr_ip=["{0}.0.0.0/0".format(i) for i in range(110)], ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") sg.rules.should.be.empty # authorize a rule targeting a different sec group (because this count too) @@ -627,17 +626,17 @@ def test_sec_group_rule_limit_vpc(): ) # verify that we cannot authorize past the limit for a CIDR IP success.should.be.true - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group( group_id=sg.id, ip_protocol="-1", cidr_ip=["100.0.0.0/0"] ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") # verify that we cannot authorize past the limit for a different sec group - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group( group_id=sg.id, ip_protocol="-1", src_security_group_group_id=other_sg.id ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") # EGRESS # authorize a rule targeting a different sec group (because this count too) @@ -652,17 +651,17 @@ def test_sec_group_rule_limit_vpc(): group_id=sg.id, ip_protocol="-1", cidr_ip="{0}.0.0.0/0".format(i) ) # verify that we cannot authorize past the limit for a CIDR IP - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group_egress( group_id=sg.id, ip_protocol="-1", cidr_ip="50.0.0.0/0" ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") # verify that we cannot authorize past the limit for a different sec group - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: ec2_conn.authorize_security_group_egress( group_id=sg.id, ip_protocol="-1", src_group_id=other_sg.id ) - cm.exception.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") + cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") """ @@ -689,7 +688,7 @@ def test_add_same_rule_twice_throws_error(): ] sg.authorize_ingress(IpPermissions=ip_permissions) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: sg.authorize_ingress(IpPermissions=ip_permissions) @@ -761,15 +760,15 @@ def test_security_group_tagging_boto3(): sg = conn.create_security_group(GroupName="test-sg", Description="Test SG") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_tags( Resources=[sg["GroupId"]], Tags=[{"Key": "Test", "Value": "Tag"}], DryRun=True, ) - ex.exception.response["Error"]["Code"].should.equal("DryRunOperation") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("DryRunOperation") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) @@ -926,11 +925,11 @@ def test_get_all_security_groups_filter_with_same_vpc_id(): ) security_groups.should.have.length_of(1) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_security_groups(group_ids=["does_not_exist"]) - cm.exception.code.should.equal("InvalidGroup.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidGroup.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 diff --git a/tests/test_ec2/test_spot_instances.py b/tests/test_ec2/test_spot_instances.py index 5eb5a6e48..bb4ccac3b 100644 --- a/tests/test_ec2/test_spot_instances.py +++ b/tests/test_ec2/test_spot_instances.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from nose.tools import assert_raises +import pytest import datetime import boto @@ -31,7 +31,7 @@ def test_request_spot_instances(): start = iso_8601_datetime_with_milliseconds(start_dt) end = iso_8601_datetime_with_milliseconds(end_dt) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: request = conn.request_spot_instances( SpotPrice="0.5", InstanceCount=1, @@ -54,9 +54,9 @@ def test_request_spot_instances(): }, DryRun=True, ) - ex.exception.response["Error"]["Code"].should.equal("DryRunOperation") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("DryRunOperation") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal( "An error occurred (DryRunOperation) when calling the RequestSpotInstance operation: Request would have succeeded, but DryRun flag is set" ) @@ -155,11 +155,11 @@ def test_cancel_spot_instance_request(): requests = conn.get_all_spot_instance_requests() requests.should.have.length_of(1) - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.cancel_spot_instance_requests([requests[0].id], dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CancelSpotInstance operation: Request would have succeeded, but DryRun flag is set" ) diff --git a/tests/test_ec2/test_subnets.py b/tests/test_ec2/test_subnets.py index 416235f43..246cacf6b 100644 --- a/tests/test_ec2/test_subnets.py +++ b/tests/test_ec2/test_subnets.py @@ -1,17 +1,16 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises # noqa -from nose.tools import assert_raises - -import boto3 -import boto -import boto.vpc -from boto.exception import EC2ResponseError -from botocore.exceptions import ParamValidationError, ClientError -import sure # noqa import random +import boto +import boto3 +import boto.vpc + +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest +import sure # noqa +from boto.exception import EC2ResponseError +from botocore.exceptions import ClientError, ParamValidationError from moto import mock_ec2, mock_ec2_deprecated @@ -30,22 +29,22 @@ def test_subnets(): all_subnets = conn.get_all_subnets() all_subnets.should.have.length_of(0 + len(ec2.get_all_zones())) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_subnet(subnet.id) - cm.exception.code.should.equal("InvalidSubnetID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSubnetID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated def test_subnet_create_vpc_validation(): conn = boto.connect_vpc("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_subnet("vpc-abcd1234", "10.0.0.0/18") - cm.exception.code.should.equal("InvalidVpcID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVpcID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -202,7 +201,7 @@ def test_modify_subnet_attribute_validation(): VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a" ) - with assert_raises(ParamValidationError): + with pytest.raises(ParamValidationError): client.modify_subnet_attribute( SubnetId=subnet.id, MapPublicIpOnLaunch={"Value": "invalid"} ) @@ -228,11 +227,11 @@ def test_subnet_get_by_id(): subnetA.id.should.be.within(subnets_by_id) subnetB1.id.should.be.within(subnets_by_id) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_subnets(subnet_ids=["subnet-does_not_exist"]) - cm.exception.code.should.equal("InvalidSubnetID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidSubnetID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -386,13 +385,13 @@ def test_create_subnet_with_invalid_availability_zone(): vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") subnet_availability_zone = "asfasfas" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: subnet = client.create_subnet( VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone=subnet_availability_zone, ) - assert str(ex.exception).startswith( + assert str(ex.value).startswith( "An error occurred (InvalidParameterValue) when calling the CreateSubnet " "operation: Value ({}) for parameter availabilityZone is invalid. Subnets can currently only be created in the following availability zones: ".format( subnet_availability_zone @@ -409,9 +408,9 @@ def test_create_subnet_with_invalid_cidr_range(): vpc.is_default.shouldnt.be.ok subnet_cidr_block = "10.1.0.0/20" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock=subnet_cidr_block) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidSubnet.Range) when calling the CreateSubnet " "operation: The CIDR '{}' is invalid.".format(subnet_cidr_block) ) @@ -427,9 +426,9 @@ def test_create_subnet_with_invalid_cidr_range_multiple_vpc_cidr_blocks(): vpc.is_default.shouldnt.be.ok subnet_cidr_block = "10.2.0.0/20" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock=subnet_cidr_block) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidSubnet.Range) when calling the CreateSubnet " "operation: The CIDR '{}' is invalid.".format(subnet_cidr_block) ) @@ -444,9 +443,9 @@ def test_create_subnet_with_invalid_cidr_block_parameter(): vpc.is_default.shouldnt.be.ok subnet_cidr_block = "1000.1.0.0/20" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock=subnet_cidr_block) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidParameterValue) when calling the CreateSubnet " "operation: Value ({}) for parameter cidrBlock is invalid. This is not a valid CIDR block.".format( subnet_cidr_block @@ -503,10 +502,10 @@ def test_create_subnets_with_overlapping_cidr_blocks(): vpc.is_default.shouldnt.be.ok subnet_cidr_block = "10.0.0.0/24" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: subnet1 = ec2.create_subnet(VpcId=vpc.id, CidrBlock=subnet_cidr_block) subnet2 = ec2.create_subnet(VpcId=vpc.id, CidrBlock=subnet_cidr_block) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidSubnet.Conflict) when calling the CreateSubnet " "operation: The CIDR '{}' conflicts with another subnet".format( subnet_cidr_block diff --git a/tests/test_ec2/test_tags.py b/tests/test_ec2/test_tags.py index 8480f8bc0..82a23c91c 100644 --- a/tests/test_ec2/test_tags.py +++ b/tests/test_ec2/test_tags.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from nose.tools import assert_raises +import pytest import itertools @@ -11,7 +11,7 @@ from boto.ec2.instance import Reservation import sure # noqa from moto import mock_ec2_deprecated, mock_ec2 -from nose.tools import assert_raises +import pytest @mock_ec2_deprecated @@ -20,11 +20,11 @@ def test_add_tag(): reservation = conn.run_instances("ami-1234abcd") instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.add_tag("a key", "some value", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) @@ -51,11 +51,11 @@ def test_remove_tag(): tag.name.should.equal("a key") tag.value.should.equal("some value") - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: instance.remove_tag("a key", dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set" ) @@ -106,11 +106,11 @@ def test_create_tags(): "blank key": "", } - with assert_raises(EC2ResponseError) as ex: + with pytest.raises(EC2ResponseError) as ex: conn.create_tags(instance.id, tag_dict, dry_run=True) - ex.exception.error_code.should.equal("DryRunOperation") - ex.exception.status.should.equal(400) - ex.exception.message.should.equal( + ex.value.error_code.should.equal("DryRunOperation") + ex.value.status.should.equal(400) + ex.value.message.should.equal( "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" ) @@ -131,18 +131,18 @@ def test_tag_limit_exceeded(): for i in range(51): tag_dict["{0:02d}".format(i + 1)] = "" - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_tags(instance.id, tag_dict) - cm.exception.code.should.equal("TagLimitExceeded") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("TagLimitExceeded") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none instance.add_tag("a key", "a value") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_tags(instance.id, tag_dict) - cm.exception.code.should.equal("TagLimitExceeded") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("TagLimitExceeded") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none tags = conn.get_all_tags() tag = tags[0] @@ -157,27 +157,27 @@ def test_invalid_parameter_tag_null(): reservation = conn.run_instances("ami-1234abcd") instance = reservation.instances[0] - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: instance.add_tag("a key", None) - cm.exception.code.should.equal("InvalidParameterValue") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidParameterValue") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated def test_invalid_id(): conn = boto.connect_ec2("the_key", "the_secret") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_tags("ami-blah", {"key": "tag"}) - cm.exception.code.should.equal("InvalidID") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidID") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.create_tags("blah-blah", {"key": "tag"}) - cm.exception.code.should.equal("InvalidID") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidID") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -449,10 +449,10 @@ def test_create_tag_empty_resource(): # create ec2 client in us-west-1 client = boto3.client("ec2", region_name="us-west-1") # create tag with empty resource - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.create_tags(Resources=[], Tags=[{"Key": "Value"}]) - ex.exception.response["Error"]["Code"].should.equal("MissingParameter") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("MissingParameter") + ex.value.response["Error"]["Message"].should.equal( "The request must contain the parameter resourceIdSet" ) @@ -462,10 +462,10 @@ def test_delete_tag_empty_resource(): # create ec2 client in us-west-1 client = boto3.client("ec2", region_name="us-west-1") # delete tag with empty resource - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.delete_tags(Resources=[], Tags=[{"Key": "Value"}]) - ex.exception.response["Error"]["Code"].should.equal("MissingParameter") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("MissingParameter") + ex.value.response["Error"]["Message"].should.equal( "The request must contain the parameter resourceIdSet" ) diff --git a/tests/test_ec2/test_vpc_peering.py b/tests/test_ec2/test_vpc_peering.py index b535518de..2ffe89fca 100644 --- a/tests/test_ec2/test_vpc_peering.py +++ b/tests/test_ec2/test_vpc_peering.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest from moto.ec2.exceptions import EC2ClientError from botocore.exceptions import ClientError @@ -49,11 +48,11 @@ def test_vpc_peering_connections_accept(): vpc_pcx = conn.accept_vpc_peering_connection(vpc_pcx.id) vpc_pcx._status.code.should.equal("active") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.reject_vpc_peering_connection(vpc_pcx.id) - cm.exception.code.should.equal("InvalidStateTransition") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidStateTransition") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none all_vpc_pcxs = conn.get_all_vpc_peering_connections() all_vpc_pcxs.should.have.length_of(1) @@ -69,11 +68,11 @@ def test_vpc_peering_connections_reject(): verdict = conn.reject_vpc_peering_connection(vpc_pcx.id) verdict.should.equal(True) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.accept_vpc_peering_connection(vpc_pcx.id) - cm.exception.code.should.equal("InvalidStateTransition") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidStateTransition") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none all_vpc_pcxs = conn.get_all_vpc_peering_connections() all_vpc_pcxs.should.have.length_of(1) @@ -93,11 +92,11 @@ def test_vpc_peering_connections_delete(): all_vpc_pcxs.should.have.length_of(1) all_vpc_pcxs[0]._status.code.should.equal("deleted") - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_vpc_peering_connection("pcx-1234abcd") - cm.exception.code.should.equal("InvalidVpcPeeringConnectionId.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVpcPeeringConnectionId.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2 @@ -129,11 +128,11 @@ def test_vpc_peering_connections_cross_region_fail(): ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1") vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16") # create peering wrong region with no vpc - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_usw1.create_vpc_peering_connection( VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-2" ) - cm.exception.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound") + cm.value.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound") @mock_ec2 @@ -253,15 +252,15 @@ def test_vpc_peering_connections_cross_region_accept_wrong_region(): # accept wrong peering from us-west-1 which will raise error ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1") ec2_usw1 = boto3.client("ec2", region_name="us-west-1") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_usw1.accept_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_usw1.id) - cm.exception.response["Error"]["Code"].should.equal("OperationNotPermitted") + cm.value.response["Error"]["Code"].should.equal("OperationNotPermitted") exp_msg = ( "Incorrect region ({0}) specified for this request.VPC " "peering connection {1} must be " "accepted in region {2}".format("us-west-1", vpc_pcx_usw1.id, "ap-northeast-1") ) - cm.exception.response["Error"]["Message"].should.equal(exp_msg) + cm.value.response["Error"]["Message"].should.equal(exp_msg) @mock_ec2 @@ -278,12 +277,12 @@ def test_vpc_peering_connections_cross_region_reject_wrong_region(): # reject wrong peering from us-west-1 which will raise error ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1") ec2_usw1 = boto3.client("ec2", region_name="us-west-1") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: ec2_usw1.reject_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_usw1.id) - cm.exception.response["Error"]["Code"].should.equal("OperationNotPermitted") + cm.value.response["Error"]["Code"].should.equal("OperationNotPermitted") exp_msg = ( "Incorrect region ({0}) specified for this request.VPC " "peering connection {1} must be accepted or " "rejected in region {2}".format("us-west-1", vpc_pcx_usw1.id, "ap-northeast-1") ) - cm.exception.response["Error"]["Message"].should.equal(exp_msg) + cm.value.response["Error"]["Message"].should.equal(exp_msg) diff --git a/tests/test_ec2/test_vpcs.py b/tests/test_ec2/test_vpcs.py index 8ad85072c..5344098ba 100644 --- a/tests/test_ec2/test_vpcs.py +++ b/tests/test_ec2/test_vpcs.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises # noqa -from nose.tools import assert_raises +# Ensure 'pytest.raises' context manager support for Python 2.6 +import pytest from moto.ec2.exceptions import EC2ClientError from botocore.exceptions import ClientError @@ -31,11 +30,11 @@ def test_vpcs(): all_vpcs = conn.get_all_vpcs() all_vpcs.should.have.length_of(1) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.delete_vpc("vpc-1234abcd") - cm.exception.code.should.equal("InvalidVpcID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVpcID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -114,11 +113,11 @@ def test_vpc_get_by_id(): vpc1.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids) - with assert_raises(EC2ResponseError) as cm: + with pytest.raises(EC2ResponseError) as cm: conn.get_all_vpcs(vpc_ids=["vpc-does_not_exist"]) - cm.exception.code.should.equal("InvalidVpcID.NotFound") - cm.exception.status.should.equal(400) - cm.exception.request_id.should_not.be.none + cm.value.code.should.equal("InvalidVpcID.NotFound") + cm.value.status.should.equal(400) + cm.value.request_id.should_not.be.none @mock_ec2_deprecated @@ -402,11 +401,11 @@ def test_associate_vpc_ipv4_cidr_block(): ) # Check error on adding 6th association. - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: response = ec2.meta.client.associate_vpc_cidr_block( VpcId=vpc.id, CidrBlock="10.10.50.0/22" ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (CidrLimitExceeded) when calling the AssociateVpcCidrBlock " "operation: This network '{}' has met its maximum number of allowed CIDRs: 5".format( vpc.id @@ -447,11 +446,11 @@ def test_disassociate_vpc_ipv4_cidr_block(): ) # Error attempting to delete a non-existent CIDR_BLOCK association - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: response = ec2.meta.client.disassociate_vpc_cidr_block( AssociationId="vpc-cidr-assoc-BORING123" ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidVpcCidrBlockAssociationIdError.NotFound) when calling the " "DisassociateVpcCidrBlock operation: The vpc CIDR block association ID " "'vpc-cidr-assoc-BORING123' does not exist" @@ -469,11 +468,11 @@ def test_disassociate_vpc_ipv4_cidr_block(): {}, )["AssociationId"] - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: response = ec2.meta.client.disassociate_vpc_cidr_block( AssociationId=vpc_base_cidr_assoc_id ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (OperationNotPermitted) when calling the DisassociateVpcCidrBlock operation: " "The vpc CIDR block with association ID {} may not be disassociated. It is the primary " "IPv4 CIDR block of the VPC".format(vpc_base_cidr_assoc_id) @@ -549,11 +548,11 @@ def test_vpc_associate_ipv6_cidr_block(): ipv6_cidr_block_association_set["AssociationId"].should.contain("vpc-cidr-assoc") # Test Fail on adding 2nd IPV6 association - AWS only allows 1 at this time! - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: response = ec2.meta.client.associate_vpc_cidr_block( VpcId=vpc.id, AmazonProvidedIpv6CidrBlock=True ) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (CidrLimitExceeded) when calling the AssociateVpcCidrBlock " "operation: This network '{}' has met its maximum number of allowed CIDRs: 1".format( vpc.id @@ -657,9 +656,9 @@ def test_create_vpc_with_invalid_cidr_block_parameter(): ec2 = boto3.resource("ec2", region_name="us-west-1") vpc_cidr_block = "1000.1.0.0/20" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: vpc = ec2.create_vpc(CidrBlock=vpc_cidr_block) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidParameterValue) when calling the CreateVpc " "operation: Value ({}) for parameter cidrBlock is invalid. This is not a valid CIDR block.".format( vpc_cidr_block @@ -672,9 +671,9 @@ def test_create_vpc_with_invalid_cidr_range(): ec2 = boto3.resource("ec2", region_name="us-west-1") vpc_cidr_block = "10.1.0.0/29" - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: vpc = ec2.create_vpc(CidrBlock=vpc_cidr_block) - str(ex.exception).should.equal( + str(ex.value).should.equal( "An error occurred (InvalidVpc.Range) when calling the CreateVpc " "operation: The CIDR '{}' is invalid.".format(vpc_cidr_block) ) diff --git a/tests/test_ec2/test_vpn_connections.py b/tests/test_ec2/test_vpn_connections.py index 4360c8b2e..ca8897417 100644 --- a/tests/test_ec2/test_vpn_connections.py +++ b/tests/test_ec2/test_vpn_connections.py @@ -1,11 +1,11 @@ from __future__ import unicode_literals + import boto import boto3 -from nose.tools import assert_raises +import pytest import sure # noqa from boto.exception import EC2ResponseError - -from moto import mock_ec2_deprecated, mock_ec2 +from moto import mock_ec2, mock_ec2_deprecated @mock_ec2_deprecated @@ -35,7 +35,7 @@ def test_delete_vpn_connections(): @mock_ec2_deprecated def test_delete_vpn_connections_bad_id(): conn = boto.connect_vpc("the_key", "the_secret") - with assert_raises(EC2ResponseError): + with pytest.raises(EC2ResponseError): conn.delete_vpn_connection("vpn-0123abcd") diff --git a/tests/test_ecr/__init__.py b/tests/test_ecr/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_ecr/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_ecr/test_ecr_boto3.py b/tests/test_ecr/test_ecr_boto3.py index fd678f661..e44307bee 100644 --- a/tests/test_ecr/test_ecr_boto3.py +++ b/tests/test_ecr/test_ecr_boto3.py @@ -15,7 +15,7 @@ from botocore.exceptions import ClientError, ParamValidationError from dateutil.tz import tzlocal from moto import mock_ecr -from nose import SkipTest +from unittest import SkipTest def _create_image_digest(contents=None): diff --git a/tests/test_ecs/__init__.py b/tests/test_ecs/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_ecs/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_ecs/test_ecs_boto3.py b/tests/test_ecs/test_ecs_boto3.py index 2ef801807..8b6b27987 100644 --- a/tests/test_ecs/test_ecs_boto3.py +++ b/tests/test_ecs/test_ecs_boto3.py @@ -10,7 +10,7 @@ from uuid import UUID from moto import mock_ecs from moto import mock_ec2 -from nose.tools import assert_raises +import pytest @mock_ecs @@ -860,7 +860,7 @@ def test_deregister_container_instance(): containerInstances=[container_instance_id], startedBy="moto", ) - with assert_raises(Exception) as e: + with pytest.raises(Exception) as e: ecs_client.deregister_container_instance( cluster=test_cluster_name, containerInstance=container_instance_id ).should.have.raised(Exception) @@ -952,7 +952,7 @@ def test_describe_container_instances(): instance.keys().should.contain("pendingTasksCount") instance["registeredAt"].should.be.a("datetime.datetime") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: ecs_client.describe_container_instances( cluster=test_cluster_name, containerInstances=[] ) @@ -2611,7 +2611,7 @@ def test_delete_task_set(): assert len(task_sets) == 0 - with assert_raises(ClientError): + with pytest.raises(ClientError): _ = client.delete_task_set( cluster=cluster_name, service=service_name, taskSet=task_set["taskSetArn"], ) diff --git a/tests/test_elb/__init__.py b/tests/test_elb/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_elb/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_elb/test_elb.py b/tests/test_elb/test_elb.py index 1583ea544..427cb740c 100644 --- a/tests/test_elb/test_elb.py +++ b/tests/test_elb/test_elb.py @@ -11,7 +11,7 @@ from boto.ec2.elb.attributes import ( ) from botocore.exceptions import ClientError from boto.exception import BotoServerError -from nose.tools import assert_raises +import pytest import sure # noqa from moto import mock_elb, mock_ec2, mock_elb_deprecated, mock_ec2_deprecated @@ -123,7 +123,7 @@ def test_create_and_delete_boto3_support(): def test_create_load_balancer_with_no_listeners_defined(): client = boto3.client("elb", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): client.create_load_balancer( LoadBalancerName="my-lb", Listeners=[], @@ -180,12 +180,12 @@ def test_apply_security_groups_to_load_balancer(): assert balancer["SecurityGroups"] == [security_group.id] # Using a not-real security group raises an error - with assert_raises(ClientError) as error: + with pytest.raises(ClientError) as error: response = client.apply_security_groups_to_load_balancer( LoadBalancerName="my-lb", SecurityGroups=["not-really-a-security-group"] ) assert "One or more of the specified security groups do not exist." in str( - error.exception + error.value ) @@ -255,7 +255,7 @@ def test_create_and_delete_listener_boto3_support(): balancer["ListenerDescriptions"][1]["Listener"]["InstancePort"].should.equal(8443) # Creating this listener with an conflicting definition throws error - with assert_raises(ClientError): + with pytest.raises(ClientError): client.create_load_balancer_listeners( LoadBalancerName="my-lb", Listeners=[ diff --git a/tests/test_elbv2/__init__.py b/tests/test_elbv2/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_elbv2/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_elbv2/test_elbv2.py b/tests/test_elbv2/test_elbv2.py index 5ab85284d..cb8e13e52 100644 --- a/tests/test_elbv2/test_elbv2.py +++ b/tests/test_elbv2/test_elbv2.py @@ -4,7 +4,7 @@ import os import boto3 import botocore from botocore.exceptions import ClientError, ParamValidationError -from nose.tools import assert_raises +import pytest import sure # noqa from moto import mock_elbv2, mock_ec2, mock_acm @@ -96,9 +96,9 @@ def test_describe_load_balancers(): response = conn.describe_load_balancers(Names=["my-lb"]) response.get("LoadBalancers")[0].get("LoadBalancerName").should.equal("my-lb") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.describe_load_balancers(LoadBalancerArns=["not-a/real/arn"]) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.describe_load_balancers(Names=["nope"]) @@ -132,7 +132,7 @@ def test_add_remove_tags(): lbs.should.have.length_of(1) lb = lbs[0] - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.add_tags(ResourceArns=["missing-arn"], Tags=[{"Key": "a", "Value": "b"}]) conn.add_tags( @@ -274,7 +274,7 @@ def test_create_target_group_and_listeners(): load_balancer_arn = response.get("LoadBalancers")[0].get("LoadBalancerArn") # Can't create a target group with an invalid protocol - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_target_group( Name="a-target", Protocol="HTTP", @@ -389,10 +389,10 @@ def test_create_target_group_and_listeners(): # Try to delete the target group and it fails because there's a # listener referencing it - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: conn.delete_target_group(TargetGroupArn=target_group.get("TargetGroupArn")) - e.exception.operation_name.should.equal("DeleteTargetGroup") - e.exception.args.should.equal( + e.value.operation_name.should.equal("DeleteTargetGroup") + e.value.args.should.equal( ( "An error occurred (ResourceInUse) when calling the DeleteTargetGroup operation: The target group 'arn:aws:elasticloadbalancing:us-east-1:1:targetgroup/a-target/50dc6c495c0c9188' is currently in use by a listener or a rule", ) @@ -477,7 +477,7 @@ def test_create_invalid_target_group(): # Fail to create target group with name which length is 33 long_name = "A" * 33 - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_target_group( Name=long_name, Protocol="HTTP", @@ -495,7 +495,7 @@ def test_create_invalid_target_group(): invalid_names = ["-name", "name-", "-name-", "example.com", "test@test", "Na--me"] for name in invalid_names: - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_target_group( Name=name, Protocol="HTTP", @@ -941,7 +941,7 @@ def test_handle_listener_rules(): load_balancer_arn = response.get("LoadBalancers")[0].get("LoadBalancerArn") # Can't create a target group with an invalid protocol - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_target_group( Name="a-target", Protocol="HTTP", @@ -1032,7 +1032,7 @@ def test_handle_listener_rules(): ) # test for PriorityInUse - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_rule( ListenerArn=http_listener_arn, Priority=priority, @@ -1079,11 +1079,11 @@ def test_handle_listener_rules(): ) # test for invalid describe rule request - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.describe_rules() - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.describe_rules(RuleArns=[]) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.describe_rules( ListenerArn=http_listener_arn, RuleArns=[first_rule["RuleArn"]] ) @@ -1125,7 +1125,7 @@ def test_handle_listener_rules(): } ] ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.set_rule_priorities( RulePriorities=[ {"RuleArn": first_rule["RuleArn"], "Priority": 999}, @@ -1141,7 +1141,7 @@ def test_handle_listener_rules(): # test for invalid action type safe_priority = 2 - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_rule( ListenerArn=http_listener_arn, Priority=safe_priority, @@ -1160,7 +1160,7 @@ def test_handle_listener_rules(): # test for invalid action type safe_priority = 2 invalid_target_group_arn = target_group.get("TargetGroupArn") + "x" - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_rule( ListenerArn=http_listener_arn, Priority=safe_priority, @@ -1173,7 +1173,7 @@ def test_handle_listener_rules(): # test for invalid condition field_name safe_priority = 2 - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_rule( ListenerArn=http_listener_arn, Priority=safe_priority, @@ -1188,7 +1188,7 @@ def test_handle_listener_rules(): # test for emptry condition value safe_priority = 2 - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_rule( ListenerArn=http_listener_arn, Priority=safe_priority, @@ -1203,7 +1203,7 @@ def test_handle_listener_rules(): # test for multiple condition value safe_priority = 2 - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_rule( ListenerArn=http_listener_arn, Priority=safe_priority, @@ -1260,7 +1260,7 @@ def test_describe_invalid_target_group(): ) # Check error raises correctly - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.describe_target_groups(Names=["invalid"]) @@ -1358,7 +1358,7 @@ def test_set_ip_address_type(): arn = response["LoadBalancers"][0]["LoadBalancerArn"] # Internal LBs cant be dualstack yet - with assert_raises(ClientError): + with pytest.raises(ClientError): client.set_ip_address_type(LoadBalancerArn=arn, IpAddressType="dualstack") # Create internet facing one @@ -1410,7 +1410,7 @@ def test_set_security_groups(): resp = client.describe_load_balancers(LoadBalancerArns=[arn]) len(resp["LoadBalancers"][0]["SecurityGroups"]).should.equal(2) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.set_security_groups(LoadBalancerArn=arn, SecurityGroups=["non_existent"]) @@ -1451,11 +1451,11 @@ def test_set_subnets(): len(resp["LoadBalancers"][0]["AvailabilityZones"]).should.equal(3) # Only 1 AZ - with assert_raises(ClientError): + with pytest.raises(ClientError): client.set_subnets(LoadBalancerArn=arn, Subnets=[subnet1.id]) # Multiple subnets in same AZ - with assert_raises(ClientError): + with pytest.raises(ClientError): client.set_subnets( LoadBalancerArn=arn, Subnets=[subnet1.id, subnet2.id, subnet2.id] ) @@ -1644,7 +1644,7 @@ def test_modify_listener_http_to_https(): listener.certificate.should.equal(yahoo_arn) # No default cert - with assert_raises(ClientError): + with pytest.raises(ClientError): client.modify_listener( ListenerArn=listener_arn, Port=443, @@ -1655,7 +1655,7 @@ def test_modify_listener_http_to_https(): ) # Bad cert - with assert_raises(ClientError): + with pytest.raises(ClientError): client.modify_listener( ListenerArn=listener_arn, Port=443, @@ -1884,7 +1884,7 @@ def test_fixed_response_action_listener_rule_validates_status_code(): "MessageBody": "This page does not exist", }, } - with assert_raises(ParamValidationError): + with pytest.raises(ParamValidationError): conn.create_listener( LoadBalancerArn=load_balancer_arn, Protocol="HTTP", @@ -1934,7 +1934,7 @@ def test_fixed_response_action_listener_rule_validates_status_code(): "MessageBody": "This page does not exist", }, } - with assert_raises(ParamValidationError): + with pytest.raises(ParamValidationError): conn.create_listener( LoadBalancerArn=load_balancer_arn, Protocol="HTTP", @@ -1951,7 +1951,7 @@ def test_fixed_response_action_listener_rule_validates_status_code(): }, } - with assert_raises(ClientError) as invalid_status_code_exception: + with pytest.raises(ClientError) as invalid_status_code_exception: conn.create_listener( LoadBalancerArn=load_balancer_arn, Protocol="HTTP", @@ -1959,7 +1959,7 @@ def test_fixed_response_action_listener_rule_validates_status_code(): DefaultActions=[invalid_status_code_action], ) - invalid_status_code_exception.exception.response["Error"]["Code"].should.equal( + invalid_status_code_exception.value.response["Error"]["Code"].should.equal( "ValidationError" ) @@ -1998,13 +1998,13 @@ def test_fixed_response_action_listener_rule_validates_content_type(): "StatusCode": "200", }, } - with assert_raises(ClientError) as invalid_content_type_exception: + with pytest.raises(ClientError) as invalid_content_type_exception: conn.create_listener( LoadBalancerArn=load_balancer_arn, Protocol="HTTP", Port=80, DefaultActions=[invalid_content_type_action], ) - invalid_content_type_exception.exception.response["Error"]["Code"].should.equal( + invalid_content_type_exception.value.response["Error"]["Code"].should.equal( "InvalidLoadBalancerAction" ) diff --git a/tests/test_emr/__init__.py b/tests/test_emr/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_emr/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_emr/test_emr_boto3.py b/tests/test_emr/test_emr_boto3.py index af6939f80..de8f4edbb 100644 --- a/tests/test_emr/test_emr_boto3.py +++ b/tests/test_emr/test_emr_boto3.py @@ -5,11 +5,12 @@ from copy import deepcopy from datetime import datetime import boto3 +import json import pytz import six import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_emr @@ -395,13 +396,13 @@ def test_run_job_flow(): @mock_emr def test_run_job_flow_with_invalid_params(): client = boto3.client("emr", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: # cannot set both AmiVersion and ReleaseLabel args = deepcopy(run_job_flow_args) args["AmiVersion"] = "2.4" args["ReleaseLabel"] = "emr-5.0.0" client.run_job_flow(**args) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Code"].should.equal("ValidationException") @mock_emr @@ -592,34 +593,34 @@ def _patch_cluster_id_placeholder_in_autoscaling_policy( def test_run_job_flow_with_custom_ami(): client = boto3.client("emr", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: # CustomAmiId available in Amazon EMR 5.7.0 and later args = deepcopy(run_job_flow_args) args["CustomAmiId"] = "MyEmrCustomId" args["ReleaseLabel"] = "emr-5.6.0" client.run_job_flow(**args) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal("Custom AMI is not allowed") + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal("Custom AMI is not allowed") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: args = deepcopy(run_job_flow_args) args["CustomAmiId"] = "MyEmrCustomId" args["AmiVersion"] = "3.8.1" client.run_job_flow(**args) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.equal( "Custom AMI is not supported in this version of EMR" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: # AMI version and release label exception raises before CustomAmi exception args = deepcopy(run_job_flow_args) args["CustomAmiId"] = "MyEmrCustomId" args["ReleaseLabel"] = "emr-5.6.0" args["AmiVersion"] = "3.8.1" client.run_job_flow(**args) - ex.exception.response["Error"]["Code"].should.equal("ValidationException") - ex.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("ValidationException") + ex.value.response["Error"]["Message"].should.contain( "Only one AMI version and release label may be specified." ) @@ -799,11 +800,12 @@ def test_instance_groups(): x["AutoScalingPolicy"]["Status"]["State"].should.equal("ATTACHED") returned_policy = dict(x["AutoScalingPolicy"]) del returned_policy["Status"] - for dimension in y["AutoScalingPolicy"]["Rules"]["Trigger"][ - "CloudWatchAlarmDefinition" - ]["Dimensions"]: - dimension["Value"] = cluster_id - returned_policy.should.equal(y["AutoScalingPolicy"]) + policy = json.loads( + json.dumps(y["AutoScalingPolicy"]).replace( + "${emr.clusterId}", cluster_id + ) + ) + returned_policy.should.equal(policy) if "EbsConfiguration" in y: _do_assertion_ebs_configuration(x, y) # Configurations diff --git a/tests/test_events/__init__.py b/tests/test_events/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_events/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_events/test_events.py b/tests/test_events/test_events.py index b65171603..4b5bbd4cb 100644 --- a/tests/test_events/test_events.py +++ b/tests/test_events/test_events.py @@ -6,7 +6,7 @@ import boto3 import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto.core import ACCOUNT_ID from moto.core.exceptions import JsonRESTError @@ -331,7 +331,7 @@ def test_put_events(): response["FailedEntryCount"].should.equal(0) response["Entries"].should.have.length_of(1) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.put_events(Entries=[event] * 20) diff --git a/tests/test_forecast/test_forecast.py b/tests/test_forecast/test_forecast.py index 32af519c7..7936a500d 100644 --- a/tests/test_forecast/test_forecast.py +++ b/tests/test_forecast/test_forecast.py @@ -1,11 +1,9 @@ from __future__ import unicode_literals import boto3 +import pytest import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises -from parameterized import parameterized - from moto import mock_forecast from moto.core import ACCOUNT_ID @@ -22,7 +20,7 @@ valid_domains = [ ] -@parameterized(valid_domains) +@pytest.mark.parametrize("domain", valid_domains) @mock_forecast def test_forecast_dataset_group_create(domain): name = "example_dataset_group" @@ -40,25 +38,25 @@ def test_forecast_dataset_group_create_invalid_domain(): client = boto3.client("forecast", region_name=region) invalid_domain = "INVALID" - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.create_dataset_group(DatasetGroupName=name, Domain=invalid_domain) - exc.exception.response["Error"]["Code"].should.equal("ValidationException") - exc.exception.response["Error"]["Message"].should.equal( + exc.value.response["Error"]["Code"].should.equal("ValidationException") + exc.value.response["Error"]["Message"].should.equal( "1 validation error detected: Value '" + invalid_domain + "' at 'domain' failed to satisfy constraint: Member must satisfy enum value set ['INVENTORY_PLANNING', 'METRICS', 'RETAIL', 'EC2_CAPACITY', 'CUSTOM', 'WEB_TRAFFIC', 'WORK_FORCE']" ) -@parameterized([" ", "a" * 64]) +@pytest.mark.parametrize("name", [" ", "a" * 64]) @mock_forecast def test_forecast_dataset_group_create_invalid_name(name): client = boto3.client("forecast", region_name=region) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.create_dataset_group(DatasetGroupName=name, Domain="CUSTOM") - exc.exception.response["Error"]["Code"].should.equal("ValidationException") - exc.exception.response["Error"]["Message"].should.contain( + exc.value.response["Error"]["Code"].should.equal("ValidationException") + exc.value.response["Error"]["Message"].should.contain( "1 validation error detected: Value '" + name + "' at 'datasetGroupName' failed to satisfy constraint: Member must" @@ -70,12 +68,10 @@ def test_forecast_dataset_group_create_duplicate_fails(): client = boto3.client("forecast", region_name=region) client.create_dataset_group(DatasetGroupName="name", Domain="RETAIL") - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.create_dataset_group(DatasetGroupName="name", Domain="RETAIL") - exc.exception.response["Error"]["Code"].should.equal( - "ResourceAlreadyExistsException" - ) + exc.value.response["Error"]["Code"].should.equal("ResourceAlreadyExistsException") @mock_forecast @@ -122,10 +118,10 @@ def test_forecast_delete_dataset_group_missing(): "arn:aws:forecast:" + region + ":" + ACCOUNT_ID + ":dataset-group/missing" ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.delete_dataset_group(DatasetGroupArn=missing_dsg_arn) - exc.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - exc.exception.response["Error"]["Message"].should.equal( + exc.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + exc.value.response["Error"]["Message"].should.equal( "No resource found " + missing_dsg_arn ) @@ -152,10 +148,10 @@ def test_forecast_update_dataset_group_not_found(): dataset_group_arn = ( "arn:aws:forecast:" + region + ":" + ACCOUNT_ID + ":dataset-group/" + "test" ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.update_dataset_group(DatasetGroupArn=dataset_group_arn, DatasetArns=[]) - exc.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - exc.exception.response["Error"]["Message"].should.equal( + exc.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + exc.value.response["Error"]["Message"].should.equal( "No resource found " + dataset_group_arn ) @@ -180,10 +176,10 @@ def test_describe_dataset_group_missing(): dataset_group_arn = ( "arn:aws:forecast:" + region + ":" + ACCOUNT_ID + ":dataset-group/name" ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.describe_dataset_group(DatasetGroupArn=dataset_group_arn) - exc.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - exc.exception.response["Error"]["Message"].should.equal( + exc.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + exc.value.response["Error"]["Message"].should.equal( "No resource found " + dataset_group_arn ) @@ -192,12 +188,12 @@ def test_describe_dataset_group_missing(): def test_create_dataset_group_missing_datasets(): client = boto3.client("forecast", region_name=region) dataset_arn = "arn:aws:forecast:" + region + ":" + ACCOUNT_ID + ":dataset/name" - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.create_dataset_group( DatasetGroupName="name", Domain="CUSTOM", DatasetArns=[dataset_arn] ) - exc.exception.response["Error"]["Code"].should.equal("InvalidInputException") - exc.exception.response["Error"]["Message"].should.equal( + exc.value.response["Error"]["Code"].should.equal("InvalidInputException") + exc.value.response["Error"]["Message"].should.equal( "Dataset arns: [" + dataset_arn + "] are not found" ) @@ -212,11 +208,11 @@ def test_update_dataset_group_missing_datasets(): client.create_dataset_group(DatasetGroupName=name, Domain="CUSTOM") dataset_arn = "arn:aws:forecast:" + region + ":" + ACCOUNT_ID + ":dataset/name" - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.update_dataset_group( DatasetGroupArn=dataset_group_arn, DatasetArns=[dataset_arn] ) - exc.exception.response["Error"]["Code"].should.equal("InvalidInputException") - exc.exception.response["Error"]["Message"].should.equal( + exc.value.response["Error"]["Code"].should.equal("InvalidInputException") + exc.value.response["Error"]["Message"].should.equal( "Dataset arns: [" + dataset_arn + "] are not found" ) diff --git a/tests/test_glacier/__init__.py b/tests/test_glacier/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_glacier/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_glue/test_datacatalog.py b/tests/test_glue/test_datacatalog.py index bc68b48f6..38a3831d5 100644 --- a/tests/test_glue/test_datacatalog.py +++ b/tests/test_glue/test_datacatalog.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import sure # noqa import re -from nose.tools import assert_raises +import pytest import boto3 from botocore.client import ClientError @@ -32,10 +32,10 @@ def test_create_database_already_exists(): database_name = "cantcreatethisdatabasetwice" helpers.create_database(client, database_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.create_database(client, database_name) - exc.exception.response["Error"]["Code"].should.equal("AlreadyExistsException") + exc.value.response["Error"]["Code"].should.equal("AlreadyExistsException") @mock_glue @@ -43,11 +43,11 @@ def test_get_database_not_exits(): client = boto3.client("glue", region_name="us-east-1") database_name = "nosuchdatabase" - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_database(client, database_name) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match( + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match( "Database nosuchdatabase not found" ) @@ -102,10 +102,10 @@ def test_create_table_already_exists(): table_name = "cantcreatethistabletwice" helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.create_table(client, database_name, table_name) - exc.exception.response["Error"]["Code"].should.equal("AlreadyExistsException") + exc.value.response["Error"]["Code"].should.equal("AlreadyExistsException") @mock_glue @@ -192,11 +192,11 @@ def test_get_table_version_not_found(): helpers.create_database(client, database_name) helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_table_version(client, database_name, "myfirsttable", "20") - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match("version", re.I) + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match("version", re.I) @mock_glue @@ -207,10 +207,10 @@ def test_get_table_version_invalid_input(): helpers.create_database(client, database_name) helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_table_version(client, database_name, "myfirsttable", "10not-an-int") - exc.exception.response["Error"]["Code"].should.equal("InvalidInputException") + exc.value.response["Error"]["Code"].should.equal("InvalidInputException") @mock_glue @@ -219,13 +219,11 @@ def test_get_table_not_exits(): database_name = "myspecialdatabase" helpers.create_database(client, database_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_table(client, database_name, "myfirsttable") - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match( - "Table myfirsttable not found" - ) + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match("Table myfirsttable not found") @mock_glue @@ -233,11 +231,11 @@ def test_get_table_when_database_not_exits(): client = boto3.client("glue", region_name="us-east-1") database_name = "nosuchdatabase" - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_table(client, database_name, "myfirsttable") - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match( + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match( "Database nosuchdatabase not found" ) @@ -256,11 +254,11 @@ def test_delete_table(): result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) # confirm table is deleted - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_table(client, database_name, table_name) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match( + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match( "Table myspecialtable not found" ) @@ -281,11 +279,11 @@ def test_batch_delete_table(): result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) # confirm table is deleted - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_table(client, database_name, table_name) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match( + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match( "Table myspecialtable not found" ) @@ -350,10 +348,10 @@ def test_create_partition_already_exist(): helpers.create_partition(client, database_name, table_name, values=values) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.create_partition(client, database_name, table_name, values=values) - exc.exception.response["Error"]["Code"].should.equal("AlreadyExistsException") + exc.value.response["Error"]["Code"].should.equal("AlreadyExistsException") @mock_glue @@ -366,11 +364,11 @@ def test_get_partition_not_found(): helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_partition(client, database_name, table_name, values) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match("partition") + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match("partition") @mock_glue @@ -542,7 +540,7 @@ def test_update_partition_not_found_moving(): helpers.create_database(client, database_name) helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.update_partition( client, database_name, @@ -551,8 +549,8 @@ def test_update_partition_not_found_moving(): values=["2018-10-02"], ) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match("partition") + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match("partition") @mock_glue @@ -565,13 +563,13 @@ def test_update_partition_not_found_change_in_place(): helpers.create_database(client, database_name) helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.update_partition( client, database_name, table_name, old_values=values, values=values ) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") - exc.exception.response["Error"]["Message"].should.match("partition") + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Message"].should.match("partition") @mock_glue @@ -588,12 +586,12 @@ def test_update_partition_cannot_overwrite(): helpers.create_partition(client, database_name, table_name, values=values[0]) helpers.create_partition(client, database_name, table_name, values=values[1]) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.update_partition( client, database_name, table_name, old_values=values[0], values=values[1] ) - exc.exception.response["Error"]["Code"].should.equal("AlreadyExistsException") + exc.value.response["Error"]["Code"].should.equal("AlreadyExistsException") @mock_glue @@ -648,11 +646,11 @@ def test_update_partition_move(): columns=[{"Name": "country", "Type": "string"}], ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: helpers.get_partition(client, database_name, table_name, values) # Old partition shouldn't exist anymore - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") response = client.get_partition( DatabaseName=database_name, TableName=table_name, PartitionValues=new_values @@ -697,12 +695,12 @@ def test_delete_partition_bad_partition(): helpers.create_database(client, database_name) helpers.create_table(client, database_name, table_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: client.delete_partition( DatabaseName=database_name, TableName=table_name, PartitionValues=values ) - exc.exception.response["Error"]["Code"].should.equal("EntityNotFoundException") + exc.value.response["Error"]["Code"].should.equal("EntityNotFoundException") @mock_glue diff --git a/tests/test_iam/__init__.py b/tests/test_iam/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_iam/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_iam/test_iam.py b/tests/test_iam/test_iam.py index 7db2f0162..bd9a8ab82 100644 --- a/tests/test_iam/test_iam.py +++ b/tests/test_iam/test_iam.py @@ -13,8 +13,7 @@ from moto import mock_config, mock_iam, mock_iam_deprecated, settings from moto.core import ACCOUNT_ID from moto.iam.models import aws_managed_policies from moto.backends import get_backend -from nose.tools import assert_raises, assert_equals -from nose.tools import raises +import pytest from datetime import datetime from tests.helpers import requires_boto_gte @@ -93,7 +92,7 @@ def test_get_all_server_certs(): def test_get_server_cert_doesnt_exist(): conn = boto.connect_iam() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.get_server_certificate("NonExistant") @@ -128,14 +127,14 @@ def test_delete_server_cert(): conn.upload_server_cert("certname", "certbody", "privatekey") conn.get_server_certificate("certname") conn.delete_server_cert("certname") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.get_server_certificate("certname") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.delete_server_cert("certname") @mock_iam_deprecated() -@raises(BotoServerError) +@pytest.mark.xfail(raises=BotoServerError) def test_get_role__should_throw__when_role_does_not_exist(): conn = boto.connect_iam() @@ -143,7 +142,7 @@ def test_get_role__should_throw__when_role_does_not_exist(): @mock_iam_deprecated() -@raises(BotoServerError) +@pytest.mark.xfail(raises=BotoServerError) def test_get_instance_profile__should_throw__when_instance_profile_does_not_exist(): conn = boto.connect_iam() @@ -181,7 +180,7 @@ def test_create_role_and_instance_profile(): def test_create_instance_profile_should_throw_when_name_is_not_unique(): conn = boto3.client("iam", region_name="us-east-1") conn.create_instance_profile(InstanceProfileName="unique-instance-profile") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_instance_profile(InstanceProfileName="unique-instance-profile") @@ -208,19 +207,19 @@ def test_remove_role_from_instance_profile(): def test_delete_instance_profile(): conn = boto3.client("iam", region_name="us-east-1") conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) conn.create_instance_profile(InstanceProfileName="my-profile") conn.add_role_to_instance_profile( InstanceProfileName="my-profile", RoleName="my-role" ) - with assert_raises(conn.exceptions.DeleteConflictException): + with pytest.raises(conn.exceptions.DeleteConflictException): conn.delete_instance_profile(InstanceProfileName="my-profile") conn.remove_role_from_instance_profile( InstanceProfileName="my-profile", RoleName="my-role" ) conn.delete_instance_profile(InstanceProfileName="my-profile") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): profile = conn.get_instance_profile(InstanceProfileName="my-profile") @@ -253,62 +252,62 @@ def test_update_login_profile(): def test_delete_role(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.delete_role(RoleName="my-role") # Test deletion failure with a managed policy conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) response = conn.create_policy( PolicyName="my-managed-policy", PolicyDocument=MOCK_POLICY ) conn.attach_role_policy(PolicyArn=response["Policy"]["Arn"], RoleName="my-role") - with assert_raises(conn.exceptions.DeleteConflictException): + with pytest.raises(conn.exceptions.DeleteConflictException): conn.delete_role(RoleName="my-role") conn.detach_role_policy(PolicyArn=response["Policy"]["Arn"], RoleName="my-role") conn.delete_policy(PolicyArn=response["Policy"]["Arn"]) conn.delete_role(RoleName="my-role") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_role(RoleName="my-role") # Test deletion failure with an inline policy conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) conn.put_role_policy( - RoleName="my-role", PolicyName="my-role-policy", PolicyDocument=MOCK_POLICY + RoleName="my-role", PolicyName="my-role-policy", PolicyDocument=MOCK_POLICY, ) - with assert_raises(conn.exceptions.DeleteConflictException): + with pytest.raises(conn.exceptions.DeleteConflictException): conn.delete_role(RoleName="my-role") conn.delete_role_policy(RoleName="my-role", PolicyName="my-role-policy") conn.delete_role(RoleName="my-role") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_role(RoleName="my-role") # Test deletion failure with attachment to an instance profile conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) conn.create_instance_profile(InstanceProfileName="my-profile") conn.add_role_to_instance_profile( InstanceProfileName="my-profile", RoleName="my-role" ) - with assert_raises(conn.exceptions.DeleteConflictException): + with pytest.raises(conn.exceptions.DeleteConflictException): conn.delete_role(RoleName="my-role") conn.remove_role_from_instance_profile( InstanceProfileName="my-profile", RoleName="my-role" ) conn.delete_role(RoleName="my-role") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_role(RoleName="my-role") # Test deletion with no conflicts conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) conn.delete_role(RoleName="my-role") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_role(RoleName="my-role") @@ -332,7 +331,7 @@ def test_list_instance_profiles_for_role(): conn = boto.connect_iam() conn.create_role( - role_name="my-role", assume_role_policy_document="some policy", path="my-path" + role_name="my-role", assume_role_policy_document="some policy", path="my-path", ) conn.create_role( role_name="my-role2", @@ -344,7 +343,7 @@ def test_list_instance_profiles_for_role(): profile_path_list = ["my-path", "my-path2"] for profile_count in range(0, 2): conn.create_instance_profile( - profile_name_list[profile_count], path=profile_path_list[profile_count] + profile_name_list[profile_count], path=profile_path_list[profile_count], ) for profile_count in range(0, 2): @@ -389,7 +388,7 @@ def test_list_role_policies(): role.policy_names.should.have.length_of(1) role.policy_names[0].should.equal("test policy 2") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.delete_role_policy("my-role", "test policy") @@ -410,9 +409,9 @@ def test_put_role_policy(): def test_get_role_policy(): conn = boto3.client("iam", region_name="us-east-1") conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="my-path" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="my-path", ) - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_role_policy(RoleName="my-role", PolicyName="does-not-exist") @@ -442,13 +441,13 @@ def test_create_policy_already_exists(): response = conn.create_policy( PolicyName="TestCreatePolicy", PolicyDocument=MOCK_POLICY ) - with assert_raises(conn.exceptions.EntityAlreadyExistsException) as ex: + with pytest.raises(conn.exceptions.EntityAlreadyExistsException) as ex: response = conn.create_policy( PolicyName="TestCreatePolicy", PolicyDocument=MOCK_POLICY ) - ex.exception.response["Error"]["Code"].should.equal("EntityAlreadyExists") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(409) - ex.exception.response["Error"]["Message"].should.contain("TestCreatePolicy") + ex.value.response["Error"]["Code"].should.equal("EntityAlreadyExists") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(409) + ex.value.response["Error"]["Message"].should.contain("TestCreatePolicy") @mock_iam @@ -467,7 +466,7 @@ def test_delete_policy(): @mock_iam def test_create_policy_versions(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_policy_version( PolicyArn="arn:aws:iam::{}:policy/TestCreatePolicyVersion".format( ACCOUNT_ID @@ -508,7 +507,7 @@ def test_create_many_policy_versions(): ), PolicyDocument=MOCK_POLICY, ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_policy_version( PolicyArn="arn:aws:iam::{}:policy/TestCreateManyPolicyVersions".format( ACCOUNT_ID @@ -639,7 +638,7 @@ def test_get_policy_version(): PolicyArn="arn:aws:iam::{}:policy/TestGetPolicyVersion".format(ACCOUNT_ID), PolicyDocument=MOCK_POLICY, ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.get_policy_version( PolicyArn="arn:aws:iam::{}:policy/TestGetPolicyVersion".format(ACCOUNT_ID), VersionId="v2-does-not-exist", @@ -661,7 +660,7 @@ def test_get_aws_managed_policy_version(): managed_policy_version_create_date = datetime.strptime( "2015-04-09T15:03:43+00:00", "%Y-%m-%dT%H:%M:%S+00:00" ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.get_policy_version( PolicyArn=managed_policy_arn, VersionId="v2-does-not-exist" ) @@ -679,7 +678,7 @@ def test_get_aws_managed_policy_v4_version(): managed_policy_version_create_date = datetime.strptime( "2018-10-08T21:33:45+00:00", "%Y-%m-%dT%H:%M:%S+00:00" ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.get_policy_version( PolicyArn=managed_policy_arn, VersionId="v2-does-not-exist" ) @@ -693,7 +692,7 @@ def test_get_aws_managed_policy_v4_version(): @mock_iam def test_list_policy_versions(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): versions = conn.list_policy_versions( PolicyArn="arn:aws:iam::{}:policy/TestListPolicyVersions".format(ACCOUNT_ID) ) @@ -729,7 +728,7 @@ def test_delete_policy_version(): PolicyArn="arn:aws:iam::{}:policy/TestDeletePolicyVersion".format(ACCOUNT_ID), PolicyDocument=MOCK_POLICY, ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.delete_policy_version( PolicyArn="arn:aws:iam::{}:policy/TestDeletePolicyVersion".format( ACCOUNT_ID @@ -754,7 +753,7 @@ def test_delete_default_policy_version(): PolicyArn="arn:aws:iam::{}:policy/TestDeletePolicyVersion".format(ACCOUNT_ID), PolicyDocument=MOCK_POLICY_2, ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.delete_policy_version( PolicyArn="arn:aws:iam::{}:policy/TestDeletePolicyVersion".format( ACCOUNT_ID @@ -767,14 +766,14 @@ def test_delete_default_policy_version(): def test_create_user(): conn = boto.connect_iam() conn.create_user("my-user") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.create_user("my-user") @mock_iam_deprecated() def test_get_user(): conn = boto.connect_iam() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.get_user("my-user") conn.create_user("my-user") conn.get_user("my-user") @@ -783,13 +782,13 @@ def test_get_user(): @mock_iam() def test_update_user(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.update_user(UserName="my-user") conn.create_user(UserName="my-user") conn.update_user(UserName="my-user", NewPath="/new-path/", NewUserName="new-user") response = conn.get_user(UserName="new-user") response["User"].get("Path").should.equal("/new-path/") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_user(UserName="my-user") @@ -846,11 +845,11 @@ def test_user_policies(): @mock_iam_deprecated() def test_create_login_profile(): conn = boto.connect_iam() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.create_login_profile("my-user", "my-pass") conn.create_user("my-user") conn.create_login_profile("my-user", "my-pass") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.create_login_profile("my-user", "my-pass") @@ -858,7 +857,7 @@ def test_create_login_profile(): def test_delete_login_profile(): conn = boto.connect_iam() conn.create_user("my-user") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.delete_login_profile("my-user") conn.create_login_profile("my-user", "my-pass") conn.delete_login_profile("my-user") @@ -867,7 +866,7 @@ def test_delete_login_profile(): @mock_iam def test_create_access_key(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_access_key(UserName="my-user") conn.create_user(UserName="my-user") access_key = conn.create_access_key(UserName="my-user")["AccessKey"] @@ -899,22 +898,19 @@ def test_get_all_access_keys(): conn = boto.connect_iam() conn.create_user("my-user") response = conn.get_all_access_keys("my-user") - assert_equals( + assert ( response["list_access_keys_response"]["list_access_keys_result"][ "access_key_metadata" - ], - [], + ] + == [] ) conn.create_access_key("my-user") response = conn.get_all_access_keys("my-user") - assert_equals( - sorted( - response["list_access_keys_response"]["list_access_keys_result"][ - "access_key_metadata" - ][0].keys() - ), - sorted(["status", "create_date", "user_name", "access_key_id"]), - ) + assert sorted( + response["list_access_keys_response"]["list_access_keys_result"][ + "access_key_metadata" + ][0].keys() + ) == sorted(["status", "create_date", "user_name", "access_key_id"]) @mock_iam @@ -922,12 +918,11 @@ def test_list_access_keys(): conn = boto3.client("iam", region_name="us-east-1") conn.create_user(UserName="my-user") response = conn.list_access_keys(UserName="my-user") - assert_equals(response["AccessKeyMetadata"], []) + assert response["AccessKeyMetadata"] == [] access_key = conn.create_access_key(UserName="my-user")["AccessKey"] response = conn.list_access_keys(UserName="my-user") - assert_equals( - sorted(response["AccessKeyMetadata"][0].keys()), - sorted(["Status", "CreateDate", "UserName", "AccessKeyId"]), + assert sorted(response["AccessKeyMetadata"][0].keys()) == sorted( + ["Status", "CreateDate", "UserName", "AccessKeyId"] ) conn = boto3.client( "iam", @@ -936,9 +931,8 @@ def test_list_access_keys(): aws_secret_access_key=access_key["SecretAccessKey"], ) response = conn.list_access_keys() - assert_equals( - sorted(response["AccessKeyMetadata"][0].keys()), - sorted(["Status", "CreateDate", "UserName", "AccessKeyId"]), + assert sorted(response["AccessKeyMetadata"][0].keys()) == sorted( + ["Status", "CreateDate", "UserName", "AccessKeyId"] ) @@ -1028,7 +1022,7 @@ def test_create_virtual_mfa_device_errors(): client.create_virtual_mfa_device.when.called_with( VirtualMFADeviceName="test-device" ).should.throw( - ClientError, "MFADevice entity at the same path and name already exists." + ClientError, "MFADevice entity at the same path and name already exists.", ) client.create_virtual_mfa_device.when.called_with( @@ -1188,7 +1182,7 @@ def test_enable_virtual_mfa_device(): @mock_iam_deprecated() def test_delete_user_deprecated(): conn = boto.connect_iam() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.delete_user("my-user") conn.create_user("my-user") conn.delete_user("my-user") @@ -1197,7 +1191,7 @@ def test_delete_user_deprecated(): @mock_iam() def test_delete_user(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.delete_user(UserName="my-user") # Test deletion failure with a managed policy @@ -1206,30 +1200,30 @@ def test_delete_user(): PolicyName="my-managed-policy", PolicyDocument=MOCK_POLICY ) conn.attach_user_policy(PolicyArn=response["Policy"]["Arn"], UserName="my-user") - with assert_raises(conn.exceptions.DeleteConflictException): + with pytest.raises(conn.exceptions.DeleteConflictException): conn.delete_user(UserName="my-user") conn.detach_user_policy(PolicyArn=response["Policy"]["Arn"], UserName="my-user") conn.delete_policy(PolicyArn=response["Policy"]["Arn"]) conn.delete_user(UserName="my-user") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_user(UserName="my-user") # Test deletion failure with an inline policy conn.create_user(UserName="my-user") conn.put_user_policy( - UserName="my-user", PolicyName="my-user-policy", PolicyDocument=MOCK_POLICY + UserName="my-user", PolicyName="my-user-policy", PolicyDocument=MOCK_POLICY, ) - with assert_raises(conn.exceptions.DeleteConflictException): + with pytest.raises(conn.exceptions.DeleteConflictException): conn.delete_user(UserName="my-user") conn.delete_user_policy(UserName="my-user", PolicyName="my-user-policy") conn.delete_user(UserName="my-user") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_user(UserName="my-user") # Test deletion with no conflicts conn.create_user(UserName="my-user") conn.delete_user(UserName="my-user") - with assert_raises(conn.exceptions.NoSuchEntityException): + with pytest.raises(conn.exceptions.NoSuchEntityException): conn.get_user(UserName="my-user") @@ -1259,7 +1253,7 @@ def test_boto3_generate_credential_report(): def test_get_credential_report(): conn = boto.connect_iam() conn.create_user("my-user") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.get_credential_report() result = conn.generate_credential_report() while ( @@ -1282,7 +1276,7 @@ def test_get_credential_report(): def test_boto3_get_credential_report(): conn = boto3.client("iam", region_name="us-east-1") conn.create_user(UserName="my-user") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.get_credential_report() result = conn.generate_credential_report() while result["State"] != "COMPLETE": @@ -1306,7 +1300,7 @@ def test_boto3_get_credential_report_content(): if not settings.TEST_SERVER_MODE: iam_backend = get_backend("iam")["global"] iam_backend.users[username].access_keys[1].last_used = timestamp - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.get_credential_report() result = conn.generate_credential_report() while result["State"] != "COMPLETE": @@ -1336,7 +1330,7 @@ def test_get_access_key_last_used_when_used(): client = iam.meta.client username = "test-user" iam.create_user(UserName=username) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.get_access_key_last_used(AccessKeyId="non-existent-key-id") create_key_response = client.create_access_key(UserName=username)["AccessKey"] # Set last used date using the IAM backend. Moto currently does not have a mechanism for tracking usage of access keys @@ -1402,7 +1396,7 @@ def test_managed_policy(): role_name = "my-role" conn.create_role( - role_name, assume_role_policy_document={"policy": "test"}, path="my-path" + role_name, assume_role_policy_document={"policy": "test"}, path="my-path", ) for policy_name in [ "AmazonElasticMapReduceRole", @@ -1429,7 +1423,7 @@ def test_managed_policy(): ].should.have.length_of(2) conn.detach_role_policy( - "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole", role_name + "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole", role_name, ) rows = conn.list_policies(only_attached=True)["list_policies_response"][ "list_policies_result" @@ -1448,12 +1442,13 @@ def test_managed_policy(): "attached_policies" ].should.have.length_of(1) - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.detach_role_policy( - "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole", role_name + "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole", + role_name, ) - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.detach_role_policy("arn:aws:iam::aws:policy/Nonexistent", role_name) @@ -1461,13 +1456,13 @@ def test_managed_policy(): def test_boto3_create_login_profile(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_login_profile(UserName="my-user", Password="Password") conn.create_user(UserName="my-user") conn.create_login_profile(UserName="my-user", Password="Password") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_login_profile(UserName="my-user", Password="Password") @@ -1506,7 +1501,7 @@ def test_update_access_key(): client = iam.meta.client username = "test-user" iam.create_user(UserName=username) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.update_access_key( UserName=username, AccessKeyId="non-existent-key", Status="Inactive" ) @@ -1527,7 +1522,7 @@ def test_get_access_key_last_used_when_unused(): client = iam.meta.client username = "test-user" iam.create_user(UserName=username) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.get_access_key_last_used(AccessKeyId="non-existent-key-id") create_key_response = client.create_access_key(UserName=username)["AccessKey"] resp = client.get_access_key_last_used( @@ -1566,9 +1561,9 @@ def test_get_ssh_public_key(): iam.create_user(UserName=username) public_key = MOCK_CERT - with assert_raises(ClientError): + with pytest.raises(ClientError): client.get_ssh_public_key( - UserName=username, SSHPublicKeyId="xxnon-existent-keyxx", Encoding="SSH" + UserName=username, SSHPublicKeyId="xxnon-existent-keyxx", Encoding="SSH", ) resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key) @@ -1607,9 +1602,9 @@ def test_update_ssh_public_key(): iam.create_user(UserName=username) public_key = MOCK_CERT - with assert_raises(ClientError): + with pytest.raises(ClientError): client.update_ssh_public_key( - UserName=username, SSHPublicKeyId="xxnon-existent-keyxx", Status="Inactive" + UserName=username, SSHPublicKeyId="xxnon-existent-keyxx", Status="Inactive", ) resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key) @@ -1634,7 +1629,7 @@ def test_delete_ssh_public_key(): iam.create_user(UserName=username) public_key = MOCK_CERT - with assert_raises(ClientError): + with pytest.raises(ClientError): client.delete_ssh_public_key( UserName=username, SSHPublicKeyId="xxnon-existent-keyxx" ) @@ -1687,7 +1682,7 @@ def test_get_account_authorization_details(): UserName="testUser", PolicyName="testPolicy", PolicyDocument=test_policy ) conn.put_group_policy( - GroupName="testGroup", PolicyName="testPolicy", PolicyDocument=test_policy + GroupName="testGroup", PolicyName="testPolicy", PolicyDocument=test_policy, ) conn.attach_user_policy( @@ -1827,14 +1822,14 @@ def test_signing_certs(): assert resp["CertificateId"] # Upload a the cert with an invalid body: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.upload_signing_certificate( UserName="testing", CertificateBody="notacert" ) - assert ce.exception.response["Error"]["Code"] == "MalformedCertificate" + assert ce.value.response["Error"]["Code"] == "MalformedCertificate" # Upload with an invalid user: - with assert_raises(ClientError): + with pytest.raises(ClientError): client.upload_signing_certificate( UserName="notauser", CertificateBody=MOCK_CERT ) @@ -1844,17 +1839,17 @@ def test_signing_certs(): UserName="testing", CertificateId=cert_id, Status="Inactive" ) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.update_signing_certificate( UserName="notauser", CertificateId=cert_id, Status="Inactive" ) - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.update_signing_certificate( UserName="testing", CertificateId="x" * 32, Status="Inactive" ) - assert ce.exception.response["Error"][ + assert ce.value.response["Error"][ "Message" ] == "The Certificate with id {id} cannot be found.".format(id="x" * 32) @@ -1864,13 +1859,13 @@ def test_signing_certs(): assert resp[0]["CertificateBody"] == MOCK_CERT assert resp[0]["Status"] == "Inactive" # Changed with the update call above. - with assert_raises(ClientError): + with pytest.raises(ClientError): client.list_signing_certificates(UserName="notauser") # Delete: client.delete_signing_certificate(UserName="testing", CertificateId=cert_id) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.delete_signing_certificate(UserName="notauser", CertificateId=cert_id) @@ -1921,10 +1916,10 @@ def test_delete_saml_provider(): conn.create_user(UserName="testing") cert_id = "123456789012345678901234" - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.delete_signing_certificate(UserName="testing", CertificateId=cert_id) - assert ce.exception.response["Error"][ + assert ce.value.response["Error"][ "Message" ] == "The Certificate with id {id} cannot be found.".format(id=cert_id) @@ -1982,20 +1977,20 @@ def test_create_role_with_tags(): # Test creating tags with invalid values: # With more than 50 tags: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: too_many_tags = list( map(lambda x: {"Key": str(x), "Value": str(x)}, range(0, 51)) ) conn.create_role( - RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=too_many_tags + RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=too_many_tags, ) assert ( "failed to satisfy constraint: Member must have length less than or equal to 50." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a duplicate tag: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.create_role( RoleName="my-role3", AssumeRolePolicyDocument="{}", @@ -2003,11 +1998,11 @@ def test_create_role_with_tags(): ) assert ( "Duplicate tag keys found. Please note that Tag keys are case insensitive." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Duplicate tag with different casing: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.create_role( RoleName="my-role3", AssumeRolePolicyDocument="{}", @@ -2015,11 +2010,11 @@ def test_create_role_with_tags(): ) assert ( "Duplicate tag keys found. Please note that Tag keys are case insensitive." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a really big key: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.create_role( RoleName="my-role3", AssumeRolePolicyDocument="{}", @@ -2027,11 +2022,11 @@ def test_create_role_with_tags(): ) assert ( "Member must have length less than or equal to 128." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a really big value: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.create_role( RoleName="my-role3", AssumeRolePolicyDocument="{}", @@ -2039,11 +2034,11 @@ def test_create_role_with_tags(): ) assert ( "Member must have length less than or equal to 256." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With an invalid character: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.create_role( RoleName="my-role3", AssumeRolePolicyDocument="{}", @@ -2051,7 +2046,7 @@ def test_create_role_with_tags(): ) assert ( "Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) @@ -2125,64 +2120,64 @@ def test_tag_role(): # Test creating tags with invalid values: # With more than 50 tags: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: too_many_tags = list( map(lambda x: {"Key": str(x), "Value": str(x)}, range(0, 51)) ) conn.tag_role(RoleName="my-role", Tags=too_many_tags) assert ( "failed to satisfy constraint: Member must have length less than or equal to 50." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a duplicate tag: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.tag_role( RoleName="my-role", Tags=[{"Key": "0", "Value": ""}, {"Key": "0", "Value": ""}], ) assert ( "Duplicate tag keys found. Please note that Tag keys are case insensitive." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Duplicate tag with different casing: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.tag_role( RoleName="my-role", Tags=[{"Key": "a", "Value": ""}, {"Key": "A", "Value": ""}], ) assert ( "Duplicate tag keys found. Please note that Tag keys are case insensitive." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a really big key: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.tag_role(RoleName="my-role", Tags=[{"Key": "0" * 129, "Value": ""}]) assert ( "Member must have length less than or equal to 128." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a really big value: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.tag_role(RoleName="my-role", Tags=[{"Key": "0", "Value": "0" * 257}]) assert ( "Member must have length less than or equal to 256." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With an invalid character: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.tag_role(RoleName="my-role", Tags=[{"Key": "NOWAY!", "Value": ""}]) assert ( "Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # With a role that doesn't exist: - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.tag_role(RoleName="notarole", Tags=[{"Key": "some", "Value": "value"}]) @@ -2214,34 +2209,34 @@ def test_untag_role(): # Test removing tags with invalid values: # With more than 50 tags: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.untag_role(RoleName="my-role", TagKeys=[str(x) for x in range(0, 51)]) assert ( "failed to satisfy constraint: Member must have length less than or equal to 50." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert "tagKeys" in ce.exception.response["Error"]["Message"] + assert "tagKeys" in ce.value.response["Error"]["Message"] # With a really big key: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.untag_role(RoleName="my-role", TagKeys=["0" * 129]) assert ( "Member must have length less than or equal to 128." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert "tagKeys" in ce.exception.response["Error"]["Message"] + assert "tagKeys" in ce.value.response["Error"]["Message"] # With an invalid character: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: conn.untag_role(RoleName="my-role", TagKeys=["NOWAY!"]) assert ( "Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+" - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) - assert "tagKeys" in ce.exception.response["Error"]["Message"] + assert "tagKeys" in ce.value.response["Error"]["Message"] # With a role that doesn't exist: - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.untag_role(RoleName="notarole", TagKeys=["somevalue"]) @@ -2249,11 +2244,11 @@ def test_untag_role(): def test_update_role_description(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.delete_role(RoleName="my-role") conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) response = conn.update_role_description(RoleName="my-role", Description="test") @@ -2264,11 +2259,11 @@ def test_update_role_description(): def test_update_role(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.delete_role(RoleName="my-role") conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) response = conn.update_role_description(RoleName="my-role", Description="test") assert response["Role"]["RoleName"] == "my-role" @@ -2278,11 +2273,11 @@ def test_update_role(): def test_update_role(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.delete_role(RoleName="my-role") conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) response = conn.update_role(RoleName="my-role", Description="test") assert len(response.keys()) == 1 @@ -2292,7 +2287,7 @@ def test_update_role(): def test_update_role_defaults(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.delete_role(RoleName="my-role") conn.create_role( @@ -2323,7 +2318,7 @@ def test_list_entities_for_policy(): conn = boto3.client("iam", region_name="us-east-1") conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", ) conn.create_user(Path="/", UserName="testUser") conn.create_group(Path="/", GroupName="testGroup") @@ -2339,7 +2334,7 @@ def test_list_entities_for_policy(): UserName="testUser", PolicyName="testPolicy", PolicyDocument=test_policy ) conn.put_group_policy( - GroupName="testGroup", PolicyName="testPolicy", PolicyDocument=test_policy + GroupName="testGroup", PolicyName="testPolicy", PolicyDocument=test_policy, ) conn.attach_user_policy( @@ -2402,7 +2397,7 @@ def test_list_entities_for_policy(): def test_create_role_no_path(): conn = boto3.client("iam", region_name="us-east-1") resp = conn.create_role( - RoleName="my-role", AssumeRolePolicyDocument="some policy", Description="test" + RoleName="my-role", AssumeRolePolicyDocument="some policy", Description="test", ) resp.get("Role").get("Arn").should.equal( "arn:aws:iam::{}:role/my-role".format(ACCOUNT_ID) @@ -2436,12 +2431,12 @@ def test_create_role_with_permissions_boundary(): invalid_boundary_arn = "arn:aws:iam::123456789:not_a_boundary" - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.put_role_permissions_boundary( RoleName="my-role", PermissionsBoundary=invalid_boundary_arn ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_role( RoleName="bad-boundary", AssumeRolePolicyDocument="some policy", @@ -2458,17 +2453,17 @@ def test_create_role_with_same_name_should_fail(): iam = boto3.client("iam", region_name="us-east-1") test_role_name = str(uuid4()) iam.create_role( - RoleName=test_role_name, AssumeRolePolicyDocument="policy", Description="test" + RoleName=test_role_name, AssumeRolePolicyDocument="policy", Description="test", ) # Create the role again, and verify that it fails - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: iam.create_role( RoleName=test_role_name, AssumeRolePolicyDocument="policy", Description="test", ) - err.exception.response["Error"]["Code"].should.equal("EntityAlreadyExists") - err.exception.response["Error"]["Message"].should.equal( + err.value.response["Error"]["Code"].should.equal("EntityAlreadyExists") + err.value.response["Error"]["Message"].should.equal( "Role with name {0} already exists.".format(test_role_name) ) @@ -2479,10 +2474,10 @@ def test_create_policy_with_same_name_should_fail(): test_policy_name = str(uuid4()) policy = iam.create_policy(PolicyName=test_policy_name, PolicyDocument=MOCK_POLICY) # Create the role again, and verify that it fails - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: iam.create_policy(PolicyName=test_policy_name, PolicyDocument=MOCK_POLICY) - err.exception.response["Error"]["Code"].should.equal("EntityAlreadyExists") - err.exception.response["Error"]["Message"].should.equal( + err.value.response["Error"]["Code"].should.equal("EntityAlreadyExists") + err.value.response["Error"]["Message"].should.equal( "A policy called {0} already exists. Duplicate names are not allowed.".format( test_policy_name ) @@ -2545,14 +2540,14 @@ def test_create_open_id_connect_provider_errors(): client.create_open_id_connect_provider.when.called_with( Url="http://example.org", - ThumbprintList=["a" * 40, "b" * 40, "c" * 40, "d" * 40, "e" * 40, "f" * 40], + ThumbprintList=["a" * 40, "b" * 40, "c" * 40, "d" * 40, "e" * 40, "f" * 40,], ).should.throw(ClientError, "Thumbprint list must contain fewer than 5 entries.") too_many_client_ids = ["{}".format(i) for i in range(101)] client.create_open_id_connect_provider.when.called_with( - Url="http://example.org", ThumbprintList=[], ClientIDList=too_many_client_ids + Url="http://example.org", ThumbprintList=[], ClientIDList=too_many_client_ids, ).should.throw( - ClientError, "Cannot exceed quota for ClientIdsPerOpenIdConnectProvider: 100" + ClientError, "Cannot exceed quota for ClientIdsPerOpenIdConnectProvider: 100", ) too_long_url = "b" * 256 @@ -2593,7 +2588,7 @@ def test_delete_open_id_connect_provider(): client.get_open_id_connect_provider.when.called_with( OpenIDConnectProviderArn=open_id_arn ).should.throw( - ClientError, "OpenIDConnect Provider not found for arn {}".format(open_id_arn) + ClientError, "OpenIDConnect Provider not found for arn {}".format(open_id_arn), ) # deleting a non existing provider should be successful @@ -2685,7 +2680,7 @@ def test_update_account_password_policy_errors(): client = boto3.client("iam", region_name="us-east-1") client.update_account_password_policy.when.called_with( - MaxPasswordAge=1096, MinimumPasswordLength=129, PasswordReusePrevention=25 + MaxPasswordAge=1096, MinimumPasswordLength=129, PasswordReusePrevention=25, ).should.throw( ClientError, "3 validation errors detected: " @@ -2763,7 +2758,7 @@ def test_delete_account_password_policy_errors(): client = boto3.client("iam", region_name="us-east-1") client.delete_account_password_policy.when.called_with().should.throw( - ClientError, "The account policy with name PasswordPolicy cannot be found." + ClientError, "The account policy with name PasswordPolicy cannot be found.", ) @@ -2891,7 +2886,7 @@ def test_list_user_tags(): conn = boto3.client("iam", region_name="us-east-1") conn.create_user(UserName="kenny-bania") conn.create_user( - UserName="jackie-chiles", Tags=[{"Key": "Sue-Allen", "Value": "Oh-Henry"}] + UserName="jackie-chiles", Tags=[{"Key": "Sue-Allen", "Value": "Oh-Henry"}], ) conn.create_user( UserName="cosmo", @@ -2910,7 +2905,7 @@ def test_list_user_tags(): response = conn.list_user_tags(UserName="cosmo") response["Tags"].should.equal( - [{"Key": "Stan", "Value": "The Caddy"}, {"Key": "like-a", "Value": "glove"}] + [{"Key": "Stan", "Value": "The Caddy"}, {"Key": "like-a", "Value": "glove"},] ) response["IsTruncated"].should_not.be.ok @@ -2953,7 +2948,7 @@ def test_delete_account_password_policy_errors(): client = boto3.client("iam", region_name="us-east-1") client.delete_account_password_policy.when.called_with().should.throw( - ClientError, "The account policy with name PasswordPolicy cannot be found." + ClientError, "The account policy with name PasswordPolicy cannot be found.", ) @@ -3040,7 +3035,7 @@ def test_role_config_dict(): basic_assume_role = { "Version": "2012-10-17", "Statement": [ - {"Effect": "Allow", "Principal": {"AWS": "*"}, "Action": "sts:AssumeRole"} + {"Effect": "Allow", "Principal": {"AWS": "*"}, "Action": "sts:AssumeRole",} ], } @@ -3357,7 +3352,7 @@ def test_role_config_client(): # Test non-aggregated pagination assert ( config_client.list_discovered_resources( - resourceType="AWS::IAM::Role", limit=1, nextToken=result["nextToken"] + resourceType="AWS::IAM::Role", limit=1, nextToken=result["nextToken"], )["resourceIdentifiers"][0]["resourceId"] ) != first_result @@ -3787,7 +3782,7 @@ def test_policy_config_client(): # Test non-aggregated pagination assert ( config_client.list_discovered_resources( - resourceType="AWS::IAM::Policy", limit=1, nextToken=result["nextToken"] + resourceType="AWS::IAM::Policy", limit=1, nextToken=result["nextToken"], )["resourceIdentifiers"][0]["resourceId"] ) != first_result @@ -3912,7 +3907,7 @@ def test_policy_config_client(): assert ( config_client.batch_get_resource_config( resourceKeys=[ - {"resourceType": "AWS::IAM::Policy", "resourceId": policies[7]["id"]} + {"resourceType": "AWS::IAM::Policy", "resourceId": policies[7]["id"],} ] )["baseConfigurationItems"][0]["resourceName"] == policies[7]["name"] diff --git a/tests/test_iam/test_iam_cloudformation.py b/tests/test_iam/test_iam_cloudformation.py index aa063273f..a50ed8234 100644 --- a/tests/test_iam/test_iam_cloudformation.py +++ b/tests/test_iam/test_iam_cloudformation.py @@ -2,7 +2,7 @@ import boto3 import yaml import sure # noqa -from nose.tools import assert_raises +import pytest from botocore.exceptions import ClientError from moto import mock_iam, mock_cloudformation, mock_s3, mock_sts @@ -111,9 +111,9 @@ Resources: cf_client.update_stack(StackName=stack_name, TemplateBody=template) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: iam_client.get_user(UserName=original_user_name) - e.exception.response["Error"]["Code"].should.equal("NoSuchEntity") + e.value.response["Error"]["Code"].should.equal("NoSuchEntity") iam_client.get_user(UserName=new_user_name) @@ -175,9 +175,9 @@ Resources: second_user_name.should.equal(second_provisioned_user["PhysicalResourceId"]) iam_client.get_user(UserName=second_user_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: iam_client.get_user(UserName=first_user_name) - e.exception.response["Error"]["Code"].should.equal("NoSuchEntity") + e.value.response["Error"]["Code"].should.equal("NoSuchEntity") @mock_iam @@ -205,9 +205,9 @@ Resources: cf_client.delete_stack(StackName=stack_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: user = iam_client.get_user(UserName=user_name) - e.exception.response["Error"]["Code"].should.equal("NoSuchEntity") + e.value.response["Error"]["Code"].should.equal("NoSuchEntity") @mock_iam @@ -235,9 +235,9 @@ Resources: cf_client.delete_stack(StackName=stack_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: user = iam_client.get_user(UserName=user_name) - e.exception.response["Error"]["Code"].should.equal("NoSuchEntity") + e.value.response["Error"]["Code"].should.equal("NoSuchEntity") @mock_iam diff --git a/tests/test_iam/test_iam_groups.py b/tests/test_iam/test_iam_groups.py index 64d838e2b..85464b44d 100644 --- a/tests/test_iam/test_iam_groups.py +++ b/tests/test_iam/test_iam_groups.py @@ -6,7 +6,7 @@ import boto import boto3 import sure # noqa -from nose.tools import assert_raises +import pytest from boto.exception import BotoServerError from botocore.exceptions import ClientError from moto import mock_iam, mock_iam_deprecated @@ -29,7 +29,7 @@ MOCK_POLICY = """ def test_create_group(): conn = boto.connect_iam() conn.create_group("my-group") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.create_group("my-group") @@ -38,7 +38,7 @@ def test_get_group(): conn = boto.connect_iam() conn.create_group("my-group") conn.get_group("my-group") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.get_group("not-group") @@ -77,10 +77,10 @@ def test_get_all_groups(): @mock_iam_deprecated() def test_add_user_to_group(): conn = boto.connect_iam() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.add_user_to_group("my-group", "my-user") conn.create_group("my-group") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.add_user_to_group("my-group", "my-user") conn.create_user("my-user") conn.add_user_to_group("my-group", "my-user") @@ -89,11 +89,11 @@ def test_add_user_to_group(): @mock_iam_deprecated() def test_remove_user_from_group(): conn = boto.connect_iam() - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.remove_user_from_group("my-group", "my-user") conn.create_group("my-group") conn.create_user("my-user") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.remove_user_from_group("my-group", "my-user") conn.add_user_to_group("my-group", "my-user") conn.remove_user_from_group("my-group", "my-user") @@ -150,7 +150,7 @@ def test_attach_group_policies(): def test_get_group_policy(): conn = boto.connect_iam() conn.create_group("my-group") - with assert_raises(BotoServerError): + with pytest.raises(BotoServerError): conn.get_group_policy("my-group", "my-policy") conn.put_group_policy("my-group", "my-policy", MOCK_POLICY) @@ -199,9 +199,9 @@ def test_delete_group(): @mock_iam def test_delete_unknown_group(): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: conn.delete_group(GroupName="unknown-group") - err.exception.response["Error"]["Code"].should.equal("NoSuchEntity") - err.exception.response["Error"]["Message"].should.equal( + err.value.response["Error"]["Code"].should.equal("NoSuchEntity") + err.value.response["Error"]["Message"].should.equal( "The group with name unknown-group cannot be found." ) diff --git a/tests/test_iam/test_iam_policies.py b/tests/test_iam/test_iam_policies.py index 6348b0cba..fec291c94 100644 --- a/tests/test_iam/test_iam_policies.py +++ b/tests/test_iam/test_iam_policies.py @@ -2,7 +2,7 @@ import json import boto3 from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_iam @@ -1624,14 +1624,14 @@ def test_create_policy_with_valid_policy_documents(): @mock_iam def check_create_policy_with_invalid_policy_document(test_case): conn = boto3.client("iam", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_policy( PolicyName="TestCreatePolicy", PolicyDocument=json.dumps(test_case["document"]), ) - ex.exception.response["Error"]["Code"].should.equal("MalformedPolicyDocument") - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.exception.response["Error"]["Message"].should.equal(test_case["error_message"]) + ex.value.response["Error"]["Code"].should.equal("MalformedPolicyDocument") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.value.response["Error"]["Message"].should.equal(test_case["error_message"]) @mock_iam diff --git a/tests/test_iot/__init__.py b/tests/test_iot/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_iot/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_iot/test_iot.py b/tests/test_iot/test_iot.py index e80a12a0f..7a39e0987 100644 --- a/tests/test_iot/test_iot.py +++ b/tests/test_iot/test_iot.py @@ -6,7 +6,7 @@ import boto3 from moto import mock_iot from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest def generate_thing_group_tree(iot_client, tree_dict, _parent=None): @@ -604,19 +604,19 @@ def test_create_certificate_validation(): client = boto3.client("iot", region_name="us-east-1") cert = client.create_keys_and_certificate(setAsActive=False) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.register_certificate( certificatePem=cert["certificatePem"], setAsActive=False ) - e.exception.response["Error"]["Message"].should.contain( + e.value.response["Error"]["Message"].should.contain( "The certificate is already provisioned or registered" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.register_certificate_without_ca( certificatePem=cert["certificatePem"], status="ACTIVE" ) - e.exception.response["Error"]["Message"].should.contain( + e.value.response["Error"]["Message"].should.contain( "The certificate is already provisioned or registered" ) @@ -643,9 +643,9 @@ def test_delete_policy_validation(): client.create_policy(policyName=policy_name, policyDocument=doc) client.attach_principal_policy(policyName=policy_name, principal=cert_arn) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_policy(policyName=policy_name) - e.exception.response["Error"]["Message"].should.contain( + e.value.response["Error"]["Message"].should.contain( "The policy cannot be deleted as the policy is attached to one or more principals (name=%s)" % policy_name ) @@ -684,27 +684,27 @@ def test_delete_certificate_validation(): client.create_thing(thingName=thing_name) client.attach_thing_principal(thingName=thing_name, principal=cert_arn) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_certificate(certificateId=cert_id) - e.exception.response["Error"]["Message"].should.contain( + e.value.response["Error"]["Message"].should.contain( "Certificate must be deactivated (not ACTIVE) before deletion." ) res = client.list_certificates() res.should.have.key("certificates").which.should.have.length_of(1) client.update_certificate(certificateId=cert_id, newStatus="REVOKED") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_certificate(certificateId=cert_id) - e.exception.response["Error"]["Message"].should.contain( + e.value.response["Error"]["Message"].should.contain( "Things must be detached before deletion (arn: %s)" % cert_arn ) res = client.list_certificates() res.should.have.key("certificates").which.should.have.length_of(1) client.detach_thing_principal(thingName=thing_name, principal=cert_arn) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_certificate(certificateId=cert_id) - e.exception.response["Error"]["Message"].should.contain( + e.value.response["Error"]["Message"].should.contain( "Certificate policies must be detached before deletion (arn: %s)" % cert_arn ) res = client.list_certificates() @@ -798,9 +798,9 @@ def test_principal_policy(): res.should.have.key("policies").which.should.have.length_of(0) res = client.list_policy_principals(policyName=policy_name) res.should.have.key("principals").which.should.have.length_of(0) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.detach_policy(policyName=policy_name, target=cert_arn) - e.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") + e.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") @mock_iot @@ -857,11 +857,11 @@ def test_principal_thing(): res = client.list_thing_principals(thingName=thing_name) res.should.have.key("principals").which.should.have.length_of(0) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_thing_principals(thingName="xxx") - e.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") - e.exception.response["Error"]["Message"].should.equal( + e.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") + e.value.response["Error"]["Message"].should.equal( "Failed to list principals for thing xxx because the thing does not exist in your account" ) @@ -937,11 +937,9 @@ class TestListThingGroup: resp = client.list_thing_groups(parentGroup=self.group_name_1b) resp.should.have.key("thingGroups") resp["thingGroups"].should.have.length_of(0) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_thing_groups(parentGroup="inexistant-group-name") - e.exception.response["Error"]["Code"].should.equal( - "ResourceNotFoundException" - ) + e.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") @mock_iot def test_should_list_all_groups_filtered_by_parent_non_recursively(self): diff --git a/tests/test_iotdata/__init__.py b/tests/test_iotdata/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_iotdata/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_iotdata/test_iotdata.py b/tests/test_iotdata/test_iotdata.py index ac0a04244..bbef49348 100644 --- a/tests/test_iotdata/test_iotdata.py +++ b/tests/test_iotdata/test_iotdata.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import json import boto3 import sure # noqa -from nose.tools import assert_raises +import pytest from botocore.exceptions import ClientError from moto import mock_iotdata, mock_iot @@ -17,7 +17,7 @@ def test_basic(): raw_payload = b'{"state": {"desired": {"led": "on"}}}' iot_client.create_thing(thingName=name) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.get_thing_shadow(thingName=name) res = client.update_thing_shadow(thingName=name, payload=raw_payload) @@ -42,7 +42,7 @@ def test_basic(): payload.should.have.key("timestamp") client.delete_thing_shadow(thingName=name) - with assert_raises(ClientError): + with pytest.raises(ClientError): client.get_thing_shadow(thingName=name) @@ -99,10 +99,10 @@ def test_update(): payload.should.have.key("timestamp") raw_payload = b'{"state": {"desired": {"led": "on"}}, "version": 1}' - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.update_thing_shadow(thingName=name, payload=raw_payload) - ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(409) - ex.exception.response["Error"]["Message"].should.equal("Version conflict") + ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(409) + ex.value.response["Error"]["Message"].should.equal("Version conflict") @mock_iotdata diff --git a/tests/test_kinesis/__init__.py b/tests/test_kinesis/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_kinesis/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_kinesisvideo/__init__.py b/tests/test_kinesisvideo/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_kinesisvideo/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_kinesisvideo/test_kinesisvideo.py b/tests/test_kinesisvideo/test_kinesisvideo.py index de3d9ebbb..abd63bbda 100644 --- a/tests/test_kinesisvideo/test_kinesisvideo.py +++ b/tests/test_kinesisvideo/test_kinesisvideo.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import boto3 import sure # noqa -from nose.tools import assert_raises +import pytest from moto import mock_kinesisvideo from botocore.exceptions import ClientError import json @@ -28,7 +28,7 @@ def test_create_stream_with_same_name(): client.create_stream(StreamName=stream_name, DeviceName=device_name) # cannot create with same stream name - with assert_raises(ClientError): + with pytest.raises(ClientError): client.create_stream(StreamName=stream_name, DeviceName=device_name) @@ -43,7 +43,7 @@ def test_describe_stream(): stream_arn = res["StreamARN"] # cannot create with existing stream name - with assert_raises(ClientError): + with pytest.raises(ClientError): client.create_stream(StreamName=stream_name, DeviceName=device_name) # stream can be described with name @@ -69,7 +69,7 @@ def test_describe_stream_with_name_not_exist(): stream_name_not_exist = "not-exist-stream" # cannot describe with not exist stream name - with assert_raises(ClientError): + with pytest.raises(ClientError): client.describe_stream(StreamName=stream_name_not_exist) @@ -123,7 +123,7 @@ def test_delete_stream_with_arn_not_exist(): # cannot delete with not exist stream stream_arn_not_exist = stream_2_arn - with assert_raises(ClientError): + with pytest.raises(ClientError): client.delete_stream(StreamARN=stream_arn_not_exist) diff --git a/tests/test_kinesisvideoarchivedmedia/__init__.py b/tests/test_kinesisvideoarchivedmedia/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_kinesisvideoarchivedmedia/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_kms/__init__.py b/tests/test_kms/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_kms/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_kms/test_kms.py b/tests/test_kms/test_kms.py index a04a24a82..bb1b013e0 100644 --- a/tests/test_kms/test_kms.py +++ b/tests/test_kms/test_kms.py @@ -9,18 +9,17 @@ import six import sure # noqa from boto.exception import JSONResponseError from boto.kms.exceptions import AlreadyExistsException, NotFoundException -from nose.tools import assert_raises -from parameterized import parameterized +import pytest from moto.core.exceptions import JsonRESTError from moto.kms.models import KmsBackend from moto.kms.exceptions import NotFoundException as MotoNotFoundException from moto import mock_kms_deprecated, mock_kms -PLAINTEXT_VECTORS = ( - (b"some encodeable plaintext",), - (b"some unencodeable plaintext \xec\x8a\xcf\xb6r\xe9\xb5\xeb\xff\xa23\x16",), - ("some unicode characters ø˚∆øˆˆ∆ßçøˆˆçßøˆ¨¥",), -) +PLAINTEXT_VECTORS = [ + b"some encodeable plaintext", + b"some unencodeable plaintext \xec\x8a\xcf\xb6r\xe9\xb5\xeb\xff\xa23\x16", + "some unicode characters ø˚∆øˆˆ∆ßçøˆˆçßøˆ¨¥", +] def _get_encoded_value(plaintext): @@ -192,10 +191,10 @@ def test_generate_data_key(): response = conn.generate_data_key(key_id=key_id, number_of_bytes=32) # CiphertextBlob must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(response["CiphertextBlob"], validate=True) # Plaintext must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(response["Plaintext"], validate=True) response["KeyId"].should.equal(key_arn) @@ -364,10 +363,10 @@ def test__create_alias__raises_if_reserved_alias(): ] for alias_name in reserved_aliases: - with assert_raises(JSONResponseError) as err: + with pytest.raises(JSONResponseError) as err: kms.create_alias(alias_name, key_id) - ex = err.exception + ex = err.value ex.error_message.should.be.none ex.error_code.should.equal("NotAuthorizedException") ex.body.should.equal({"__type": "NotAuthorizedException"}) @@ -392,10 +391,10 @@ def test__create_alias__raises_if_wrong_prefix(): create_resp = kms.create_key() key_id = create_resp["KeyMetadata"]["KeyId"] - with assert_raises(JSONResponseError) as err: + with pytest.raises(JSONResponseError) as err: kms.create_alias("wrongprefix/my-alias", key_id) - ex = err.exception + ex = err.value ex.error_message.should.equal("Invalid identifier") ex.error_code.should.equal("ValidationException") ex.body.should.equal( @@ -415,10 +414,10 @@ def test__create_alias__raises_if_duplicate(): kms.create_alias(alias, key_id) - with assert_raises(AlreadyExistsException) as err: + with pytest.raises(AlreadyExistsException) as err: kms.create_alias(alias, key_id) - ex = err.exception + ex = err.value ex.error_message.should.match( r"An alias with the name arn:aws:kms:{region}:\d{{12}}:{alias} already exists".format( **locals() @@ -450,9 +449,9 @@ def test__create_alias__raises_if_alias_has_restricted_characters(): ] for alias_name in alias_names_with_restricted_characters: - with assert_raises(JSONResponseError) as err: + with pytest.raises(JSONResponseError) as err: kms.create_alias(alias_name, key_id) - ex = err.exception + ex = err.value ex.body["__type"].should.equal("ValidationException") ex.body["message"].should.equal( "1 validation error detected: Value '{alias_name}' at 'aliasName' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-zA-Z0-9:/_-]+$".format( @@ -480,9 +479,9 @@ def test__create_alias__raises_if_alias_has_colon_character(): alias_names_with_restricted_characters = ["alias/my:alias"] for alias_name in alias_names_with_restricted_characters: - with assert_raises(JSONResponseError) as err: + with pytest.raises(JSONResponseError) as err: kms.create_alias(alias_name, key_id) - ex = err.exception + ex = err.value ex.body["__type"].should.equal("ValidationException") ex.body["message"].should.equal( "{alias_name} contains invalid characters for an alias".format(**locals()) @@ -495,7 +494,7 @@ def test__create_alias__raises_if_alias_has_colon_character(): ex.status.should.equal(400) -@parameterized((("alias/my-alias_/",), ("alias/my_alias-/",))) +@pytest.mark.parametrize("alias_name", ["alias/my-alias_/", "alias/my_alias-/"]) @mock_kms_deprecated def test__create_alias__accepted_characters(alias_name): kms = boto.connect_kms() @@ -514,10 +513,10 @@ def test__create_alias__raises_if_target_key_id_is_existing_alias(): kms.create_alias(alias, key_id) - with assert_raises(JSONResponseError) as err: + with pytest.raises(JSONResponseError) as err: kms.create_alias(alias, alias) - ex = err.exception + ex = err.value ex.body["__type"].should.equal("ValidationException") ex.body["message"].should.equal("Aliases must refer to keys. Not aliases") ex.error_code.should.equal("ValidationException") @@ -554,10 +553,10 @@ def test__delete_alias(): def test__delete_alias__raises_if_wrong_prefix(): kms = boto.connect_kms() - with assert_raises(JSONResponseError) as err: + with pytest.raises(JSONResponseError) as err: kms.delete_alias("wrongprefix/my-alias") - ex = err.exception + ex = err.value ex.body["__type"].should.equal("ValidationException") ex.body["message"].should.equal("Invalid identifier") ex.error_code.should.equal("ValidationException") @@ -572,13 +571,13 @@ def test__delete_alias__raises_if_alias_is_not_found(): kms = boto.kms.connect_to_region(region) alias_name = "alias/unexisting-alias" - with assert_raises(NotFoundException) as err: + with pytest.raises(NotFoundException) as err: kms.delete_alias(alias_name) expected_message_match = r"Alias arn:aws:kms:{region}:[0-9]{{12}}:{alias_name} is not found.".format( region=region, alias_name=alias_name ) - ex = err.exception + ex = err.value ex.body["__type"].should.equal("NotFoundException") ex.body["message"].should.match(expected_message_match) ex.box_usage.should.be.none diff --git a/tests/test_kms/test_kms_boto3.py b/tests/test_kms/test_kms_boto3.py index c125c0557..25a8d5942 100644 --- a/tests/test_kms/test_kms_boto3.py +++ b/tests/test_kms/test_kms_boto3.py @@ -10,16 +10,15 @@ import botocore.exceptions import six import sure # noqa from freezegun import freeze_time -from nose.tools import assert_raises -from parameterized import parameterized +import pytest from moto import mock_kms -PLAINTEXT_VECTORS = ( - (b"some encodeable plaintext",), - (b"some unencodeable plaintext \xec\x8a\xcf\xb6r\xe9\xb5\xeb\xff\xa23\x16",), - ("some unicode characters ø˚∆øˆˆ∆ßçøˆˆçßøˆ¨¥",), -) +PLAINTEXT_VECTORS = [ + b"some encodeable plaintext", + b"some unencodeable plaintext \xec\x8a\xcf\xb6r\xe9\xb5\xeb\xff\xa23\x16", + "some unicode characters ø˚∆øˆˆ∆ßçøˆˆçßøˆ¨¥", +] def _get_encoded_value(plaintext): @@ -120,19 +119,20 @@ def test_describe_key(): response["KeyMetadata"].should_not.have.key("SigningAlgorithms") -@parameterized( - ( - ("alias/does-not-exist",), - ("arn:aws:kms:us-east-1:012345678912:alias/does-not-exist",), - ("invalid",), - ) +@pytest.mark.parametrize( + "key_id", + [ + "alias/does-not-exist", + "arn:aws:kms:us-east-1:012345678912:alias/does-not-exist", + "invalid", + ], ) @mock_kms def test_describe_key_via_alias_invalid_alias(key_id): client = boto3.client("kms", region_name="us-east-1") client.create_key(Description="key") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.describe_key(KeyId=key_id) @@ -147,16 +147,16 @@ def test_generate_data_key(): response = kms.generate_data_key(KeyId=key_id, NumberOfBytes=32) # CiphertextBlob must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(response["CiphertextBlob"], validate=True) # Plaintext must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(response["Plaintext"], validate=True) response["KeyId"].should.equal(key_arn) -@parameterized(PLAINTEXT_VECTORS) +@pytest.mark.parametrize("plaintext", PLAINTEXT_VECTORS) @mock_kms def test_encrypt(plaintext): client = boto3.client("kms", region_name="us-west-2") @@ -169,13 +169,13 @@ def test_encrypt(plaintext): response["CiphertextBlob"].should_not.equal(plaintext) # CiphertextBlob must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(response["CiphertextBlob"], validate=True) response["KeyId"].should.equal(key_arn) -@parameterized(PLAINTEXT_VECTORS) +@pytest.mark.parametrize("plaintext", PLAINTEXT_VECTORS) @mock_kms def test_decrypt(plaintext): client = boto3.client("kms", region_name="us-west-2") @@ -188,39 +188,38 @@ def test_decrypt(plaintext): client.create_key(Description="key") # CiphertextBlob must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(encrypt_response["CiphertextBlob"], validate=True) decrypt_response = client.decrypt(CiphertextBlob=encrypt_response["CiphertextBlob"]) # Plaintext must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(decrypt_response["Plaintext"], validate=True) decrypt_response["Plaintext"].should.equal(_get_encoded_value(plaintext)) decrypt_response["KeyId"].should.equal(key_arn) -@parameterized( - ( - ("not-a-uuid",), - ("alias/DoesNotExist",), - ("arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist",), - ("d25652e4-d2d2-49f7-929a-671ccda580c6",), - ( - "arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6", - ), - ) +@pytest.mark.parametrize( + "key_id", + [ + "not-a-uuid", + "alias/DoesNotExist", + "arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist", + "d25652e4-d2d2-49f7-929a-671ccda580c6", + "arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6", + ], ) @mock_kms def test_invalid_key_ids(key_id): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.generate_data_key(KeyId=key_id, NumberOfBytes=5) -@parameterized(PLAINTEXT_VECTORS) +@pytest.mark.parametrize("plaintext", PLAINTEXT_VECTORS) @mock_kms def test_kms_encrypt(plaintext): client = boto3.client("kms", region_name="us-east-1") @@ -357,14 +356,15 @@ def test_list_resource_tags(): assert response["Tags"][0]["TagValue"] == "string" -@parameterized( +@pytest.mark.parametrize( + "kwargs,expected_key_length", ( (dict(KeySpec="AES_256"), 32), (dict(KeySpec="AES_128"), 16), (dict(NumberOfBytes=64), 64), (dict(NumberOfBytes=1), 1), (dict(NumberOfBytes=1024), 1024), - ) + ), ) @mock_kms def test_generate_data_key_sizes(kwargs, expected_key_length): @@ -389,51 +389,52 @@ def test_generate_data_key_decrypt(): assert resp1["Plaintext"] == resp2["Plaintext"] -@parameterized( - ( - (dict(KeySpec="AES_257"),), - (dict(KeySpec="AES_128", NumberOfBytes=16),), - (dict(NumberOfBytes=2048),), - (dict(NumberOfBytes=0),), - (dict(),), - ) +@pytest.mark.parametrize( + "kwargs", + [ + dict(KeySpec="AES_257"), + dict(KeySpec="AES_128", NumberOfBytes=16), + dict(NumberOfBytes=2048), + dict(NumberOfBytes=0), + dict(), + ], ) @mock_kms def test_generate_data_key_invalid_size_params(kwargs): client = boto3.client("kms", region_name="us-east-1") key = client.create_key(Description="generate-data-key-size") - with assert_raises( + with pytest.raises( (botocore.exceptions.ClientError, botocore.exceptions.ParamValidationError) ) as err: client.generate_data_key(KeyId=key["KeyMetadata"]["KeyId"], **kwargs) -@parameterized( - ( - ("alias/DoesNotExist",), - ("arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist",), - ("d25652e4-d2d2-49f7-929a-671ccda580c6",), - ( - "arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6", - ), - ) +@pytest.mark.parametrize( + "key_id", + [ + "alias/DoesNotExist", + "arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist", + "d25652e4-d2d2-49f7-929a-671ccda580c6", + "arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6", + ], ) @mock_kms def test_generate_data_key_invalid_key(key_id): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.generate_data_key(KeyId=key_id, KeySpec="AES_256") -@parameterized( - ( +@pytest.mark.parametrize( + "prefix,append_key_id", + [ ("alias/DoesExist", False), ("arn:aws:kms:us-east-1:012345678912:alias/DoesExist", False), ("", True), ("arn:aws:kms:us-east-1:012345678912:key/", True), - ) + ], ) @mock_kms def test_generate_data_key_all_valid_key_ids(prefix, append_key_id): @@ -461,7 +462,7 @@ def test_generate_data_key_without_plaintext_decrypt(): assert "Plaintext" not in resp1 -@parameterized(PLAINTEXT_VECTORS) +@pytest.mark.parametrize("plaintext", PLAINTEXT_VECTORS) @mock_kms def test_re_encrypt_decrypt(plaintext): client = boto3.client("kms", region_name="us-west-2") @@ -485,7 +486,7 @@ def test_re_encrypt_decrypt(plaintext): ) # CiphertextBlob must NOT be base64-encoded - with assert_raises(Exception): + with pytest.raises(Exception): base64.b64decode(re_encrypt_response["CiphertextBlob"], validate=True) re_encrypt_response["SourceKeyId"].should.equal(key_1_arn) @@ -517,14 +518,14 @@ def test_re_encrypt_to_invalid_destination(): encrypt_response = client.encrypt(KeyId=key_id, Plaintext=b"some plaintext") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.re_encrypt( CiphertextBlob=encrypt_response["CiphertextBlob"], DestinationKeyId="alias/DoesNotExist", ) -@parameterized(((12,), (44,), (91,), (1,), (1024,))) +@pytest.mark.parametrize("number_of_bytes", [12, 44, 91, 1, 1024]) @mock_kms def test_generate_random(number_of_bytes): client = boto3.client("kms", region_name="us-west-2") @@ -535,20 +536,21 @@ def test_generate_random(number_of_bytes): len(response["Plaintext"]).should.equal(number_of_bytes) -@parameterized( - ( +@pytest.mark.parametrize( + "number_of_bytes,error_type", + [ (2048, botocore.exceptions.ClientError), (1025, botocore.exceptions.ClientError), (0, botocore.exceptions.ParamValidationError), (-1, botocore.exceptions.ParamValidationError), (-1024, botocore.exceptions.ParamValidationError), - ) + ], ) @mock_kms def test_generate_random_invalid_number_of_bytes(number_of_bytes, error_type): client = boto3.client("kms", region_name="us-west-2") - with assert_raises(error_type): + with pytest.raises(error_type): client.generate_random(NumberOfBytes=number_of_bytes) @@ -556,7 +558,7 @@ def test_generate_random_invalid_number_of_bytes(number_of_bytes, error_type): def test_enable_key_rotation_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.enable_key_rotation(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -564,7 +566,7 @@ def test_enable_key_rotation_key_not_found(): def test_disable_key_rotation_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.disable_key_rotation(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -572,7 +574,7 @@ def test_disable_key_rotation_key_not_found(): def test_enable_key_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.enable_key(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -580,7 +582,7 @@ def test_enable_key_key_not_found(): def test_disable_key_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.disable_key(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -588,7 +590,7 @@ def test_disable_key_key_not_found(): def test_cancel_key_deletion_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.cancel_key_deletion(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -596,7 +598,7 @@ def test_cancel_key_deletion_key_not_found(): def test_schedule_key_deletion_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.schedule_key_deletion(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -604,7 +606,7 @@ def test_schedule_key_deletion_key_not_found(): def test_get_key_rotation_status_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.get_key_rotation_status(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -612,7 +614,7 @@ def test_get_key_rotation_status_key_not_found(): def test_get_key_policy_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.get_key_policy( KeyId="12366f9b-1230-123d-123e-123e6ae60c02", PolicyName="default" ) @@ -622,7 +624,7 @@ def test_get_key_policy_key_not_found(): def test_list_key_policies_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.list_key_policies(KeyId="12366f9b-1230-123d-123e-123e6ae60c02") @@ -630,7 +632,7 @@ def test_list_key_policies_key_not_found(): def test_put_key_policy_key_not_found(): client = boto3.client("kms", region_name="us-east-1") - with assert_raises(client.exceptions.NotFoundException): + with pytest.raises(client.exceptions.NotFoundException): client.put_key_policy( KeyId="00000000-0000-0000-0000-000000000000", PolicyName="default", diff --git a/tests/test_kms/test_utils.py b/tests/test_kms/test_utils.py index 4446635f3..92d85610e 100644 --- a/tests/test_kms/test_utils.py +++ b/tests/test_kms/test_utils.py @@ -1,8 +1,7 @@ from __future__ import unicode_literals import sure # noqa -from nose.tools import assert_raises -from parameterized import parameterized +import pytest from moto.kms.exceptions import ( AccessDeniedException, @@ -22,7 +21,7 @@ from moto.kms.utils import ( Ciphertext, ) -ENCRYPTION_CONTEXT_VECTORS = ( +ENCRYPTION_CONTEXT_VECTORS = [ ( {"this": "is", "an": "encryption", "context": "example"}, b"an" b"encryption" b"context" b"example" b"this" b"is", @@ -31,8 +30,8 @@ ENCRYPTION_CONTEXT_VECTORS = ( {"a_this": "one", "b_is": "actually", "c_in": "order"}, b"a_this" b"one" b"b_is" b"actually" b"c_in" b"order", ), -) -CIPHERTEXT_BLOB_VECTORS = ( +] +CIPHERTEXT_BLOB_VECTORS = [ ( Ciphertext( key_id="d25652e4-d2d2-49f7-929a-671ccda580c6", @@ -57,7 +56,7 @@ CIPHERTEXT_BLOB_VECTORS = ( b"1234567890123456" b"some ciphertext that is much longer now", ), -) +] def test_generate_data_key(): @@ -74,32 +73,34 @@ def test_generate_master_key(): len(test).should.equal(MASTER_KEY_LEN) -@parameterized(ENCRYPTION_CONTEXT_VECTORS) +@pytest.mark.parametrize("raw,serialized", ENCRYPTION_CONTEXT_VECTORS) def test_serialize_encryption_context(raw, serialized): test = _serialize_encryption_context(raw) test.should.equal(serialized) -@parameterized(CIPHERTEXT_BLOB_VECTORS) +@pytest.mark.parametrize("raw,_serialized", CIPHERTEXT_BLOB_VECTORS) def test_cycle_ciphertext_blob(raw, _serialized): test_serialized = _serialize_ciphertext_blob(raw) test_deserialized = _deserialize_ciphertext_blob(test_serialized) test_deserialized.should.equal(raw) -@parameterized(CIPHERTEXT_BLOB_VECTORS) +@pytest.mark.parametrize("raw,serialized", CIPHERTEXT_BLOB_VECTORS) def test_serialize_ciphertext_blob(raw, serialized): test = _serialize_ciphertext_blob(raw) test.should.equal(serialized) -@parameterized(CIPHERTEXT_BLOB_VECTORS) +@pytest.mark.parametrize("raw,serialized", CIPHERTEXT_BLOB_VECTORS) def test_deserialize_ciphertext_blob(raw, serialized): test = _deserialize_ciphertext_blob(serialized) test.should.equal(raw) -@parameterized(((ec[0],) for ec in ENCRYPTION_CONTEXT_VECTORS)) +@pytest.mark.parametrize( + "encryption_context", [ec[0] for ec in ENCRYPTION_CONTEXT_VECTORS] +) def test_encrypt_decrypt_cycle(encryption_context): plaintext = b"some secret plaintext" master_key = Key("nop", "nop", "nop", "nop", "nop") @@ -123,7 +124,7 @@ def test_encrypt_decrypt_cycle(encryption_context): def test_encrypt_unknown_key_id(): - with assert_raises(NotFoundException): + with pytest.raises(NotFoundException): encrypt( master_keys={}, key_id="anything", @@ -136,7 +137,7 @@ def test_decrypt_invalid_ciphertext_format(): master_key = Key("nop", "nop", "nop", "nop", "nop") master_key_map = {master_key.id: master_key} - with assert_raises(InvalidCiphertextException): + with pytest.raises(InvalidCiphertextException): decrypt(master_keys=master_key_map, ciphertext_blob=b"", encryption_context={}) @@ -148,7 +149,7 @@ def test_decrypt_unknwown_key_id(): b"some ciphertext" ) - with assert_raises(AccessDeniedException): + with pytest.raises(AccessDeniedException): decrypt(master_keys={}, ciphertext_blob=ciphertext_blob, encryption_context={}) @@ -161,7 +162,7 @@ def test_decrypt_invalid_ciphertext(): b"some ciphertext" ) - with assert_raises(InvalidCiphertextException): + with pytest.raises(InvalidCiphertextException): decrypt( master_keys=master_key_map, ciphertext_blob=ciphertext_blob, @@ -181,7 +182,7 @@ def test_decrypt_invalid_encryption_context(): encryption_context={"some": "encryption", "context": "here"}, ) - with assert_raises(InvalidCiphertextException): + with pytest.raises(InvalidCiphertextException): decrypt( master_keys=master_key_map, ciphertext_blob=ciphertext_blob, diff --git a/tests/test_logs/__init__.py b/tests/test_logs/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_logs/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_logs/test_integration.py b/tests/test_logs/test_integration.py index bda233485..eab839970 100644 --- a/tests/test_logs/test_integration.py +++ b/tests/test_logs/test_integration.py @@ -7,7 +7,7 @@ import zlib from botocore.exceptions import ClientError from io import BytesIO from moto import mock_logs, mock_lambda, mock_iam -from nose.tools import assert_raises +import pytest from zipfile import ZipFile, ZIP_DEFLATED @@ -78,7 +78,7 @@ def test_put_subscription_filter_update(): # when # only one subscription filter can be associated with a log group - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client_logs.put_subscription_filter( logGroupName=log_group_name, filterName="test-2", @@ -87,7 +87,7 @@ def test_put_subscription_filter_update(): ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("PutSubscriptionFilter") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("LimitExceededException") @@ -96,6 +96,7 @@ def test_put_subscription_filter_update(): @mock_lambda @mock_logs +@pytest.mark.network def test_put_subscription_filter_with_lambda(): # given region_name = "us-east-1" @@ -240,13 +241,13 @@ def test_delete_subscription_filter_errors(): ) # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client_logs.delete_subscription_filter( logGroupName="not-existing-log-group", filterName="test", ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeleteSubscriptionFilter") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") @@ -255,13 +256,13 @@ def test_delete_subscription_filter_errors(): ) # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client_logs.delete_subscription_filter( logGroupName="/test", filterName="wrong-filter-name", ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeleteSubscriptionFilter") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") @@ -278,7 +279,7 @@ def test_put_subscription_filter_errors(): client.create_log_group(logGroupName=log_group_name) # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.put_subscription_filter( logGroupName="not-existing-log-group", filterName="test", @@ -287,7 +288,7 @@ def test_put_subscription_filter_errors(): ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("PutSubscriptionFilter") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") @@ -296,7 +297,7 @@ def test_put_subscription_filter_errors(): ) # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.put_subscription_filter( logGroupName="/test", filterName="test", @@ -305,7 +306,7 @@ def test_put_subscription_filter_errors(): ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("PutSubscriptionFilter") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterException") @@ -315,7 +316,7 @@ def test_put_subscription_filter_errors(): ) # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.put_subscription_filter( logGroupName="/test", filterName="test", @@ -324,7 +325,7 @@ def test_put_subscription_filter_errors(): ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("PutSubscriptionFilter") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterException") diff --git a/tests/test_logs/test_logs.py b/tests/test_logs/test_logs.py index 648d561aa..fc9868ffb 100644 --- a/tests/test_logs/test_logs.py +++ b/tests/test_logs/test_logs.py @@ -5,8 +5,8 @@ import six from botocore.exceptions import ClientError from moto import mock_logs, settings -from nose.tools import assert_raises -from nose import SkipTest +import pytest +from unittest import SkipTest _logs_region = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2" @@ -28,13 +28,13 @@ def test_exceptions(): log_group_name = "dummy" log_stream_name = "dummp-stream" conn.create_log_group(logGroupName=log_group_name) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_log_group(logGroupName=log_group_name) # descrine_log_groups is not implemented yet conn.create_log_stream(logGroupName=log_group_name, logStreamName=log_stream_name) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.create_log_stream( logGroupName=log_group_name, logStreamName=log_stream_name ) @@ -45,7 +45,7 @@ def test_exceptions(): logEvents=[{"timestamp": 0, "message": "line"}], ) - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.put_log_events( logGroupName=log_group_name, logStreamName="invalid-stream", @@ -117,7 +117,7 @@ def test_filter_logs_raises_if_filter_pattern(): conn.put_log_events( logGroupName=log_group_name, logStreamName=log_stream_name, logEvents=messages ) - with assert_raises(NotImplementedError): + with pytest.raises(NotImplementedError): conn.filter_log_events( logGroupName=log_group_name, logStreamNames=[log_stream_name], @@ -332,13 +332,13 @@ def test_get_log_events_errors(): client.create_log_group(logGroupName=log_group_name) client.create_log_stream(logGroupName=log_group_name, logStreamName=log_stream_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_log_events( logGroupName=log_group_name, logStreamName=log_stream_name, nextToken="n/00000000000000000000000000000000000000000000000000000000", ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetLogEvents") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.equal("InvalidParameterException") @@ -346,13 +346,13 @@ def test_get_log_events_errors(): "The specified nextToken is invalid." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_log_events( logGroupName=log_group_name, logStreamName=log_stream_name, nextToken="not-existing-token", ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetLogEvents") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.equal("InvalidParameterException") @@ -447,11 +447,11 @@ def test_describe_subscription_filters_errors(): client = boto3.client("logs", "us-east-1") # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.describe_subscription_filters(logGroupName="not-existing-log-group",) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeSubscriptionFilters") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") diff --git a/tests/test_managedblockchain/test_managedblockchain_proposalvotes.py b/tests/test_managedblockchain/test_managedblockchain_proposalvotes.py index eda728398..e8f4043d5 100644 --- a/tests/test_managedblockchain/test_managedblockchain_proposalvotes.py +++ b/tests/test_managedblockchain/test_managedblockchain_proposalvotes.py @@ -5,7 +5,7 @@ import os import boto3 import sure # noqa from freezegun import freeze_time -from nose import SkipTest +from unittest import SkipTest from moto import mock_managedblockchain, settings from . import helpers diff --git a/tests/test_opsworks/__init__.py b/tests/test_opsworks/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_opsworks/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py index 65f964082..07cd3afa6 100644 --- a/tests/test_organizations/test_organizations_boto3.py +++ b/tests/test_organizations/test_organizations_boto3.py @@ -7,7 +7,7 @@ import json import six import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_organizations from moto.core import ACCOUNT_ID @@ -61,9 +61,9 @@ def test_describe_organization(): @mock_organizations def test_describe_organization_exception(): client = boto3.client("organizations", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.describe_organization() - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeOrganization") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AWSOrganizationsNotInUseException") @@ -110,11 +110,11 @@ def test_describe_organizational_unit(): def test_describe_organizational_unit_exception(): client = boto3.client("organizations", region_name="us-east-1") org = client.create_organization(FeatureSet="ALL")["Organization"] - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.describe_organizational_unit( OrganizationalUnitId=utils.make_random_root_id() ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeOrganizationalUnit") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain( @@ -139,11 +139,11 @@ def test_list_organizational_units_for_parent(): @mock_organizations def test_list_organizational_units_for_parent_exception(): client = boto3.client("organizations", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_organizational_units_for_parent( ParentId=utils.make_random_root_id() ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListOrganizationalUnitsForParent") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("ParentNotFoundException") @@ -193,9 +193,9 @@ def test_describe_account(): @mock_organizations def test_describe_account_exception(): client = boto3.client("organizations", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.describe_account(AccountId=utils.make_random_account_id()) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribeAccount") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotFoundException") @@ -335,17 +335,17 @@ def test_list_children_exception(): client = boto3.client("organizations", region_name="us-east-1") org = client.create_organization(FeatureSet="ALL")["Organization"] root_id = client.list_roots()["Roots"][0]["Id"] - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_children( ParentId=utils.make_random_root_id(), ChildType="ACCOUNT" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListChildren") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("ParentNotFoundException") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_children(ParentId=root_id, ChildType="BLEE") - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListChildren") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -387,7 +387,7 @@ def test_create_policy_errors(): # invalid policy type # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_policy( Content=json.dumps(policy_doc01), Description="moto", @@ -396,7 +396,7 @@ def test_create_policy_errors(): ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreatePolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -427,15 +427,15 @@ def test_describe_policy_exception(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL")["Organization"] policy_id = "p-47fhe9s3" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.describe_policy(PolicyId=policy_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribePolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("PolicyNotFoundException") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.describe_policy(PolicyId="meaninglessstring") - ex = e.exception + ex = e.value ex.operation_name.should.equal("DescribePolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -514,9 +514,9 @@ def test_detach_policy_root_ou_not_found_exception(): )["Policy"]["PolicySummary"]["Id"] client.attach_policy(PolicyId=policy_id, TargetId=root_id) client.attach_policy(PolicyId=policy_id, TargetId=account_id) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.detach_policy(PolicyId=policy_id, TargetId="r-xy85") - ex = e.exception + ex = e.value ex.operation_name.should.equal("DetachPolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain( @@ -539,11 +539,11 @@ def test_detach_policy_ou_not_found_exception(): Type="SERVICE_CONTROL_POLICY", )["Policy"]["PolicySummary"]["Id"] client.attach_policy(PolicyId=policy_id, TargetId=ou_id) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.detach_policy( PolicyId=policy_id, TargetId="ou-zx86-z3x4yr2t7" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DetachPolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain( @@ -565,9 +565,9 @@ def test_detach_policy_account_id_not_found_exception(): Type="SERVICE_CONTROL_POLICY", )["Policy"]["PolicySummary"]["Id"] client.attach_policy(PolicyId=policy_id, TargetId=account_id) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.detach_policy(PolicyId=policy_id, TargetId="111619863336") - ex = e.exception + ex = e.value ex.operation_name.should.equal("DetachPolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotFoundException") @@ -591,9 +591,9 @@ def test_detach_policy_invalid_target_exception(): Type="SERVICE_CONTROL_POLICY", )["Policy"]["PolicySummary"]["Id"] client.attach_policy(PolicyId=policy_id, TargetId=ou_id) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.detach_policy(PolicyId=policy_id, TargetId="invalidtargetid") - ex = e.exception + ex = e.value ex.operation_name.should.equal("DetachPolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -626,9 +626,9 @@ def test_delete_policy_exception(): client = boto3.client("organizations", region_name="us-east-1") org = client.create_organization(FeatureSet="ALL")["Organization"] non_existent_policy_id = utils.make_random_policy_id() - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.delete_policy(PolicyId=non_existent_policy_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeletePolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("PolicyNotFoundException") @@ -642,9 +642,9 @@ def test_delete_policy_exception(): )["Policy"]["PolicySummary"]["Id"] root_id = client.list_roots()["Roots"][0]["Id"] client.attach_policy(PolicyId=policy_id, TargetId=root_id) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.delete_policy(PolicyId=policy_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeletePolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("PolicyInUseException") @@ -663,36 +663,36 @@ def test_attach_policy_exception(): Name="MockServiceControlPolicy", Type="SERVICE_CONTROL_POLICY", )["Policy"]["PolicySummary"]["Id"] - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.attach_policy(PolicyId=policy_id, TargetId=root_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AttachPolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain( "OrganizationalUnitNotFoundException" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.attach_policy(PolicyId=policy_id, TargetId=ou_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AttachPolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain( "OrganizationalUnitNotFoundException" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.attach_policy(PolicyId=policy_id, TargetId=account_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AttachPolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotFoundException") ex.response["Error"]["Message"].should.equal( "You specified an account that doesn't exist." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.attach_policy( PolicyId=policy_id, TargetId="meaninglessstring" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AttachPolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -729,9 +729,9 @@ def test_update_policy_exception(): client = boto3.client("organizations", region_name="us-east-1") org = client.create_organization(FeatureSet="ALL")["Organization"] non_existent_policy_id = utils.make_random_policy_id() - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.update_policy(PolicyId=non_existent_policy_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("UpdatePolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("PolicyNotFoundException") @@ -791,32 +791,32 @@ def test_list_policies_for_target_exception(): root_id = client.list_roots()["Roots"][0]["Id"] ou_id = "ou-gi99-i7r8eh2i2" account_id = "126644886543" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_policies_for_target( TargetId=ou_id, Filter="SERVICE_CONTROL_POLICY" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListPoliciesForTarget") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain( "OrganizationalUnitNotFoundException" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_policies_for_target( TargetId=account_id, Filter="SERVICE_CONTROL_POLICY" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListPoliciesForTarget") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotFoundException") ex.response["Error"]["Message"].should.equal( "You specified an account that doesn't exist." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_policies_for_target( TargetId="meaninglessstring", Filter="SERVICE_CONTROL_POLICY" ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListPoliciesForTarget") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -824,13 +824,13 @@ def test_list_policies_for_target_exception(): # not existing root # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_policies_for_target( TargetId="r-0000", Filter="SERVICE_CONTROL_POLICY" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListPoliciesForTarget") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("TargetNotFoundException") @@ -840,11 +840,11 @@ def test_list_policies_for_target_exception(): # invalid policy type # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_policies_for_target(TargetId=root_id, Filter="MOTO") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListPoliciesForTarget") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -887,15 +887,15 @@ def test_list_targets_for_policy_exception(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL")["Organization"] policy_id = "p-47fhe9s3" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_targets_for_policy(PolicyId=policy_id) - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListTargetsForPolicy") ex.response["Error"]["Code"].should.equal("400") ex.response["Error"]["Message"].should.contain("PolicyNotFoundException") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: response = client.list_targets_for_policy(PolicyId="meaninglessstring") - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListTargetsForPolicy") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -929,11 +929,11 @@ def test_tag_resource_errors(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.tag_resource( ResourceId="000000000000", Tags=[{"Key": "key", "Value": "value"},], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("TagResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -961,9 +961,9 @@ def test_list_tags_for_resource_errors(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_tags_for_resource(ResourceId="000000000000") - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListTagsForResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -998,9 +998,9 @@ def test_untag_resource_errors(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.untag_resource(ResourceId="000000000000", TagKeys=["key"]) - ex = e.exception + ex = e.value ex.operation_name.should.equal("UntagResource") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1035,11 +1035,11 @@ def test_update_organizational_unit_duplicate_error(): response = client.create_organizational_unit(ParentId=root_id, Name=ou_name) validate_organizational_unit(org, response) response["OrganizationalUnit"]["Name"].should.equal(ou_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.update_organizational_unit( OrganizationalUnitId=response["OrganizationalUnit"]["Id"], Name=ou_name ) - exc = e.exception + exc = e.value exc.operation_name.should.equal("UpdateOrganizationalUnit") exc.response["Error"]["Code"].should.contain("DuplicateOrganizationalUnitException") exc.response["Error"]["Message"].should.equal( @@ -1081,9 +1081,9 @@ def test_enable_aws_service_access(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.enable_aws_service_access(ServicePrincipal="moto.amazonaws.com") - ex = e.exception + ex = e.value ex.operation_name.should.equal("EnableAWSServiceAccess") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1142,9 +1142,9 @@ def test_disable_aws_service_access_errors(): client = boto3.client("organizations", region_name="us-east-1") client.create_organization(FeatureSet="ALL") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.disable_aws_service_access(ServicePrincipal="moto.amazonaws.com") - ex = e.exception + ex = e.value ex.operation_name.should.equal("DisableAWSServiceAccess") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1199,13 +1199,13 @@ def test_register_delegated_administrator_errors(): # register master Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.register_delegated_administrator( AccountId=ACCOUNT_ID, ServicePrincipal="ssm.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("RegisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ConstraintViolationException") @@ -1215,13 +1215,13 @@ def test_register_delegated_administrator_errors(): # register not existing Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.register_delegated_administrator( AccountId="000000000000", ServicePrincipal="ssm.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("RegisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotFoundException") @@ -1231,13 +1231,13 @@ def test_register_delegated_administrator_errors(): # register not supported service # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.register_delegated_administrator( AccountId=account_id, ServicePrincipal="moto.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("RegisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1247,13 +1247,13 @@ def test_register_delegated_administrator_errors(): # register service again # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.register_delegated_administrator( AccountId=account_id, ServicePrincipal="ssm.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("RegisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountAlreadyRegisteredException") @@ -1319,11 +1319,11 @@ def test_list_delegated_administrators_erros(): # list not supported service # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_delegated_administrators(ServicePrincipal="moto.amazonaws.com") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListDelegatedAdministrators") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1365,11 +1365,11 @@ def test_list_delegated_services_for_account_erros(): # list services for not existing Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_delegated_services_for_account(AccountId="000000000000") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListDelegatedServicesForAccount") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AWSOrganizationsNotInUseException") @@ -1379,11 +1379,11 @@ def test_list_delegated_services_for_account_erros(): # list services for not registered Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.list_delegated_services_for_account(AccountId=ACCOUNT_ID) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("ListDelegatedServicesForAccount") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotRegisteredException") @@ -1425,13 +1425,13 @@ def test_deregister_delegated_administrator_erros(): # deregister master Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.deregister_delegated_administrator( AccountId=ACCOUNT_ID, ServicePrincipal="ssm.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeregisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ConstraintViolationException") @@ -1441,13 +1441,13 @@ def test_deregister_delegated_administrator_erros(): # deregister not existing Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.deregister_delegated_administrator( AccountId="000000000000", ServicePrincipal="ssm.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeregisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotFoundException") @@ -1457,13 +1457,13 @@ def test_deregister_delegated_administrator_erros(): # deregister not registered Account # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.deregister_delegated_administrator( AccountId=account_id, ServicePrincipal="ssm.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeregisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("AccountNotRegisteredException") @@ -1478,13 +1478,13 @@ def test_deregister_delegated_administrator_erros(): # deregister not registered service # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.deregister_delegated_administrator( AccountId=account_id, ServicePrincipal="guardduty.amazonaws.com" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeregisterDelegatedAdministrator") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1529,13 +1529,13 @@ def test_enable_policy_type_errors(): # not existing root # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.enable_policy_type( RootId="r-0000", PolicyType="AISERVICES_OPT_OUT_POLICY" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("EnablePolicyType") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("RootNotFoundException") @@ -1545,11 +1545,11 @@ def test_enable_policy_type_errors(): # enable policy again ('SERVICE_CONTROL_POLICY' is enabled by default) # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.enable_policy_type(RootId=root_id, PolicyType="SERVICE_CONTROL_POLICY") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("EnablePolicyType") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("PolicyTypeAlreadyEnabledException") @@ -1559,11 +1559,11 @@ def test_enable_policy_type_errors(): # invalid policy type # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.enable_policy_type(RootId=root_id, PolicyType="MOTO") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("EnablePolicyType") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") @@ -1604,13 +1604,13 @@ def test_disable_policy_type_errors(): # not existing root # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.disable_policy_type( RootId="r-0000", PolicyType="AISERVICES_OPT_OUT_POLICY" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DisablePolicyType") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("RootNotFoundException") @@ -1620,13 +1620,13 @@ def test_disable_policy_type_errors(): # disable not enabled policy # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.disable_policy_type( RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY" ) # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DisablePolicyType") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("PolicyTypeNotEnabledException") @@ -1636,11 +1636,11 @@ def test_disable_policy_type_errors(): # invalid policy type # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.disable_policy_type(RootId=root_id, PolicyType="MOTO") # then - ex = e.exception + ex = e.value ex.operation_name.should.equal("DisablePolicyType") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidInputException") diff --git a/tests/test_packages/__init__.py b/tests/test_packages/__init__.py index 05b1d476b..01fe5ab1f 100644 --- a/tests/test_packages/__init__.py +++ b/tests/test_packages/__init__.py @@ -6,4 +6,3 @@ import logging logging.getLogger("boto").setLevel(logging.CRITICAL) logging.getLogger("boto3").setLevel(logging.CRITICAL) logging.getLogger("botocore").setLevel(logging.CRITICAL) -logging.getLogger("nose").setLevel(logging.CRITICAL) diff --git a/tests/test_polly/__init__.py b/tests/test_polly/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_polly/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_polly/test_polly.py b/tests/test_polly/test_polly.py index 5428cdeb7..6c99d0538 100644 --- a/tests/test_polly/test_polly.py +++ b/tests/test_polly/test_polly.py @@ -3,19 +3,19 @@ from __future__ import unicode_literals from botocore.exceptions import ClientError import boto3 import sure # noqa -from nose.tools import assert_raises +import pytest from moto import mock_polly # Polly only available in a few regions DEFAULT_REGION = "eu-west-1" LEXICON_XML = """ - W3C diff --git a/tests/test_ram/test_ram.py b/tests/test_ram/test_ram.py index 624221929..73a23331b 100644 --- a/tests/test_ram/test_ram.py +++ b/tests/test_ram/test_ram.py @@ -4,7 +4,7 @@ from datetime import datetime import boto3 import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_ram, mock_organizations from moto.core import ACCOUNT_ID @@ -65,9 +65,9 @@ def test_create_resource_share_errors(): # invalid ARN # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_resource_share(name="test", resourceArns=["inalid-arn"]) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("MalformedArnException") @@ -78,11 +78,11 @@ def test_create_resource_share_errors(): # valid ARN, but not shareable resource type # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_resource_share( name="test", resourceArns=["arn:aws:iam::{}:role/test".format(ACCOUNT_ID)] ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("MalformedArnException") @@ -92,7 +92,7 @@ def test_create_resource_share_errors(): # invalid principal ID # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_resource_share( name="test", principals=["invalid"], @@ -102,7 +102,7 @@ def test_create_resource_share_errors(): ) ], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterException") @@ -162,7 +162,7 @@ def test_create_resource_share_with_organization_errors(): # unknown Organization # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_resource_share( name="test", principals=[ @@ -174,7 +174,7 @@ def test_create_resource_share_with_organization_errors(): ) ], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("UnknownResourceException") @@ -184,7 +184,7 @@ def test_create_resource_share_with_organization_errors(): # unknown OU # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.create_resource_share( name="test", principals=[ @@ -196,7 +196,7 @@ def test_create_resource_share_with_organization_errors(): ) ], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("CreateResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("UnknownResourceException") @@ -236,9 +236,9 @@ def test_get_resource_shares_errors(): # invalid resource owner # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_resource_shares(resourceOwner="invalid") - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetResourceShares") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterException") @@ -282,14 +282,14 @@ def test_update_resource_share_errors(): # invalid resource owner # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.update_resource_share( resourceShareArn="arn:aws:ram:us-east-1:{}:resource-share/not-existing".format( ACCOUNT_ID ), name="test-update", ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("UpdateResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("UnknownResourceException") @@ -328,13 +328,13 @@ def test_delete_resource_share_errors(): # invalid resource owner # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.delete_resource_share( resourceShareArn="arn:aws:ram:us-east-1:{}:resource-share/not-existing".format( ACCOUNT_ID ) ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("DeleteResourceShare") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("UnknownResourceException") @@ -368,9 +368,9 @@ def test_enable_sharing_with_aws_organization_errors(): # no Organization defined # when - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.enable_sharing_with_aws_organization() - ex = e.exception + ex = e.value ex.operation_name.should.equal("EnableSharingWithAwsOrganization") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("OperationNotPermittedException") diff --git a/tests/test_rds/__init__.py b/tests/test_rds/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_rds/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_rds2/__init__.py b/tests/test_rds2/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_rds2/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_redshift/__init__.py b/tests/test_redshift/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_redshift/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_route53/__init__.py b/tests/test_route53/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_route53/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_route53/test_route53.py b/tests/test_route53/test_route53.py index 8c036441c..68436a40e 100644 --- a/tests/test_route53/test_route53.py +++ b/tests/test_route53/test_route53.py @@ -10,7 +10,7 @@ import sure # noqa import uuid import botocore -from nose.tools import assert_raises +import pytest from moto import mock_route53, mock_route53_deprecated @@ -855,7 +855,7 @@ def test_change_resource_record_invalid(): ], } - with assert_raises(botocore.exceptions.ClientError): + with pytest.raises(botocore.exceptions.ClientError): conn.change_resource_record_sets( HostedZoneId=hosted_zone_id, ChangeBatch=invalid_a_record_payload ) @@ -878,7 +878,7 @@ def test_change_resource_record_invalid(): ], } - with assert_raises(botocore.exceptions.ClientError): + with pytest.raises(botocore.exceptions.ClientError): conn.change_resource_record_sets( HostedZoneId=hosted_zone_id, ChangeBatch=invalid_cname_record_payload ) diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index d8f08e9ef..bac03ed6a 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -24,13 +24,11 @@ from botocore.handlers import disable_signing from boto.s3.connection import S3Connection from boto.s3.key import Key from freezegun import freeze_time -from parameterized import parameterized import six import requests -import tests.backport_assert_raises # noqa from moto.s3.responses import DEFAULT_REGION_NAME -from nose import SkipTest -from nose.tools import assert_raises +from unittest import SkipTest +import pytest import sure # noqa @@ -49,8 +47,8 @@ else: def reduced_min_part_size(f): - """ speed up tests by temporarily making the multipart minimum part size - small + """speed up tests by temporarily making the multipart minimum part size + small """ orig_size = s3model.UPLOAD_PART_MIN_SIZE @@ -427,7 +425,7 @@ def test_copy_key(): bucket.get_key("new-key").get_contents_as_string().should.equal(b"some value") -@parameterized([("the-unicode-💩-key",), ("key-with?question-mark",)]) +@pytest.mark.parametrize("key_name", ["the-unicode-💩-key", "key-with?question-mark"]) @mock_s3_deprecated def test_copy_key_with_special_chars(key_name): conn = boto.connect_s3("the_key", "the_secret") @@ -523,7 +521,7 @@ def test_create_existing_bucket(): "Trying to create a bucket that already exists should raise an Error" conn = boto.s3.connect_to_region("us-west-2") conn.create_bucket("foobar", location="us-west-2") - with assert_raises(S3CreateError): + with pytest.raises(S3CreateError): conn.create_bucket("foobar", location="us-west-2") @@ -665,9 +663,9 @@ def test_delete_keys_invalid(): @mock_s3 def test_boto3_delete_empty_keys_list(): - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: boto3.client("s3").delete_objects(Bucket="foobar", Delete={"Objects": []}) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" @mock_s3_deprecated @@ -1015,9 +1013,9 @@ def test_s3_object_in_public_bucket(): bucket.put_object(ACL="private", Body=b"ABCD", Key="file.txt") - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3_anonymous.Object(key="file.txt", bucket_name="test-bucket").get() - exc.exception.response["Error"]["Code"].should.equal("403") + exc.value.response["Error"]["Code"].should.equal("403") @mock_s3 @@ -1089,9 +1087,9 @@ def test_s3_object_in_private_bucket(): s3_anonymous = boto3.resource("s3") s3_anonymous.meta.client.meta.events.register("choose-signer.s3.*", disable_signing) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3_anonymous.Object(key="file.txt", bucket_name="test-bucket").get() - exc.exception.response["Error"]["Code"].should.equal("403") + exc.value.response["Error"]["Code"].should.equal("403") bucket.put_object(ACL="public-read", Body=b"ABCD", Key="file.txt") contents = ( @@ -1181,9 +1179,9 @@ if not settings.TEST_SERVER_MODE: bucket_name = "asdfasdfsdfdsfasda" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.create_bucket(Bucket=bucket_name) - e.exception.response["Error"]["Message"].should.equal( + e.value.response["Error"]["Message"].should.equal( "The unspecified location constraint is incompatible for the region specific endpoint this request was sent to." ) @@ -1200,35 +1198,34 @@ if not settings.TEST_SERVER_MODE: client = boto3.client("s3control", region_name="us-west-2") # With an invalid account ID: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_public_access_block(AccountId="111111111111") - assert ce.exception.response["Error"]["Code"] == "AccessDenied" + assert ce.value.response["Error"]["Code"] == "AccessDenied" # Without one defined: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_public_access_block(AccountId=ACCOUNT_ID) assert ( - ce.exception.response["Error"]["Code"] - == "NoSuchPublicAccessBlockConfiguration" + ce.value.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration" ) # Put a with an invalid account ID: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_public_access_block( AccountId="111111111111", PublicAccessBlockConfiguration={"BlockPublicAcls": True}, ) - assert ce.exception.response["Error"]["Code"] == "AccessDenied" + assert ce.value.response["Error"]["Code"] == "AccessDenied" # Put with an invalid PAB: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_public_access_block( AccountId=ACCOUNT_ID, PublicAccessBlockConfiguration={} ) - assert ce.exception.response["Error"]["Code"] == "InvalidRequest" + assert ce.value.response["Error"]["Code"] == "InvalidRequest" assert ( "Must specify at least one configuration." - in ce.exception.response["Error"]["Message"] + in ce.value.response["Error"]["Message"] ) # Correct PAB: @@ -1255,19 +1252,18 @@ if not settings.TEST_SERVER_MODE: } # Delete with an invalid account ID: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.delete_public_access_block(AccountId="111111111111") - assert ce.exception.response["Error"]["Code"] == "AccessDenied" + assert ce.value.response["Error"]["Code"] == "AccessDenied" # Delete successfully: client.delete_public_access_block(AccountId=ACCOUNT_ID) # Confirm that it's deleted: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_public_access_block(AccountId=ACCOUNT_ID) assert ( - ce.exception.response["Error"]["Code"] - == "NoSuchPublicAccessBlockConfiguration" + ce.value.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration" ) @mock_s3 @@ -1462,13 +1458,11 @@ if not settings.TEST_SERVER_MODE: ) # Without a PAB in place: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: config_client.get_resource_config_history( resourceType="AWS::S3::AccountPublicAccessBlock", resourceId=ACCOUNT_ID ) - assert ( - ce.exception.response["Error"]["Code"] == "ResourceNotDiscoveredException" - ) + assert ce.value.response["Error"]["Code"] == "ResourceNotDiscoveredException" # aggregate result = config_client.batch_get_resource_config( resourceKeys=[ @@ -1633,10 +1627,10 @@ def test_policy(): } ) - with assert_raises(S3ResponseError) as err: + with pytest.raises(S3ResponseError) as err: bucket.get_policy() - ex = err.exception + ex = err.value ex.box_usage.should.be.none ex.error_code.should.equal("NoSuchBucketPolicy") ex.message.should.equal("The bucket policy does not exist") @@ -1654,7 +1648,7 @@ def test_policy(): bucket.delete_policy() - with assert_raises(S3ResponseError) as err: + with pytest.raises(S3ResponseError) as err: bucket.get_policy() @@ -1976,22 +1970,22 @@ def test_bucket_create_duplicate(): s3.create_bucket( Bucket="blah", CreateBucketConfiguration={"LocationConstraint": "us-west-2"} ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.create_bucket( Bucket="blah", CreateBucketConfiguration={"LocationConstraint": "us-west-2"} ) - exc.exception.response["Error"]["Code"].should.equal("BucketAlreadyExists") + exc.value.response["Error"]["Code"].should.equal("BucketAlreadyExists") @mock_s3 def test_bucket_create_force_us_east_1(): s3 = boto3.resource("s3", region_name=DEFAULT_REGION_NAME) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.create_bucket( Bucket="blah", CreateBucketConfiguration={"LocationConstraint": DEFAULT_REGION_NAME}, ) - exc.exception.response["Error"]["Code"].should.equal("InvalidLocationConstraint") + exc.value.response["Error"]["Code"].should.equal("InvalidLocationConstraint") @mock_s3 @@ -2011,10 +2005,10 @@ def test_boto3_bucket_create_eu_central(): @mock_s3 def test_bucket_create_empty_bucket_configuration_should_return_malformed_xml_error(): s3 = boto3.resource("s3", region_name="us-east-1") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.create_bucket(Bucket="whatever", CreateBucketConfiguration={}) - e.exception.response["Error"]["Code"].should.equal("MalformedXML") - e.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + e.value.response["Error"]["Code"].should.equal("MalformedXML") + e.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) @mock_s3 @@ -2028,11 +2022,11 @@ def test_boto3_head_object(): Bucket="blah", Key="hello.txt" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.Object("blah", "hello2.txt").meta.client.head_object( Bucket="blah", Key="hello_bad.txt" ) - e.exception.response["Error"]["Code"].should.equal("404") + e.value.response["Error"]["Code"].should.equal("404") @mock_s3 @@ -2077,10 +2071,10 @@ def test_boto3_get_object(): Bucket="blah", Key="hello.txt" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.Object("blah", "hello2.txt").get() - e.exception.response["Error"]["Code"].should.equal("NoSuchKey") + e.value.response["Error"]["Code"].should.equal("NoSuchKey") @mock_s3 @@ -2104,12 +2098,12 @@ def test_boto3_get_missing_object_with_part_number(): s3 = boto3.resource("s3", region_name=DEFAULT_REGION_NAME) s3.create_bucket(Bucket="blah") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.Object("blah", "hello.txt").meta.client.head_object( Bucket="blah", Key="hello.txt", PartNumber=123 ) - e.exception.response["Error"]["Code"].should.equal("404") + e.value.response["Error"]["Code"].should.equal("404") @mock_s3 @@ -2176,13 +2170,13 @@ def test_boto3_copy_object_with_versioning(): obj3_version_new.should_not.equal(obj2_version_new) # Copy file that doesn't exist - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.copy_object( CopySource={"Bucket": "blah", "Key": "test4", "VersionId": obj2_version}, Bucket="blah", Key="test5", ) - e.exception.response["Error"]["Code"].should.equal("404") + e.value.response["Error"]["Code"].should.equal("404") response = client.create_multipart_upload(Bucket="blah", Key="test4") upload_id = response["UploadId"] @@ -2212,11 +2206,11 @@ def test_s3_abort_multipart_data_with_invalid_upload_and_key(): client.create_bucket(Bucket="blah") - with assert_raises(Exception) as err: + with pytest.raises(Exception) as err: client.abort_multipart_upload( Bucket="blah", Key="foobar", UploadId="dummy_upload_id" ) - err.exception.response["Error"]["Code"].should.equal("NoSuchUpload") + err.value.response["Error"]["Code"].should.equal("NoSuchUpload") @mock_s3 @@ -2360,13 +2354,13 @@ def test_boto3_get_object_if_modified_since(): s3.put_object(Bucket=bucket_name, Key=key, Body="test") - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.get_object( Bucket=bucket_name, Key=key, IfModifiedSince=datetime.datetime.utcnow() + datetime.timedelta(hours=1), ) - e = err.exception + e = err.value e.response["Error"].should.equal({"Code": "304", "Message": "Not Modified"}) @@ -2380,13 +2374,13 @@ def test_boto3_get_object_if_unmodified_since(): s3.put_object(Bucket=bucket_name, Key=key, Body="test") - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.get_object( Bucket=bucket_name, Key=key, IfUnmodifiedSince=datetime.datetime.utcnow() - datetime.timedelta(hours=1), ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("PreconditionFailed") e.response["Error"]["Condition"].should.equal("If-Unmodified-Since") @@ -2401,11 +2395,11 @@ def test_boto3_get_object_if_match(): s3.put_object(Bucket=bucket_name, Key=key, Body="test") - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.get_object( Bucket=bucket_name, Key=key, IfMatch='"hello"', ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("PreconditionFailed") e.response["Error"]["Condition"].should.equal("If-Match") @@ -2420,11 +2414,11 @@ def test_boto3_get_object_if_none_match(): etag = s3.put_object(Bucket=bucket_name, Key=key, Body="test")["ETag"] - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.get_object( Bucket=bucket_name, Key=key, IfNoneMatch=etag, ) - e = err.exception + e = err.value e.response["Error"].should.equal({"Code": "304", "Message": "Not Modified"}) @@ -2438,13 +2432,13 @@ def test_boto3_head_object_if_modified_since(): s3.put_object(Bucket=bucket_name, Key=key, Body="test") - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.head_object( Bucket=bucket_name, Key=key, IfModifiedSince=datetime.datetime.utcnow() + datetime.timedelta(hours=1), ) - e = err.exception + e = err.value e.response["Error"].should.equal({"Code": "304", "Message": "Not Modified"}) @@ -2458,13 +2452,13 @@ def test_boto3_head_object_if_unmodified_since(): s3.put_object(Bucket=bucket_name, Key=key, Body="test") - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.head_object( Bucket=bucket_name, Key=key, IfUnmodifiedSince=datetime.datetime.utcnow() - datetime.timedelta(hours=1), ) - e = err.exception + e = err.value e.response["Error"].should.equal({"Code": "412", "Message": "Precondition Failed"}) @@ -2478,11 +2472,11 @@ def test_boto3_head_object_if_match(): s3.put_object(Bucket=bucket_name, Key=key, Body="test") - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.head_object( Bucket=bucket_name, Key=key, IfMatch='"hello"', ) - e = err.exception + e = err.value e.response["Error"].should.equal({"Code": "412", "Message": "Precondition Failed"}) @@ -2496,11 +2490,11 @@ def test_boto3_head_object_if_none_match(): etag = s3.put_object(Bucket=bucket_name, Key=key, Body="test")["ETag"] - with assert_raises(botocore.exceptions.ClientError) as err: + with pytest.raises(botocore.exceptions.ClientError) as err: s3.head_object( Bucket=bucket_name, Key=key, IfNoneMatch=etag, ) - e = err.exception + e = err.value e.response["Error"].should.equal({"Code": "304", "Message": "Not Modified"}) @@ -2633,7 +2627,7 @@ def test_boto3_put_bucket_tagging(): resp["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) # With duplicate tag keys: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: resp = s3.put_bucket_tagging( Bucket=bucket_name, Tagging={ @@ -2643,19 +2637,19 @@ def test_boto3_put_bucket_tagging(): ] }, ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("InvalidTag") e.response["Error"]["Message"].should.equal( "Cannot provide multiple Tags with the same key" ) # Cannot put tags that are "system" tags - i.e. tags that start with "aws:" - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: s3.put_bucket_tagging( Bucket=bucket_name, Tagging={"TagSet": [{"Key": "aws:sometag", "Value": "nope"}]}, ) - e = ce.exception + e = ce.value e.response["Error"]["Code"].should.equal("InvalidTag") e.response["Error"]["Message"].should.equal( "System tags cannot be added/updated by requester" @@ -2691,10 +2685,10 @@ def test_boto3_get_bucket_tagging(): # With no tags: s3.put_bucket_tagging(Bucket=bucket_name, Tagging={"TagSet": []}) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.get_bucket_tagging(Bucket=bucket_name) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("NoSuchTagSet") e.response["Error"]["Message"].should.equal("The TagSet does not exist") @@ -2718,10 +2712,10 @@ def test_boto3_delete_bucket_tagging(): resp = s3.delete_bucket_tagging(Bucket=bucket_name) resp["ResponseMetadata"]["HTTPStatusCode"].should.equal(204) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.get_bucket_tagging(Bucket=bucket_name) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("NoSuchTagSet") e.response["Error"]["Message"].should.equal("The TagSet does not exist") @@ -2756,7 +2750,7 @@ def test_boto3_put_bucket_cors(): resp["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_cors( Bucket=bucket_name, CORSConfiguration={ @@ -2765,24 +2759,24 @@ def test_boto3_put_bucket_cors(): ] }, ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("InvalidRequest") e.response["Error"]["Message"].should.equal( "Found unsupported HTTP method in CORS config. " "Unsupported method is NOTREAL" ) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_cors(Bucket=bucket_name, CORSConfiguration={"CORSRules": []}) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("MalformedXML") # And 101: many_rules = [{"AllowedOrigins": ["*"], "AllowedMethods": ["GET"]}] * 101 - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_cors( Bucket=bucket_name, CORSConfiguration={"CORSRules": many_rules} ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("MalformedXML") @@ -2793,10 +2787,10 @@ def test_boto3_get_bucket_cors(): s3.create_bucket(Bucket=bucket_name) # Without CORS: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.get_bucket_cors(Bucket=bucket_name) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("NoSuchCORSConfiguration") e.response["Error"]["Message"].should.equal("The CORS configuration does not exist") @@ -2843,10 +2837,10 @@ def test_boto3_delete_bucket_cors(): resp["ResponseMetadata"]["HTTPStatusCode"].should.equal(204) # Verify deletion: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.get_bucket_cors(Bucket=bucket_name) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("NoSuchCORSConfiguration") e.response["Error"]["Message"].should.equal("The CORS configuration does not exist") @@ -2906,7 +2900,7 @@ def test_put_bucket_acl_body(): assert len(result["Grants"]) == 1 # With no owner: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_acl( Bucket="bucket", AccessControlPolicy={ @@ -2921,10 +2915,10 @@ def test_put_bucket_acl_body(): ] }, ) - assert err.exception.response["Error"]["Code"] == "MalformedACLError" + assert err.value.response["Error"]["Code"] == "MalformedACLError" # With incorrect permission: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_acl( Bucket="bucket", AccessControlPolicy={ @@ -2940,7 +2934,7 @@ def test_put_bucket_acl_body(): "Owner": bucket_owner, }, ) - assert err.exception.response["Error"]["Code"] == "MalformedACLError" + assert err.value.response["Error"]["Code"] == "MalformedACLError" # Clear the ACLs: result = s3.put_bucket_acl( @@ -3185,7 +3179,7 @@ def test_put_bucket_notification_errors(): # With incorrect ARNs: for tech, arn in [("Queue", "sqs"), ("Topic", "sns"), ("LambdaFunction", "lambda")]: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_notification_configuration( Bucket="bucket", NotificationConfiguration={ @@ -3200,13 +3194,11 @@ def test_put_bucket_notification_errors(): }, ) - assert err.exception.response["Error"]["Code"] == "InvalidArgument" - assert ( - err.exception.response["Error"]["Message"] == "The ARN is not well formed" - ) + assert err.value.response["Error"]["Code"] == "InvalidArgument" + assert err.value.response["Error"]["Message"] == "The ARN is not well formed" # Region not the same as the bucket: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_notification_configuration( Bucket="bucket", NotificationConfiguration={ @@ -3219,14 +3211,14 @@ def test_put_bucket_notification_errors(): }, ) - assert err.exception.response["Error"]["Code"] == "InvalidArgument" + assert err.value.response["Error"]["Code"] == "InvalidArgument" assert ( - err.exception.response["Error"]["Message"] + err.value.response["Error"]["Message"] == "The notification destination service region is not valid for the bucket location constraint" ) # Invalid event name: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_notification_configuration( Bucket="bucket", NotificationConfiguration={ @@ -3238,9 +3230,9 @@ def test_put_bucket_notification_errors(): ] }, ) - assert err.exception.response["Error"]["Code"] == "InvalidArgument" + assert err.value.response["Error"]["Code"] == "InvalidArgument" assert ( - err.exception.response["Error"]["Message"] + err.value.response["Error"]["Message"] == "The event is not supported for notifications" ) @@ -3263,25 +3255,25 @@ def test_boto3_put_bucket_logging(): assert not result.get("LoggingEnabled") # A log-bucket that doesn't exist: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_logging( Bucket=bucket_name, BucketLoggingStatus={ "LoggingEnabled": {"TargetBucket": "IAMNOTREAL", "TargetPrefix": ""} }, ) - assert err.exception.response["Error"]["Code"] == "InvalidTargetBucketForLogging" + assert err.value.response["Error"]["Code"] == "InvalidTargetBucketForLogging" # A log-bucket that's missing the proper ACLs for LogDelivery: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_logging( Bucket=bucket_name, BucketLoggingStatus={ "LoggingEnabled": {"TargetBucket": log_bucket, "TargetPrefix": ""} }, ) - assert err.exception.response["Error"]["Code"] == "InvalidTargetBucketForLogging" - assert "log-delivery" in err.exception.response["Error"]["Message"] + assert err.value.response["Error"]["Code"] == "InvalidTargetBucketForLogging" + assert "log-delivery" in err.value.response["Error"]["Message"] # Add the proper "log-delivery" ACL to the log buckets: bucket_owner = s3.get_bucket_acl(Bucket=log_bucket)["Owner"] @@ -3314,7 +3306,7 @@ def test_boto3_put_bucket_logging(): ) # A log-bucket that's in the wrong region: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_logging( Bucket=bucket_name, BucketLoggingStatus={ @@ -3324,7 +3316,7 @@ def test_boto3_put_bucket_logging(): } }, ) - assert err.exception.response["Error"]["Code"] == "CrossLocationLoggingProhibitted" + assert err.value.response["Error"]["Code"] == "CrossLocationLoggingProhibitted" # Correct logging: s3.put_bucket_logging( @@ -3402,7 +3394,7 @@ def test_boto3_put_bucket_logging(): assert len(result["LoggingEnabled"]["TargetGrants"]) == 1 # With an invalid grant: - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_bucket_logging( Bucket=bucket_name, BucketLoggingStatus={ @@ -3421,7 +3413,7 @@ def test_boto3_put_bucket_logging(): } }, ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" @mock_s3 @@ -3431,7 +3423,7 @@ def test_boto3_put_object_tagging(): key = "key-with-tags" s3.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_object_tagging( Bucket=bucket_name, Key=key, @@ -3443,7 +3435,7 @@ def test_boto3_put_object_tagging(): }, ) - e = err.exception + e = err.value e.response["Error"].should.equal( { "Code": "NoSuchKey", @@ -3479,7 +3471,7 @@ def test_boto3_put_object_tagging_on_earliest_version(): bucket_versioning.enable() bucket_versioning.status.should.equal("Enabled") - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_object_tagging( Bucket=bucket_name, Key=key, @@ -3491,7 +3483,7 @@ def test_boto3_put_object_tagging_on_earliest_version(): }, ) - e = err.exception + e = err.value e.response["Error"].should.equal( { "Code": "NoSuchKey", @@ -3547,7 +3539,7 @@ def test_boto3_put_object_tagging_on_both_version(): bucket_versioning.enable() bucket_versioning.status.should.equal("Enabled") - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_object_tagging( Bucket=bucket_name, Key=key, @@ -3559,7 +3551,7 @@ def test_boto3_put_object_tagging_on_both_version(): }, ) - e = err.exception + e = err.value e.response["Error"].should.equal( { "Code": "NoSuchKey", @@ -3772,9 +3764,9 @@ def test_boto3_delete_markers(): s3.delete_objects(Bucket=bucket_name, Delete={"Objects": [{"Key": key}]}) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.get_object(Bucket=bucket_name, Key=key) - e.exception.response["Error"]["Code"].should.equal("NoSuchKey") + e.value.response["Error"]["Code"].should.equal("NoSuchKey") response = s3.list_object_versions(Bucket=bucket_name) response["Versions"].should.have.length_of(2) @@ -3820,7 +3812,7 @@ def test_boto3_multiple_delete_markers(): response = s3.list_object_versions(Bucket=bucket_name) response["DeleteMarkers"].should.have.length_of(2) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.get_object(Bucket=bucket_name, Key=key) e.response["Error"]["Code"].should.equal("404") @@ -3892,17 +3884,17 @@ TEST_XML = """\ @mock_s3 def test_boto3_bucket_name_too_long(): s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.create_bucket(Bucket="x" * 64) - exc.exception.response["Error"]["Code"].should.equal("InvalidBucketName") + exc.value.response["Error"]["Code"].should.equal("InvalidBucketName") @mock_s3 def test_boto3_bucket_name_too_short(): s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.create_bucket(Bucket="x" * 2) - exc.exception.response["Error"]["Code"].should.equal("InvalidBucketName") + exc.value.response["Error"]["Code"].should.equal("InvalidBucketName") @mock_s3 @@ -3972,11 +3964,11 @@ def test_accelerate_configuration_status_validation(): bucket_name = "some_bucket" s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) s3.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.put_bucket_accelerate_configuration( Bucket=bucket_name, AccelerateConfiguration={"Status": "bad_status"} ) - exc.exception.response["Error"]["Code"].should.equal("MalformedXML") + exc.value.response["Error"]["Code"].should.equal("MalformedXML") @mock_s3 @@ -3984,11 +3976,11 @@ def test_accelerate_configuration_is_not_supported_when_bucket_name_has_dots(): bucket_name = "some.bucket.with.dots" s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) s3.create_bucket(Bucket=bucket_name) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.put_bucket_accelerate_configuration( Bucket=bucket_name, AccelerateConfiguration={"Status": "Enabled"} ) - exc.exception.response["Error"]["Code"].should.equal("InvalidRequest") + exc.value.response["Error"]["Code"].should.equal("InvalidRequest") def store_and_read_back_a_key(key): @@ -4015,7 +4007,7 @@ def test_root_dir_with_empty_name_works(): store_and_read_back_a_key("/") -@parameterized(["mybucket", "my.bucket"]) +@pytest.mark.parametrize("bucket_name", ["mybucket", "my.bucket"]) @mock_s3 def test_leading_slashes_not_removed(bucket_name): """Make sure that leading slashes are not removed internally.""" @@ -4028,17 +4020,17 @@ def test_leading_slashes_not_removed(bucket_name): s3.put_object(Bucket=bucket_name, Key=uploaded_key, Body=b"Some body") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.get_object(Bucket=bucket_name, Key=invalid_key_1) - e.exception.response["Error"]["Code"].should.equal("NoSuchKey") + e.value.response["Error"]["Code"].should.equal("NoSuchKey") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.get_object(Bucket=bucket_name, Key=invalid_key_2) - e.exception.response["Error"]["Code"].should.equal("NoSuchKey") + e.value.response["Error"]["Code"].should.equal("NoSuchKey") -@parameterized( - [("foo/bar/baz",), ("foo",), ("foo/run_dt%3D2019-01-01%252012%253A30%253A00",)] +@pytest.mark.parametrize( + "key", ["foo/bar/baz", "foo", "foo/run_dt%3D2019-01-01%252012%253A30%253A00"] ) @mock_s3 def test_delete_objects_with_url_encoded_key(key): @@ -4052,10 +4044,10 @@ def test_delete_objects_with_url_encoded_key(key): s3.put_object(Bucket=bucket_name, Key=key, Body=body) def assert_deleted(): - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: s3.get_object(Bucket=bucket_name, Key=key) - e.exception.response["Error"]["Code"].should.equal("NoSuchKey") + e.value.response["Error"]["Code"].should.equal("NoSuchKey") put_object() s3.delete_object(Bucket=bucket_name, Key=key) @@ -4073,17 +4065,15 @@ def test_public_access_block(): client.create_bucket(Bucket="mybucket") # Try to get the public access block (should not exist by default) - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_public_access_block(Bucket="mybucket") + assert ce.value.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration" assert ( - ce.exception.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration" - ) - assert ( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] == "The public access block configuration was not found" ) - assert ce.exception.response["ResponseMetadata"]["HTTPStatusCode"] == 404 + assert ce.value.response["ResponseMetadata"]["HTTPStatusCode"] == 404 # Put a public block in place: test_map = { @@ -4123,17 +4113,17 @@ def test_public_access_block(): } # Test with a blank PublicAccessBlockConfiguration: - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.put_public_access_block( Bucket="mybucket", PublicAccessBlockConfiguration={} ) - assert ce.exception.response["Error"]["Code"] == "InvalidRequest" + assert ce.value.response["Error"]["Code"] == "InvalidRequest" assert ( - ce.exception.response["Error"]["Message"] + ce.value.response["Error"]["Message"] == "Must specify at least one configuration." ) - assert ce.exception.response["ResponseMetadata"]["HTTPStatusCode"] == 400 + assert ce.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 # Test that things work with AWS Config: config_client = boto3.client("config", region_name=DEFAULT_REGION_NAME) @@ -4156,11 +4146,9 @@ def test_public_access_block(): # Delete: client.delete_public_access_block(Bucket="mybucket") - with assert_raises(ClientError) as ce: + with pytest.raises(ClientError) as ce: client.get_public_access_block(Bucket="mybucket") - assert ( - ce.exception.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration" - ) + assert ce.value.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration" @mock_s3 @@ -4301,10 +4289,10 @@ def test_list_config_discovered_resources(): ) # With an invalid page: - with assert_raises(InvalidNextTokenException) as inte: + with pytest.raises(InvalidNextTokenException) as inte: s3_config_query.list_config_service_resources(None, None, 1, "notabucket") - assert "The nextToken provided is invalid" in inte.exception.message + assert "The nextToken provided is invalid" in inte.value.message @mock_s3 @@ -4761,7 +4749,7 @@ def test_encryption(): conn = boto3.client("s3", region_name="us-east-1") conn.create_bucket(Bucket="mybucket") - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: conn.get_bucket_encryption(Bucket="mybucket") sse_config = { @@ -4784,7 +4772,7 @@ def test_encryption(): assert resp["ServerSideEncryptionConfiguration"] == sse_config conn.delete_bucket_encryption(Bucket="mybucket") - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: conn.get_bucket_encryption(Bucket="mybucket") @@ -4799,12 +4787,12 @@ def test_presigned_url_restrict_parameters(): s3 = boto3.client("s3", region_name="us-east-1") # Create a pre-signed url with some metadata. - with assert_raises(botocore.exceptions.ParamValidationError) as err: + with pytest.raises(botocore.exceptions.ParamValidationError) as err: s3.generate_presigned_url( ClientMethod="put_object", Params={"Bucket": bucket, "Key": key, "Unknown": "metadata"}, ) - assert str(err.exception).should.match( + assert str(err.value).should.match( r'Parameter validation failed:\nUnknown parameter in input: "Unknown", must be one of:.*' ) diff --git a/tests/test_s3/test_s3_lifecycle.py b/tests/test_s3/test_s3_lifecycle.py index 0a2e66b5c..d3d9344ef 100644 --- a/tests/test_s3/test_s3_lifecycle.py +++ b/tests/test_s3/test_s3_lifecycle.py @@ -8,7 +8,7 @@ from boto.s3.lifecycle import Lifecycle, Transition, Expiration, Rule import sure # noqa from botocore.exceptions import ClientError from datetime import datetime -from nose.tools import assert_raises +import pytest from moto import mock_s3_deprecated, mock_s3 @@ -56,7 +56,7 @@ def test_lifecycle_with_filters(): assert result["Rules"][0]["Filter"]["Prefix"] == "" assert not result["Rules"][0]["Filter"].get("And") assert not result["Rules"][0]["Filter"].get("Tag") - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Prefix"] # Without any prefixes and an empty filter (this is by default a prefix for the whole bucket): @@ -75,16 +75,16 @@ def test_lifecycle_with_filters(): ) result = client.get_bucket_lifecycle_configuration(Bucket="bucket") assert len(result["Rules"]) == 1 - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Prefix"] # If we remove the filter -- and don't specify a Prefix, then this is bad: lfc["Rules"][0].pop("Filter") - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" # With a tag: lfc["Rules"][0]["Filter"] = {"Tag": {"Key": "mytag", "Value": "mytagvalue"}} @@ -93,12 +93,12 @@ def test_lifecycle_with_filters(): ) result = client.get_bucket_lifecycle_configuration(Bucket="bucket") assert len(result["Rules"]) == 1 - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Filter"]["Prefix"] assert not result["Rules"][0]["Filter"].get("And") assert result["Rules"][0]["Filter"]["Tag"]["Key"] == "mytag" assert result["Rules"][0]["Filter"]["Tag"]["Value"] == "mytagvalue" - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Prefix"] # With And (single tag): @@ -118,7 +118,7 @@ def test_lifecycle_with_filters(): assert len(result["Rules"][0]["Filter"]["And"]["Tags"]) == 1 assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Key"] == "mytag" assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Value"] == "mytagvalue" - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Prefix"] # With multiple And tags: @@ -141,7 +141,7 @@ def test_lifecycle_with_filters(): assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Value"] == "mytagvalue" assert result["Rules"][0]["Filter"]["And"]["Tags"][1]["Key"] == "mytag2" assert result["Rules"][0]["Filter"]["And"]["Tags"][1]["Value"] == "mytagvalue2" - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Prefix"] # And filter without Prefix but multiple Tags: @@ -156,30 +156,30 @@ def test_lifecycle_with_filters(): ) result = client.get_bucket_lifecycle_configuration(Bucket="bucket") assert len(result["Rules"]) == 1 - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Filter"]["And"]["Prefix"] assert len(result["Rules"][0]["Filter"]["And"]["Tags"]) == 2 assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Key"] == "mytag" assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Value"] == "mytagvalue" assert result["Rules"][0]["Filter"]["And"]["Tags"][1]["Key"] == "mytag2" assert result["Rules"][0]["Filter"]["And"]["Tags"][1]["Value"] == "mytagvalue2" - with assert_raises(KeyError): + with pytest.raises(KeyError): assert result["Rules"][0]["Prefix"] # Can't have both filter and prefix: lfc["Rules"][0]["Prefix"] = "" - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" lfc["Rules"][0]["Prefix"] = "some/path" - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" # No filters -- just a prefix: del lfc["Rules"][0]["Filter"] @@ -196,11 +196,11 @@ def test_lifecycle_with_filters(): "Prefix": "some/prefix", "Tag": {"Key": "mytag", "Value": "mytagvalue"}, } - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" lfc["Rules"][0]["Filter"] = { "Tag": {"Key": "mytag", "Value": "mytagvalue"}, @@ -212,11 +212,11 @@ def test_lifecycle_with_filters(): ], }, } - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" # Make sure multiple rules work: lfc = { @@ -279,19 +279,19 @@ def test_lifecycle_with_eodm(): # With failure: lfc["Rules"][0]["Expiration"]["Days"] = 7 - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" del lfc["Rules"][0]["Expiration"]["Days"] lfc["Rules"][0]["Expiration"]["Date"] = datetime(2015, 1, 1) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" @mock_s3 @@ -383,19 +383,19 @@ def test_lifecycle_with_nvt(): # With failures for missing children: del lfc["Rules"][0]["NoncurrentVersionTransitions"][0]["NoncurrentDays"] - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" lfc["Rules"][0]["NoncurrentVersionTransitions"][0]["NoncurrentDays"] = 30 del lfc["Rules"][0]["NoncurrentVersionTransitions"][0]["StorageClass"] - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: client.put_bucket_lifecycle_configuration( Bucket="bucket", LifecycleConfiguration=lfc ) - assert err.exception.response["Error"]["Code"] == "MalformedXML" + assert err.value.response["Error"]["Code"] == "MalformedXML" @mock_s3 diff --git a/tests/test_s3/test_s3_storageclass.py b/tests/test_s3/test_s3_storageclass.py index a89b4a896..ec7090369 100644 --- a/tests/test_s3/test_s3_storageclass.py +++ b/tests/test_s3/test_s3_storageclass.py @@ -4,7 +4,7 @@ import boto3 import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_s3 @@ -105,7 +105,7 @@ def test_s3_invalid_copied_storage_class(): ) # Try to copy an object with an invalid storage class - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.copy_object( CopySource={"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket2", @@ -113,7 +113,7 @@ def test_s3_invalid_copied_storage_class(): StorageClass="STANDARD2", ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("InvalidStorageClass") e.response["Error"]["Message"].should.equal( "The storage class you specified is not valid" @@ -128,12 +128,12 @@ def test_s3_invalid_storage_class(): ) # Try to add an object with an invalid storage class - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: s3.put_object( Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARDD" ) - e = err.exception + e = err.value e.response["Error"]["Code"].should.equal("InvalidStorageClass") e.response["Error"]["Message"].should.equal( "The storage class you specified is not valid" @@ -166,14 +166,14 @@ def test_s3_copy_object_error_for_glacier_storage_class_not_restored(): Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="GLACIER" ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as ex: s3.copy_object( CopySource={"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket", Key="Second_Object", ) - exc.exception.response["Error"]["Code"].should.equal("ObjectNotInActiveTierError") + ex.value.response["Error"]["Code"].should.equal("ObjectNotInActiveTierError") @mock_s3 @@ -187,14 +187,14 @@ def test_s3_copy_object_error_for_deep_archive_storage_class_not_restored(): Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="DEEP_ARCHIVE" ) - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as exc: s3.copy_object( CopySource={"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket", Key="Second_Object", ) - exc.exception.response["Error"]["Code"].should.equal("ObjectNotInActiveTierError") + exc.value.response["Error"]["Code"].should.equal("ObjectNotInActiveTierError") @mock_s3 diff --git a/tests/test_s3/test_s3_utils.py b/tests/test_s3/test_s3_utils.py index b90225597..64d1c2ca8 100644 --- a/tests/test_s3/test_s3_utils.py +++ b/tests/test_s3/test_s3_utils.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals import os +import pytest from sure import expect from moto.s3.utils import ( bucket_name_from_url, @@ -8,7 +9,6 @@ from moto.s3.utils import ( clean_key_name, undo_clean_key_name, ) -from parameterized import parameterized def test_base_url(): @@ -93,7 +93,8 @@ def test_parse_region_from_url(): parse_region_from_url(url).should.equal(expected) -@parameterized( +@pytest.mark.parametrize( + "key,expected", [ ("foo/bar/baz", "foo/bar/baz"), ("foo", "foo"), @@ -101,13 +102,14 @@ def test_parse_region_from_url(): "foo/run_dt%3D2019-01-01%252012%253A30%253A00", "foo/run_dt=2019-01-01%2012%3A30%3A00", ), - ] + ], ) def test_clean_key_name(key, expected): clean_key_name(key).should.equal(expected) -@parameterized( +@pytest.mark.parametrize( + "key,expected", [ ("foo/bar/baz", "foo/bar/baz"), ("foo", "foo"), @@ -115,7 +117,7 @@ def test_clean_key_name(key, expected): "foo/run_dt%3D2019-01-01%252012%253A30%253A00", "foo/run_dt%253D2019-01-01%25252012%25253A30%25253A00", ), - ] + ], ) def test_undo_clean_key_name(key, expected): undo_clean_key_name(key).should.equal(expected) diff --git a/tests/test_s3bucket_path/__init__.py b/tests/test_s3bucket_path/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_s3bucket_path/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_sagemaker/test_sagemaker_endpoint.py b/tests/test_sagemaker/test_sagemaker_endpoint.py index b048439ff..45ae96b12 100644 --- a/tests/test_sagemaker/test_sagemaker_endpoint.py +++ b/tests/test_sagemaker/test_sagemaker_endpoint.py @@ -3,12 +3,12 @@ from __future__ import unicode_literals import datetime import boto3 -from botocore.exceptions import ClientError, ParamValidationError +from botocore.exceptions import ClientError import sure # noqa from moto import mock_sagemaker from moto.sts.models import ACCOUNT_ID -from nose.tools import assert_true, assert_equal, assert_raises +import pytest TEST_REGION_NAME = "us-east-1" FAKE_ROLE_ARN = "arn:aws:iam::{}:role/FakeRole".format(ACCOUNT_ID) @@ -33,14 +33,12 @@ def test_create_endpoint_config(): ] endpoint_config_name = "MyEndpointConfig" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.create_endpoint_config( EndpointConfigName=endpoint_config_name, ProductionVariants=production_variants, ) - assert_true( - e.exception.response["Error"]["Message"].startswith("Could not find model") - ) + assert e.value.response["Error"]["Message"].startswith("Could not find model") _create_model(sagemaker, model_name) resp = sagemaker.create_endpoint_config( @@ -88,22 +86,17 @@ def test_delete_endpoint_config(): ) resp = sagemaker.delete_endpoint_config(EndpointConfigName=endpoint_config_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.describe_endpoint_config(EndpointConfigName=endpoint_config_name) - assert_true( - e.exception.response["Error"]["Message"].startswith( - "Could not find endpoint configuration" - ) + assert e.value.response["Error"]["Message"].startswith( + "Could not find endpoint configuration" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.delete_endpoint_config(EndpointConfigName=endpoint_config_name) - assert_true( - e.exception.response["Error"]["Message"].startswith( - "Could not find endpoint configuration" - ) + assert e.value.response["Error"]["Message"].startswith( + "Could not find endpoint configuration" ) - pass @mock_sagemaker @@ -124,16 +117,16 @@ def test_create_endpoint_invalid_instance_type(): ] endpoint_config_name = "MyEndpointConfig" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.create_endpoint_config( EndpointConfigName=endpoint_config_name, ProductionVariants=production_variants, ) - assert_equal(e.exception.response["Error"]["Code"], "ValidationException") + assert e.value.response["Error"]["Code"] == "ValidationException" expected_message = "Value '{}' at 'instanceType' failed to satisfy constraint: Member must satisfy enum value set: [".format( instance_type ) - assert_true(expected_message in e.exception.response["Error"]["Message"]) + assert expected_message in e.value.response["Error"]["Message"] @mock_sagemaker @@ -141,14 +134,12 @@ def test_create_endpoint(): sagemaker = boto3.client("sagemaker", region_name=TEST_REGION_NAME) endpoint_name = "MyEndpoint" - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.create_endpoint( EndpointName=endpoint_name, EndpointConfigName="NonexistentEndpointConfig" ) - assert_true( - e.exception.response["Error"]["Message"].startswith( - "Could not find endpoint configuration" - ) + assert e.value.response["Error"]["Message"].startswith( + "Could not find endpoint configuration" ) model_name = "MyModel" @@ -173,12 +164,12 @@ def test_create_endpoint(): resp["EndpointName"].should.equal(endpoint_name) resp["EndpointConfigName"].should.equal(endpoint_config_name) resp["EndpointStatus"].should.equal("InService") - assert_true(isinstance(resp["CreationTime"], datetime.datetime)) - assert_true(isinstance(resp["LastModifiedTime"], datetime.datetime)) + assert isinstance(resp["CreationTime"], datetime.datetime) + assert isinstance(resp["LastModifiedTime"], datetime.datetime) resp["ProductionVariants"][0]["VariantName"].should.equal("MyProductionVariant") resp = sagemaker.list_tags(ResourceArn=resp["EndpointArn"]) - assert_equal(resp["Tags"], GENERIC_TAGS_PARAM) + assert resp["Tags"] == GENERIC_TAGS_PARAM @mock_sagemaker @@ -195,17 +186,13 @@ def test_delete_endpoint(): _create_endpoint(sagemaker, endpoint_name, endpoint_config_name) sagemaker.delete_endpoint(EndpointName=endpoint_name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.describe_endpoint(EndpointName=endpoint_name) - assert_true( - e.exception.response["Error"]["Message"].startswith("Could not find endpoint") - ) + assert e.value.response["Error"]["Message"].startswith("Could not find endpoint") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.delete_endpoint(EndpointName=endpoint_name) - assert_true( - e.exception.response["Error"]["Message"].startswith("Could not find endpoint") - ) + assert e.value.response["Error"]["Message"].startswith("Could not find endpoint") def _create_model(boto_client, model_name): @@ -217,7 +204,7 @@ def _create_model(boto_client, model_name): }, ExecutionRoleArn=FAKE_ROLE_ARN, ) - assert_equal(resp["ResponseMetadata"]["HTTPStatusCode"], 200) + assert resp["ResponseMetadata"]["HTTPStatusCode"] == 200 def _create_endpoint_config(boto_client, endpoint_config_name, model_name): diff --git a/tests/test_sagemaker/test_sagemaker_models.py b/tests/test_sagemaker/test_sagemaker_models.py index 4139ca575..91fc3bb5b 100644 --- a/tests/test_sagemaker/test_sagemaker_models.py +++ b/tests/test_sagemaker/test_sagemaker_models.py @@ -2,9 +2,8 @@ from __future__ import unicode_literals import boto3 -import tests.backport_assert_raises # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_sagemaker import sure # noqa @@ -76,11 +75,11 @@ def test_delete_model(): @mock_sagemaker def test_delete_model_not_found(): - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: boto3.client("sagemaker", region_name="us-east-1").delete_model( ModelName="blah" ) - assert err.exception.response["Error"]["Code"].should.equal("404") + assert err.value.response["Error"]["Code"].should.equal("404") @mock_sagemaker diff --git a/tests/test_sagemaker/test_sagemaker_notebooks.py b/tests/test_sagemaker/test_sagemaker_notebooks.py index c04618c77..3a3137dec 100644 --- a/tests/test_sagemaker/test_sagemaker_notebooks.py +++ b/tests/test_sagemaker/test_sagemaker_notebooks.py @@ -8,7 +8,7 @@ import sure # noqa from moto import mock_sagemaker from moto.sts.models import ACCOUNT_ID -from nose.tools import assert_true, assert_equal, assert_raises +import pytest TEST_REGION_NAME = "us-east-1" FAKE_SUBNET_ID = "subnet-012345678" @@ -41,26 +41,26 @@ def test_create_notebook_instance_minimal_params(): "RoleArn": FAKE_ROLE_ARN, } resp = sagemaker.create_notebook_instance(**args) - assert_true(resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker")) - assert_true(resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"])) + assert resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"]) resp = sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_true(resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker")) - assert_true(resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"])) - assert_equal(resp["NotebookInstanceName"], NAME_PARAM) - assert_equal(resp["NotebookInstanceStatus"], "InService") - assert_equal( - resp["Url"], "{}.notebook.{}.sagemaker.aws".format(NAME_PARAM, TEST_REGION_NAME) + assert resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"]) + assert resp["NotebookInstanceName"] == NAME_PARAM + assert resp["NotebookInstanceStatus"] == "InService" + assert resp["Url"] == "{}.notebook.{}.sagemaker.aws".format( + NAME_PARAM, TEST_REGION_NAME ) - assert_equal(resp["InstanceType"], INSTANCE_TYPE_PARAM) - assert_equal(resp["RoleArn"], FAKE_ROLE_ARN) - assert_true(isinstance(resp["LastModifiedTime"], datetime.datetime)) - assert_true(isinstance(resp["CreationTime"], datetime.datetime)) - assert_equal(resp["DirectInternetAccess"], "Enabled") - assert_equal(resp["VolumeSizeInGB"], 5) + assert resp["InstanceType"] == INSTANCE_TYPE_PARAM + assert resp["RoleArn"] == FAKE_ROLE_ARN + assert isinstance(resp["LastModifiedTime"], datetime.datetime) + assert isinstance(resp["CreationTime"], datetime.datetime) + assert resp["DirectInternetAccess"] == "Enabled" + assert resp["VolumeSizeInGB"] == 5 -# assert_equal(resp["RootAccess"], True) # ToDo: Not sure if this defaults... +# assert resp["RootAccess"] == True # ToDo: Not sure if this defaults... @mock_sagemaker @@ -92,36 +92,34 @@ def test_create_notebook_instance_params(): "RootAccess": ROOT_ACCESS_PARAM, } resp = sagemaker.create_notebook_instance(**args) - assert_true(resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker")) - assert_true(resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"])) + assert resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"]) resp = sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_true(resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker")) - assert_true(resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"])) - assert_equal(resp["NotebookInstanceName"], NAME_PARAM) - assert_equal(resp["NotebookInstanceStatus"], "InService") - assert_equal( - resp["Url"], "{}.notebook.{}.sagemaker.aws".format(NAME_PARAM, TEST_REGION_NAME) + assert resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"]) + assert resp["NotebookInstanceName"] == NAME_PARAM + assert resp["NotebookInstanceStatus"] == "InService" + assert resp["Url"] == "{}.notebook.{}.sagemaker.aws".format( + NAME_PARAM, TEST_REGION_NAME ) - assert_equal(resp["InstanceType"], INSTANCE_TYPE_PARAM) - assert_equal(resp["RoleArn"], FAKE_ROLE_ARN) - assert_true(isinstance(resp["LastModifiedTime"], datetime.datetime)) - assert_true(isinstance(resp["CreationTime"], datetime.datetime)) - assert_equal(resp["DirectInternetAccess"], "Enabled") - assert_equal(resp["VolumeSizeInGB"], VOLUME_SIZE_IN_GB_PARAM) - # assert_equal(resp["RootAccess"], True) # ToDo: Not sure if this defaults... - assert_equal(resp["SubnetId"], FAKE_SUBNET_ID) - assert_equal(resp["SecurityGroups"], FAKE_SECURITY_GROUP_IDS) - assert_equal(resp["KmsKeyId"], FAKE_KMS_KEY_ID) - assert_equal( - resp["NotebookInstanceLifecycleConfigName"], FAKE_LIFECYCLE_CONFIG_NAME - ) - assert_equal(resp["AcceleratorTypes"], ACCELERATOR_TYPES_PARAM) - assert_equal(resp["DefaultCodeRepository"], FAKE_DEFAULT_CODE_REPO) - assert_equal(resp["AdditionalCodeRepositories"], FAKE_ADDL_CODE_REPOS) + assert resp["InstanceType"] == INSTANCE_TYPE_PARAM + assert resp["RoleArn"] == FAKE_ROLE_ARN + assert isinstance(resp["LastModifiedTime"], datetime.datetime) + assert isinstance(resp["CreationTime"], datetime.datetime) + assert resp["DirectInternetAccess"] == "Enabled" + assert resp["VolumeSizeInGB"] == VOLUME_SIZE_IN_GB_PARAM + # assert resp["RootAccess"] == True # ToDo: Not sure if this defaults... + assert resp["SubnetId"] == FAKE_SUBNET_ID + assert resp["SecurityGroups"] == FAKE_SECURITY_GROUP_IDS + assert resp["KmsKeyId"] == FAKE_KMS_KEY_ID + assert resp["NotebookInstanceLifecycleConfigName"] == FAKE_LIFECYCLE_CONFIG_NAME + assert resp["AcceleratorTypes"] == ACCELERATOR_TYPES_PARAM + assert resp["DefaultCodeRepository"] == FAKE_DEFAULT_CODE_REPO + assert resp["AdditionalCodeRepositories"] == FAKE_ADDL_CODE_REPOS resp = sagemaker.list_tags(ResourceArn=resp["NotebookInstanceArn"]) - assert_equal(resp["Tags"], GENERIC_TAGS_PARAM) + assert resp["Tags"] == GENERIC_TAGS_PARAM @mock_sagemaker @@ -136,13 +134,12 @@ def test_create_notebook_instance_bad_volume_size(): "RoleArn": FAKE_ROLE_ARN, "VolumeSizeInGB": vol_size, } - with assert_raises(ParamValidationError) as ex: - resp = sagemaker.create_notebook_instance(**args) - assert_equal( - ex.exception.args[0], - "Parameter validation failed:\nInvalid range for parameter VolumeSizeInGB, value: {}, valid range: 5-inf".format( - vol_size - ), + with pytest.raises(ParamValidationError) as ex: + sagemaker.create_notebook_instance(**args) + assert ex.value.args[ + 0 + ] == "Parameter validation failed:\nInvalid range for parameter VolumeSizeInGB, value: {}, valid range: 5-inf".format( + vol_size ) @@ -157,14 +154,14 @@ def test_create_notebook_instance_invalid_instance_type(): "InstanceType": instance_type, "RoleArn": FAKE_ROLE_ARN, } - with assert_raises(ClientError) as ex: - resp = sagemaker.create_notebook_instance(**args) - assert_equal(ex.exception.response["Error"]["Code"], "ValidationException") + with pytest.raises(ClientError) as ex: + sagemaker.create_notebook_instance(**args) + assert ex.value.response["Error"]["Code"] == "ValidationException" expected_message = "Value '{}' at 'instanceType' failed to satisfy constraint: Member must satisfy enum value set: [".format( instance_type ) - assert_true(expected_message in ex.exception.response["Error"]["Message"]) + assert expected_message in ex.value.response["Error"]["Message"] @mock_sagemaker @@ -180,51 +177,49 @@ def test_notebook_instance_lifecycle(): "RoleArn": FAKE_ROLE_ARN, } resp = sagemaker.create_notebook_instance(**args) - assert_true(resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker")) - assert_true(resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"])) + assert resp["NotebookInstanceArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceArn"].endswith(args["NotebookInstanceName"]) resp = sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) notebook_instance_arn = resp["NotebookInstanceArn"] - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: sagemaker.delete_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_equal(ex.exception.response["Error"]["Code"], "ValidationException") + assert ex.value.response["Error"]["Code"] == "ValidationException" expected_message = "Status (InService) not in ([Stopped, Failed]). Unable to transition to (Deleting) for Notebook Instance ({})".format( notebook_instance_arn ) - assert_true(expected_message in ex.exception.response["Error"]["Message"]) + assert expected_message in ex.value.response["Error"]["Message"] sagemaker.stop_notebook_instance(NotebookInstanceName=NAME_PARAM) resp = sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_equal(resp["NotebookInstanceStatus"], "Stopped") + assert resp["NotebookInstanceStatus"] == "Stopped" sagemaker.start_notebook_instance(NotebookInstanceName=NAME_PARAM) resp = sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_equal(resp["NotebookInstanceStatus"], "InService") + assert resp["NotebookInstanceStatus"] == "InService" sagemaker.stop_notebook_instance(NotebookInstanceName=NAME_PARAM) resp = sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_equal(resp["NotebookInstanceStatus"], "Stopped") + assert resp["NotebookInstanceStatus"] == "Stopped" sagemaker.delete_notebook_instance(NotebookInstanceName=NAME_PARAM) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: sagemaker.describe_notebook_instance(NotebookInstanceName=NAME_PARAM) - assert_equal(ex.exception.response["Error"]["Message"], "RecordNotFound") + assert ex.value.response["Error"]["Message"] == "RecordNotFound" @mock_sagemaker def test_describe_nonexistent_model(): sagemaker = boto3.client("sagemaker", region_name=TEST_REGION_NAME) - with assert_raises(ClientError) as e: - resp = sagemaker.describe_model(ModelName="Nonexistent") - assert_true( - e.exception.response["Error"]["Message"].startswith("Could not find model") - ) + with pytest.raises(ClientError) as e: + sagemaker.describe_model(ModelName="Nonexistent") + assert e.value.response["Error"]["Message"].startswith("Could not find model") @mock_sagemaker @@ -237,56 +232,46 @@ def test_notebook_instance_lifecycle_config(): resp = sagemaker.create_notebook_instance_lifecycle_config( NotebookInstanceLifecycleConfigName=name, OnCreate=on_create, OnStart=on_start ) - assert_true( - resp["NotebookInstanceLifecycleConfigArn"].startswith("arn:aws:sagemaker") - ) - assert_true(resp["NotebookInstanceLifecycleConfigArn"].endswith(name)) + assert resp["NotebookInstanceLifecycleConfigArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceLifecycleConfigArn"].endswith(name) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: resp = sagemaker.create_notebook_instance_lifecycle_config( NotebookInstanceLifecycleConfigName=name, OnCreate=on_create, OnStart=on_start, ) - assert_true( - e.exception.response["Error"]["Message"].endswith( - "Notebook Instance Lifecycle Config already exists.)" - ) + assert e.value.response["Error"]["Message"].endswith( + "Notebook Instance Lifecycle Config already exists.)" ) resp = sagemaker.describe_notebook_instance_lifecycle_config( NotebookInstanceLifecycleConfigName=name, ) - assert_equal(resp["NotebookInstanceLifecycleConfigName"], name) - assert_true( - resp["NotebookInstanceLifecycleConfigArn"].startswith("arn:aws:sagemaker") - ) - assert_true(resp["NotebookInstanceLifecycleConfigArn"].endswith(name)) - assert_equal(resp["OnStart"], on_start) - assert_equal(resp["OnCreate"], on_create) - assert_true(isinstance(resp["LastModifiedTime"], datetime.datetime)) - assert_true(isinstance(resp["CreationTime"], datetime.datetime)) + assert resp["NotebookInstanceLifecycleConfigName"] == name + assert resp["NotebookInstanceLifecycleConfigArn"].startswith("arn:aws:sagemaker") + assert resp["NotebookInstanceLifecycleConfigArn"].endswith(name) + assert resp["OnStart"] == on_start + assert resp["OnCreate"] == on_create + assert isinstance(resp["LastModifiedTime"], datetime.datetime) + assert isinstance(resp["CreationTime"], datetime.datetime) sagemaker.delete_notebook_instance_lifecycle_config( NotebookInstanceLifecycleConfigName=name, ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.describe_notebook_instance_lifecycle_config( NotebookInstanceLifecycleConfigName=name, ) - assert_true( - e.exception.response["Error"]["Message"].endswith( - "Notebook Instance Lifecycle Config does not exist.)" - ) + assert e.value.response["Error"]["Message"].endswith( + "Notebook Instance Lifecycle Config does not exist.)" ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sagemaker.delete_notebook_instance_lifecycle_config( NotebookInstanceLifecycleConfigName=name, ) - assert_true( - e.exception.response["Error"]["Message"].endswith( - "Notebook Instance Lifecycle Config does not exist.)" - ) + assert e.value.response["Error"]["Message"].endswith( + "Notebook Instance Lifecycle Config does not exist.)" ) diff --git a/tests/test_sagemaker/test_sagemaker_training.py b/tests/test_sagemaker/test_sagemaker_training.py index feaf9f713..c7b631ae3 100644 --- a/tests/test_sagemaker/test_sagemaker_training.py +++ b/tests/test_sagemaker/test_sagemaker_training.py @@ -7,7 +7,6 @@ import sure # noqa from moto import mock_sagemaker from moto.sts.models import ACCOUNT_ID -from nose.tools import assert_true, assert_equal, assert_raises, assert_regexp_matches FAKE_ROLE_ARN = "arn:aws:iam::{}:role/FakeRole".format(ACCOUNT_ID) TEST_REGION_NAME = "us-east-1" @@ -82,46 +81,42 @@ def test_create_training_job(): resp["TrainingJobArn"].should.match( r"^arn:aws:sagemaker:.*:.*:training-job/{}$".format(training_job_name) ) - assert_true( - resp["ModelArtifacts"]["S3ModelArtifacts"].startswith( - params["OutputDataConfig"]["S3OutputPath"] - ) + assert resp["ModelArtifacts"]["S3ModelArtifacts"].startswith( + params["OutputDataConfig"]["S3OutputPath"] ) - assert_true(training_job_name in (resp["ModelArtifacts"]["S3ModelArtifacts"])) - assert_true( - resp["ModelArtifacts"]["S3ModelArtifacts"].endswith("output/model.tar.gz") + assert training_job_name in (resp["ModelArtifacts"]["S3ModelArtifacts"]) + assert resp["ModelArtifacts"]["S3ModelArtifacts"].endswith("output/model.tar.gz") + assert resp["TrainingJobStatus"] == "Completed" + assert resp["SecondaryStatus"] == "Completed" + assert resp["HyperParameters"] == params["HyperParameters"] + assert ( + resp["AlgorithmSpecification"]["TrainingImage"] + == params["AlgorithmSpecification"]["TrainingImage"] ) - assert_equal(resp["TrainingJobStatus"], "Completed") - assert_equal(resp["SecondaryStatus"], "Completed") - assert_equal(resp["HyperParameters"], params["HyperParameters"]) - assert_equal( - resp["AlgorithmSpecification"]["TrainingImage"], - params["AlgorithmSpecification"]["TrainingImage"], + assert ( + resp["AlgorithmSpecification"]["TrainingInputMode"] + == params["AlgorithmSpecification"]["TrainingInputMode"] ) - assert_equal( - resp["AlgorithmSpecification"]["TrainingInputMode"], - params["AlgorithmSpecification"]["TrainingInputMode"], - ) - assert_true("MetricDefinitions" in resp["AlgorithmSpecification"]) - assert_true("Name" in resp["AlgorithmSpecification"]["MetricDefinitions"][0]) - assert_true("Regex" in resp["AlgorithmSpecification"]["MetricDefinitions"][0]) - assert_equal(resp["RoleArn"], FAKE_ROLE_ARN) - assert_equal(resp["InputDataConfig"], params["InputDataConfig"]) - assert_equal(resp["OutputDataConfig"], params["OutputDataConfig"]) - assert_equal(resp["ResourceConfig"], params["ResourceConfig"]) - assert_equal(resp["StoppingCondition"], params["StoppingCondition"]) - assert_true(isinstance(resp["CreationTime"], datetime.datetime)) - assert_true(isinstance(resp["TrainingStartTime"], datetime.datetime)) - assert_true(isinstance(resp["TrainingEndTime"], datetime.datetime)) - assert_true(isinstance(resp["LastModifiedTime"], datetime.datetime)) - assert_true("SecondaryStatusTransitions" in resp) - assert_true("Status" in resp["SecondaryStatusTransitions"][0]) - assert_true("StartTime" in resp["SecondaryStatusTransitions"][0]) - assert_true("EndTime" in resp["SecondaryStatusTransitions"][0]) - assert_true("StatusMessage" in resp["SecondaryStatusTransitions"][0]) - assert_true("FinalMetricDataList" in resp) - assert_true("MetricName" in resp["FinalMetricDataList"][0]) - assert_true("Value" in resp["FinalMetricDataList"][0]) - assert_true("Timestamp" in resp["FinalMetricDataList"][0]) + assert "MetricDefinitions" in resp["AlgorithmSpecification"] + assert "Name" in resp["AlgorithmSpecification"]["MetricDefinitions"][0] + assert "Regex" in resp["AlgorithmSpecification"]["MetricDefinitions"][0] + assert resp["RoleArn"] == FAKE_ROLE_ARN + assert resp["InputDataConfig"] == params["InputDataConfig"] + assert resp["OutputDataConfig"] == params["OutputDataConfig"] + assert resp["ResourceConfig"] == params["ResourceConfig"] + assert resp["StoppingCondition"] == params["StoppingCondition"] + assert isinstance(resp["CreationTime"], datetime.datetime) + assert isinstance(resp["TrainingStartTime"], datetime.datetime) + assert isinstance(resp["TrainingEndTime"], datetime.datetime) + assert isinstance(resp["LastModifiedTime"], datetime.datetime) + assert "SecondaryStatusTransitions" in resp + assert "Status" in resp["SecondaryStatusTransitions"][0] + assert "StartTime" in resp["SecondaryStatusTransitions"][0] + assert "EndTime" in resp["SecondaryStatusTransitions"][0] + assert "StatusMessage" in resp["SecondaryStatusTransitions"][0] + assert "FinalMetricDataList" in resp + assert "MetricName" in resp["FinalMetricDataList"][0] + assert "Value" in resp["FinalMetricDataList"][0] + assert "Timestamp" in resp["FinalMetricDataList"][0] pass diff --git a/tests/test_secretsmanager/__init__.py b/tests/test_secretsmanager/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_secretsmanager/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_secretsmanager/test_list_secrets.py b/tests/test_secretsmanager/test_list_secrets.py index 5470e3e12..8d8ddbd64 100644 --- a/tests/test_secretsmanager/test_list_secrets.py +++ b/tests/test_secretsmanager/test_list_secrets.py @@ -6,12 +6,7 @@ import boto3 from moto import mock_secretsmanager from botocore.exceptions import ClientError import sure # noqa -from nose.tools import assert_raises - -try: - from nose.tools import assert_items_equal -except ImportError: - from nose.tools import assert_count_equal as assert_items_equal +import pytest def boto_client(): @@ -24,7 +19,7 @@ def test_empty(): secrets = conn.list_secrets() - assert_items_equal(secrets["SecretList"], []) + assert secrets["SecretList"] == [] @mock_secretsmanager @@ -60,7 +55,7 @@ def test_with_name_filter(): secrets = conn.list_secrets(Filters=[{"Key": "name", "Values": ["foo"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo"]) + assert secret_names == ["foo"] @mock_secretsmanager @@ -75,7 +70,7 @@ def test_with_tag_key_filter(): secrets = conn.list_secrets(Filters=[{"Key": "tag-key", "Values": ["baz"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo"]) + assert secret_names == ["foo"] @mock_secretsmanager @@ -90,7 +85,7 @@ def test_with_tag_value_filter(): secrets = conn.list_secrets(Filters=[{"Key": "tag-value", "Values": ["baz"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo"]) + assert secret_names == ["foo"] @mock_secretsmanager @@ -103,7 +98,7 @@ def test_with_description_filter(): secrets = conn.list_secrets(Filters=[{"Key": "description", "Values": ["baz"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo"]) + assert secret_names == ["foo"] @mock_secretsmanager @@ -128,18 +123,18 @@ def test_with_all_filter(): secrets = conn.list_secrets(Filters=[{"Key": "all", "Values": ["foo"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo", "bar", "baz", "qux", "multi"]) + assert sorted(secret_names) == ["bar", "baz", "foo", "multi", "qux"] @mock_secretsmanager def test_with_no_filter_key(): conn = boto_client() - with assert_raises(ClientError) as ire: + with pytest.raises(ClientError) as ire: conn.list_secrets(Filters=[{"Values": ["foo"]}]) - ire.exception.response["Error"]["Code"].should.equal("InvalidParameterException") - ire.exception.response["Error"]["Message"].should.equal("Invalid filter key") + ire.value.response["Error"]["Code"].should.equal("InvalidParameterException") + ire.value.response["Error"]["Message"].should.equal("Invalid filter key") @mock_secretsmanager @@ -148,11 +143,11 @@ def test_with_no_filter_values(): conn.create_secret(Name="foo", SecretString="secret", Description="hello") - with assert_raises(ClientError) as ire: + with pytest.raises(ClientError) as ire: conn.list_secrets(Filters=[{"Key": "description"}]) - ire.exception.response["Error"]["Code"].should.equal("InvalidParameterException") - ire.exception.response["Error"]["Message"].should.equal( + ire.value.response["Error"]["Code"].should.equal("InvalidParameterException") + ire.value.response["Error"]["Message"].should.equal( "Invalid filter values for key: description" ) @@ -161,11 +156,11 @@ def test_with_no_filter_values(): def test_with_invalid_filter_key(): conn = boto_client() - with assert_raises(ClientError) as ire: + with pytest.raises(ClientError) as ire: conn.list_secrets(Filters=[{"Key": "invalid", "Values": ["foo"]}]) - ire.exception.response["Error"]["Code"].should.equal("ValidationException") - ire.exception.response["Error"]["Message"].should.equal( + ire.value.response["Error"]["Code"].should.equal("ValidationException") + ire.value.response["Error"]["Message"].should.equal( "1 validation error detected: Value 'invalid' at 'filters.1.member.key' failed to satisfy constraint: Member " "must satisfy enum value set: [all, name, tag-key, description, tag-value]" ) @@ -190,7 +185,7 @@ def test_with_duplicate_filter_keys(): ) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo"]) + assert secret_names == ["foo"] @mock_secretsmanager @@ -220,7 +215,7 @@ def test_with_multiple_filters(): ) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo"]) + assert secret_names == ["foo"] @mock_secretsmanager @@ -234,7 +229,7 @@ def test_with_filter_with_multiple_values(): secrets = conn.list_secrets(Filters=[{"Key": "name", "Values": ["foo", "bar"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo", "bar"]) + assert secret_names == ["foo", "bar"] @mock_secretsmanager @@ -250,4 +245,4 @@ def test_with_filter_with_value_with_multiple_words(): secrets = conn.list_secrets(Filters=[{"Key": "description", "Values": ["one two"]}]) secret_names = list(map(lambda s: s["Name"], secrets["SecretList"])) - assert_items_equal(secret_names, ["foo", "bar"]) + assert secret_names == ["foo", "bar"] diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index 68a7e6742..539b878f9 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -9,7 +9,7 @@ import string import pytz from datetime import datetime import sure # noqa -from nose.tools import assert_raises, assert_equal +import pytest from six import b DEFAULT_SECRET_NAME = "test-secret" @@ -53,12 +53,12 @@ def test_get_secret_value_binary(): def test_get_secret_that_does_not_exist(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: result = conn.get_secret_value(SecretId="i-dont-exist") - assert_equal( - "Secrets Manager can't find the specified secret.", - cm.exception.response["Error"]["Message"], + assert ( + "Secrets Manager can't find the specified secret." + == cm.value.response["Error"]["Message"] ) @@ -69,12 +69,12 @@ def test_get_secret_that_does_not_match(): Name="java-util-test-password", SecretString="foosecret" ) - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: result = conn.get_secret_value(SecretId="i-dont-match") - assert_equal( - "Secrets Manager can't find the specified secret.", - cm.exception.response["Error"]["Message"], + assert ( + "Secrets Manager can't find the specified secret." + == cm.value.response["Error"]["Message"] ) @@ -86,7 +86,7 @@ def test_get_secret_value_that_is_marked_deleted(): conn.delete_secret(SecretId="test-secret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.get_secret_value(SecretId="test-secret") @@ -96,12 +96,12 @@ def test_get_secret_that_has_no_value(): create_secret = conn.create_secret(Name="java-util-test-password") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: result = conn.get_secret_value(SecretId="java-util-test-password") - assert_equal( - "Secrets Manager can't find the specified secret value for staging label: AWSCURRENT", - cm.exception.response["Error"]["Message"], + assert ( + "Secrets Manager can't find the specified secret value for staging label: AWSCURRENT" + == cm.value.response["Error"]["Message"] ) @@ -113,16 +113,13 @@ def test_get_secret_version_that_does_not_exist(): secret_arn = result["ARN"] missing_version_id = "00000000-0000-0000-0000-000000000000" - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: conn.get_secret_value(SecretId=secret_arn, VersionId=missing_version_id) - assert_equal( - ( - "An error occurred (ResourceNotFoundException) when calling the GetSecretValue operation: Secrets " - "Manager can't find the specified secret value for VersionId: 00000000-0000-0000-0000-000000000000" - ), - cm.exception.response["Error"]["Message"], - ) + assert ( + "An error occurred (ResourceNotFoundException) when calling the GetSecretValue operation: Secrets " + "Manager can't find the specified secret value for VersionId: 00000000-0000-0000-0000-000000000000" + ) == cm.value.response["Error"]["Message"] @mock_secretsmanager @@ -227,7 +224,7 @@ def test_delete_secret_force(): assert result["DeletionDate"] > datetime.fromtimestamp(1, pytz.utc) assert result["Name"] == "test-secret" - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.get_secret_value(SecretId="test-secret") @@ -245,7 +242,7 @@ def test_delete_secret_force_with_arn(): assert result["DeletionDate"] > datetime.fromtimestamp(1, pytz.utc) assert result["Name"] == "test-secret" - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.get_secret_value(SecretId="test-secret") @@ -253,7 +250,7 @@ def test_delete_secret_force_with_arn(): def test_delete_secret_that_does_not_exist(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.delete_secret( SecretId="i-dont-exist", ForceDeleteWithoutRecovery=True ) @@ -265,7 +262,7 @@ def test_delete_secret_fails_with_both_force_delete_flag_and_recovery_window_fla conn.create_secret(Name="test-secret", SecretString="foosecret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.delete_secret( SecretId="test-secret", RecoveryWindowInDays=1, @@ -279,7 +276,7 @@ def test_delete_secret_recovery_window_too_short(): conn.create_secret(Name="test-secret", SecretString="foosecret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.delete_secret(SecretId="test-secret", RecoveryWindowInDays=6) @@ -289,7 +286,7 @@ def test_delete_secret_recovery_window_too_long(): conn.create_secret(Name="test-secret", SecretString="foosecret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.delete_secret(SecretId="test-secret", RecoveryWindowInDays=31) @@ -301,7 +298,7 @@ def test_delete_secret_that_is_marked_deleted(): deleted_secret = conn.delete_secret(SecretId="test-secret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.delete_secret(SecretId="test-secret") @@ -339,7 +336,7 @@ def test_get_random_exclude_lowercase(): conn = boto3.client("secretsmanager", region_name="us-west-2") random_password = conn.get_random_password(PasswordLength=55, ExcludeLowercase=True) - assert any(c.islower() for c in random_password["RandomPassword"]) == False + assert not any(c.islower() for c in random_password["RandomPassword"]) @mock_secretsmanager @@ -347,7 +344,7 @@ def test_get_random_exclude_uppercase(): conn = boto3.client("secretsmanager", region_name="us-west-2") random_password = conn.get_random_password(PasswordLength=55, ExcludeUppercase=True) - assert any(c.isupper() for c in random_password["RandomPassword"]) == False + assert not any(c.isupper() for c in random_password["RandomPassword"]) @mock_secretsmanager @@ -357,7 +354,7 @@ def test_get_random_exclude_characters_and_symbols(): random_password = conn.get_random_password( PasswordLength=20, ExcludeCharacters="xyzDje@?!." ) - assert any(c in "xyzDje@?!." for c in random_password["RandomPassword"]) == False + assert not any(c in "xyzDje@?!." for c in random_password["RandomPassword"]) assert len(random_password["RandomPassword"]) == 20 @@ -366,7 +363,7 @@ def test_get_random_exclude_numbers(): conn = boto3.client("secretsmanager", region_name="us-west-2") random_password = conn.get_random_password(PasswordLength=100, ExcludeNumbers=True) - assert any(c.isdigit() for c in random_password["RandomPassword"]) == False + assert not any(c.isdigit() for c in random_password["RandomPassword"]) @mock_secretsmanager @@ -376,9 +373,7 @@ def test_get_random_exclude_punctuation(): random_password = conn.get_random_password( PasswordLength=100, ExcludePunctuation=True ) - assert ( - any(c in string.punctuation for c in random_password["RandomPassword"]) == False - ) + assert not any(c in string.punctuation for c in random_password["RandomPassword"]) @mock_secretsmanager @@ -386,7 +381,7 @@ def test_get_random_include_space_false(): conn = boto3.client("secretsmanager", region_name="us-west-2") random_password = conn.get_random_password(PasswordLength=300) - assert any(c.isspace() for c in random_password["RandomPassword"]) == False + assert not any(c.isspace() for c in random_password["RandomPassword"]) @mock_secretsmanager @@ -394,7 +389,7 @@ def test_get_random_include_space_true(): conn = boto3.client("secretsmanager", region_name="us-west-2") random_password = conn.get_random_password(PasswordLength=4, IncludeSpace=True) - assert any(c.isspace() for c in random_password["RandomPassword"]) == True + assert any(c.isspace() for c in random_password["RandomPassword"]) @mock_secretsmanager @@ -404,25 +399,17 @@ def test_get_random_require_each_included_type(): random_password = conn.get_random_password( PasswordLength=4, RequireEachIncludedType=True ) - assert ( - any(c in string.punctuation for c in random_password["RandomPassword"]) == True - ) - assert ( - any(c in string.ascii_lowercase for c in random_password["RandomPassword"]) - == True - ) - assert ( - any(c in string.ascii_uppercase for c in random_password["RandomPassword"]) - == True - ) - assert any(c in string.digits for c in random_password["RandomPassword"]) == True + assert any(c in string.punctuation for c in random_password["RandomPassword"]) + assert any(c in string.ascii_lowercase for c in random_password["RandomPassword"]) + assert any(c in string.ascii_uppercase for c in random_password["RandomPassword"]) + assert any(c in string.digits for c in random_password["RandomPassword"]) @mock_secretsmanager def test_get_random_too_short_password(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError): + with pytest.raises(ClientError): random_password = conn.get_random_password(PasswordLength=3) @@ -430,7 +417,7 @@ def test_get_random_too_short_password(): def test_get_random_too_long_password(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(Exception): + with pytest.raises(Exception): random_password = conn.get_random_password(PasswordLength=5555) @@ -468,7 +455,7 @@ def test_describe_secret_with_arn(): def test_describe_secret_that_does_not_exist(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.get_secret_value(SecretId="i-dont-exist") @@ -477,7 +464,7 @@ def test_describe_secret_that_does_not_match(): conn = boto3.client("secretsmanager", region_name="us-west-2") conn.create_secret(Name="test-secret", SecretString="foosecret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.get_secret_value(SecretId="i-dont-match") @@ -515,7 +502,7 @@ def test_restore_secret_that_is_not_deleted(): def test_restore_secret_that_does_not_exist(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.restore_secret(SecretId="i-dont-exist") @@ -566,7 +553,7 @@ def test_rotate_secret_that_is_marked_deleted(): conn.delete_secret(SecretId="test-secret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.rotate_secret(SecretId="test-secret") @@ -574,7 +561,7 @@ def test_rotate_secret_that_is_marked_deleted(): def test_rotate_secret_that_does_not_exist(): conn = boto3.client("secretsmanager", "us-west-2") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.rotate_secret(SecretId="i-dont-exist") @@ -583,7 +570,7 @@ def test_rotate_secret_that_does_not_match(): conn = boto3.client("secretsmanager", region_name="us-west-2") conn.create_secret(Name="test-secret", SecretString="foosecret") - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.rotate_secret(SecretId="i-dont-match") @@ -603,7 +590,7 @@ def test_rotate_secret_client_request_token_too_long(): client_request_token = ( "ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C-" "ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C" ) - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.rotate_secret( SecretId=DEFAULT_SECRET_NAME, ClientRequestToken=client_request_token ) @@ -615,7 +602,7 @@ def test_rotate_secret_rotation_lambda_arn_too_long(): conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretString="foosecret") rotation_lambda_arn = "85B7-446A-B7E4" * 147 # == 2058 characters - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.rotate_secret( SecretId=DEFAULT_SECRET_NAME, RotationLambdaARN=rotation_lambda_arn ) @@ -635,7 +622,7 @@ def test_rotate_secret_rotation_period_too_long(): conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretString="foosecret") rotation_rules = {"AutomaticallyAfterDays": 1001} - with assert_raises(ClientError): + with pytest.raises(ClientError): result = conn.rotate_secret( SecretId=DEFAULT_SECRET_NAME, RotationRules=rotation_rules ) @@ -644,16 +631,15 @@ def test_rotate_secret_rotation_period_too_long(): @mock_secretsmanager def test_put_secret_value_on_non_existing_secret(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: conn.put_secret_value( SecretId=DEFAULT_SECRET_NAME, SecretString="foosecret", VersionStages=["AWSCURRENT"], ) - assert_equal( - "Secrets Manager can't find the specified secret.", - cm.exception.response["Error"]["Message"], + cm.value.response["Error"]["Message"].should.equal( + "Secrets Manager can't find the specified secret." ) @@ -712,11 +698,11 @@ def test_create_and_put_secret_binary_value_puts_new_secret(): @mock_secretsmanager def test_put_secret_binary_requires_either_string_or_binary(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError) as ire: + with pytest.raises(ClientError) as ire: conn.put_secret_value(SecretId=DEFAULT_SECRET_NAME) - ire.exception.response["Error"]["Code"].should.equal("InvalidRequestException") - ire.exception.response["Error"]["Message"].should.equal( + ire.value.response["Error"]["Code"].should.equal("InvalidRequestException") + ire.value.response["Error"]["Message"].should.equal( "You must provide either SecretString or SecretBinary." ) @@ -889,14 +875,14 @@ def test_update_secret_with_tags_and_description(): def test_update_secret_which_does_not_exit(): conn = boto3.client("secretsmanager", region_name="us-west-2") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: updated_secret = conn.update_secret( SecretId="test-secret", SecretString="barsecret" ) - assert_equal( - "Secrets Manager can't find the specified secret.", - cm.exception.response["Error"]["Message"], + assert ( + "Secrets Manager can't find the specified secret." + == cm.value.response["Error"]["Message"] ) @@ -907,14 +893,13 @@ def test_update_secret_marked_as_deleted(): created_secret = conn.create_secret(Name="test-secret", SecretString="foosecret") deleted_secret = conn.delete_secret(SecretId="test-secret") - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: updated_secret = conn.update_secret( SecretId="test-secret", SecretString="barsecret" ) assert ( - "because it was marked for deletion." - in cm.exception.response["Error"]["Message"] + "because it was marked for deletion." in cm.value.response["Error"]["Message"] ) @@ -953,15 +938,15 @@ def test_tag_resource(): {"Key": "SecondTag", "Value": "AnotherValue"}, ] - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: conn.tag_resource( SecretId="dummy-test-secret", Tags=[{"Key": "FirstTag", "Value": "SomeValue"},], ) - assert_equal( - "Secrets Manager can't find the specified secret.", - cm.exception.response["Error"]["Message"], + assert ( + "Secrets Manager can't find the specified secret." + == cm.value.response["Error"]["Message"] ) diff --git a/tests/test_ses/__init__.py b/tests/test_ses/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_ses/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_ses/test_ses_boto3.py b/tests/test_ses/test_ses_boto3.py index efd4b980c..5af4d9cbf 100644 --- a/tests/test_ses/test_ses_boto3.py +++ b/tests/test_ses/test_ses_boto3.py @@ -4,7 +4,7 @@ import boto3 from botocore.exceptions import ClientError from six.moves.email_mime_multipart import MIMEMultipart from six.moves.email_mime_text import MIMEText -from nose.tools import assert_raises +import pytest import sure # noqa @@ -276,7 +276,7 @@ def test_send_email_notification_with_encoded_sender(): response = conn.send_email( Source=sender, Destination={"ToAddresses": ["your.friend@hotmail.com"]}, - Message={"Subject": {"Data": "hi",}, "Body": {"Text": {"Data": "there",}}}, + Message={"Subject": {"Data": "hi",}, "Body": {"Text": {"Data": "there",}},}, ) response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) @@ -298,7 +298,7 @@ def test_create_configuration_set(): }, ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_configuration_set_event_destination( ConfigurationSetName="failtest", EventDestination={ @@ -311,9 +311,9 @@ def test_create_configuration_set(): }, ) - ex.exception.response["Error"]["Code"].should.equal("ConfigurationSetDoesNotExist") + ex.value.response["Error"]["Code"].should.equal("ConfigurationSetDoesNotExist") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_configuration_set_event_destination( ConfigurationSetName="test", EventDestination={ @@ -326,7 +326,7 @@ def test_create_configuration_set(): }, ) - ex.exception.response["Error"]["Code"].should.equal("EventDestinationAlreadyExists") + ex.value.response["Error"]["Code"].should.equal("EventDestinationAlreadyExists") @mock_ses @@ -336,10 +336,10 @@ def test_create_receipt_rule_set(): result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_receipt_rule_set(RuleSetName="testRuleSet") - ex.exception.response["Error"]["Code"].should.equal("RuleSetNameAlreadyExists") + ex.value.response["Error"]["Code"].should.equal("RuleSetNameAlreadyExists") @mock_ses @@ -378,7 +378,7 @@ def test_create_receipt_rule(): result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_receipt_rule( RuleSetName=rule_set_name, Rule={ @@ -407,9 +407,9 @@ def test_create_receipt_rule(): }, ) - ex.exception.response["Error"]["Code"].should.equal("RuleAlreadyExists") + ex.value.response["Error"]["Code"].should.equal("RuleAlreadyExists") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_receipt_rule( RuleSetName="InvalidRuleSetaName", Rule={ @@ -438,7 +438,7 @@ def test_create_receipt_rule(): }, ) - ex.exception.response["Error"]["Code"].should.equal("RuleSetDoesNotExist") + ex.value.response["Error"]["Code"].should.equal("RuleSetDoesNotExist") @mock_ses @@ -455,7 +455,7 @@ def test_create_ses_template(): "

Your favorite animal is {{favoriteanimal}}.

", } ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.create_template( Template={ "TemplateName": "MyTemplate", @@ -467,7 +467,7 @@ def test_create_ses_template(): } ) - ex.exception.response["Error"]["Code"].should.equal("TemplateNameAlreadyExists") + ex.value.response["Error"]["Code"].should.equal("TemplateNameAlreadyExists") # get a template which is already added result = conn.get_template(TemplateName="MyTemplate") @@ -475,10 +475,10 @@ def test_create_ses_template(): result["Template"]["SubjectPart"].should.equal("Greetings, {{name}}!") # get a template which is not present - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: conn.get_template(TemplateName="MyFakeTemplate") - ex.exception.response["Error"]["Code"].should.equal("TemplateDoesNotExist") + ex.value.response["Error"]["Code"].should.equal("TemplateDoesNotExist") result = conn.list_templates() result["TemplatesMetadata"][0]["Name"].should.equal("MyTemplate") diff --git a/tests/test_ses/test_ses_sns_boto3.py b/tests/test_ses/test_ses_sns_boto3.py index 43d4000bf..2a165080e 100644 --- a/tests/test_ses/test_ses_sns_boto3.py +++ b/tests/test_ses/test_ses_sns_boto3.py @@ -7,7 +7,6 @@ from six.moves.email_mime_multipart import MIMEMultipart from six.moves.email_mime_text import MIMEText import sure # noqa -from nose import tools from moto import mock_ses, mock_sns, mock_sqs from moto.ses.models import SESFeedback from moto.core import ACCOUNT_ID diff --git a/tests/test_sns/__init__.py b/tests/test_sns/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_sns/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_sns/test_publishing_boto3.py b/tests/test_sns/test_publishing_boto3.py index 63c409302..797ccdaba 100644 --- a/tests/test_sns/test_publishing_boto3.py +++ b/tests/test_sns/test_publishing_boto3.py @@ -10,7 +10,7 @@ import sure # noqa import responses from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_sns, mock_sqs, settings from moto.core import ACCOUNT_ID from moto.sns import sns_backend @@ -233,16 +233,16 @@ def test_publish_bad_sms(): client = boto3.client("sns", region_name="us-east-1") # Test invalid number - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: client.publish(PhoneNumber="NAA+15551234567", Message="my message") - cm.exception.response["Error"]["Code"].should.equal("InvalidParameter") - cm.exception.response["Error"]["Message"].should.contain("not meet the E164") + cm.value.response["Error"]["Code"].should.equal("InvalidParameter") + cm.value.response["Error"]["Message"].should.contain("not meet the E164") # Test to long ASCII message - with assert_raises(ClientError) as cm: + with pytest.raises(ClientError) as cm: client.publish(PhoneNumber="+15551234567", Message="a" * 1601) - cm.exception.response["Error"]["Code"].should.equal("InvalidParameter") - cm.exception.response["Error"]["Message"].should.contain("must be less than 1600") + cm.value.response["Error"]["Code"].should.equal("InvalidParameter") + cm.value.response["Error"]["Message"].should.contain("must be less than 1600") @mock_sqs @@ -387,7 +387,7 @@ def test_publish_message_too_long(): sns = boto3.resource("sns", region_name="us-east-1") topic = sns.create_topic(Name="some-topic") - with assert_raises(ClientError): + with pytest.raises(ClientError): topic.publish(Message="".join(["." for i in range(0, 262145)])) # message short enough - does not raise an error diff --git a/tests/test_sns/test_subscriptions_boto3.py b/tests/test_sns/test_subscriptions_boto3.py index c15658dca..b476cd86d 100644 --- a/tests/test_sns/test_subscriptions_boto3.py +++ b/tests/test_sns/test_subscriptions_boto3.py @@ -5,7 +5,7 @@ import json import sure # noqa from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_sns, mock_sqs from moto.sns.models import ( @@ -293,7 +293,7 @@ def test_creating_subscription_with_attributes(): subscriptions.should.have.length_of(0) # invalid attr name - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.subscribe( TopicArn=topic_arn, Protocol="http", @@ -387,17 +387,17 @@ def test_set_subscription_attributes(): attrs["Attributes"]["FilterPolicy"].should.equal(filter_policy) # not existing subscription - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.set_subscription_attributes( SubscriptionArn="invalid", AttributeName="RawMessageDelivery", AttributeValue="true", ) - with assert_raises(ClientError): + with pytest.raises(ClientError): attrs = conn.get_subscription_attributes(SubscriptionArn="invalid") # invalid attr name - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.set_subscription_attributes( SubscriptionArn=subscription_arn, AttributeName="InvalidName", @@ -502,7 +502,7 @@ def test_check_opted_out_invalid(): conn = boto3.client("sns", region_name="us-east-1") # Invalid phone number - with assert_raises(ClientError): + with pytest.raises(ClientError): conn.check_if_phone_number_is_opted_out(phoneNumber="+44742LALALA") diff --git a/tests/test_sns/test_topics_boto3.py b/tests/test_sns/test_topics_boto3.py index 49aa656aa..6b1e52df6 100644 --- a/tests/test_sns/test_topics_boto3.py +++ b/tests/test_sns/test_topics_boto3.py @@ -538,7 +538,7 @@ def test_topic_kms_master_key_id_attribute(): resp["Attributes"]["KmsMasterKeyId"].should.equal("test-key") resp = client.create_topic( - Name="test-sns-with-key-attr", Attributes={"KmsMasterKeyId": "key-id",} + Name="test-sns-with-key-attr", Attributes={"KmsMasterKeyId": "key-id",}, ) topic_arn = resp["TopicArn"] resp = client.get_topic_attributes(TopicArn=topic_arn) diff --git a/tests/test_sqs/__init__.py b/tests/test_sqs/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_sqs/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index b974e04f6..c234f5cdc 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -11,14 +11,13 @@ import boto3 import botocore.exceptions import six import sure # noqa -import tests.backport_assert_raises # noqa from boto.exception import SQSError from boto.sqs.message import Message, RawMessage from botocore.exceptions import ClientError from freezegun import freeze_time from moto import mock_sqs, mock_sqs_deprecated, mock_lambda, mock_logs, settings -from nose import SkipTest -from nose.tools import assert_raises +from unittest import SkipTest +import pytest from tests.helpers import requires_boto_gte from tests.test_awslambda.test_lambda import get_test_zip_file1, get_role_name from moto.core import ACCOUNT_ID @@ -220,18 +219,18 @@ def test_get_queue_url_errors(): @mock_sqs def test_get_nonexistent_queue(): sqs = boto3.resource("sqs", region_name="us-east-1") - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: sqs.get_queue_by_name(QueueName="non-existing-queue") - ex = err.exception + ex = err.value ex.operation_name.should.equal("GetQueueUrl") ex.response["Error"]["Code"].should.equal("AWS.SimpleQueueService.NonExistentQueue") ex.response["Error"]["Message"].should.equal( "The specified queue non-existing-queue does not exist for this wsdl version." ) - with assert_raises(ClientError) as err: + with pytest.raises(ClientError) as err: sqs.Queue("http://whatever-incorrect-queue-address").load() - ex = err.exception + ex = err.value ex.operation_name.should.equal("GetQueueAttributes") ex.response["Error"]["Code"].should.equal("AWS.SimpleQueueService.NonExistentQueue") @@ -274,14 +273,14 @@ def test_message_send_with_attributes(): def test_message_with_invalid_attributes(): sqs = boto3.resource("sqs", region_name="us-east-1") queue = sqs.create_queue(QueueName="blah") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: queue.send_message( MessageBody="derp", MessageAttributes={ "öther_encodings": {"DataType": "String", "StringValue": "str"}, }, ) - ex = e.exception + ex = e.value ex.response["Error"]["Code"].should.equal("MessageAttributesInvalid") ex.response["Error"]["Message"].should.equal( "The message attribute name 'öther_encodings' is invalid. " @@ -368,7 +367,7 @@ def test_message_with_attributes_invalid_datatype(): sqs = boto3.resource("sqs", region_name="us-east-1") queue = sqs.create_queue(QueueName="blah") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: queue.send_message( MessageBody="derp", MessageAttributes={ @@ -378,7 +377,7 @@ def test_message_with_attributes_invalid_datatype(): } }, ) - ex = e.exception + ex = e.value ex.response["Error"]["Code"].should.equal("MessageAttributesInvalid") ex.response["Error"]["Message"].should.equal( "The message attribute 'timestamp' has an invalid message attribute type, the set of supported type " @@ -491,7 +490,7 @@ def test_delete_queue(): queue.delete() conn.list_queues().get("QueueUrls").should.equal(None) - with assert_raises(botocore.exceptions.ClientError): + with pytest.raises(botocore.exceptions.ClientError): queue.delete() @@ -758,10 +757,10 @@ def test_max_number_of_messages_invalid_param(): sqs = boto3.resource("sqs", region_name="us-east-1") queue = sqs.create_queue(QueueName="test-queue") - with assert_raises(ClientError): + with pytest.raises(ClientError): queue.receive_messages(MaxNumberOfMessages=11) - with assert_raises(ClientError): + with pytest.raises(ClientError): queue.receive_messages(MaxNumberOfMessages=0) # no error but also no messages returned @@ -773,10 +772,10 @@ def test_wait_time_seconds_invalid_param(): sqs = boto3.resource("sqs", region_name="us-east-1") queue = sqs.create_queue(QueueName="test-queue") - with assert_raises(ClientError): + with pytest.raises(ClientError): queue.receive_messages(WaitTimeSeconds=-1) - with assert_raises(ClientError): + with pytest.raises(ClientError): queue.receive_messages(WaitTimeSeconds=21) # no error but also no messages returned @@ -1652,14 +1651,14 @@ def test_add_permission_errors(): Actions=["ReceiveMessage"], ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.add_permission( QueueUrl=queue_url, Label="test", AWSAccountIds=["111111111111"], Actions=["ReceiveMessage", "SendMessage"], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AddPermission") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterValue") @@ -1667,14 +1666,14 @@ def test_add_permission_errors(): "Value test for parameter Label is invalid. " "Reason: Already exists." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.add_permission( QueueUrl=queue_url, Label="test-2", AWSAccountIds=["111111111111"], Actions=["RemovePermission"], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AddPermission") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterValue") @@ -1683,14 +1682,14 @@ def test_add_permission_errors(): "Reason: Only the queue owner is allowed to invoke this action." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.add_permission( QueueUrl=queue_url, Label="test-2", AWSAccountIds=["111111111111"], Actions=[], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AddPermission") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("MissingParameter") @@ -1698,14 +1697,14 @@ def test_add_permission_errors(): "The request must contain the parameter Actions." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.add_permission( QueueUrl=queue_url, Label="test-2", AWSAccountIds=[], Actions=["ReceiveMessage"], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AddPermission") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterValue") @@ -1713,7 +1712,7 @@ def test_add_permission_errors(): "Value [] for parameter PrincipalId is invalid. Reason: Unable to verify." ) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.add_permission( QueueUrl=queue_url, Label="test-2", @@ -1729,7 +1728,7 @@ def test_add_permission_errors(): "SendMessage", ], ) - ex = e.exception + ex = e.value ex.operation_name.should.equal("AddPermission") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403) ex.response["Error"]["Code"].should.contain("OverLimit") @@ -1744,9 +1743,9 @@ def test_remove_permission_errors(): response = client.create_queue(QueueName="test-queue") queue_url = response["QueueUrl"] - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.remove_permission(QueueUrl=queue_url, Label="test") - ex = e.exception + ex = e.value ex.operation_name.should.equal("RemovePermission") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("InvalidParameterValue") @@ -1876,7 +1875,7 @@ def test_create_fifo_queue_with_dlq(): ) # Cant have fifo queue with non fifo DLQ - with assert_raises(ClientError): + with pytest.raises(ClientError): sqs.create_queue( QueueName="test-queue2.fifo", Attributes={ @@ -1970,7 +1969,7 @@ def test_redrive_policy_available(): assert json.loads(attributes["RedrivePolicy"]) == redrive_policy # Cant have redrive policy without maxReceiveCount - with assert_raises(ClientError): + with pytest.raises(ClientError): sqs.create_queue( QueueName="test-queue2", Attributes={ @@ -1988,7 +1987,7 @@ def test_redrive_policy_non_existent_queue(): "maxReceiveCount": 1, } - with assert_raises(ClientError): + with pytest.raises(ClientError): sqs.create_queue( QueueName="test-queue", Attributes={"RedrivePolicy": json.dumps(redrive_policy)}, @@ -2173,9 +2172,9 @@ def test_send_messages_to_fifo_without_message_group_id(): Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"}, ) - with assert_raises(Exception) as e: + with pytest.raises(Exception) as e: queue.send_message(MessageBody="message-1") - ex = e.exception + ex = e.value ex.response["Error"]["Code"].should.equal("MissingParameter") ex.response["Error"]["Message"].should.equal( "The request must contain the parameter MessageGroupId." @@ -2245,9 +2244,9 @@ def test_maximum_message_size_attribute_default(): sqs = boto3.resource("sqs", region_name="eu-west-3") queue = sqs.create_queue(QueueName="test-queue",) int(queue.attributes["MaximumMessageSize"]).should.equal(MAXIMUM_MESSAGE_LENGTH) - with assert_raises(Exception) as e: + with pytest.raises(Exception) as e: queue.send_message(MessageBody="a" * (MAXIMUM_MESSAGE_LENGTH + 1)) - ex = e.exception + ex = e.value ex.response["Error"]["Code"].should.equal("InvalidParameterValue") @@ -2259,12 +2258,12 @@ def test_maximum_message_size_attribute_fails_for_invalid_values(): MAXIMUM_MESSAGE_SIZE_ATTR_UPPER_BOUND + 1, ] for message_size in invalid_values: - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: sqs.create_queue( QueueName="test-queue", Attributes={"MaximumMessageSize": str(message_size)}, ) - ex = e.exception + ex = e.value ex.response["Error"]["Code"].should.equal("InvalidAttributeValue") @@ -2277,9 +2276,9 @@ def test_send_message_fails_when_message_size_greater_than_max_message_size(): Attributes={"MaximumMessageSize": str(message_size_limit)}, ) int(queue.attributes["MaximumMessageSize"]).should.equal(message_size_limit) - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: queue.send_message(MessageBody="a" * (message_size_limit + 1)) - ex = e.exception + ex = e.value ex.response["Error"]["Code"].should.equal("InvalidParameterValue") ex.response["Error"]["Message"].should.contain( "{} bytes".format(message_size_limit) diff --git a/tests/test_ssm/__init__.py b/tests/test_ssm/__init__.py index e69de29bb..08a1c1568 100644 --- a/tests/test_ssm/__init__.py +++ b/tests/test_ssm/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_ssm/test_ssm_boto3.py b/tests/test_ssm/test_ssm_boto3.py index c590e75b7..5aad14429 100644 --- a/tests/test_ssm/test_ssm_boto3.py +++ b/tests/test_ssm/test_ssm_boto3.py @@ -9,7 +9,7 @@ import datetime import uuid from botocore.exceptions import ClientError, ParamValidationError -from nose.tools import assert_raises +import pytest from moto import mock_ec2, mock_ssm @@ -35,10 +35,10 @@ def test_delete_parameter(): def test_delete_nonexistent_parameter(): client = boto3.client("ssm", region_name="us-east-1") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.delete_parameter(Name="test_noexist") - ex.exception.response["Error"]["Code"].should.equal("ParameterNotFound") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ParameterNotFound") + ex.value.response["Error"]["Message"].should.equal( "Parameter test_noexist not found." ) @@ -438,19 +438,17 @@ def test_get_parameter_with_version_and_labels(): "arn:aws:ssm:us-east-1:1234567890:parameter/test-2" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_parameter(Name="test-2:2:3", WithDecryption=False) - ex.exception.response["Error"]["Code"].should.equal("ParameterNotFound") - ex.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Code"].should.equal("ParameterNotFound") + ex.value.response["Error"]["Message"].should.equal( "Parameter test-2:2:3 not found." ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.get_parameter(Name="test-2:2", WithDecryption=False) - ex.exception.response["Error"]["Code"].should.equal("ParameterNotFound") - ex.exception.response["Error"]["Message"].should.equal( - "Parameter test-2:2 not found." - ) + ex.value.response["Error"]["Code"].should.equal("ParameterNotFound") + ex.value.response["Error"]["Message"].should.equal("Parameter test-2:2 not found.") @mock_ssm @@ -462,9 +460,9 @@ def test_get_parameters_errors(): for name, value in ssm_parameters.items(): client.put_parameter(Name=name, Value=value, Type="String") - with assert_raises(ClientError) as e: + with pytest.raises(ClientError) as e: client.get_parameters(Names=list(ssm_parameters.keys())) - ex = e.exception + ex = e.value ex.operation_name.should.equal("GetParameters") ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["Error"]["Code"].should.contain("ValidationException") @@ -1671,7 +1669,7 @@ def test_list_commands(): cmd["InstanceIds"].should.contain("i-123456") # test the error case for an invalid command id - with assert_raises(ClientError): + with pytest.raises(ClientError): response = client.list_commands(CommandId=str(uuid.uuid4())) @@ -1703,13 +1701,13 @@ def test_get_command_invocation(): invocation_response["InstanceId"].should.equal(instance_id) # test the error case for an invalid instance id - with assert_raises(ClientError): + with pytest.raises(ClientError): invocation_response = client.get_command_invocation( CommandId=cmd_id, InstanceId="i-FAKE" ) # test the error case for an invalid plugin name - with assert_raises(ClientError): + with pytest.raises(ClientError): invocation_response = client.get_command_invocation( CommandId=cmd_id, InstanceId=instance_id, PluginName="FAKE" ) diff --git a/tests/test_stepfunctions/__init__.py b/tests/test_stepfunctions/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_stepfunctions/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_stepfunctions/test_stepfunctions.py b/tests/test_stepfunctions/test_stepfunctions.py index dd11e7961..13a6809f5 100644 --- a/tests/test_stepfunctions/test_stepfunctions.py +++ b/tests/test_stepfunctions/test_stepfunctions.py @@ -6,7 +6,7 @@ import sure # noqa from datetime import datetime from botocore.exceptions import ClientError -from nose.tools import assert_raises +import pytest from moto import mock_cloudformation, mock_sts, mock_stepfunctions from moto.core import ACCOUNT_ID @@ -134,7 +134,7 @@ def test_state_machine_creation_fails_with_invalid_names(): # for invalid_name in invalid_names: - with assert_raises(ClientError): + with pytest.raises(ClientError): client.create_state_machine( name=invalid_name, definition=str(simple_definition), @@ -147,7 +147,7 @@ def test_state_machine_creation_requires_valid_role_arn(): client = boto3.client("stepfunctions", region_name=region) name = "example_step_function" # - with assert_raises(ClientError): + with pytest.raises(ClientError): client.create_state_machine( name=name, definition=str(simple_definition), @@ -291,7 +291,7 @@ def test_state_machine_creation_can_be_described(): def test_state_machine_throws_error_when_describing_unknown_machine(): client = boto3.client("stepfunctions", region_name=region) # - with assert_raises(ClientError): + with pytest.raises(ClientError): unknown_state_machine = ( "arn:aws:states:" + region @@ -307,7 +307,7 @@ def test_state_machine_throws_error_when_describing_unknown_machine(): def test_state_machine_throws_error_when_describing_bad_arn(): client = boto3.client("stepfunctions", region_name=region) # - with assert_raises(ClientError): + with pytest.raises(ClientError): client.describe_state_machine(stateMachineArn="bad") @@ -316,7 +316,7 @@ def test_state_machine_throws_error_when_describing_bad_arn(): def test_state_machine_throws_error_when_describing_machine_in_different_account(): client = boto3.client("stepfunctions", region_name=region) # - with assert_raises(ClientError): + with pytest.raises(ClientError): unknown_state_machine = ( "arn:aws:states:" + region + ":000000000000:stateMachine:unknown" ) @@ -359,10 +359,10 @@ def test_state_machine_tagging_non_existent_resource_fails(): non_existent_arn = "arn:aws:states:{region}:{account}:stateMachine:non-existent".format( region=region, account=ACCOUNT_ID ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.tag_resource(resourceArn=non_existent_arn, tags=[]) - ex.exception.response["Error"]["Code"].should.equal("ResourceNotFound") - ex.exception.response["Error"]["Message"].should.contain(non_existent_arn) + ex.value.response["Error"]["Code"].should.equal("ResourceNotFound") + ex.value.response["Error"]["Message"].should.contain(non_existent_arn) @mock_stepfunctions @@ -371,10 +371,10 @@ def test_state_machine_untagging_non_existent_resource_fails(): non_existent_arn = "arn:aws:states:{region}:{account}:stateMachine:non-existent".format( region=region, account=ACCOUNT_ID ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.untag_resource(resourceArn=non_existent_arn, tagKeys=[]) - ex.exception.response["Error"]["Code"].should.equal("ResourceNotFound") - ex.exception.response["Error"]["Message"].should.contain(non_existent_arn) + ex.value.response["Error"]["Code"].should.equal("ResourceNotFound") + ex.value.response["Error"]["Message"].should.contain(non_existent_arn) @mock_stepfunctions @@ -504,7 +504,7 @@ def test_state_machine_start_execution(): def test_state_machine_start_execution_bad_arn_raises_exception(): client = boto3.client("stepfunctions", region_name=region) # - with assert_raises(ClientError): + with pytest.raises(ClientError): client.start_execution(stateMachineArn="bad") @@ -544,11 +544,11 @@ def test_state_machine_start_execution_fails_on_duplicate_execution_name(): stateMachineArn=sm["stateMachineArn"], name="execution_name" ) # - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as ex: _ = client.start_execution( stateMachineArn=sm["stateMachineArn"], name="execution_name" ) - exc.exception.response["Error"]["Message"].should.equal( + ex.value.response["Error"]["Message"].should.equal( "Execution Already Exists: '" + execution_one["executionArn"] + "'" ) @@ -588,9 +588,9 @@ def test_state_machine_start_execution_with_invalid_input(): sm = client.create_state_machine( name="name", definition=str(simple_definition), roleArn=_get_default_role() ) - with assert_raises(ClientError): + with pytest.raises(ClientError): _ = client.start_execution(stateMachineArn=sm["stateMachineArn"], input="") - with assert_raises(ClientError): + with pytest.raises(ClientError): _ = client.start_execution(stateMachineArn=sm["stateMachineArn"], input="{") @@ -658,7 +658,7 @@ def test_state_machine_list_executions_with_pagination(): for page in page_iterator: page["executions"].should.have.length_of(25) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: resp = client.list_executions( stateMachineArn=sm["stateMachineArn"], maxResults=10 ) @@ -668,16 +668,16 @@ def test_state_machine_list_executions_with_pagination(): statusFilter="ABORTED", nextToken=resp["nextToken"], ) - ex.exception.response["Error"]["Code"].should.equal("InvalidToken") - ex.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("InvalidToken") + ex.value.response["Error"]["Message"].should.contain( "Input inconsistent with page token" ) - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: client.list_executions( stateMachineArn=sm["stateMachineArn"], nextToken="invalid" ) - ex.exception.response["Error"]["Code"].should.equal("InvalidToken") + ex.value.response["Error"]["Code"].should.equal("InvalidToken") @mock_stepfunctions @@ -744,7 +744,7 @@ def test_state_machine_describe_execution_with_custom_input(): def test_execution_throws_error_when_describing_unknown_execution(): client = boto3.client("stepfunctions", region_name=region) # - with assert_raises(ClientError): + with pytest.raises(ClientError): unknown_execution = ( "arn:aws:states:" + region + ":" + _get_account_id() + ":execution:unknown" ) @@ -775,7 +775,7 @@ def test_state_machine_can_be_described_by_execution(): def test_state_machine_throws_error_when_describing_unknown_execution(): client = boto3.client("stepfunctions", region_name=region) # - with assert_raises(ClientError): + with pytest.raises(ClientError): unknown_execution = ( "arn:aws:states:" + region + ":" + _get_account_id() + ":execution:unknown" ) @@ -861,10 +861,10 @@ def test_state_machine_cloudformation(): tag["value"].should.equal("value{}".format(i)) cf.Stack("test_stack").delete() - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: sf.describe_state_machine(stateMachineArn=output["StateMachineArn"]) - ex.exception.response["Error"]["Code"].should.equal("StateMachineDoesNotExist") - ex.exception.response["Error"]["Message"].should.contain("Does Not Exist") + ex.value.response["Error"]["Code"].should.equal("StateMachineDoesNotExist") + ex.value.response["Error"]["Message"].should.contain("Does Not Exist") @mock_stepfunctions @@ -935,12 +935,10 @@ def test_state_machine_cloudformation_update_with_replacement(): if tag["key"] == "key1": tag["value"].should.equal("updated_value") - with assert_raises(ClientError) as ex: + with pytest.raises(ClientError) as ex: sf.describe_state_machine(stateMachineArn=original_machine_arn) - ex.exception.response["Error"]["Code"].should.equal("StateMachineDoesNotExist") - ex.exception.response["Error"]["Message"].should.contain( - "State Machine Does Not Exist" - ) + ex.value.response["Error"]["Code"].should.equal("StateMachineDoesNotExist") + ex.value.response["Error"]["Message"].should.contain("State Machine Does Not Exist") @mock_stepfunctions diff --git a/tests/test_sts/__init__.py b/tests/test_sts/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_sts/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tests/test_sts/test_sts.py b/tests/test_sts/test_sts.py index efc04beb4..098da5881 100644 --- a/tests/test_sts/test_sts.py +++ b/tests/test_sts/test_sts.py @@ -6,7 +6,7 @@ import boto import boto3 from botocore.client import ClientError from freezegun import freeze_time -from nose.tools import assert_raises +import pytest import sure # noqa @@ -357,9 +357,9 @@ def test_federation_token_with_too_long_policy(): json_policy = json.dumps(policy) assert len(json_policy) > MAX_FEDERATION_TOKEN_POLICY_LENGTH - with assert_raises(ClientError) as exc: + with pytest.raises(ClientError) as ex: cli.get_federation_token(Name="foo", DurationSeconds=3600, Policy=json_policy) - exc.exception.response["Error"]["Code"].should.equal("ValidationError") - exc.exception.response["Error"]["Message"].should.contain( + ex.value.response["Error"]["Code"].should.equal("ValidationError") + ex.value.response["Error"]["Message"].should.contain( str(MAX_FEDERATION_TOKEN_POLICY_LENGTH) ) diff --git a/tests/test_swf/models/test_domain.py b/tests/test_swf/models/test_domain.py index 32940753f..9e7579ddd 100644 --- a/tests/test_swf/models/test_domain.py +++ b/tests/test_swf/models/test_domain.py @@ -4,9 +4,6 @@ import sure # noqa from moto.swf.exceptions import SWFUnknownResourceFault from moto.swf.models import Domain -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises # noqa - # Fake WorkflowExecution for tests purposes WorkflowExecution = namedtuple( "WorkflowExecution", ["workflow_id", "run_id", "execution_status", "open"] diff --git a/tests/test_swf/responses/test_workflow_executions.py b/tests/test_swf/responses/test_workflow_executions.py index bec352ce8..2832abf75 100644 --- a/tests/test_swf/responses/test_workflow_executions.py +++ b/tests/test_swf/responses/test_workflow_executions.py @@ -4,9 +4,6 @@ from datetime import datetime, timedelta import sure # noqa -# Ensure 'assert_raises' context manager support for Python 2.6 -import tests.backport_assert_raises # noqa - from moto import mock_swf_deprecated from moto.core.utils import unix_time diff --git a/tests/test_xray/__init__.py b/tests/test_xray/__init__.py new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/tests/test_xray/__init__.py @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/tox.ini b/tox.ini index 9dacca18c..f77df29b3 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ deps = -r{toxinidir}/requirements-dev.txt commands = {envpython} setup.py test - nosetests {posargs} + pytest -v {posargs} [flake8] ignore = W503,W605,E128,E501,E203,E266,E501,E231 diff --git a/update_version_from_git.py b/update_version_from_git.py index d72dc4ae9..707f2f1e8 100644 --- a/update_version_from_git.py +++ b/update_version_from_git.py @@ -30,7 +30,7 @@ def migrate_source_attribute(attr, to_this, target_file, regex): new_file = [] found = False - with open(target_file, 'r') as fp: + with open(target_file, "r") as fp: lines = fp.readlines() for line in lines: @@ -40,61 +40,78 @@ def migrate_source_attribute(attr, to_this, target_file, regex): new_file.append(line) if found: - with open(target_file, 'w') as fp: + with open(target_file, "w") as fp: fp.writelines(new_file) + def migrate_version(target_file, new_version): """Updates __version__ in the source file""" regex = r"['\"](.*)['\"]" - migrate_source_attribute('__version__', "'{new_version}'".format(new_version=new_version), target_file, regex) + migrate_source_attribute( + "__version__", + "'{new_version}'".format(new_version=new_version), + target_file, + regex, + ) def is_master_branch(): - cmd = ('git rev-parse --abbrev-ref HEAD') + cmd = "git rev-parse --abbrev-ref HEAD" tag_branch = subprocess.check_output(cmd, shell=True) - return tag_branch in [b'master\n'] + return tag_branch in [b"master\n"] + def git_tag_name(): - cmd = ('git describe --tags') + cmd = "git describe --tags" tag_branch = subprocess.check_output(cmd, shell=True) tag_branch = tag_branch.decode().strip() return tag_branch + def get_git_version_info(): - cmd = 'git describe --tags' + cmd = "git describe --tags" ver_str = subprocess.check_output(cmd, shell=True) - ver, commits_since, githash = ver_str.decode().strip().split('-') + ver, commits_since, githash = ver_str.decode().strip().split("-") return ver, commits_since, githash + def prerelease_version(): - """ return what the prerelease version should be. + """return what the prerelease version should be. https://packaging.python.org/tutorials/distributing-packages/#pre-release-versioning 0.0.2.dev22 """ ver, commits_since, githash = get_git_version_info() initpy_ver = get_version() - assert len(initpy_ver.split('.')) in [3, 4], 'moto/__init__.py version should be like 0.0.2.dev' - assert initpy_ver > ver, 'the moto/__init__.py version should be newer than the last tagged release.' - return '{initpy_ver}.{commits_since}'.format(initpy_ver=initpy_ver, commits_since=commits_since) + assert len(initpy_ver.split(".")) in [ + 3, + 4, + ], "moto/__init__.py version should be like 0.0.2.dev" + assert ( + initpy_ver > ver + ), "the moto/__init__.py version should be newer than the last tagged release." + return "{initpy_ver}.{commits_since}".format( + initpy_ver=initpy_ver, commits_since=commits_since + ) + def read(*parts): - """ Reads in file from *parts. - """ + """Reads in file from *parts.""" try: - return io.open(os.path.join(*parts), 'r', encoding='utf-8').read() + return io.open(os.path.join(*parts), "r", encoding="utf-8").read() except IOError: - return '' + return "" + def get_version(): - """ Returns version from moto/__init__.py - """ - version_file = read('moto', '__init__.py') - version_match = re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', - version_file, re.MULTILINE) + """Returns version from moto/__init__.py""" + version_file = read("moto", "__init__.py") + version_match = re.search( + r'^__version__ = [\'"]([^\'"]*)[\'"]', version_file, re.MULTILINE + ) if version_match: return version_match.group(1) - raise RuntimeError('Unable to find version string.') + raise RuntimeError("Unable to find version string.") def release_version_correct(): @@ -107,14 +124,22 @@ def release_version_correct(): initpy = os.path.abspath("moto/__init__.py") new_version = prerelease_version() - print('updating version in __init__.py to {new_version}'.format(new_version=new_version)) - assert len(new_version.split('.')) >= 4, 'moto/__init__.py version should be like 0.0.2.dev' + print( + "updating version in __init__.py to {new_version}".format( + new_version=new_version + ) + ) + assert ( + len(new_version.split(".")) >= 4 + ), "moto/__init__.py version should be like 0.0.2.dev" migrate_version(initpy, new_version) else: assert False, "No non-master deployments yet" # check that we are a tag with the same version as in __init__.py - assert get_version() == git_tag_name(), 'git tag/branch name not the same as moto/__init__.py __verion__' + assert ( + get_version() == git_tag_name() + ), "git tag/branch name not the same as moto/__init__.py __verion__" -if __name__ == '__main__': +if __name__ == "__main__": release_version_correct() diff --git a/wait_for.py b/wait_for.py index 1f291c16b..be29b0140 100755 --- a/wait_for.py +++ b/wait_for.py @@ -21,12 +21,12 @@ start_ts = time.time() print("Waiting for service to come up") while True: try: - urllib.urlopen('http://localhost:5000/', timeout=1) + urllib.urlopen("http://localhost:5000/", timeout=1) break except EXCEPTIONS: elapsed_s = time.time() - start_ts if elapsed_s > 60: raise - print('.') + print(".") time.sleep(1)