"""Unit tests for Base Workflow class.""" import datetime from unittest.mock import call, MagicMock, patch from garcon import activity import pytest from analytics_aggregation.flows import base @patch('garcon.activity.create') def test_flow_base_init(mock_activity, monkeypatch): """Test FlowBase init sets domain, name, version, activity properties.""" monkeypatch.setattr( base, 'get_domain', MagicMock(return_value='domain')) monkeypatch.setattr( base, 'generate_feed_name', MagicMock(return_value='feed_name')) flow = base.FlowBase('feed_name', '1.0') assert flow.domain == 'domain' assert flow.name == 'feed_name' assert flow.feed_name == 'feed_name' assert flow.version == '1.0' assert mock_activity.call_count == 1 @patch('analytics_aggregation.flows.base.get_domain') @patch('garcon.activity.create') def test_flow_base_workflow_id(mock_domain, mock_create, monkeypatch): """Test FlowBase workflow_id method.""" monkeypatch.setattr( base, 'generate_feed_name', MagicMock(return_value='feed_name')) flow = base.FlowBase('feed_name', '1.0') # test for passed context date dt = '2015-10-01' context = {'context_date': dt} expected_result = 'feed_name-{date}'.format(date=dt) assert flow.workflow_id(context) == expected_result # test for missing context date (defaults to today) expected_result = 'feed_name-{date}'.format( date=datetime.datetime.today().strftime('%Y-%m-%d')) assert flow.workflow_id(initial_context={}) == expected_result @patch('analytics_aggregation.flows.base.raven') @patch('analytics_aggregation.flows.base.get_domain') @patch('analytics_aggregation.flows.base.generate_feed_name') @patch('garcon.activity.create') @patch('analytics_aggregation.flows.base.logger') def test_flow_base_exception( mock_logging, mock_create, mock_feed, mock_domain, mock_raven): """Test FlowBase default on_exception logs to actor.logger.""" flow = base.FlowBase('feed_name', '1.0') # Non Activity calls FlowBase logger actor_mock = MagicMock() flow.on_exception(actor_mock, 'exception') mock_logging.error.assert_called_with('exception', exc_info=True) # Assert Activity error calls activity's own logger activity_obj = activity.Activity() on_exception_mock = MagicMock() activity_obj.logger.error = on_exception_mock flow.on_exception(activity_obj, 'exception') on_exception_mock.assert_called_with('exception', exc_info=True) # Sentry called if DSN is an os var with patch.dict('os.environ', {'SENTRY_DSN': 'https://sentryblah.com'}): flow.on_exception(MagicMock(), 'exception') mock_raven.assert_has_calls([call.Client().captureException()]) @patch('analytics_aggregation.flows.base.get_domain') @patch('analytics_aggregation.flows.base.generate_feed_name') @patch('garcon.activity.create') def test_flow_base_decider(mock_domain, mock_feed, mock_create): """Test FlowBase decider throws not implemented error.""" flow = base.FlowBase('feed_name', '1.0') with pytest.raises(NotImplementedError): flow.decider('schedule') def test_get_dev_domain(mock_config): """Test default domain is dev.""" mock_config['environment'] = 'foo' assert base.get_domain() == base.DEV_DOMAIN def test_get_prod_domain(mock_config): """Test generating domain for prod.""" mock_config['environment'] = 'prod' assert base.get_domain() == base.PROD_DOMAIN def test_generate_feed_name(): """Test generating feed name.""" # valid feedname feed_name = 'feed_name' expected_result = 'feed_name_analytics_aggregation' actual_result = base.generate_feed_name(feed_name) assert actual_result == expected_result # invalid feedname feed_name = 'feed_Name' with pytest.raises(AssertionError): base.generate_feed_name(feed_name) # invalid feedname feed_name = 'feed name' with pytest.raises(AssertionError): base.generate_feed_name(feed_name)