1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 */
16- using OptimizelySDK . Entity ;
17- using OptimizelySDK . Logger ;
1816using Moq ;
1917using NUnit . Framework ;
2018using OptimizelySDK . Bucketing ;
19+ using OptimizelySDK . Entity ;
20+ using OptimizelySDK . Logger ;
2121
2222namespace OptimizelySDK . Tests
2323{
@@ -27,6 +27,11 @@ public class BucketerTest
2727 private Mock < ILogger > LoggerMock ;
2828 private ProjectConfig Config ;
2929 private const string TestUserId = "testUserId" ;
30+ public string TestBucketingIdControl { get ; } = "testBucketingIdControl!" ; // generates bucketing number 3741
31+ public string TestBucketingIdVariation { get ; } = "123456789'" ; // generates bucketing number 4567
32+ public string TestBucketingIdGroupExp2Var2 { get ; } = "123456789" ; // group_exp_2_var_2
33+ public string TestUserIdBucketsToVariation { get ; } = "bucketsToVariation!" ;
34+ public string TestUserIdBucketsToNoGroup { get ; } = "testUserId" ;
3035
3136 /// <summary>
3237 /// Bucket Testing helper class
@@ -36,7 +41,7 @@ private class BucketerTestItem
3641 public string UserId { get ; set ; }
3742 public string ExperimentId { get ; set ; }
3843 public int ExpectedBucketValue { get ; set ; }
39-
44+
4045 public string BucketingId
4146 {
4247 get { return UserId + ExperimentId ; }
@@ -92,26 +97,26 @@ public void TestBucketValidExperimentNotInGroup()
9297
9398 // control
9499 Assert . AreEqual ( new Variation { Id = "7722370027" , Key = "control" } ,
95- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestUserId ) ) ;
100+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestBucketingIdControl , TestUserId ) ) ;
96101
97102 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Exactly ( 2 ) ) ;
98- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [3000] to user [testUserId]" ) ) ;
103+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [3000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
99104 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in variation [control] of experiment [test_experiment]." ) ) ;
100105
101106 // variation
102107 Assert . AreEqual ( new Variation { Id = "7721010009" , Key = "variation" } ,
103- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestUserId ) ) ;
108+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestBucketingIdControl , TestUserId ) ) ;
104109
105110 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Exactly ( 4 ) ) ;
106- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [7000] to user [testUserId]" ) ) ;
111+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [7000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
107112 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in variation [variation] of experiment [test_experiment]." ) ) ;
108113
109114 // no variation
110115 Assert . AreEqual ( new Variation { } ,
111- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestUserId ) ) ;
116+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestBucketingIdControl , TestUserId ) ) ;
112117
113118 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Exactly ( 6 ) ) ;
114- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [9000] to user [testUserId]" ) ) ;
119+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [9000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
115120 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in no variation." ) ) ;
116121 }
117122
@@ -124,26 +129,26 @@ public void TestBucketValidExperimentInGroup()
124129 // variation 1
125130 bucketer . SetBucketValues ( new [ ] { 1000 , 4000 } ) ;
126131 Assert . AreEqual ( new Variation { Id = "7722260071" , Key = "group_exp_1_var_1" } ,
127- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestUserId ) ) ;
128- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [1000] to user [testUserId]" ) ) ;
132+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestBucketingIdControl , TestUserId ) ) ;
133+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [1000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
129134 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in experiment [group_experiment_1] of group [7722400015]." ) ) ;
130- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [4000] to user [testUserId]" ) ) ;
135+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [4000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
131136 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in variation [group_exp_1_var_1] of experiment [group_experiment_1]." ) ) ;
132137
133138 // variation 2
134139 bucketer . SetBucketValues ( new [ ] { 1500 , 7000 } ) ;
135140 Assert . AreEqual ( new Variation { Id = "7722360022" , Key = "group_exp_1_var_2" } ,
136- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestUserId ) ) ;
137- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [1500] to user [testUserId]" ) ) ;
141+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestBucketingIdControl , TestUserId ) ) ;
142+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [1500] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
138143 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in experiment [group_experiment_1] of group [7722400015]." ) ) ;
139- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [7000] to user [testUserId]" ) ) ;
144+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [7000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
140145 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is in variation [group_exp_1_var_1] of experiment [group_experiment_1]." ) ) ;
141146
142147 // User not in experiment
143148 bucketer . SetBucketValues ( new [ ] { 5000 , 7000 } ) ;
144149 Assert . AreEqual ( new Variation { } ,
145- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestUserId ) ) ;
146- LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [5000] to user [testUserId]" ) ) ;
150+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestBucketingIdControl , TestUserId ) ) ;
151+ LoggerMock . Verify ( l => l . Log ( LogLevel . DEBUG , "Assigned bucket [5000] to user [testUserId] with bucketing ID [testBucketingIdControl!]. " ) ) ;
147152 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [testUserId] is not in experiment [group_experiment_1] of group [7722400015]." ) ) ;
148153
149154 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Exactly ( 10 ) ) ;
@@ -155,7 +160,7 @@ public void TestBucketInvalidExperiment()
155160 var bucketer = new Bucketer ( LoggerMock . Object ) ;
156161
157162 Assert . AreEqual ( new Variation { } ,
158- bucketer . Bucket ( Config , new Experiment ( ) , TestUserId ) ) ;
163+ bucketer . Bucket ( Config , new Experiment ( ) , TestBucketingIdControl , TestUserId ) ) ;
159164
160165 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Never ) ;
161166 }
@@ -166,7 +171,7 @@ public void TestBucketValidExperimentNotInGroupUserInForcedVariation()
166171 var bucketer = new Bucketer ( LoggerMock . Object ) ;
167172
168173 Assert . AreEqual ( new Variation { Id = "7722370027" , Key = "control" } ,
169- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , "user1" ) ) ;
174+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "test_experiment" ) , TestBucketingIdControl , "user1" ) ) ;
170175
171176 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [user1] is forced into variation [control]." ) ) ;
172177 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Exactly ( 1 ) ) ;
@@ -178,10 +183,47 @@ public void TestBucketValidExperimentInGroupUserInForcedVariation()
178183 var bucketer = new Bucketer ( LoggerMock . Object ) ;
179184
180185 Assert . AreEqual ( new Variation { Id = "7722260071" , Key = "group_exp_1_var_1" } ,
181- bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , "user1" ) ) ;
186+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_1" ) , TestBucketingIdControl , "user1" ) ) ;
182187
183188 LoggerMock . Verify ( l => l . Log ( LogLevel . INFO , "User [user1] is forced into variation [group_exp_1_var_1]." ) ) ;
184189 LoggerMock . Verify ( l => l . Log ( It . IsAny < LogLevel > ( ) , It . IsAny < string > ( ) ) , Times . Exactly ( 1 ) ) ;
185190 }
191+
192+ [ Test ]
193+ public void TestBucketWithBucketingId ( )
194+ {
195+ var bucketer = new Bucketer ( LoggerMock . Object ) ;
196+ var experiment = Config . GetExperimentFromKey ( "test_experiment" ) ;
197+ var expectedVariation = new Variation { Id = "7722370027" , Key = "control" } ;
198+ var expectedVariation2 = new Variation { Id = "7721010009" , Key = "variation" } ;
199+
200+ // make sure that the bucketing ID is used for the variation bucketing and not the user ID
201+ Assert . AreEqual ( expectedVariation ,
202+ bucketer . Bucket ( Config , experiment , TestBucketingIdControl , TestUserIdBucketsToVariation ) ) ;
203+ }
204+
205+ // Test for invalid experiment keys, null variation should be returned
206+ [ Test ]
207+ public void TestBucketVariationInvalidExperimentsWithBucketingId ( )
208+ {
209+ var bucketer = new Bucketer ( LoggerMock . Object ) ;
210+ var expectedVariation = new Variation ( ) ;
211+
212+ Assert . AreEqual ( expectedVariation ,
213+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "invalid_experiment" ) , TestBucketingIdVariation , TestUserId ) ) ;
214+ }
215+
216+ // Make sure that the bucketing ID is used to bucket the user into a group and not the user ID
217+ [ Test ]
218+ public void TestBucketVariationGroupedExperimentsWithBucketingId ( )
219+ {
220+ var bucketer = new Bucketer ( LoggerMock . Object ) ;
221+ var expectedVariation = new Variation ( ) ;
222+ var expectedGroupVariation = new Variation { Id = "7725250007" , Key = "group_exp_2_var_2" } ;
223+
224+ Assert . AreEqual ( expectedGroupVariation ,
225+ bucketer . Bucket ( Config , Config . GetExperimentFromKey ( "group_experiment_2" ) ,
226+ TestBucketingIdGroupExp2Var2 , TestUserIdBucketsToNoGroup ) ) ;
227+ }
186228 }
187229}
0 commit comments