Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.

Commit fd71593

Browse files
committed
Merge pull request #406 from Yelp/sclark_36_testify_to_pytest
Moved from testify to pytest
2 parents 26ae969 + 7a9b1e1 commit fd71593

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+382
-612
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* Changes
66

7+
* Switched from `testify` to `py.test` - http://pytest.org/ (#36)
78
* [cleanup] Moved bandits into their own sub directories (#375)
89

910
* Bugs

Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ production:
88
python setup.py install
99

1010
test:
11-
testify -v --exclude-suite=disabled moe.tests
12-
testify -v --exclude-suite=disabled moe_examples.tests
11+
py.test -v moe/tests moe_examples/tests
1312

1413
style-test:
1514
pip install flake8 flake8-import-order pep8-naming flake8-docstrings pyflakes

docs/contributing.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ MOE uses ``doxygen`` (http://www.stack.nl/~dimitri/doxygen) to extract the C++ d
159159
Testing
160160
-------
161161

162-
MOE currently uses ``testify`` (https://github.com/Yelp/Testify) to run all unit and integration tests.
162+
MOE currently uses ``pytest`` (http://pytest.org/) to run all unit and integration tests.
163163

164164
Tests can be run using ``make test``. Continuous integration testing is provided by http://travis-ci.org. All builds are tested in a fresh ubuntu VM and need to be passing before being pulled into master.
165165

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
11
# -*- coding: utf-8 -*-
22
"""Test bandit interface implementation."""
3-
import logging
3+
import pytest
44

5-
import testify as T
5+
import logging
66

77
from moe.bandit.bandit_interface import BanditInterface
88
from moe.tests.bandit.bandit_test_case import BanditTestCase
99

1010

11-
class BanditInterfaceTest(BanditTestCase):
12-
13-
"""Verify that different historical infos return correct results."""
14-
15-
@T.class_setup
16-
def disable_logging(self):
17-
"""Disable logging (for the duration of this test case)."""
18-
logging.disable(logging.CRITICAL)
11+
@pytest.fixture()
12+
def disable_logging(request):
13+
"""Disable logging (for the duration of this test case)."""
14+
logging.disable(logging.CRITICAL)
1915

20-
@T.class_teardown
21-
def enable_logging(self):
16+
def finalize():
2217
"""Re-enable logging (so other test cases are unaffected)."""
2318
logging.disable(logging.NOTSET)
19+
request.addfinalizer(finalize)
2420

21+
22+
class TestBanditInterface(BanditTestCase):
23+
24+
"""Verify that different historical infos return correct results."""
25+
26+
@pytest.mark.usefixtures("disable_logging")
2527
def test_empty_arm_invalid(self):
2628
"""Test empty ``arms_to_allocations`` causes an ValueError."""
27-
T.assert_raises(ValueError, BanditInterface.choose_arm, {})
29+
with pytest.raises(ValueError):
30+
BanditInterface.choose_arm({})
2831

2932
def test_one_arm(self):
3033
"""Check that the one-arm case always returns the given arm as the winning arm."""
3134
arms_to_allocations = {"arm1": 1.0}
32-
T.assert_equal(BanditInterface.choose_arm(arms_to_allocations), "arm1")
35+
assert BanditInterface.choose_arm(arms_to_allocations) == "arm1"
3336

3437
def test_two_arms_one_winner(self):
3538
"""Check that the two-arms case with one winner always returns the winning arm."""
3639
arms_to_allocations = {"arm1": 1.0, "arm2": 0.0}
37-
T.assert_equal(BanditInterface.choose_arm(arms_to_allocations), "arm1")
40+
assert BanditInterface.choose_arm(arms_to_allocations) == "arm1"
3841

3942
def test_three_arms_two_winners(self):
4043
"""Check that the three-arms cases with two winners return one of the two winners."""
4144
arms_to_allocations = {"arm1": 0.5, "arm2": 0.5, "arm3": 0.0}
42-
T.assert_in(BanditInterface.choose_arm(arms_to_allocations), frozenset(["arm1", "arm2"]))
43-
44-
if __name__ == "__main__":
45-
T.run()
45+
assert BanditInterface.choose_arm(arms_to_allocations) in frozenset(["arm1", "arm2"])

moe/tests/bandit/bandit_test_case.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
# -*- coding: utf-8 -*-
22
"""Base test case class for bandit tests; includes different historical infos (different sampled arms)."""
3-
import testify as T
4-
53
from moe.bandit.data_containers import BernoulliArm, HistoricalData, SampleArm
64

75

8-
class BanditTestCase(T.TestCase):
6+
class BanditTestCase(object):
97

108
"""Base test case for the bandit library.
119
@@ -51,5 +49,5 @@ def _test_one_arm(self, bandit):
5149
"""Check that the one-arm case always returns the given arm as the winning arm and the allocation is 1.0."""
5250
bandit = self.bandit_class(self.one_arm_test_case)
5351
arms_to_allocations = bandit.allocate_arms()
54-
T.assert_dicts_equal(arms_to_allocations, {"arm1": 1.0})
55-
T.assert_equal(bandit.choose_arm(arms_to_allocations), "arm1")
52+
assert arms_to_allocations == {"arm1": 1.0}
53+
assert bandit.choose_arm(arms_to_allocations) == "arm1"

moe/tests/bandit/bla/bla_test.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
# -*- coding: utf-8 -*-
32
"""Test UCB1 bandit implementation.
43
54
Test that the one arm case returns the given arm as the winning arm.
@@ -8,14 +7,12 @@
87
"""
98
import numpy
109

11-
import testify as T
12-
1310
from moe.bandit.bla.bla import BLA
1411
from moe.bandit.constant import DEFAULT_BLA_SUBTYPE
1512
from moe.tests.bandit.bandit_test_case import BanditTestCase
1613

1714

18-
class BLATest(BanditTestCase):
15+
class TestBLA(BanditTestCase):
1916

2017
"""Verify that different historical infos return correct results."""
2118

@@ -32,10 +29,6 @@ def test_two_arms_one_winner(self):
3229
numpy.random.seed(0)
3330
bandit = self.bandit_class(self.two_arms_test_case, DEFAULT_BLA_SUBTYPE)
3431
arms_to_allocations = bandit.allocate_arms()
35-
T.assert_dicts_equal(arms_to_allocations, {"arm1": 1.0, "arm2": 0.0})
36-
T.assert_equal(bandit.choose_arm(arms_to_allocations), "arm1")
32+
assert arms_to_allocations == {"arm1": 1.0, "arm2": 0.0}
33+
assert bandit.choose_arm(arms_to_allocations) == "arm1"
3734
numpy.random.set_state(old_state)
38-
39-
40-
if __name__ == "__main__":
41-
T.run()
Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,53 @@
11
# -*- coding: utf-8 -*-
22
"""Tests for functions in SampleArm and HistoricalData."""
3-
import copy
3+
import pytest
44

5+
import copy
56
import logging
6-
77
import pprint
88

9-
import testify as T
10-
119
from moe.bandit.data_containers import HistoricalData, SampleArm
1210
from moe.tests.bandit.bandit_test_case import BanditTestCase
1311

1412

15-
class DataContainersTest(BanditTestCase):
13+
@pytest.fixture()
14+
def disable_logging(request):
15+
"""Disable logging (for the duration of this test case)."""
16+
logging.disable(logging.CRITICAL)
1617

17-
"""Tests functions in :class:`moe.bandit.data_containers.SampleArm` and :class:`moe.bandit.data_containers.HistoricalData`."""
18-
19-
@T.class_setup
20-
def disable_logging(self):
21-
"""Disable logging (for the duration of this test case)."""
22-
logging.disable(logging.CRITICAL)
23-
24-
@T.class_teardown
25-
def enable_logging(self):
18+
def finalize():
2619
"""Re-enable logging (so other test cases are unaffected)."""
2720
logging.disable(logging.NOTSET)
21+
request.addfinalizer(finalize)
22+
23+
24+
class TestDataContainers(BanditTestCase):
25+
26+
"""Tests functions in :class:`moe.bandit.data_containers.SampleArm` and :class:`moe.bandit.data_containers.HistoricalData`."""
2827

2928
def test_sample_arm_str(self):
3029
"""Test SampleArm's __str__ overload operator."""
3130
for historical_info in self.historical_infos_to_test:
3231
for arm in historical_info.arms_sampled.itervalues():
33-
T.assert_equals(str(arm), pprint.pformat(arm.json_payload()))
32+
assert str(arm) == pprint.pformat(arm.json_payload())
3433

3534
def test_sample_arm_add(self):
3635
"""Test SampleArm's __add__ overload operator."""
3736
arm1 = SampleArm(win=2, loss=1, total=3)
3837
arm2 = SampleArm(win=3, loss=2, total=5)
3938
arm3 = arm1 + arm2
40-
T.assert_equals(arm3.json_payload(), SampleArm(win=5, loss=3, total=8).json_payload())
39+
assert arm3.json_payload() == SampleArm(win=5, loss=3, total=8).json_payload()
40+
4141
# Verify that the + operator does not modify arm1 and arm2
42-
T.assert_equals(arm1.json_payload(), SampleArm(win=2, loss=1, total=3).json_payload())
43-
T.assert_equals(arm2.json_payload(), SampleArm(win=3, loss=2, total=5).json_payload())
42+
assert arm1.json_payload() == SampleArm(win=2, loss=1, total=3).json_payload()
43+
assert arm2.json_payload() == SampleArm(win=3, loss=2, total=5).json_payload()
4444

4545
arm1 += arm2
4646
arm2 += arm1
47-
T.assert_equals(arm1.json_payload(), SampleArm(win=5, loss=3, total=8).json_payload())
48-
T.assert_equals(arm2.json_payload(), SampleArm(win=8, loss=5, total=13).json_payload())
47+
assert arm1.json_payload() == SampleArm(win=5, loss=3, total=8).json_payload()
48+
assert arm2.json_payload() == SampleArm(win=8, loss=5, total=13).json_payload()
4949
# Verify that modifying arm1 and arm2 does not change arm3
50-
T.assert_equals(arm3.json_payload(), SampleArm(win=5, loss=3, total=8).json_payload())
50+
assert arm3.json_payload() == SampleArm(win=5, loss=3, total=8).json_payload()
5151

5252
def test_sample_arm_iadd(self):
5353
"""Test SampleArm's __iadd__ overload operator.
@@ -61,29 +61,30 @@ def test_sample_arm_iadd(self):
6161
arm1_old_id = id(arm1)
6262
arm1 += arm2
6363
arm1_new_id = id(arm1)
64-
T.assert_equals(arm1_old_id, arm1_new_id)
65-
T.assert_equals(arm1.json_payload(), arm3.json_payload())
64+
assert arm1_old_id == arm1_new_id
65+
assert arm1.json_payload() == arm3.json_payload()
6666

67+
@pytest.mark.usefixtures("disable_logging")
6768
def test_sample_arm_add_arm_with_variance_invalid(self):
6869
"""Test that adding arms with variance causes a ValueError. Neither of the arms can have non-None variance."""
69-
arm = SampleArm(win=2, loss=1, total=500, variance=0.1)
70-
T.assert_raises(ValueError, arm.__add__, SampleArm(win=2, loss=1, total=500, variance=None))
71-
arm = SampleArm(win=2, loss=1, total=500, variance=None)
72-
T.assert_raises(ValueError, arm.__add__, SampleArm(win=2, loss=1, total=500, variance=0.1))
70+
with pytest.raises(ValueError):
71+
arm = SampleArm(win=2, loss=1, total=500, variance=0.1)
72+
arm.__add__(SampleArm(win=2, loss=1, total=500, variance=None))
73+
74+
with pytest.raises(ValueError):
75+
arm = SampleArm(win=2, loss=1, total=500, variance=None)
76+
arm.__add__(SampleArm(win=2, loss=1, total=500, variance=0.1))
7377

7478
def test_historical_data_str(self):
7579
"""Test HistoricalData's __str__ overload operator."""
7680
for historical_info in self.historical_infos_to_test:
77-
T.assert_equals(str(historical_info), pprint.pformat(historical_info.json_payload()))
81+
assert str(historical_info) == pprint.pformat(historical_info.json_payload())
7882

7983
def test_historical_data_append_unsampled_arm(self):
8084
"""Test that adding an unsampled arm (already exists in historical info) to HistoricalData does not change anything."""
8185
historical_info = self.two_unsampled_arms_test_case
8286
historical_info.append_sample_arms(self.one_arm_test_case.arms_sampled)
83-
T.assert_dicts_equal(
84-
historical_info.json_payload(),
85-
self.two_unsampled_arms_test_case.json_payload()
86-
)
87+
assert historical_info.json_payload() == self.two_unsampled_arms_test_case.json_payload()
8788

8889
def test_historical_data_append_arms(self):
8990
"""Test that appending arms to HistoricalData updates historical info correctly."""
@@ -96,20 +97,13 @@ def test_historical_data_append_arms(self):
9697
"arm3": SampleArm(win=0, loss=0, total=0),
9798
}
9899
)
99-
T.assert_dicts_equal(
100-
historical_info.json_payload(),
101-
expected_historical_info.json_payload()
102-
)
100+
assert historical_info.json_payload() == expected_historical_info.json_payload()
103101

102+
@pytest.mark.usefixtures("disable_logging")
104103
def test_historical_data_append_arms_with_variance_invalid(self):
105104
"""Test that adding arms with variance causes a ValueError."""
106105
historical_info = copy.deepcopy(self.three_arms_with_variance_no_unsampled_arm_test_case)
107-
T.assert_raises(
108-
ValueError,
109-
historical_info.append_sample_arms,
110-
self.three_arms_with_variance_no_unsampled_arm_test_case.arms_sampled
111-
)
112-
113-
114-
if __name__ == "__main__":
115-
T.run()
106+
with pytest.raises(ValueError):
107+
historical_info.append_sample_arms(
108+
self.three_arms_with_variance_no_unsampled_arm_test_case.arms_sampled
109+
)

moe/tests/bandit/epsilon/epsilon_first_test.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
Test one arm with various epsilon values.
66
77
"""
8-
import testify as T
9-
108
from moe.bandit.epsilon.epsilon_first import EpsilonFirst
119
from moe.tests.bandit.epsilon.epsilon_test_case import EpsilonTestCase
1210

1311

14-
class EpsilonFirstTest(EpsilonTestCase):
12+
class TestEpsilonFirst(EpsilonTestCase):
1513

1614
"""Verify that different epsilon values and historical infos return correct results."""
1715

@@ -35,21 +33,21 @@ def test_two_unsampled_arms(self):
3533
for epsilon in self.epsilons_to_test:
3634
for total_samples in self.total_samples_to_test:
3735
bandit = self.bandit_class(self.two_unsampled_arms_test_case, epsilon, total_samples)
38-
T.assert_dicts_equal(bandit.allocate_arms(), {"arm1": 0.5, "arm2": 0.5})
36+
assert bandit.allocate_arms() == {"arm1": 0.5, "arm2": 0.5}
3937

4038
def test_two_arms_epsilon_zero(self):
4139
"""Check that the two-arms case with zero epsilon (always exploit) always allocate arm1:1.0 and arm2:0.0 when average payoffs are arm1:1.0 and arm2:0.0."""
4240
epsilon = 0.0
4341
bandit = self.bandit_class(self.two_arms_test_case, epsilon)
4442
arms_to_allocations = bandit.allocate_arms()
45-
T.assert_dicts_equal(arms_to_allocations, {"arm1": 1.0, "arm2": 0.0})
46-
T.assert_equal(bandit.choose_arm(arms_to_allocations), "arm1")
43+
assert arms_to_allocations == {"arm1": 1.0, "arm2": 0.0}
44+
assert bandit.choose_arm(arms_to_allocations) == "arm1"
4745

4846
def test_two_arms_epsilon_one(self):
4947
"""Check that the two-arms case with one epsilon (always explore) always allocate arm1:0.5 and arm2:0.5 when average payoffs are arm1:1.0 and arm2:0.0."""
5048
epsilon = 1.0
5149
bandit = self.bandit_class(self.two_arms_test_case, epsilon)
52-
T.assert_dicts_equal(bandit.allocate_arms(), {"arm1": 0.5, "arm2": 0.5})
50+
assert bandit.allocate_arms() == {"arm1": 0.5, "arm2": 0.5}
5351

5452
def test_three_arms_explore(self):
5553
"""Check that the three-arms cases with integer and float payoffs in exploration phase return the expected arm allocations."""
@@ -58,23 +56,19 @@ def test_three_arms_explore(self):
5856
equal_allocation = 1.0 / 3
5957
for historical_info in [self.three_arms_test_case, self.three_arms_float_payoffs_test_case]:
6058
bandit = self.bandit_class(historical_info, epsilon, total_samples)
61-
T.assert_dicts_equal(bandit.allocate_arms(), {"arm1": equal_allocation, "arm2": equal_allocation, "arm3": equal_allocation})
59+
assert bandit.allocate_arms() == {"arm1": equal_allocation, "arm2": equal_allocation, "arm3": equal_allocation}
6260

6361
def test_three_arms_exploit(self):
6462
"""Check that the three-arms cases with integer and float payoffs in exploitation phase return the expected arm allocations."""
6563
epsilon = 0.5
6664
total_samples = 10
6765
for historical_info in [self.three_arms_test_case, self.three_arms_float_payoffs_test_case]:
6866
bandit = self.bandit_class(historical_info, epsilon, total_samples)
69-
T.assert_dicts_equal(bandit.allocate_arms(), {"arm1": 1.0, "arm2": 0.0, "arm3": 0.0})
67+
assert bandit.allocate_arms() == {"arm1": 1.0, "arm2": 0.0, "arm3": 0.0}
7068

7169
def test_three_arms_exploit_two_winners(self):
7270
"""Check that the three-arms cases with two winners in exploitation phase return the expected arm allocations. This tests num_arms > num_winning_arms > 1."""
7371
epsilon = 0.5
7472
total_samples = 10
7573
bandit = self.bandit_class(self.three_arms_two_winners_test_case, epsilon, total_samples)
76-
T.assert_dicts_equal(bandit.allocate_arms(), {"arm1": 0.5, "arm2": 0.5, "arm3": 0.0})
77-
78-
79-
if __name__ == "__main__":
80-
T.run()
74+
assert bandit.allocate_arms() == {"arm1": 0.5, "arm2": 0.5, "arm3": 0.0}

0 commit comments

Comments
 (0)