def test_get_variation_for_feature__returns_variation_if_user_not_in_experiment_but_in_rollout( self): """ Test that get_variation_for_feature returns the variation of the experiment in the feature's rollout even if the user is not bucketed into the feature's experiment. """ feature = self.project_config.get_feature_from_key( 'test_feature_in_experiment_and_rollout') expected_experiment = self.project_config.get_experiment_from_key( '211127') expected_variation = self.project_config.get_variation_from_id( '211127', '211129') with mock.patch( 'optimizely.helpers.audience.is_user_in_experiment', side_effect=[False, True]) as mock_audience_check, \ mock.patch('optimizely.bucketer.Bucketer.bucket', return_value=expected_variation): self.assertEqual( decision_service.Decision( expected_experiment, expected_variation, decision_service.DECISION_SOURCE_ROLLOUT), self.decision_service.get_variation_for_feature( feature, 'test_user')) self.assertEqual(2, mock_audience_check.call_count) mock_audience_check.assert_any_call( self.project_config, self.project_config.get_experiment_from_key('test_experiment'), None) mock_audience_check.assert_any_call( self.project_config, self.project_config.get_experiment_from_key('211127'), None)
def test_get_variation_for_feature__returns_variation_for_feature_in_group( self): """ Test that get_variation_for_feature returns the variation of the experiment the user is bucketed in the feature's group. """ feature = self.project_config.get_feature_from_key( 'test_feature_in_group') expected_experiment = self.project_config.get_experiment_from_key( 'group_exp_1') expected_variation = self.project_config.get_variation_from_id( 'group_exp_1', '28901') with mock.patch( 'optimizely.decision_service.DecisionService.get_experiment_in_group', return_value=self.project_config.get_experiment_from_key('group_exp_1')) as mock_get_experiment_in_group, \ mock.patch('optimizely.decision_service.DecisionService.get_variation', return_value=expected_variation) as mock_decision: self.assertEqual( decision_service.Decision( expected_experiment, expected_variation, decision_service.DECISION_SOURCE_EXPERIMENT), self.decision_service.get_variation_for_feature( feature, 'test_user')) mock_get_experiment_in_group.assert_called_once_with( self.project_config.get_group('19228'), 'test_user') mock_decision.assert_called_once_with( self.project_config.get_experiment_from_key('group_exp_1'), 'test_user', None)
def test_get_variation_for_rollout__calls_bucket_with_bucketing_id(self): """ Test that get_variation_for_rollout calls Bucketer.bucket with bucketing ID when provided. """ rollout = self.project_config.get_rollout_from_id('211111') with mock.patch('optimizely.helpers.audience.is_user_in_experiment', return_value=True),\ self.mock_decision_logger as mock_decision_logging, \ mock.patch('optimizely.bucketer.Bucketer.bucket', return_value=self.project_config.get_variation_from_id('211127', '211129')) as mock_bucket: self.assertEqual( decision_service.Decision( self.project_config.get_experiment_from_id('211127'), self.project_config.get_variation_from_id( '211127', '211129'), decision_service.DECISION_SOURCE_ROLLOUT), self.decision_service.get_variation_for_rollout( rollout, 'test_user', {'$opt_bucketing_id': 'user_bucket_value'})) # Check all log messages mock_decision_logging.debug.assert_has_calls([ mock.call( 'User "test_user" meets conditions for targeting rule 1.'), mock.call( 'User "test_user" is in variation 211129 of experiment 211127.' ) ]) # Check that bucket is called with correct parameters mock_bucket.assert_called_once_with( self.project_config.get_experiment_from_id('211127'), 'test_user', 'user_bucket_value')
def test_get_variation_for_feature__returns_variation_for_feature_in_experiment( self): """ Test that get_variation_for_feature returns the variation of the experiment the feature is associated with. """ feature = self.project_config.get_feature_from_key( 'test_feature_in_experiment') expected_experiment = self.project_config.get_experiment_from_key( 'test_experiment') expected_variation = self.project_config.get_variation_from_id( 'test_experiment', '111129') decision_patch = mock.patch( 'optimizely.decision_service.DecisionService.get_variation', return_value=expected_variation) with decision_patch as mock_decision, self.mock_decision_logger as mock_decision_logging: self.assertEqual( decision_service.Decision( expected_experiment, expected_variation, decision_service.DECISION_SOURCE_EXPERIMENT), self.decision_service.get_variation_for_feature( feature, 'test_user')) mock_decision.assert_called_once_with( self.project_config.get_experiment_from_key('test_experiment'), 'test_user', None) # Check log message mock_decision_logging.debug.assert_called_once_with( 'User "test_user" is in variation variation of experiment test_experiment.' )
def test_get_variation_for_rollout__skips_to_everyone_else_rule(self): """ Test that if a user is in an audience, but does not qualify for the experiment, then it skips to the Everyone Else rule. """ rollout = self.project_config.get_rollout_from_id('211111') everyone_else_exp = self.project_config.get_experiment_from_id('211147') variation_to_mock = self.project_config.get_variation_from_id('211147', '211149') with mock.patch('optimizely.helpers.audience.is_user_in_experiment', return_value=True) as mock_audience_check,\ self.mock_decision_logger as mock_decision_logging, \ mock.patch('optimizely.bucketer.Bucketer.bucket', side_effect=[None, variation_to_mock]): self.assertEqual( decision_service.Decision(everyone_else_exp, variation_to_mock, decision_service.DECISION_SOURCE_ROLLOUT), self.decision_service.get_variation_for_rollout(rollout, 'test_user')) # Check that after first experiment, it skips to the last experiment to check self.assertEqual( [mock.call(self.project_config, self.project_config.get_experiment_from_key('211127'), None), mock.call(self.project_config, self.project_config.get_experiment_from_key('211147'), None)], mock_audience_check.call_args_list ) # Check all log messages mock_decision_logging.debug.assert_has_calls([ mock.call('User "test_user" meets conditions for targeting rule 1.'), mock.call('User "test_user" is not in the traffic group for the targeting else. ' 'Checking "Everyone Else" rule now.'), mock.call('User "test_user" meets conditions for targeting rule "Everyone Else".') ])
def test_get_variation_for_rollout__returns_none_if_no_experiments(self): """ Test that get_variation_for_rollout returns None if there are no experiments (targeting rules). """ with self.mock_config_logger as mock_logging: no_experiment_rollout = self.project_config.get_rollout_from_id('201111') self.assertEqual( decision_service.Decision(None, None, decision_service.DECISION_SOURCE_ROLLOUT), self.decision_service.get_variation_for_rollout(no_experiment_rollout, 'test_user') ) # Assert no log messages were generated self.assertEqual(0, mock_logging.call_count)
def test_get_variation_for_feature__returns_none_for_invalid_group_id(self): """ Test that get_variation_for_feature returns None for unknown group ID. """ feature = self.project_config.get_feature_from_key('test_feature_in_group') feature.groupId = 'aabbccdd' with self.mock_decision_logger as mock_decision_logging: self.assertEqual( decision_service.Decision(None, None, decision_service.DECISION_SOURCE_EXPERIMENT), self.decision_service.get_variation_for_feature(feature, 'test_user') ) mock_decision_logging.error.assert_called_once_with( enums.Errors.INVALID_GROUP_ID_ERROR.format('_get_variation_for_feature') )
def test_get_variation_for_feature__returns_none_for_user_not_in_group(self): """ Test that get_variation_for_feature returns None for user not in group and the feature is not part of a rollout. """ feature = self.project_config.get_feature_from_key('test_feature_in_group') with mock.patch('optimizely.decision_service.DecisionService.get_experiment_in_group', return_value=None) as mock_get_experiment_in_group, \ mock.patch('optimizely.decision_service.DecisionService.get_variation') as mock_decision: self.assertEqual(decision_service.Decision(None, None, decision_service.DECISION_SOURCE_EXPERIMENT), self.decision_service.get_variation_for_feature(feature, 'test_user')) mock_get_experiment_in_group.assert_called_once_with(self.project_config.get_group('19228'), 'test_user') self.assertFalse(mock_decision.called)
def test_get_variation_for_feature__returns_none_for_user_in_group_experiment_not_associated_with_feature(self): """ Test that if a user is in the mutex group but the experiment is not targeting a feature, then None is returned. """ feature = self.project_config.get_feature_from_key('test_feature_in_group') expected_experiment = self.project_config.get_experiment_from_key('group_exp_2') with mock.patch('optimizely.decision_service.DecisionService.get_experiment_in_group', return_value=self.project_config.get_experiment_from_key('group_exp_2')) as mock_decision: self.assertEqual(decision_service.Decision(expected_experiment, None, decision_service.DECISION_SOURCE_EXPERIMENT), self.decision_service.get_variation_for_feature(feature, 'test_user')) mock_decision.assert_called_once_with(self.project_config.get_group('19228'), 'test_user')
def test_get_variation_for_feature__returns_none_for_user_not_in_experiment(self): """ Test that get_variation_for_feature returns None for user not in the associated experiment. """ feature = self.project_config.get_feature_from_key('test_feature_in_experiment') expected_experiment = self.project_config.get_experiment_from_key('test_experiment') with mock.patch('optimizely.decision_service.DecisionService.get_variation', return_value=None) as mock_decision: self.assertEqual(decision_service.Decision(expected_experiment, None, decision_service.DECISION_SOURCE_EXPERIMENT), self.decision_service.get_variation_for_feature(feature, 'test_user')) mock_decision.assert_called_once_with( self.project_config.get_experiment_from_key('test_experiment'), 'test_user', None )
def test_get_variation_for_rollout__returns_none_for_user_not_in_rollout(self): """ Test that get_variation_for_rollout returns None for the user not in the associated rollout. """ rollout = self.project_config.get_rollout_from_id('211111') with mock.patch('optimizely.helpers.audience.is_user_in_experiment', return_value=False) as mock_audience_check, \ self.mock_decision_logger as mock_decision_logging: self.assertEqual(decision_service.Decision(None, None, decision_service.DECISION_SOURCE_ROLLOUT), self.decision_service.get_variation_for_rollout(rollout, 'test_user')) # Check that all experiments in rollout layer were checked self.assertEqual( [mock.call(self.project_config, self.project_config.get_experiment_from_key('211127'), None), mock.call(self.project_config, self.project_config.get_experiment_from_key('211137'), None), mock.call(self.project_config, self.project_config.get_experiment_from_key('211147'), None)], mock_audience_check.call_args_list ) # Check all log messages mock_decision_logging.debug.assert_has_calls([ mock.call('User "test_user" does not meet conditions for targeting rule 1.'), mock.call('User "test_user" does not meet conditions for targeting rule 2.') ])