Esempio n. 1
0
        /// <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));
        }