Casos de prueba para el módulo Lambda Ansible para la implementación de AWS Lambdas -- python campo con unit-testing campo con amazon-web-services campo con ansible camp codereview Relacionados El problema

Test cases for Ansible lambda module for deployment of AWS Lambdas


4
vote

problema

Español

He escrito un conjunto de casos de prueba que cubren el módulo lambda ansible. El Toda la fuente está disponible en GitHub , bifurcado de ansible / ansible

the archivo original es visible en GitHub como es el Módulo, lambda.py, prueba

Me gustaría tener una revisión de código centrada en

  • haciendo las pruebas más confiables / menos frágiles
  • haciendo el código más nuevo / mejor / más pythonic
  • Simplemente mejorando el valor de las pruebas sin agregar muchos más

Al mismo tiempo, los casos de prueba deben caber dentro del entorno de prueba de la unidad de ANSIBLE SO:

  • deberían trabajar para Python temprano y moderno, al menos 2.6,2.7 y 3.6
  • Las pruebas deben pasar en el entorno enviable utilizado por Ansible
  • Ansible usa su propio corredor de prueba basado en Pytest
  • Hay algunas funciones especiales / módulos que se espera que se usen
    • ansible.compat.tests.mock / ansible.module_utils
  • Se necesitan algunos hacks para manejar la forma en que se ejecuta el módulo independiente

En esta versión, no quiero cambiar la forma en que Lambda.py está escrito para mejorar su prueba. Antes de incluso considerar que me gustaría algunas pruebas básicas en su lugar para que pueda refactorarse o reemplazarse de manera más segura. Además, el objetivo es simple / principalmente el código estático que puede ser depurado de manera simple y fácil.

  # # (c) 2017 Michael De La Rue # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.  # Make coding more python3-ish  from __future__ import (absolute_import, division, print_function)  from nose.plugins.skip import SkipTest import pytest import json import copy from ansible.module_utils._text import to_bytes from ansible.module_utils import basic from ansible.compat.tests.mock import MagicMock, Mock, patch from ansible.module_utils.ec2 import HAS_BOTO3 if not HAS_BOTO3:     raise SkipTest("test_ec2_asg.py requires the `boto3`, and `botocore` modules")  # lambda is a keyword so we have to hack this. _temp = __import__("ansible.modules.cloud.amazon.lambda")  lda = getattr(_temp.modules.cloud.amazon,"lambda")  exit_return_dict={}  def set_module_args(args):     args = json.dumps({'ANSIBLE_MODULE_ARGS': args})     basic._ANSIBLE_ARGS = to_bytes(args)  base_start_function_config_in_aws={     'FunctionName' : 'lambda_name',     'Role' : 'arn:aws:iam::987654321012:role/lambda_basic_execution',     'Handler' : 'lambda_python.my_handler',     'Description' : 'this that the other',     'Timeout' : 3,     'MemorySize' : 128,     'Runtime' : 'python2.7',     'CodeSha256' : 'AqMZ+xptM7aC9VXu+5jyp1sqO+Nj4WFMNzQxtPMP2n8=', }  one_change_start_function_config_in_aws=copy.copy(base_start_function_config_in_aws) one_change_start_function_config_in_aws['Timeout']=4 two_change_start_function_config_in_aws=copy.copy(one_change_start_function_config_in_aws) two_change_start_function_config_in_aws['Role']='arn:aws:iam::987654321012:role/lambda_advanced_execution' code_change_start_function_config_in_aws=copy.copy(base_start_function_config_in_aws) code_change_start_function_config_in_aws['CodeSha256']='P+Zy8U4T4RiiHWElhL10VBKj9jw4rSJ5bm/TiW+4Rts='  base_module_args={     "region": "us-west-1",     "name": "lambda_name",     "state": "present",     "zip_file": "test/units/modules/cloud/amazon/fixtures/thezip.zip",     "runtime": 'python2.7',     "role": 'arn:aws:iam::987654321012:role/lambda_basic_execution',     "memory_size": 128,     "timeout" : 3,     "handler": 'lambda_python.my_handler' }   #TODO: def test_handle_different_types_in_config_params(monkeypatch):   def test_update_lambda_if_code_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : code_change_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      set_module_args(base_module_args)     @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) == 0),          "unexpectedly updatede lambda configuration when only code changed"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) < 2),          "lambda function update called multiple times when only one time should be needed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) > 1),          "failed to update lambda function when code changed"     # 3 because after uploading we call into the return from mock to try to find what function version     # was returned so the MagicMock actually sees two calls for one update.     assert(len(fake_lambda_connection.update_function_code.mock_calls) < 3),          "lambda function code update called multiple times when only one time should be needed"  def test_update_lambda_if_config_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : two_change_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      set_module_args(base_module_args)     @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) > 0),          "failed to update lambda function when configuration changed"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) < 2),          "lambda function update called multiple times when only one time should be needed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) == 0),          "updated lambda code when no change should have happened"  def test_update_lambda_if_only_one_config_item_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : one_change_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) > 0),          "failed to update lambda function when configuration changed"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) < 2),          "lambda function update called multiple times when only one time should be needed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) == 0),          "updated lambda code when no change should have happened"  def test_dont_update_lambda_if_nothing_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : base_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) == 0),          "updated lambda function when no configuration changed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) == 0 ),          "updated lambda code when no change should have happened"  def test_warn_region_not_specified():      set_module_args({         "name": "lambda_name",         "state": "present",         # Module is called without a region causing error         # "region": "us-east-1",         "zip_file": "test/units/modules/cloud/amazon/fixtures/thezip.zip",         "runtime": 'python2.7',         "role": 'arn:aws:iam::987654321012:role/lambda_basic_execution',         "handler": 'lambda_python.my_handler'})      class AnsibleFailJson(Exception):         pass      def fail_json(*args, **kwargs):         kwargs['failed'] = True         raise AnsibleFailJson(kwargs)      def call_module():         with patch.object(basic.AnsibleModule, 'fail_json', fail_json):             try:                 lda.main()             except AnsibleFailJson as e:                 result = e.args[0]                 assert("region must be specified" in result['msg'])      call_module()   
Original en ingles

I have written a set of test cases which cover the ansible lambda module. The entire source is available on GitHub, forked from ansible/ansible

The original file is visible on github as is the module, lambda.py it tests

I'd like to have a code review focusing on

  • making the tests more reliable / less brittle
  • making the code neater / better / more pythonic
  • simply improving the value of the tests without adding many more

At the same time the test cases have to fit within the unit testing environment of Ansible so:

  • they should work for early and modern python, at least 2.6,2.7 and 3.6
  • the tests have to pass in the shippable environment used by ansible
  • ansible uses it's own test runner based on pytest
  • there are some special functions / modules that are expected to be used
    • ansible.compat.tests.mock / ansible.module_utils
  • some hacks are needed to handle the way the module runs stand alone

In this version I don't want to change the way that lambda.py is written to improve its testability. Before even considering that I'd like some basic tests in place so it can be refactored or replaced more safely. Also the aim is simple / mostly static code which can be simply and easily debugged.

# # (c) 2017 Michael De La Rue # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.  # Make coding more python3-ish  from __future__ import (absolute_import, division, print_function)  from nose.plugins.skip import SkipTest import pytest import json import copy from ansible.module_utils._text import to_bytes from ansible.module_utils import basic from ansible.compat.tests.mock import MagicMock, Mock, patch from ansible.module_utils.ec2 import HAS_BOTO3 if not HAS_BOTO3:     raise SkipTest("test_ec2_asg.py requires the `boto3`, and `botocore` modules")  # lambda is a keyword so we have to hack this. _temp = __import__("ansible.modules.cloud.amazon.lambda")  lda = getattr(_temp.modules.cloud.amazon,"lambda")  exit_return_dict={}  def set_module_args(args):     args = json.dumps({'ANSIBLE_MODULE_ARGS': args})     basic._ANSIBLE_ARGS = to_bytes(args)  base_start_function_config_in_aws={     'FunctionName' : 'lambda_name',     'Role' : 'arn:aws:iam::987654321012:role/lambda_basic_execution',     'Handler' : 'lambda_python.my_handler',     'Description' : 'this that the other',     'Timeout' : 3,     'MemorySize' : 128,     'Runtime' : 'python2.7',     'CodeSha256' : 'AqMZ+xptM7aC9VXu+5jyp1sqO+Nj4WFMNzQxtPMP2n8=', }  one_change_start_function_config_in_aws=copy.copy(base_start_function_config_in_aws) one_change_start_function_config_in_aws['Timeout']=4 two_change_start_function_config_in_aws=copy.copy(one_change_start_function_config_in_aws) two_change_start_function_config_in_aws['Role']='arn:aws:iam::987654321012:role/lambda_advanced_execution' code_change_start_function_config_in_aws=copy.copy(base_start_function_config_in_aws) code_change_start_function_config_in_aws['CodeSha256']='P+Zy8U4T4RiiHWElhL10VBKj9jw4rSJ5bm/TiW+4Rts='  base_module_args={     "region": "us-west-1",     "name": "lambda_name",     "state": "present",     "zip_file": "test/units/modules/cloud/amazon/fixtures/thezip.zip",     "runtime": 'python2.7',     "role": 'arn:aws:iam::987654321012:role/lambda_basic_execution',     "memory_size": 128,     "timeout" : 3,     "handler": 'lambda_python.my_handler' }   #TODO: def test_handle_different_types_in_config_params(monkeypatch):   def test_update_lambda_if_code_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : code_change_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      set_module_args(base_module_args)     @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) == 0), \         "unexpectedly updatede lambda configuration when only code changed"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) < 2), \         "lambda function update called multiple times when only one time should be needed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) > 1), \         "failed to update lambda function when code changed"     # 3 because after uploading we call into the return from mock to try to find what function version     # was returned so the MagicMock actually sees two calls for one update.     assert(len(fake_lambda_connection.update_function_code.mock_calls) < 3), \         "lambda function code update called multiple times when only one time should be needed"  def test_update_lambda_if_config_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : two_change_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      set_module_args(base_module_args)     @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) > 0), \         "failed to update lambda function when configuration changed"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) < 2), \         "lambda function update called multiple times when only one time should be needed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) == 0), \         "updated lambda code when no change should have happened"  def test_update_lambda_if_only_one_config_item_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : one_change_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) > 0), \         "failed to update lambda function when configuration changed"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) < 2), \         "lambda function update called multiple times when only one time should be needed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) == 0), \         "updated lambda code when no change should have happened"  def test_dont_update_lambda_if_nothing_changed(monkeypatch):      fake_lambda_connection = MagicMock()     fake_lambda_connection.get_function.configure_mock(         return_value={             'Configuration' : base_start_function_config_in_aws         }     )     fake_lambda_connection.update_function_configuration.configure_mock(         return_value={             'Version' : 1         }     )     fake_boto3_conn=Mock(return_value=fake_lambda_connection)      @patch("ansible.modules.cloud.amazon.lambda.boto3_conn", fake_boto3_conn)     def call_module():         with pytest.raises(SystemExit):             lda.main()      call_module()      # guard against calling other than for a lambda connection (e.g. IAM)     assert(len(fake_boto3_conn.mock_calls) == 1), "multiple boto connections used unexpectedly"     assert(len(fake_lambda_connection.update_function_configuration.mock_calls) == 0), \         "updated lambda function when no configuration changed"     assert(len(fake_lambda_connection.update_function_code.mock_calls) == 0 ), \         "updated lambda code when no change should have happened"  def test_warn_region_not_specified():      set_module_args({         "name": "lambda_name",         "state": "present",         # Module is called without a region causing error         # "region": "us-east-1",         "zip_file": "test/units/modules/cloud/amazon/fixtures/thezip.zip",         "runtime": 'python2.7',         "role": 'arn:aws:iam::987654321012:role/lambda_basic_execution',         "handler": 'lambda_python.my_handler'})      class AnsibleFailJson(Exception):         pass      def fail_json(*args, **kwargs):         kwargs['failed'] = True         raise AnsibleFailJson(kwargs)      def call_module():         with patch.object(basic.AnsibleModule, 'fail_json', fail_json):             try:                 lda.main()             except AnsibleFailJson as e:                 result = e.args[0]                 assert("region must be specified" in result['msg'])      call_module() 
           

Lista de respuestas


Relacionados problema

5  PlayBook ansible para instalar la aplicación de Tarball  ( Ansible playbook to install application from tarball ) 
Estoy haciendo esto, pero como soy el experto aquí (porque nadie más lo está haciendo), no tengo una idea real de lo increíble que es realmente mi código. E...

1  Tareas basadas en definición variable  ( Tasks based on variable definition ) 
Estoy creando un libro de reproducción que toma una variable 9988776655544331 en Tiempo de ejecución y luego ejecuta tareas según esa variable. Si se define...

4  Clonar un repo privado de gitlab connsible  ( Clone a gitlab private repo with ansible ) 
Tengo un libro de jugadas ansible que revisa un repositorio privado de Gitlab. Utiliza el Usuarios de GITLAB API Para generar una clave SSH para el host obj...

2  Ansible para automatizar la configuración del entorno de desarrollo  ( Ansible to automate dev environment setup ) 
Este es un seguimiento para Bash Script para automatizar el entorno de desarrollo Configuración . En esa pregunta, había echado un script de shell (descuid...

2  Un libro de PlayBook ansible simple que se enciende en un servidor  ( A simple ansible playbook that powers on a server ) 
Este es un libro de jugadas ansible que uso para el encendido en uno de mis servidores domésticos en un bastidor, que acaba de encender cuando sea necesario. ...

4  Casos de prueba para el módulo Lambda Ansible para la implementación de AWS Lambdas  ( Test cases for ansible lambda module for deployment of aws lambdas ) 
He escrito un conjunto de casos de prueba que cubren el módulo lambda ansible. El Toda la fuente está disponible en GitHub , bifurcado de ansible / ansible ...

2  Verificación de estado de comando de shell ansible  ( Ansible shell command status check ) 
Tengo una tarea que comprueba el estado de un proceso que se ejecuta en un servidor Linux usando un shell. La tarea debe informar como falla cuando el estado ...

2  Ansible PlayBook para generar estructura de carpetas de servidor web con usuarios y proyectos  ( Ansible playbook to generate webserver folder structure with users and projects ) 
Intento generar con una estructura de carpeta ansible para un servidor web con usuarios y proyectos vinculados. El PlayBook trabaja. Pero con más usuarios y...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos