From 1cd48cf4a60e4f89a9f732675f5f286ecb617091 Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Fri, 9 Oct 2020 16:58:29 -0700 Subject: [PATCH] sending decision on nil variation --- optimizely/optimizely.py | 2 +- tests/test_optimizely.py | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/optimizely/optimizely.py b/optimizely/optimizely.py index afd6f382..400db190 100644 --- a/optimizely/optimizely.py +++ b/optimizely/optimizely.py @@ -580,7 +580,7 @@ def is_feature_enabled(self, feature_key, user_id, attributes=None): is_source_experiment = decision.source == enums.DecisionSources.FEATURE_TEST is_source_rollout = decision.source == enums.DecisionSources.ROLLOUT - if is_source_rollout and project_config.get_send_flag_decisions_value(): + if (is_source_rollout or not decision.variation) and project_config.get_send_flag_decisions_value(): self._send_impression_event( project_config, decision.experiment, decision.variation, feature.key, decision.experiment.key if decision.experiment else '', decision.source, user_id, attributes diff --git a/tests/test_optimizely.py b/tests/test_optimizely.py index 35c0004c..4e3b9cfe 100644 --- a/tests/test_optimizely.py +++ b/tests/test_optimizely.py @@ -2371,6 +2371,48 @@ def test_is_feature_enabled__returns_false_when_user_is_not_bucketed_into_any_va # Check that impression event is sent for rollout and send_flag_decisions = True self.assertEqual(1, mock_process.call_count) + def test_is_feature_enabled__returns_false_when_variation_is_nil(self,): + """ Test that the feature is not enabled with nil variation + Also confirm that impression event is processed. """ + + opt_obj = optimizely.Optimizely(json.dumps(self.config_dict_with_features)) + project_config = opt_obj.config_manager.get_config() + feature = project_config.get_feature_from_key('test_feature_in_experiment_and_rollout') + with mock.patch( + 'optimizely.decision_service.DecisionService.get_variation_for_feature', + return_value=decision_service.Decision(None, None, enums.DecisionSources.ROLLOUT), + ) as mock_decision, mock.patch( + 'optimizely.event.event_processor.ForwardingEventProcessor.process' + ) as mock_process, mock.patch( + 'optimizely.notification_center.NotificationCenter.send_notifications' + ) as mock_broadcast_decision, mock.patch( + 'uuid.uuid4', return_value='a68cf1ad-0393-4e18-af87-efe8f01a7c9c' + ), mock.patch( + 'time.time', return_value=42 + ): + self.assertFalse(opt_obj.is_feature_enabled("test_feature_in_experiment_and_rollout", 'test_user')) + + # Check that impression event is sent for rollout and send_flag_decisions = True + self.assertEqual(1, mock_process.call_count) + + mock_decision.assert_called_once_with(opt_obj.config_manager.get_config(), feature, 'test_user', None) + + mock_broadcast_decision.assert_called_with( + enums.NotificationTypes.DECISION, + 'feature', + 'test_user', + {}, + { + 'feature_key': 'test_feature_in_experiment_and_rollout', + 'feature_enabled': False, + 'source': 'rollout', + 'source_info': {}, + }, + ) + + # Check that impression event is sent for rollout and send_flag_decisions = True + self.assertEqual(1, mock_process.call_count) + def test_is_feature_enabled__invalid_object(self): """ Test that is_feature_enabled returns False and logs error if Optimizely instance is invalid. """