"""Unit tests for Theatrical flow cli module.""" from argparse import ArgumentParser from datetime import date from unittest import mock from unittest.mock import patch import pytest from flows.flow import DatabaseParam from flows.theatrical import cli def test_init_execute_parser(): """Test init_execute_parser function.""" parser = mock.Mock(spec=ArgumentParser()) cli.init_execute_parser(parser) parser.add_argument.assert_any_call( '-u', '--upc', action='append', dest='upcs', metavar='UPC', type=mock.ANY, help=mock.ANY) parser.add_argument.assert_any_call( '-s', '--start-date', dest='date_start', metavar='YYYY-MM-DD', type=mock.ANY, help=mock.ANY) parser.add_argument.assert_any_call( '-e', '--end-date', dest='date_end', metavar='YYYY-MM-DD', type=mock.ANY, help=mock.ANY) parser.add_argument.assert_any_call( '-a', '--with-archive', dest='with_archive', action='store_true', help=mock.ANY) assert parser.add_argument.call_count == 4 @pytest.fixture(params=[ ('c_id', '2016-11-07', '2016-11-11', tuple(), False), ('c_id', '2016-11-07', '2016-11-11', tuple(), True), ('c_id', '2016-11-07', '2016-11-11', ('012345678901',), False), ('c_id', '2016-11-07', '2016-11-11', ('012345678901',), True), ('c_id', '2016-11-07', '2016-11-11', ('012345678901', '012345678902'), True), ]) def run_execute_correct_params(request): """Set fixture with correct params for run_execution function.""" return request.param @patch('flows.theatrical.cli.log') @patch('flows.theatrical.cli.util') def test_run_execute(mock_util, mock_log, run_execute_correct_params): """Test run_execute function with correct parameters.""" correlation_id, date_start, date_end, upcs, reingest = ( run_execute_correct_params) mock_upcs = DatabaseParam('upcs', data=upcs) mock_util.get_serviced_upcs.return_value = upcs expected_context = { 'correlation_id': correlation_id, 'date_end': date_end, 'date_start': date_start, 'upcs': mock_upcs, 'with_archive': reingest} run_id = 'test_run_id' response = {'runId': run_id} mock_util.start_swf_execution.return_value = response run_response = cli.run_execute( correlation_id, upcs, date_start, date_end, reingest) assert run_response == run_id mock_log.create.assert_called_once_with(**expected_context) expected_context['correlation_id'] = '{}.1'.format(correlation_id) mock_util.start_swf_execution.assert_called_once_with( expected_context, mock.ANY, mock.ANY, mock.ANY, mock.ANY) mock_log.add_run_id.assert_called_once_with( correlation_id, response['runId']) if not upcs: assert mock_util.get_serviced_upcs.called @pytest.fixture(params=[ # start-date is required if any other parameter is passed. ('c_id', None, '2016-11-10', None, False, None), ('c_id', None, None, ['012345678901'], False, None), ('c_id', None, None, None, True, None), # end-date can't be less then start-date. ('c_id', '2016-11-10', '2016-11-06', None, False, None), # Theatrical flow can be started only on Wednesday or Saturday. ('c_id', None, None, None, False, 0), ('c_id', None, None, None, False, 1), ('c_id', None, None, None, False, 3), ('c_id', None, None, None, False, 4), ('c_id', None, None, None, False, 6), ]) def run_execute_incorrect_params(request): """Set fixture with incorrect params for run_execution function.""" return request.param @patch('flows.theatrical.cli.date') def test_run_execute_fail(mock_date, run_execute_incorrect_params): """Test run_execute function with incorrect parameters.""" correlation_id, date_start, date_end, upcs, reingest, week_day = ( run_execute_incorrect_params) week_day_mock = mock.Mock() week_day_mock.weekday.return_value = week_day mock_date.today.return_value = week_day_mock with pytest.raises(ValueError): cli.run_execute(correlation_id, upcs, date_start, date_end, reingest) @pytest.fixture(params=[ (date(2016, 11, 9), '2016-11-04', '2016-11-07'), (date(2016, 11, 12), '2016-11-07', '2016-11-11') ]) def run_execute_no_params(request): """Set fixture for run_execution function without params.""" return request.param @patch('flows.theatrical.cli.log') @patch('flows.theatrical.cli.date') @patch('flows.theatrical.cli.util') def test_run_execute_no_params( mock_util, mock_date, mock_log, run_execute_no_params): """Test run_execute function without params.""" today, expected_start_date, expected_end_date = run_execute_no_params mock_date.today.return_value = today correlation_id = 'c_id' upcs = tuple() mock_util.get_serviced_upcs.return_value = upcs expected_context = { 'correlation_id': '{}.1'.format(correlation_id), 'date_end': expected_end_date, 'date_start': expected_start_date, 'upcs': DatabaseParam('upcs', data=upcs), 'with_archive': False} cli.run_execute(correlation_id, tuple(), None, None, False) mock_util.start_swf_execution.assert_called_once_with( expected_context, mock.ANY, mock.ANY, mock.ANY, mock.ANY) @pytest.fixture(params=[ (date(2016, 11, 9), '2016-11-04', '2016-11-10'), (date(2016, 11, 12), '2016-11-07', '2016-11-13') ]) def run_execute_default_end_date_params(request): """Set fixture for run_execution function without end-date param.""" return request.param @patch('flows.theatrical.cli.log') @patch('flows.theatrical.cli.date') @patch('flows.theatrical.cli.util') def test_run_execute_default_end_date_params( mock_util, mock_date, mock_log, run_execute_default_end_date_params): """Test run_execute function without end-date param.""" today, start_date, expected_end_date = run_execute_default_end_date_params mock_date.today.return_value = today correlation_id = 'c_id' upcs = tuple() mock_util.get_serviced_upcs.return_value = upcs expected_context = { 'correlation_id': '{}.1'.format(correlation_id), 'date_start': start_date, 'date_end': expected_end_date, 'upcs': DatabaseParam('upcs', data=upcs), 'with_archive': False} cli.run_execute(correlation_id, tuple(), start_date, None, False) mock_util.start_swf_execution.assert_called_once_with( expected_context, mock.ANY, mock.ANY, mock.ANY, mock.ANY) def test_init_worker_parser(): """Test init_worker_parser function.""" parser = mock.Mock() cli.init_worker_parser(parser) assert not parser.called @patch('flows.theatrical.cli.ActivityWorker') @patch('flows.theatrical.cli.Flow') def test_run_worker(flow_class_mock, activity_worker_mock): """Test run_worker function.""" activity_worker_object = mock.Mock() activity_worker_mock.return_value = activity_worker_object flow_object = mock.Mock() flow_class_mock.return_value = flow_object cli.run_worker() assert flow_class_mock.called activity_worker_mock.assert_called_with(flow_object) assert activity_worker_object.run.called def test_init_decider_parser(): """Test init_decider_parser function.""" parser = mock.Mock() cli.init_decider_parser(parser) assert not parser.called @patch('flows.theatrical.cli.sleep') @patch('flows.theatrical.cli.Flow') @patch('flows.theatrical.cli.DeciderWorker') def test_run_decider(decider_worker_mock, flow_class_mock, sleep_mock): """Test run_decider function.""" decider_worker_object = mock.Mock() # the decider runs in an infinite loop, this is a way to break out of it decider_worker_object.run.side_effect = [None, EnvironmentError] decider_worker_mock.return_value = decider_worker_object flow_object = mock.Mock() flow_class_mock.return_value = flow_object with pytest.raises(EnvironmentError): cli.run_decider() assert flow_class_mock.called decider_worker_mock.assert_called_with(flow_object) assert decider_worker_object.run.called sleep_mock.assert_called_once_with(1)