Fixed up all test cases that broke when merging in

srgutils.context.Context
This commit is contained in:
Victor Ng 2018-08-02 14:51:09 -04:00
Родитель b86e713227
Коммит b4f5f6a48c
10 изменённых файлов: 155 добавлений и 141 удалений

Просмотреть файл

@ -14,11 +14,12 @@ chain.
"""
from taar.recommenders import utils
from srgutil.context import Context
# Clobber the Context name to prevent messy name collisions
from srgutil.context import Context as _Context
def default_context():
ctx = Context()
ctx = _Context()
from taar.recommenders import CollaborativeRecommender
from taar.recommenders import SimilarityRecommender
from taar.recommenders import LocaleRecommender

Просмотреть файл

@ -1,55 +0,0 @@
from taar.adapters.dynamo import ProfileController
import boto3
import zlib
import json
def test_crashy_profile_controller(monkeypatch):
def mock_boto3_resource(*args, **kwargs):
class ExceptionRaisingMockTable:
def __init__(self, tbl_name):
pass
def get_item(self, *args, **kwargs):
raise Exception
class MockDDB:
pass
mock_ddb = MockDDB()
mock_ddb.Table = ExceptionRaisingMockTable
return mock_ddb
monkeypatch.setattr(boto3, 'resource', mock_boto3_resource)
pc = ProfileController('us-west-2', 'taar_addon_data_20180206')
assert pc.get_client_profile("exception_raising_client_id") is None
def test_profile_controller(monkeypatch):
def mock_boto3_resource(*args, **kwargs):
some_bytes = zlib.compress(json.dumps({'key': "with_some_data"}).encode('utf8'))
class ValueObj:
value = some_bytes
class MockTable:
def __init__(self, tbl_name):
pass
def get_item(self, *args, **kwargs):
value_obj = ValueObj()
response = {'Item': {'json_payload': value_obj}}
return response
class MockDDB:
pass
mock_ddb = MockDDB()
mock_ddb.Table = MockTable
return mock_ddb
monkeypatch.setattr(boto3, 'resource', mock_boto3_resource)
pc = ProfileController('us-west-2', 'taar_addon_data_20180206')
jdata = pc.get_client_profile("exception_raising_client_id")
assert jdata == {'key': 'with_some_data'}

Просмотреть файл

@ -1,6 +1,5 @@
from taar.cache import Clock, JSONCache
import time
from taar.context import Context
EXPECTED_JSON = {"foo": 42}
@ -30,9 +29,9 @@ def test_clock():
assert abs(actual - expected) < 0.1
def test_fetch_json():
def test_fetch_json(test_ctx):
""" Just test a URL that we know will fail """
ctx = Context()
ctx = test_ctx
ctx['utils'] = utils = MockUtils()
ctx['clock'] = Clock()
cache = JSONCache(ctx)
@ -45,9 +44,9 @@ def test_fetch_json():
assert utils._fetch_count == 1
def test_get_s3_json_content():
def test_get_s3_json_content(test_ctx):
""" Just test an S3 bucket and key that doesn't exist """
ctx = Context()
ctx = test_ctx
ctx['utils'] = utils = MockUtils()
ctx['clock'] = Clock()
cache = JSONCache(ctx)
@ -60,7 +59,7 @@ def test_get_s3_json_content():
assert utils._get_count == 1
def test_expiry():
def test_expiry(test_ctx):
""" Just test a URL that we know will fail """
class MockClock:
def __init__(self):
@ -69,7 +68,7 @@ def test_expiry():
def time(self):
return self._now
ctx = Context()
ctx = test_ctx
utils = MockUtils()
ctx['utils'] = utils
ctx['clock'] = MockClock()

Просмотреть файл

@ -4,16 +4,15 @@ Test cases for the TAAR CollaborativeRecommender
import numpy
from taar.context import Context
from taar.cache import JSONCache, Clock
from taar.recommenders.collaborative_recommender import ADDON_MAPPING_URL
from taar.recommenders.collaborative_recommender import ADDON_MODEL_URL
from taar.recommenders.collaborative_recommender import CollaborativeRecommender
from taar.recommenders.collaborative_recommender import positive_hash
import pytest
"""
We need to generate a synthetic list of addons and relative weights
for co-occurance. It's important to note that the
@ -87,8 +86,8 @@ def activate_responses(ctx):
return ctx
def test_can_recommend():
ctx = get_mocked_ctx()
def test_can_recommend(mocked_ctx):
ctx = mocked_ctx
r = CollaborativeRecommender(ctx)
# Test that we can't recommend if we have not enough client info.
@ -100,20 +99,20 @@ def test_can_recommend():
"client_id": "test-client"})
def get_error_ctx():
ctx = Context()
ctx = activate_error_responses(ctx)
@pytest.fixture
def error_ctx(test_ctx):
ctx = activate_error_responses(test_ctx)
return ctx
def get_mocked_ctx():
ctx = Context()
ctx = activate_responses(ctx)
@pytest.fixture
def mocked_ctx(test_ctx):
ctx = activate_responses(test_ctx)
return ctx
def test_can_recommend_no_model():
ctx = get_error_ctx()
def test_can_recommend_no_model(error_ctx):
ctx = error_ctx
r = CollaborativeRecommender(ctx)
# We should never be able to recommend if something went wrong with the model.
@ -122,10 +121,10 @@ def test_can_recommend_no_model():
assert not r.can_recommend({"installed_addons": ["uBlock0@raymondhill.net"]})
def test_empty_recommendations():
def test_empty_recommendations(mocked_ctx):
# Tests that the empty recommender always recommends an empty list
# of addons if we have no addons
ctx = get_mocked_ctx()
ctx = mocked_ctx
r = CollaborativeRecommender(ctx)
assert not r.can_recommend({})
@ -133,10 +132,10 @@ def test_empty_recommendations():
# defined.
def test_best_recommendation():
def test_best_recommendation(mocked_ctx):
# Make sure the structure of the recommendations is correct and that we
# recommended the the right addon.
ctx = get_mocked_ctx()
ctx = mocked_ctx
r = CollaborativeRecommender(ctx)
# An non-empty set of addons should give a list of recommendations
@ -158,11 +157,11 @@ def test_best_recommendation():
assert numpy.isclose(result[1], numpy.float64('0.3225'))
def test_recommendation_weights():
def test_recommendation_weights(mocked_ctx):
"""
Weights should be ordered greatest to lowest
"""
ctx = get_mocked_ctx()
ctx = mocked_ctx
r = CollaborativeRecommender(ctx)
# An non-empty set of addons should give a list of recommendations
@ -192,11 +191,11 @@ def test_recommendation_weights():
assert numpy.isclose(result[1], numpy.float64('0.29'))
def test_recommender_str():
def test_recommender_str(mocked_ctx):
"""Tests that the string representation of the recommender is correct
"""
# TODO: this test is brittle and should be removed once it is safe
# to do so
ctx = get_mocked_ctx()
ctx = mocked_ctx
r = CollaborativeRecommender(ctx)
assert str(r) == "CollaborativeRecommender"

Просмотреть файл

@ -1,4 +1,7 @@
from taar.context import Context
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from taar.cache import JSONCache, Clock
from taar.recommenders.ensemble_recommender import WeightCache, EnsembleRecommender
@ -14,9 +17,8 @@ class Mocker:
return {'ensemble_weights': EXPECTED}
def test_weight_cache(): # noqa
ctx = Context()
def test_weight_cache(test_ctx): # noqa
ctx = test_ctx
ctx['utils'] = Mocker()
ctx['clock'] = Clock()
ctx['cache'] = JSONCache(ctx)
@ -26,8 +28,8 @@ def test_weight_cache(): # noqa
assert EXPECTED == actual
def test_recommendations():
ctx = Context()
def test_recommendations(test_ctx):
ctx = test_ctx
ctx['utils'] = Mocker()
ctx['clock'] = Clock()
@ -53,8 +55,8 @@ def test_recommendations():
assert recommendation_list == EXPECTED_RESULTS
def test_preinstalled_guids():
ctx = Context()
def test_preinstalled_guids(test_ctx):
ctx = test_ctx
ctx['utils'] = Mocker()
ctx['clock'] = Clock()

Просмотреть файл

@ -1,14 +1,15 @@
import pytest
from taar.context import default_context
from taar import ProfileController, ProfileFetcher
from taar import ProfileFetcher
from taar.profile_fetcher import ProfileController
from taar import recommenders
import time
def create_recommendation_manager():
root_ctx = default_context()
client = ProfileController('us-west-2', 'taar_addon_data_20180206')
pf = ProfileFetcher(client)
pf = ProfileFetcher(root_ctx)
pf.set_client(ProfileController(root_ctx, 'us-west-2', 'taar_addon_data_20180206'))
root_ctx['profile_fetcher'] = pf
r_factory = recommenders.RecommenderFactory(root_ctx.child())
root_ctx['recommender_factory'] = r_factory

Просмотреть файл

@ -1,4 +1,8 @@
from taar.context import Context
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import pytest
from taar.cache import JSONCache, Clock
from taar.recommenders import LocaleRecommender
@ -20,16 +24,17 @@ class MockUtils:
return FAKE_LOCALE_DATA
def create_test_ctx():
ctx = Context()
@pytest.fixture
def my_context(test_ctx):
ctx = test_ctx
ctx['utils'] = MockUtils()
ctx['clock'] = Clock()
ctx['cache'] = JSONCache(ctx)
return ctx.child()
def test_can_recommend():
ctx = create_test_ctx()
def test_can_recommend(my_context):
ctx = my_context
r = LocaleRecommender(ctx)
# Test that we can't recommend if we have not enough client info.
@ -40,8 +45,8 @@ def test_can_recommend():
assert r.can_recommend({"locale": "en"})
def test_can_recommend_no_model():
ctx = create_test_ctx()
def test_can_recommend_no_model(my_context):
ctx = my_context
r = LocaleRecommender(ctx)
# We should never be able to recommend if something went
@ -51,14 +56,14 @@ def test_can_recommend_no_model():
assert not r.can_recommend({"locale": "it"})
def test_recommendations():
def test_recommendations(my_context):
"""Test that the locale recommender returns the correct
locale dependent addons.
The JSON output for this recommender should be a list of 2-tuples
of (GUID, weight).
"""
ctx = create_test_ctx()
ctx = my_context
r = LocaleRecommender(ctx)
recommendations = r.recommend({"locale": "en"}, 10)
@ -73,17 +78,17 @@ def test_recommendations():
assert addon_id in FAKE_LOCALE_DATA["en"]
def test_recommender_str():
def test_recommender_str(my_context):
"""Tests that the string representation of the recommender is correct
"""
# TODO: this test is brittle and should be removed once it is safe
# to do so
ctx = create_test_ctx()
ctx = my_context
r = LocaleRecommender(ctx)
assert str(r) == "LocaleRecommender"
def test_recommender_extra_data():
def test_recommender_extra_data(my_context):
# Test that the recommender uses locale data from the "extra"
# section if available.
def validate_recommendations(data, expected_locale):
@ -97,7 +102,7 @@ def test_recommender_extra_data():
assert addon_id in FAKE_LOCALE_DATA[expected_locale]
assert 1 == weight
ctx = create_test_ctx()
ctx = my_context
r = LocaleRecommender(ctx)
recommendations = r.recommend({}, 10, extra_data={"locale": "en"})
validate_recommendations(recommendations, "en")

Просмотреть файл

@ -1,5 +1,13 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from taar import ProfileFetcher
from taar.profile_fetcher import ProfileController
import boto3
import copy
import json
import zlib
class MockProfileController:
@ -66,3 +74,53 @@ def test_dont_crash_without_active_addons(test_ctx):
expected = copy.deepcopy(MOCK_DATA['expected_result'])
expected['installed_addons'][:] = []
assert fetcher.get("random-client-id") == expected
def test_crashy_profile_controller(test_ctx, monkeypatch):
def mock_boto3_resource(*args, **kwargs):
class ExceptionRaisingMockTable:
def __init__(self, tbl_name):
pass
def get_item(self, *args, **kwargs):
raise Exception
class MockDDB:
pass
mock_ddb = MockDDB()
mock_ddb.Table = ExceptionRaisingMockTable
return mock_ddb
monkeypatch.setattr(boto3, 'resource', mock_boto3_resource)
pc = ProfileController(test_ctx, 'us-west-2', 'taar_addon_data_20180206')
assert pc.get_client_profile("exception_raising_client_id") is None
def test_profile_controller(test_ctx, monkeypatch):
def mock_boto3_resource(*args, **kwargs):
some_bytes = zlib.compress(json.dumps({'key': "with_some_data"}).encode('utf8'))
class ValueObj:
value = some_bytes
class MockTable:
def __init__(self, tbl_name):
pass
def get_item(self, *args, **kwargs):
value_obj = ValueObj()
response = {'Item': {'json_payload': value_obj}}
return response
class MockDDB:
pass
mock_ddb = MockDDB()
mock_ddb.Table = MockTable
return mock_ddb
monkeypatch.setattr(boto3, 'resource', mock_boto3_resource)
pc = ProfileController(test_ctx, 'us-west-2', 'taar_addon_data_20180206')
jdata = pc.get_client_profile("exception_raising_client_id")
assert jdata == {'key': 'with_some_data'}

Просмотреть файл

@ -2,7 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
from taar.context import Context
from taar.cache import JSONCache, Clock
from taar.profile_fetcher import ProfileFetcher
@ -29,10 +28,13 @@ class StubRecommender(AbstractRecommender):
return self._recommendations
def get_test_ctx():
fetcher = ProfileFetcher(MockProfileController(None))
@pytest.fixture
def my_context(test_ctx):
ctx = test_ctx
fetcher = ProfileFetcher(ctx)
fetcher.set_client(MockProfileController(None))
factory = MockRecommenderFactory()
ctx = Context()
ctx['profile_fetcher'] = fetcher
ctx['recommender_factory'] = factory
@ -42,8 +44,8 @@ def get_test_ctx():
return ctx.child()
def test_none_profile_returns_empty_list():
ctx = get_test_ctx()
def test_none_profile_returns_empty_list(my_context):
ctx = my_context
ctx['clock'] = Clock()
ctx['cache'] = JSONCache(ctx)
rec_manager = RecommendationManager(ctx)
@ -58,8 +60,8 @@ def test_intervention_b():
def test_recommendations_via_manager(): # noqa
ctx = get_test_ctx()
def test_recommendations_via_manager(my_context): # noqa
ctx = my_context
EXPECTED_RESULTS = [('ghi', 3430.0),
('def', 3320.0),

Просмотреть файл

@ -5,10 +5,10 @@
import json
import six
import pytest
import numpy as np
import scipy.stats
from taar.context import Context
from taar.cache import JSONCache, Clock
from taar.recommenders.similarity_recommender import \
@ -84,25 +84,27 @@ class MockContinuousData:
return self.lrs_data
def create_cat_test_ctx():
ctx = Context()
@pytest.fixture
def cat_test_ctx(test_ctx):
ctx = test_ctx
ctx['utils'] = MockCategoricalData()
ctx['clock'] = Clock()
ctx['cache'] = JSONCache(ctx)
return ctx.child()
def create_cts_test_ctx():
ctx = Context()
@pytest.fixture
def cts_test_ctx(test_ctx):
ctx = test_ctx
ctx['utils'] = MockContinuousData()
ctx['clock'] = Clock()
ctx['cache'] = JSONCache(ctx)
return ctx.child()
def test_soft_fail():
def test_soft_fail(test_ctx):
# Create a new instance of a SimilarityRecommender.
ctx = Context()
ctx = test_ctx
ctx['utils'] = MockNoDataUtils()
ctx['clock'] = Clock()
ctx['cache'] = JSONCache(ctx)
@ -112,9 +114,9 @@ def test_soft_fail():
assert not r.can_recommend({})
def test_can_recommend():
def test_can_recommend(cts_test_ctx):
# Create a new instance of a SimilarityRecommender.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
# Test that we can't recommend if we have not enough client info.
@ -138,9 +140,9 @@ def test_can_recommend():
assert not r.can_recommend(profile_without_x)
def test_recommendations():
def test_recommendations(cts_test_ctx):
# Create a new instance of a SimilarityRecommender.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
# TODO: clobber the SimilarityRecommender::lr_curves
@ -157,25 +159,25 @@ def test_recommendations():
assert type(weight) == np.float64
def test_recommender_str():
def test_recommender_str(cts_test_ctx):
# Tests that the string representation of the recommender is correct.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
assert str(r) == "SimilarityRecommender"
def test_get_lr():
def test_get_lr(cts_test_ctx):
# Tests that the likelihood ratio values are not empty for extreme values and are realistic.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
assert r.get_lr(0.0001) is not None
assert r.get_lr(10.0) is not None
assert r.get_lr(0.001) > r.get_lr(5.0)
def test_compute_clients_dist():
def test_compute_clients_dist(cts_test_ctx):
# Test the distance function computation.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
test_clients = [
{
@ -227,9 +229,9 @@ def test_compute_clients_dist():
assert per_client_test[0] >= per_client_test[1] >= per_client_test[2]
def test_distance_functions():
def test_distance_functions(cts_test_ctx):
# Tests the similarity functions via expected output when passing modified client data.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
# Generate a fake client.
@ -269,9 +271,9 @@ def test_distance_functions():
assert abs((j_c + 0.01) * j_d) != 0.0
def test_weights_continuous():
def test_weights_continuous(cts_test_ctx):
# Create a new instance of a SimilarityRecommender.
ctx = create_cts_test_ctx()
ctx = cts_test_ctx
r = SimilarityRecommender(ctx)
# In the ensemble method recommendations should be a sorted list of tuples
@ -301,7 +303,7 @@ def test_weights_continuous():
assert rec0_weight > rec1_weight > 1.0
def test_weights_categorical():
def test_weights_categorical(cat_test_ctx, cts_test_ctx):
'''
This should get :
["{test-guid-1}", "{test-guid-2}", "{test-guid-3}", "{test-guid-4}"],
@ -311,8 +313,8 @@ def test_weights_categorical():
'''
# Create a new instance of a SimilarityRecommender.
ctx = create_cat_test_ctx()
ctx2 = create_cts_test_ctx()
ctx = cat_test_ctx
ctx2 = cts_test_ctx
wrapped = ctx2.wrap(ctx)
r = SimilarityRecommender(wrapped)