55from splitio .models .grammar .condition import Condition , ConditionType
66from splitio .models .impressions import Label
77from splitio .engine import evaluator , splitters
8- from splitio .storage import SplitStorage , SegmentStorage
9-
108
119class EvaluatorTests (object ):
1210 """Test evaluator behavior."""
1311
1412 def _build_evaluator_with_mocks (self , mocker ):
1513 """Build an evaluator with mocked dependencies."""
16- split_storage_mock = mocker .Mock (spec = SplitStorage )
1714 splitter_mock = mocker .Mock (spec = splitters .Splitter )
18- segment_storage_mock = mocker .Mock (spec = SegmentStorage )
1915 logger_mock = mocker .Mock (spec = logging .Logger )
20- e = evaluator .Evaluator (split_storage_mock , segment_storage_mock , splitter_mock )
16+ e = evaluator .Evaluator (splitter_mock )
2117 evaluator ._LOGGER = logger_mock
2218 return e
2319
24- def test_evaluate_treatment_missing_split (self , mocker ):
25- """Test that a missing split logs and returns CONTROL."""
26- e = self ._build_evaluator_with_mocks (mocker )
27- e ._feature_flag_storage .get .return_value = None
28- result = e .evaluate_feature ('feature1' , 'some_key' , 'some_bucketing_key' , {'attr1' : 1 })
29- assert result ['configurations' ] == None
30- assert result ['treatment' ] == evaluator .CONTROL
31- assert result ['impression' ]['change_number' ] == - 1
32- assert result ['impression' ]['label' ] == Label .SPLIT_NOT_FOUND
33-
3420 def test_evaluate_treatment_killed_split (self , mocker ):
3521 """Test that a killed split returns the default treatment."""
3622 e = self ._build_evaluator_with_mocks (mocker )
@@ -39,8 +25,7 @@ def test_evaluate_treatment_killed_split(self, mocker):
3925 mocked_split .killed = True
4026 mocked_split .change_number = 123
4127 mocked_split .get_configurations_for .return_value = '{"some_property": 123}'
42- e ._feature_flag_storage .get .return_value = mocked_split
43- result = e .evaluate_feature ('feature1' , 'some_key' , 'some_bucketing_key' , {'attr1' : 1 })
28+ result = e .evaluate_feature (mocked_split , 'some_key' , 'some_bucketing_key' , mocker .Mock ())
4429 assert result ['treatment' ] == 'off'
4530 assert result ['configurations' ] == '{"some_property": 123}'
4631 assert result ['impression' ]['change_number' ] == 123
@@ -50,15 +35,14 @@ def test_evaluate_treatment_killed_split(self, mocker):
5035 def test_evaluate_treatment_ok (self , mocker ):
5136 """Test that a non-killed split returns the appropriate treatment."""
5237 e = self ._build_evaluator_with_mocks (mocker )
53- e ._get_treatment_for_split = mocker .Mock ()
54- e ._get_treatment_for_split .return_value = ('on' , 'some_label' )
38+ e ._get_treatment_for_feature_flag = mocker .Mock ()
39+ e ._get_treatment_for_feature_flag .return_value = ('on' , 'some_label' )
5540 mocked_split = mocker .Mock (spec = Split )
5641 mocked_split .default_treatment = 'off'
5742 mocked_split .killed = False
5843 mocked_split .change_number = 123
5944 mocked_split .get_configurations_for .return_value = '{"some_property": 123}'
60- e ._feature_flag_storage .get .return_value = mocked_split
61- result = e .evaluate_feature ('feature1' , 'some_key' , 'some_bucketing_key' , {'attr1' : 1 })
45+ result = e .evaluate_feature (mocked_split , 'some_key' , 'some_bucketing_key' , mocker .Mock ())
6246 assert result ['treatment' ] == 'on'
6347 assert result ['configurations' ] == '{"some_property": 123}'
6448 assert result ['impression' ]['change_number' ] == 123
@@ -69,15 +53,14 @@ def test_evaluate_treatment_ok(self, mocker):
6953 def test_evaluate_treatment_ok_no_config (self , mocker ):
7054 """Test that a killed split returns the default treatment."""
7155 e = self ._build_evaluator_with_mocks (mocker )
72- e ._get_treatment_for_split = mocker .Mock ()
73- e ._get_treatment_for_split .return_value = ('on' , 'some_label' )
56+ e ._get_treatment_for_feature_flag = mocker .Mock ()
57+ e ._get_treatment_for_feature_flag .return_value = ('on' , 'some_label' )
7458 mocked_split = mocker .Mock (spec = Split )
7559 mocked_split .default_treatment = 'off'
7660 mocked_split .killed = False
7761 mocked_split .change_number = 123
7862 mocked_split .get_configurations_for .return_value = None
79- e ._feature_flag_storage .get .return_value = mocked_split
80- result = e .evaluate_feature ('feature1' , 'some_key' , 'some_bucketing_key' , {'attr1' : 1 })
63+ result = e .evaluate_feature (mocked_split , 'some_key' , 'some_bucketing_key' , mocker .Mock ())
8164 assert result ['treatment' ] == 'on'
8265 assert result ['configurations' ] == None
8366 assert result ['impression' ]['change_number' ] == 123
@@ -87,24 +70,28 @@ def test_evaluate_treatment_ok_no_config(self, mocker):
8770 def test_evaluate_treatments (self , mocker ):
8871 """Test that a missing split logs and returns CONTROL."""
8972 e = self ._build_evaluator_with_mocks (mocker )
90- e ._get_treatment_for_split = mocker .Mock ()
91- e ._get_treatment_for_split .return_value = ('on' , 'some_label' )
73+ e ._get_treatment_for_feature_flag = mocker .Mock ()
74+ e ._get_treatment_for_feature_flag .return_value = ('on' , 'some_label' )
9275 mocked_split = mocker .Mock (spec = Split )
9376 mocked_split .name = 'feature2'
9477 mocked_split .default_treatment = 'off'
9578 mocked_split .killed = False
9679 mocked_split .change_number = 123
9780 mocked_split .get_configurations_for .return_value = '{"some_property": 123}'
98- e ._feature_flag_storage .fetch_many .return_value = {
99- 'feature1' : None ,
100- 'feature2' : mocked_split ,
101- }
102- results = e .evaluate_features (['feature1' , 'feature2' ], 'some_key' , 'some_bucketing_key' , None )
103- result = results ['feature1' ]
81+
82+ mocked_split2 = mocker .Mock (spec = Split )
83+ mocked_split2 .name = 'feature4'
84+ mocked_split2 .default_treatment = 'on'
85+ mocked_split2 .killed = False
86+ mocked_split2 .change_number = 123
87+ mocked_split2 .get_configurations_for .return_value = None
88+
89+ results = e .evaluate_features ([mocked_split , mocked_split2 ], 'some_key' , 'some_bucketing_key' , mocker .Mock ())
90+ result = results ['feature4' ]
10491 assert result ['configurations' ] == None
105- assert result ['treatment' ] == evaluator . CONTROL
106- assert result ['impression' ]['change_number' ] == - 1
107- assert result ['impression' ]['label' ] == Label . SPLIT_NOT_FOUND
92+ assert result ['treatment' ] == 'on'
93+ assert result ['impression' ]['change_number' ] == 123
94+ assert result ['impression' ]['label' ] == 'some_label'
10895 result = results ['feature2' ]
10996 assert result ['configurations' ] == '{"some_property": 123}'
11097 assert result ['treatment' ] == 'on'
@@ -115,12 +102,9 @@ def test_get_gtreatment_for_split_no_condition_matches(self, mocker):
115102 """Test no condition matches."""
116103 e = self ._build_evaluator_with_mocks (mocker )
117104 e ._splitter .get_treatment .return_value = 'on'
118- conditions_mock = mocker .PropertyMock ()
119- conditions_mock .return_value = []
120105 mocked_split = mocker .Mock (spec = Split )
121106 mocked_split .killed = False
122- type(mocked_split ).conditions = conditions_mock
123- treatment , label = e ._get_treatment_for_split (mocked_split , 'some_key' , 'some_bucketing' , {'attr1' : 1 })
107+ treatment , label = e ._get_treatment_for_feature_flag (mocked_split , 'some_key' , 'some_bucketing' , [])
124108 assert treatment == None
125109 assert label == None
126110
@@ -132,30 +116,9 @@ def test_get_gtreatment_for_split_non_rollout(self, mocker):
132116 mocked_condition_1 .condition_type = ConditionType .WHITELIST
133117 mocked_condition_1 .label = 'some_label'
134118 mocked_condition_1 .matches .return_value = True
135- conditions_mock = mocker .PropertyMock ()
136- conditions_mock .return_value = [mocked_condition_1 ]
137119 mocked_split = mocker .Mock (spec = Split )
138120 mocked_split .killed = False
139- type( mocked_split ). conditions = conditions_mock
140- treatment , label = e ._get_treatment_for_split (mocked_split , 'some_key' , 'some_bucketing' , { 'attr1' : 1 } )
121+ condition_matchers = [( True , mocked_condition_1 )]
122+ treatment , label = e ._get_treatment_for_feature_flag (mocked_split , 'some_key' , 'some_bucketing' , condition_matchers )
141123 assert treatment == 'on'
142- assert label == 'some_label'
143-
144- def test_get_treatment_for_split_rollout (self , mocker ):
145- """Test rollout condition returns default treatment."""
146- e = self ._build_evaluator_with_mocks (mocker )
147- e ._splitter .get_bucket .return_value = 60
148- mocked_condition_1 = mocker .Mock (spec = Condition )
149- mocked_condition_1 .condition_type = ConditionType .ROLLOUT
150- mocked_condition_1 .label = 'some_label'
151- mocked_condition_1 .matches .return_value = True
152- conditions_mock = mocker .PropertyMock ()
153- conditions_mock .return_value = [mocked_condition_1 ]
154- mocked_split = mocker .Mock (spec = Split )
155- mocked_split .traffic_allocation = 50
156- mocked_split .default_treatment = 'almost-on'
157- mocked_split .killed = False
158- type(mocked_split ).conditions = conditions_mock
159- treatment , label = e ._get_treatment_for_split (mocked_split , 'some_key' , 'some_bucketing' , {'attr1' : 1 })
160- assert treatment == 'almost-on'
161- assert label == Label .NOT_IN_SPLIT
124+ assert label == 'some_label'
0 commit comments