Skip to content

Commit

Permalink
Merge branch 'master' into nikhil/update-3.0.0-changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
nchilada committed Mar 28, 2019
2 parents 22044cd + 44ac6c7 commit 40305de
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 23 deletions.
7 changes: 7 additions & 0 deletions optimizely/helpers/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ class NotificationTypes(object):
Experiment experiment, str user_id, dict attributes (can be None), Variation variation, Event event
TRACK notification listener has the following parameters:
str event_key, str user_id, dict attributes (can be None), event_tags (can be None), Event event
DECISION notification listener has the following parameters:
DecisionInfoTypes type, str user_id, dict attributes (can be None), dict decision_info
"""
ACTIVATE = "ACTIVATE:experiment, user_id, attributes, variation, event"
TRACK = "TRACK:event_key, user_id, attributes, event_tags, event"
DECISION = "DECISON:type, user_id, attributes, decision_info"


class DecisionInfoTypes(object):
EXPERIMENT = "experiment"
18 changes: 15 additions & 3 deletions optimizely/optimizely.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ def get_variation(self, experiment_key, user_id, attributes=None):
return None

experiment = self.config.get_experiment_from_key(experiment_key)
variation_key = None

if not experiment:
self.logger.info('Experiment key "%s" is invalid. Not activating user "%s".' % (
Expand All @@ -349,9 +350,20 @@ def get_variation(self, experiment_key, user_id, attributes=None):

variation = self.decision_service.get_variation(experiment, user_id, attributes)
if variation:
return variation.key

return None
variation_key = variation.key

self.notification_center.send_notifications(
enums.NotificationTypes.DECISION,
enums.DecisionInfoTypes.EXPERIMENT,
user_id,
attributes or {},
{
'experiment_key': experiment_key,
'variation_key': variation_key
}
)

return variation_key

def is_feature_enabled(self, feature_key, user_id, attributes=None):
""" Returns true if the feature is enabled for the given user.
Expand Down
134 changes: 114 additions & 20 deletions tests/test_optimizely.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,42 +398,92 @@ def test_remove_listener(self):
self.assertEqual(0, len(self.optimizely.notification_center.notifications[enums.NotificationTypes.TRACK]))
self.assertEqual(0, len(self.optimizely.notification_center.notifications[enums.NotificationTypes.ACTIVATE]))

def test_activate_listener(self):
""" Test that activate calls broadcast activate with proper parameters. """
def test_activate_and_decision_listener(self):
""" Test that activate calls broadcast activate and decision with proper parameters. """

with mock.patch(
'optimizely.decision_service.DecisionService.get_variation',
return_value=self.project_config.get_variation_from_id('test_experiment', '111129')), \
mock.patch('optimizely.event_dispatcher.EventDispatcher.dispatch_event') as mock_dispatch, \
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast_activate:
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast:
self.assertEqual('variation', self.optimizely.activate('test_experiment', 'test_user'))

mock_broadcast_activate.assert_called_once_with(enums.NotificationTypes.ACTIVATE,
self.project_config.get_experiment_from_key('test_experiment'),
'test_user', None,
self.project_config.get_variation_from_id('test_experiment',
'111129'),
mock_dispatch.call_args[0][0])
self.assertEqual(mock_broadcast.call_count, 2)

def test_activate_listener_with_attr(self):
""" Test that activate calls broadcast activate with proper parameters. """
mock_broadcast.assert_has_calls([
mock.call(
enums.NotificationTypes.DECISION,
'experiment',
'test_user',
{},
{
'experiment_key': 'test_experiment',
'variation_key': 'variation'
}
),
mock.call(
enums.NotificationTypes.ACTIVATE,
self.project_config.get_experiment_from_key('test_experiment'),
'test_user', None,
self.project_config.get_variation_from_id('test_experiment', '111129'),
mock_dispatch.call_args[0][0]
)
])

def test_activate_and_decision_listener_with_attr(self):
""" Test that activate calls broadcast activate and decision with proper parameters. """

with mock.patch(
'optimizely.decision_service.DecisionService.get_variation',
return_value=self.project_config.get_variation_from_id('test_experiment', '111129')), \
mock.patch('optimizely.event_dispatcher.EventDispatcher.dispatch_event') as mock_dispatch, \
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast_activate:
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast:
self.assertEqual('variation',
self.optimizely.activate('test_experiment', 'test_user', {'test_attribute': 'test_value'}))

mock_broadcast_activate.assert_called_once_with(enums.NotificationTypes.ACTIVATE,
self.project_config.get_experiment_from_key('test_experiment'),
'test_user', {'test_attribute': 'test_value'},
self.project_config.get_variation_from_id(
'test_experiment', '111129'
),
mock_dispatch.call_args[0][0]
)
self.assertEqual(mock_broadcast.call_count, 2)

mock_broadcast.assert_has_calls([
mock.call(
enums.NotificationTypes.DECISION,
'experiment',
'test_user',
{'test_attribute': 'test_value'},
{
'experiment_key': 'test_experiment',
'variation_key': 'variation'
}
),
mock.call(
enums.NotificationTypes.ACTIVATE,
self.project_config.get_experiment_from_key('test_experiment'),
'test_user', {'test_attribute': 'test_value'},
self.project_config.get_variation_from_id('test_experiment', '111129'),
mock_dispatch.call_args[0][0]
)
])

def test_decision_listener__user_not_in_experiment(self):
""" Test that activate calls broadcast decision with variation_key 'None' \
when user not in experiment. """

with mock.patch(
'optimizely.decision_service.DecisionService.get_variation',
return_value=None), \
mock.patch('optimizely.event_dispatcher.EventDispatcher.dispatch_event'), \
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast_decision:
self.assertEqual(None, self.optimizely.activate('test_experiment', 'test_user'))

mock_broadcast_decision.assert_called_once_with(
enums.NotificationTypes.DECISION,
'experiment',
'test_user',
{},
{
'experiment_key': 'test_experiment',
'variation_key': None
}
)

def test_track_listener(self):
""" Test that track calls notification broadcaster. """
Expand Down Expand Up @@ -1395,6 +1445,50 @@ def test_track__invalid_user_id(self):
self.assertIsNone(self.optimizely.track('test_event', 99))
mock_client_logging.error.assert_called_once_with('Provided "user_id" is in an invalid format.')

def test_get_variation(self):
""" Test that get_variation returns valid variation and broadcasts decision with proper parameters. """

with mock.patch(
'optimizely.decision_service.DecisionService.get_variation',
return_value=self.project_config.get_variation_from_id('test_experiment', '111129')), \
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast:
self.assertEqual('variation', self.optimizely.get_variation('test_experiment', 'test_user'))

self.assertEqual(mock_broadcast.call_count, 1)

mock_broadcast.assert_called_once_with(
enums.NotificationTypes.DECISION,
'experiment',
'test_user',
{},
{
'experiment_key': 'test_experiment',
'variation_key': 'variation'
}
)

def test_get_variation__returns_none(self):
""" Test that get_variation returns no variation and broadcasts decision with proper parameters. """

with mock.patch(
'optimizely.decision_service.DecisionService.get_variation', return_value=None), \
mock.patch('optimizely.notification_center.NotificationCenter.send_notifications') as mock_broadcast:
self.assertEqual(None, self.optimizely.get_variation('test_experiment', 'test_user',
attributes={'test_attribute': 'test_value'}))

self.assertEqual(mock_broadcast.call_count, 1)

mock_broadcast.assert_called_once_with(
enums.NotificationTypes.DECISION,
'experiment',
'test_user',
{'test_attribute': 'test_value'},
{
'experiment_key': 'test_experiment',
'variation_key': None
}
)

def test_get_variation__invalid_object(self):
""" Test that get_variation logs error if Optimizely object is not created correctly. """

Expand Down

0 comments on commit 40305de

Please sign in to comment.