Best Python code snippet using localstack_python
test_role_utils.py
Source:test_role_utils.py
1import unittest2import mock3from cgf_utils.test import mock_aws4from cgf_utils import role_utils5import time6from resource_manager_common import stack_info7from resource_manager_common.stack_info import StackInfo8from botocore.exceptions import ClientError9_STACK_INFO_MANAGER = stack_info.StackInfoManager()10class JSONStringEqualsDict(object):11 def __init__(self, dict):12 self.__dict = dict13 def __eq__(self, json_string):14 import json15 other_dict = json.loads(json_string)16 return self.__dict == other_dict17class UnitTest_CloudGemFramework_ProjectResourceHandler_role_utils_get_role_name(unittest.TestCase):18 def test_with_short_name(self):19 stack_arn = 'arn:aws:cloudformation:TestRegion:TestAccount:stack/ShortName-RandomPart/TestUUID'20 logical_role_name = 'RoleName'21 actual_role_name = role_utils.get_access_control_role_name(stack_arn, logical_role_name)22 self.assertEqual(actual_role_name, 'ShortName-RandomPart-RoleName')23 def test_with_too_long_name(self):24 stack_arn = 'arn:aws:cloudformation:TestRegion:TestAccount:stack/LongName9A123456789B123456789C123456789D123456789E123456789F123456789G-RandomPart/TestUUID'25 logical_role_name = 'RoleName9A123456789B123456789C123456789D123456789E123456789F123456789G'26 actual_role_name = role_utils.get_access_control_role_name(stack_arn, logical_role_name)27 self.assertEqual(actual_role_name, role_utils.sanitize_role_name('LongName9A123456789B123456789C123456789D123456789E123456789F123456789G-RandomPart-RoleName9A123456789B123456789C123456789D123456789E123456789F123456789G'))28class UnitTest_CloudGemFramework_ProjectResourceHandler_role_utils_create_access_control_role(unittest.TestCase):29 project_name = 'test-project-name'30 deployment_name = 'test-deployment-name'31 resource_group_name = 'test-resource-group-name'32 stack_arn = 'arn:aws:cloudformation:TestRegion:TestAccount:stack/ShortName-RandomPart/TestUUID'33 logical_role_name = 'test-logical-role-name'34 assume_role_service = 'test-assume-role-service'35 role_name = 'test-role-name'36 path = '/{project_name}/{deployment_name}/{resource_group_name}/{logical_role_name}/AccessControl/'.format(37 project_name=project_name,38 deployment_name=deployment_name,39 resource_group_name=resource_group_name,40 logical_role_name=logical_role_name)41 mock_stack_info = mock.MagicMock()42 mock_stack_info.deployment.project.project_name = project_name43 mock_stack_info.deployment.deployment_name = deployment_name44 mock_stack_info.resource_group_name = resource_group_name45 mock_stack_info.parameters = {'CloudCanvasStack': StackInfo.STACK_TYPE_RESOURCE_GROUP}46 mock_stack_info.stack_name = project_name47 mock_stack_info.stack_type = StackInfo.STACK_TYPE_RESOURCE_GROUP48 role_arn = 'test-role-arn'49 assume_role_policy_document = {50 "Version": "2012-10-17",51 "Statement": [52 {53 "Effect": "Allow",54 "Action": "sts:AssumeRole",55 "Principal": {56 "Service": assume_role_service57 }58 }59 ]60 }61 assume_role_policy_document_matcher = JSONStringEqualsDict(assume_role_policy_document)62 create_role_response = {63 'Role': {64 'Arn': role_arn65 }66 }67 default_policy = 'test-policy'68 @mock_aws.patch_client('iam', 'create_role', return_value=create_role_response, reload=role_utils)69 @mock.patch('cgf_utils.role_utils.get_access_control_role_name', return_value=role_name)70 @mock.patch('resource_manager_common.stack_info.StackInfoManager.get_stack_info', return_value=mock_stack_info)71 def test_default(self, mock_get_stack_info, mock_get_access_control_role_name, mock_create_role):72 id_data = {}73 role_utils.PROPAGATION_DELAY_SECONDS = 274 start_time = time.clock()75 created_role_arn = role_utils.create_access_control_role(76 _STACK_INFO_MANAGER,77 id_data,78 self.stack_arn,79 self.logical_role_name,80 self.assume_role_service)81 stop_time = time.clock()82 delay_time = stop_time - start_time83 self.assertAlmostEqual(delay_time, role_utils.PROPAGATION_DELAY_SECONDS, delta=0.1)84 self.assertEqual(created_role_arn, self.role_arn)85 self.assertEquals(id_data, {'AbstractRoleMappings': {self.logical_role_name: self.role_name}})86 mock_get_access_control_role_name.assert_called_once_with(self.stack_arn, self.logical_role_name)87 mock_create_role.assert_called_once_with(RoleName=self.role_name,88 AssumeRolePolicyDocument=self.assume_role_policy_document_matcher,89 Path=self.path)90 mock_get_stack_info.assert_called_once_with(self.stack_arn)91 @mock_aws.patch_client('iam', 'create_role', return_value=create_role_response, reload=role_utils)92 @mock.patch('cgf_utils.role_utils.get_access_control_role_name', return_value=role_name)93 @mock.patch('resource_manager_common.stack_info.StackInfoManager.get_stack_info', return_value=mock_stack_info)94 def test_with_delay_for_propagation_false(self, mock_get_stack_info, mock_get_access_control_role_name,95 mock_create_role):96 id_data = {}97 role_utils.PROPAGATION_DELAY_SECONDS = 298 start_time = time.clock()99 created_role_arn = role_utils.create_access_control_role(100 _STACK_INFO_MANAGER,101 id_data,102 self.stack_arn,103 self.logical_role_name,104 self.assume_role_service,105 delay_for_propagation=False)106 stop_time = time.clock()107 delay_time = stop_time - start_time108 self.assertAlmostEqual(delay_time, 0, delta=0.1)109 self.assertEqual(created_role_arn, self.role_arn)110 self.assertEquals(id_data, {'AbstractRoleMappings': {self.logical_role_name: self.role_name}})111 mock_get_access_control_role_name.assert_called_once_with(self.stack_arn, self.logical_role_name)112 mock_create_role.assert_called_once_with(RoleName=self.role_name,113 AssumeRolePolicyDocument=self.assume_role_policy_document_matcher,114 Path=self.path)115 mock_get_stack_info.assert_called_once_with(self.stack_arn)116 @mock_aws.patch_client('iam', 'create_role', return_value=create_role_response, reload=role_utils)117 @mock_aws.patch_client('iam', 'put_role_policy', return_value={})118 @mock.patch('cgf_utils.role_utils.get_access_control_role_name', return_value=role_name)119 @mock.patch('resource_manager_common.stack_info.StackInfoManager.get_stack_info', return_value=mock_stack_info)120 def test_with_default_policy(self, mock_get_stack_info, mock_get_access_control_role_name, mock_put_role_policy,121 mock_create_role):122 id_data = {}123 created_role_arn = role_utils.create_access_control_role(124 _STACK_INFO_MANAGER,125 id_data,126 self.stack_arn,127 self.logical_role_name,128 self.assume_role_service,129 delay_for_propagation=False,130 default_policy=self.default_policy)131 self.assertEqual(created_role_arn, self.role_arn)132 self.assertEquals(id_data, {'AbstractRoleMappings': {self.logical_role_name: self.role_name}})133 mock_get_access_control_role_name.assert_called_once_with(self.stack_arn, self.logical_role_name)134 mock_create_role.assert_called_once_with(RoleName=self.role_name,135 AssumeRolePolicyDocument=self.assume_role_policy_document_matcher,136 Path=self.path)137 mock_put_role_policy.assert_called_once_with(RoleName=self.role_name, PolicyName='Default',138 PolicyDocument=self.default_policy)139 mock_get_stack_info.assert_called_once_with(self.stack_arn)140class UnitTest_CloudGemFramework_ProjectResourceHandler_role_utils_delete_access_control_role(unittest.TestCase):141 policy_name_1 = 'policy_name_1'142 policy_name_2 = 'policy_name_2'143 list_role_policies_response = {144 'PolicyNames': [policy_name_1, policy_name_2]145 }146 delete_role_policy_response = {147 }148 delete_role_response = {149 }150 no_such_entity_response = {151 'Error': {152 'Code': 'NoSuchEntity'153 }154 }155 access_denied_response = {156 'Error': {157 'Code': 'AccessDenied'158 }159 }160 unknown_error_code = 'test-error-code'161 other_error_response = {162 'Error': {163 'Code': unknown_error_code164 }165 }166 resource_group_stack_arn = 'test-resource-group-stack-arn'167 logical_role_name = 'test-logical-role-name'168 role_name = 'test-role-name'169 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)170 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)171 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)172 def test_with_no_errors(self, mock_delete_role, mock_delete_role_policy, mock_list_role_policies):173 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}174 role_utils.delete_access_control_role(id_data, self.logical_role_name)175 self.assertEquals(id_data, {'AbstractRoleMappings': {}})176 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)177 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)178 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_2)179 mock_delete_role.assert_called_once_with(RoleName=self.role_name)180 @mock_aws.patch_client('iam', 'list_role_policies',181 side_effect=ClientError(no_such_entity_response, 'list_role_policies'), reload=role_utils)182 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)183 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)184 def test_with_list_role_policies_no_such_entity_error(self, mock_delete_role, mock_delete_role_policy,185 mock_list_role_policies):186 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}187 role_utils.delete_access_control_role(id_data, self.logical_role_name)188 self.assertEquals(id_data, {'AbstractRoleMappings': {}})189 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)190 mock_delete_role.assert_called_once_with(RoleName=self.role_name)191 @mock_aws.patch_client('iam', 'list_role_policies',192 side_effect=ClientError(access_denied_response, 'list_role_policies'), reload=role_utils)193 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)194 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)195 def test_with_list_role_policies_access_denied_error(self, mock_delete_role, mock_delete_role_policy,196 mock_list_role_policies):197 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}198 role_utils.delete_access_control_role(id_data, self.logical_role_name)199 self.assertEquals(id_data, {'AbstractRoleMappings': {}})200 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)201 mock_delete_role.assert_called_once_with(RoleName=self.role_name)202 @mock_aws.patch_client('iam', 'list_role_policies',203 side_effect=ClientError(other_error_response, 'list_role_policies'), reload=role_utils)204 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)205 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)206 def test_with_list_role_policies_other_error(self, mock_list_role_policies, mock_delete_role,207 mock_delete_role_policy):208 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}209 with self.assertRaisesRegexp(ClientError, self.unknown_error_code):210 role_utils.delete_access_control_role(id_data, self.logical_role_name)211 self.assertEquals(id_data, {'AbstractRoleMappings': {self.logical_role_name: self.role_name}})212 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)213 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)214 @mock_aws.patch_client('iam', 'delete_role_policy',215 side_effect=ClientError(no_such_entity_response, 'delete_role_policy'))216 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)217 def test_with_delete_role_policy_no_such_entity_error(self, mock_delete_role, mock_delete_role_policy,218 mock_list_role_policies):219 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}220 role_utils.delete_access_control_role(id_data, self.logical_role_name)221 self.assertEquals(id_data, {'AbstractRoleMappings': {}})222 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)223 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)224 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_2)225 mock_delete_role.assert_called_once_with(RoleName=self.role_name)226 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)227 @mock_aws.patch_client('iam', 'delete_role_policy',228 side_effect=ClientError(access_denied_response, 'delete_role_policy'))229 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)230 def test_with_delete_role_policy_access_denied_error(self, mock_delete_role, mock_delete_role_policy,231 mock_list_role_policies):232 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}233 role_utils.delete_access_control_role(id_data, self.logical_role_name)234 self.assertEquals(id_data, {'AbstractRoleMappings': {}})235 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)236 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)237 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_2)238 mock_delete_role.assert_called_once_with(RoleName=self.role_name)239 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)240 @mock_aws.patch_client('iam', 'delete_role_policy',241 side_effect=ClientError(other_error_response, 'delete_role_policy'))242 @mock_aws.patch_client('iam', 'delete_role', return_value=delete_role_response)243 def test_with_delete_role_policy_other_error(self, mock_list_role_policies, mock_delete_role_policy,244 mock_delete_role):245 print '===', mock_list_role_policies, mock_delete_role, mock_delete_role_policy246 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}247 with self.assertRaisesRegexp(ClientError, self.unknown_error_code):248 role_utils.delete_access_control_role(id_data, self.logical_role_name)249 self.assertEquals(id_data, {'AbstractRoleMappings': {self.logical_role_name: self.role_name}})250 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)251 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)252 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)253 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)254 @mock_aws.patch_client('iam', 'delete_role', side_effect=ClientError(no_such_entity_response, 'delete_role'))255 def test_with_delete_role_no_such_entity_error(self, mock_delete_role, mock_delete_role_policy,256 mock_list_role_policies):257 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}258 role_utils.delete_access_control_role(id_data, self.logical_role_name)259 self.assertEquals(id_data, {'AbstractRoleMappings': {}})260 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)261 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)262 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_2)263 mock_delete_role.assert_called_once_with(RoleName=self.role_name)264 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)265 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)266 @mock_aws.patch_client('iam', 'delete_role', side_effect=ClientError(access_denied_response, 'delete_role'))267 def test_with_delete_role_access_denied_error(self, mock_delete_role, mock_delete_role_policy,268 mock_list_role_policies):269 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}270 role_utils.delete_access_control_role(id_data, self.logical_role_name)271 self.assertEquals(id_data, {'AbstractRoleMappings': {}})272 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)273 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)274 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_2)275 mock_delete_role.assert_called_once_with(RoleName=self.role_name)276 @mock_aws.patch_client('iam', 'list_role_policies', return_value=list_role_policies_response, reload=role_utils)277 @mock_aws.patch_client('iam', 'delete_role_policy', return_value=delete_role_policy_response)278 @mock_aws.patch_client('iam', 'delete_role', side_effect=ClientError(other_error_response, 'delete_role'))279 def test_with_delete_role_other_error(self, mock_delete_role, mock_delete_role_policy, mock_list_role_policies):280 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}281 with self.assertRaisesRegexp(ClientError, self.unknown_error_code):282 role_utils.delete_access_control_role(id_data, self.logical_role_name)283 self.assertEquals(id_data, {'AbstractRoleMappings': {self.logical_role_name: self.role_name}})284 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_1)285 mock_delete_role_policy.assert_any_call(RoleName=self.role_name, PolicyName=self.policy_name_2)286 mock_list_role_policies.assert_called_once_with(RoleName=self.role_name)287class UnitTest_CloudGemFramework_ProjectResourceHandler_role_utils_get_access_control_role_arn(unittest.TestCase):288 resource_group_stack_arn = 'test-resource-group-stack-arn'289 logical_role_name = 'test-logical-role-name'290 role_name = 'test-role-name'291 role_arn = 'test-role-arn'292 get_role_response = {293 'Role': {294 'Arn': role_arn295 }296 }297 @mock_aws.patch_client('iam', 'get_role', return_value=get_role_response, reload=role_utils)298 def test_default(self, mock_get_role):299 id_data = {'AbstractRoleMappings': {self.logical_role_name: self.role_name}}300 actual_role_arn = role_utils.get_access_control_role_arn(id_data, self.logical_role_name)301 self.assertEquals(actual_role_arn, self.role_arn)...
test_update_lambda.py
Source:test_update_lambda.py
1import importlib2import io3import json4from unittest import mock5import pytest6MODULE = "lambda.update_lambda"7update_lambda = importlib.import_module(MODULE)8@pytest.fixture9def context():10 return mock.Mock(aws_request_id="request_1234")11@mock.patch(f"{MODULE}.get_region_cidrs")12@mock.patch(f"{MODULE}.cfnresponse")13def test_lambda_handler(mock_cfnresponse, mock_get_region_cidrs, boto3, context, monkeypatch):14 monkeypatch.setenv("iam_role_name", "role_1234")15 client = boto3.client("iam")16 client.list_role_policies.return_value = {17 "PolicyNames": ["foo", "bar"]18 }19 mock_get_region_cidrs.return_value = ["10.0.0.0/8"]20 event = {"ResponseURL": "https://example.com"}21 update_lambda.lambda_handler(event, context)22 client.put_role_policy.assert_called_once()23 client.delete_role_policy.assert_any_call(RoleName="role_1234", PolicyName="foo")24 client.delete_role_policy.assert_any_call(RoleName="role_1234", PolicyName="bar")25 mock_cfnresponse.send.assert_called_once_with(event, context, mock_cfnresponse.SUCCESS, {"Data": mock.ANY})26@mock.patch(f"{MODULE}.get_region_cidrs")27@mock.patch(f"{MODULE}.cfnresponse")28def test_lambda_handler_no_response(mock_cfnresponse, mock_get_region_cidrs, boto3, context, monkeypatch):29 monkeypatch.setenv("iam_role_name", "role_1234")30 client = boto3.client("iam")31 client.list_role_policies.return_value = {32 "PolicyNames": ["foo", "bar"]33 }34 mock_get_region_cidrs.return_value = ["10.0.0.0/8"]35 event = {}36 update_lambda.lambda_handler(event, context)37 client.put_role_policy.assert_called_once()38 client.delete_role_policy.assert_any_call(RoleName="role_1234", PolicyName="foo")39 client.delete_role_policy.assert_any_call(RoleName="role_1234", PolicyName="bar")40 mock_cfnresponse.send.assert_not_called()41@mock.patch(f"{MODULE}.get_region_cidrs")42@mock.patch(f"{MODULE}.cfnresponse")43def test_lambda_handler_no_policy_names(mock_cfnresponse, mock_get_region_cidrs, boto3, context):44 client = boto3.client("iam")45 client.list_role_policies.return_value = {}46 mock_get_region_cidrs.return_value = ["10.0.0.0/8"]47 event = {}48 update_lambda.lambda_handler(event, context)49 client.put_role_policy.assert_called_once()50 client.delete_role_policy.assert_not_called()51 mock_cfnresponse.send.assert_not_called()52@mock.patch(f"{MODULE}.get_region_cidrs")53@mock.patch(f"{MODULE}.cfnresponse")54def test_lambda_handler_error(mock_cfnresponse, mock_get_region_cidrs, context):55 mock_get_region_cidrs.side_effect = Exception("mock exception")56 event = {"ResponseURL": "https://example.com"}57 update_lambda.lambda_handler(event, context)58 mock_cfnresponse.send.assert_called_once_with(event, context, mock_cfnresponse.FAILED, {"Data": mock.ANY})59@mock.patch(f"{MODULE}.get_region_cidrs")60@mock.patch(f"{MODULE}.cfnresponse")61def test_lambda_handler_error_no_response(mock_cfnresponse, mock_get_region_cidrs, context):62 mock_get_region_cidrs.side_effect = Exception("mock exception")63 event = {}64 update_lambda.lambda_handler(event, context)65 mock_cfnresponse.send.assert_not_called()66@mock.patch(f"{MODULE}.urllib.request")67def test_get_region_cidrs(mock_request):68 data = json.dumps({69 "prefixes": [70 # Correct service and region71 {72 "ip_prefix": "10.10.0.0/24",73 "service": "AMAZON",74 "region": "us-east-1"75 },76 # Wrong service77 {78 "ip_prefix": "10.20.0.0/24",79 "service": "SOMETHING_ELSE",80 "region": "us-east-1"81 },82 # Wrong region83 {84 "ip_prefix": "10.30.0.0/24",85 "service": "AMAZON",86 "region": "us-west-2"87 },88 # Two prefixes that should be merged89 {90 "ip_prefix": "10.40.0.0/24",91 "service": "AMAZON",92 "region": "us-east-1"93 },94 {95 "ip_prefix": "10.40.0.0/16",96 "service": "AMAZON",97 "region": "us-east-1"98 },99 ]100 }).encode()101 mock_request.urlopen.return_value = io.BytesIO(data)102 ips = update_lambda.get_region_cidrs("us-east-1")103 assert ips == [104 "10.10.0.0/24",105 "10.40.0.0/16",106 "10.0.0.0/8"107 ]108def test_get_base_policy(monkeypatch):109 monkeypatch.setenv("vpcid", "vpc_1234")110 policy = update_lambda.get_base_policy("prefix_1234")111 assert isinstance(policy, dict)112 for statement in policy["Statement"]:113 for resource in statement["Resource"]:...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!