/// <summary> /// Get a Variation of an Experiment for a user to be allocated into. /// </summary> /// <param name = "experiment" > The Experiment the user will be bucketed into.</param> /// <param name = "userId" > The userId of the user. /// <param name = "filteredAttributes" > The user's attributes. This should be filtered to just attributes in the Datafile.</param> /// <returns>The Variation the user is allocated into.</returns> public virtual Variation GetVariation(Experiment experiment, string userId, UserAttributes filteredAttributes) { if (!ExperimentUtils.IsExperimentActive(experiment, Logger)) { return(null); } // check if a forced variation is set var forcedVariation = ProjectConfig.GetForcedVariation(experiment.Key, userId); if (forcedVariation != null) { return(forcedVariation); } var variation = GetWhitelistedVariation(experiment, userId); if (variation != null) { return(variation); } UserProfile userProfile = null; if (UserProfileService != null) { try { Dictionary <string, object> userProfileMap = UserProfileService.Lookup(userId); if (userProfileMap != null && UserProfileUtil.IsValidUserProfileMap(userProfileMap)) { userProfile = UserProfileUtil.ConvertMapToUserProfile(userProfileMap); variation = GetStoredVariation(experiment, userProfile); if (variation != null) { return(variation); } } else if (userProfileMap == null) { Logger.Log(LogLevel.INFO, "We were unable to get a user profile map from the UserProfileService."); } else { Logger.Log(LogLevel.ERROR, "The UserProfileService returned an invalid map."); } } catch (Exception exception) { Logger.Log(LogLevel.ERROR, exception.Message); ErrorHandler.HandleError(new Exceptions.OptimizelyRuntimeException(exception.Message)); } } if (ExperimentUtils.IsUserInExperiment(ProjectConfig, experiment, filteredAttributes, Logger)) { // Get Bucketing ID from user attributes. string bucketingId = GetBucketingId(userId, filteredAttributes); variation = Bucketer.Bucket(ProjectConfig, experiment, bucketingId, userId); if (variation != null && variation.Key != null) { if (UserProfileService != null) { var bucketerUserProfile = userProfile ?? new UserProfile(userId, new Dictionary <string, Decision>()); SaveVariation(experiment, variation, bucketerUserProfile); } else { Logger.Log(LogLevel.INFO, "This decision will not be saved since the UserProfileService is null."); } } return(variation); } Logger.Log(LogLevel.INFO, string.Format("User \"{0}\" does not meet conditions to be in experiment \"{1}\".", userId, experiment.Key)); return(null); }
public void TestSetGetForcedVariation() { var userId = "test_user"; var invalidUserId = "invalid_user"; var experimentKey = "test_experiment"; var experimentKey2 = "group_experiment_1"; var invalidExperimentKey = "invalid_experiment"; var expectedVariationKey = "control"; var expectedVariationKey2 = "group_exp_1_var_1"; var invalidVariationKey = "invalid_variation"; var userAttributes = new UserAttributes { { "device_type", "iPhone" }, { "location", "San Francisco" } }; var optlyObject = new Optimizely(TestData.Datafile, new ValidEventDispatcher(), LoggerMock.Object); optlyObject.Activate("test_experiment", "test_user", userAttributes); // invalid experiment key should return a null variation Assert.False(Config.SetForcedVariation(invalidExperimentKey, userId, expectedVariationKey)); Assert.Null(Config.GetForcedVariation(invalidExperimentKey, userId)); // setting a null variation should return a null variation Assert.True(Config.SetForcedVariation(experimentKey, userId, null)); Assert.Null(Config.GetForcedVariation(experimentKey, userId)); // setting an invalid variation should return a null variation Assert.False(Config.SetForcedVariation(experimentKey, userId, invalidVariationKey)); Assert.Null(Config.GetForcedVariation(experimentKey, userId)); // confirm the forced variation is returned after a set Assert.True(Config.SetForcedVariation(experimentKey, userId, expectedVariationKey)); var actualForcedVariation = Config.GetForcedVariation(experimentKey, userId); Assert.AreEqual(expectedVariationKey, actualForcedVariation.Key); // check multiple sets Assert.True(Config.SetForcedVariation(experimentKey2, userId, expectedVariationKey2)); var actualForcedVariation2 = Config.GetForcedVariation(experimentKey2, userId); Assert.AreEqual(expectedVariationKey2, actualForcedVariation2.Key); // make sure the second set does not overwrite the first set actualForcedVariation = Config.GetForcedVariation(experimentKey, userId); Assert.AreEqual(expectedVariationKey, actualForcedVariation.Key); // make sure unsetting the second experiment-to-variation mapping does not unset the // first experiment-to-variation mapping Assert.True(Config.SetForcedVariation(experimentKey2, userId, null)); actualForcedVariation = Config.GetForcedVariation(experimentKey, userId); Assert.AreEqual(expectedVariationKey, actualForcedVariation.Key); // an invalid user ID should return a null variation Assert.Null(Config.GetForcedVariation(experimentKey, invalidUserId)); }