Skip to content

Commit 66572d7

Browse files
mfahadahmedalda-optimizely
authored andcommitted
Implemented Bucketing ID feature (#23)
* Bug fix: Activate/Track method was sending variation to server only from the bucketer. * bucketing id, compilation errors removed. have to update logs. * Implemented Bucketing ID feature in the SDK. * Implemented Bucketing ID feature in the SDK. * Fixed code review defects in Bucketing ID feature. * Fixed bucketing ID tests.
1 parent 8e1be15 commit 66572d7

File tree

7 files changed

+455
-67
lines changed

7 files changed

+455
-67
lines changed

OptimizelySDK.Tests/BucketerTest.cs

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
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;
1816
using Moq;
1917
using NUnit.Framework;
2018
using OptimizelySDK.Bucketing;
19+
using OptimizelySDK.Entity;
20+
using OptimizelySDK.Logger;
2121

2222
namespace 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

Comments
 (0)