diff --git a/gittip/testing/__init__.py b/gittip/testing/__init__.py index 779f70b126..815623c14b 100644 --- a/gittip/testing/__init__.py +++ b/gittip/testing/__init__.py @@ -8,6 +8,7 @@ from os.path import join, dirname, realpath import pytz +import vcr from aspen import resources from aspen.testing.client import Client from gittip.billing.payday import Payday @@ -21,6 +22,7 @@ SCHEMA = open(join(TOP, "schema.sql")).read() WWW_ROOT = str(realpath(join(TOP, 'www'))) PROJECT_ROOT = str(TOP) +FIXTURES_ROOT = join(TOP, 'tests', 'fixtures') DUMMY_GITHUB_JSON = u'{"html_url":"https://github.com/whit537","type":"User",'\ @@ -106,6 +108,32 @@ def setUpClass(cls): cls.tablenames = cls.db.all("SELECT tablename FROM pg_tables " "WHERE schemaname='public'") cls.seq = 0 + cls.setUpVCR() + + + @classmethod + def setUpVCR(cls): + """Set up VCR. + + We use the VCR library to freeze API calls. Frozen calls are stored in + tests/fixtures/ for your convenience (otherwise your first test run + would take fooooorrr eeeevvveeerrrr). If you find that an API call has + drifted from our frozen version of it, simply remove that fixture file + and rerun. The VCR library should recreate the fixture with the new + information, and you can commit that with your updated tests. + + """ + cls.vcr = vcr.VCR( + cassette_library_dir = FIXTURES_ROOT, + record_mode = 'once', + match_on = ['url', 'method'], + ) + cls.vcr_cassette = cls.vcr.use_cassette('{}.yml'.format(cls.__name__)).__enter__() + + + @classmethod + def tearDownClass(cls): + cls.vcr_cassette.__exit__(None, None, None) def setUp(self): diff --git a/tests/fixtures/TestPages.yml b/tests/fixtures/TestPages.yml new file mode 100644 index 0000000000..4e6dafd9db --- /dev/null +++ b/tests/fixtures/TestPages.yml @@ -0,0 +1,52 @@ +- request: !!python/object:vcr.request.Request + body: null + headers: !!python/object/apply:__builtin__.frozenset + - - !!python/tuple [Accept-Encoding, 'gzip, deflate, compress'] + - !!python/tuple [Accept, '*/*'] + - !!python/tuple [Authorization, 'OAuth oauth_nonce="137591929179705732001392910038", + oauth_timestamp="1392910038", oauth_version="1.0", oauth_signature_method="HMAC-SHA1", + oauth_consumer_key="QBB9vEhxO4DFiieRF68zTA", oauth_token="34175404-G6W8Hh19GWuUhIMEXK0LyZsy7N9aCMcy1bYJ9rI", + oauth_signature="rgGWI%2F9gk8cryBIMurDwLG3X3lI%3D"'] + - !!python/tuple [User-Agent, python-requests/1.2.3 CPython/2.7.5 Darwin/12.5.0] + host: api.twitter.com + method: GET + path: /1.1/users/show.json?screen_name=twitter + port: 443 + protocol: https + response: + body: + string: !!binary | + H4sIAAAAAAAAAOxXbW/bNhD+K4QG7AXTbL1ZsgwMW5csaFEMGJqsxVAFAiWdbSYyqZCUHS/If99R + suT3reuGDgPmfIh59xx5vHvujn6yWGFNorHvuYGN31OlpTWxWoFlW5wuANc3K6Y1SBSoXALwdCPX + vbwUOdVMcBReU06uJOU5U7mwycULVBeAhqzaIH4VtSRiOmU5oyVRuMqBTIUkHFbKJnVVUA2KUF4Q + zSpFplIsyMYHm7zi+QC3rGWJW821ribJMBnqQS6S4Yi9ma+j1c2sRgRwzTQDZU2eWnTzD5fvnz7E + +rFCB6BID6BZKWaDzcXRapEMzf2Yqkq63mAPIQhgvGC5ceW9Y3ve7fPt80FQet9un1FVSaEh14DJ + mdJSgW1NRVmKFUiV5qLm2pp44zgcOeEYVZIBL3qF67uYD6bQuhON/ZGLQswdNVKqTU5rIFeQEc8h + bjDxR5NRQL528IMSJ0KXp3SJmWGYif7IEMOu8xRTpwDX33jjsePYlmYLSH8T3FDiZ5ozTCy5QRn5 + 8pdr8jm5oJwW9CvccgYiBU6z0lxMyxrvtQSJ+O1aaaprtT3TjTwPr0P5DDcHbnUIE7G9+7yDormP + 6xHPnzjjSTDq79Nw2TA98P3Ij4Mo9vwocMLIc3ZYf6xEKw2PZvc3N+T7DQOvKyG1mpB38IUEUivG + Z+Qt40C0IGpOUWbofS3yOSPwmGMAF8jEAXkpVqQQRM+h8YjMsIYUYVxVDG3Wov6OXM8R09AeypLg + cXPyWbORMRgk3JBQTZLac7zQRKKpHPQuqR3HzymZS5h+m1gbGJKVZqLW+2xFahV1rhWSfgWgC8jv + E4tIKNGQi5ZmSbsj3BjEpUE0B+B+rdzERdY8p7sMZTyVUJXrVIu0zVFqQs7rsjyjbON+DMD8yzO2 + G9U5y7321KqRc93XXAhZMG6aSyfCqs1hq+dasqzWQvYACU2YoEj/nHdujFWJ1DvJu3Dsx6Hrx67n + O3EU7vPuQLnl3b9Hsr4rvg7u3t5x55V2/qfcp6Rc1wEDJ26bsenFfSuOR/sDbk7VXNNZO9025Omz + ujeAXMezXdfMIEznepGJduzYp4bjWR6cmI4tdokkbeDLZPhT9INe3M3i8vXqaEaex+14io8S148a + T5ssGI7jtGzH5DYoW0L01dpLKqEUyzBVCrjCaC2hV22HyvOHBd356JB7Ll7E/S+E3I9tN3BOhvzp + 4PW3Nw+PHoukl5uy8rGGYyTt7rztZXse+LYbte+jfzK9u3W2fYJ0bUSlGh+sqqSoPiXFABwZYVOb + shLSjOb3M4kEMa+t0thbLy4uf7w0TfwEhi3oDA7flFWmTMdczPp+edIMG2g4ipzYcUIvGZZu/QDr + kVqPPRmzu/k9uGxQ4Z3/+Ny0Ic4egT7B8RrX3ROvU/+VUHQOeN44cKMgGo2RxuFIUBZNH3kQPSxj + jg/mx5QLuaDlgSMfcfm/d2BGOcfiOazUs4E2aDys/d2VDF0/wBfoyPeinT1Lxu97inleGMbxjlax + AjIq0wznDZ7c4a6azwkcLsotKjR/OyjTzXqt33x2tNgYjsjRJbeAKa1LnW6wfbkcyDujvV83zBTs + ngTH7EMNSpvy1r2OC21+Y9BNY2qkz78DAAD//wMAZp5YTcsOAAA= + headers: ["cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0\r\n", + "content-encoding: gzip\r\n", "content-length: 1235\r\n", "content-type: application/json;charset=utf-8\r\n", + "date: Thu, 20 Feb 2014 15:27:18 GMT\r\n", "expires: Tue, 31 Mar 1981 05:00:00 + GMT\r\n", "last-modified: Thu, 20 Feb 2014 15:27:18 GMT\r\n", "pragma: no-cache\r\n", + "server: tfe\r\n", "set-cookie: lang=en\r\n", "set-cookie: guest_id=v1%3A139291003823273009; + Domain=.twitter.com; Path=/; Expires=Sat, 20-Feb-2016 15:27:18 UTC\r\n", "status: + 200 OK\r\n", "strict-transport-security: max-age=631138519\r\n", "x-access-level: + read\r\n", "x-content-type-options: nosniff\r\n", "x-frame-options: SAMEORIGIN\r\n", + "x-rate-limit-limit: 180\r\n", "x-rate-limit-remaining: 177\r\n", "x-rate-limit-reset: + 1392910100\r\n", "x-transaction: d7a88e315048b4b4\r\n", "x-xss-protection: + 1; mode=block\r\n"] + status: {code: 200, message: OK} diff --git a/tests/test_billing.py b/tests/test_billing.py index 73a74b9a5c..d11fb44a9a 100644 --- a/tests/test_billing.py +++ b/tests/test_billing.py @@ -1,10 +1,7 @@ from __future__ import unicode_literals -import os - import balanced import mock -import vcr from gittip import billing from gittip.security import authentication @@ -13,12 +10,6 @@ def setUp_balanced(o): - o.vcr = vcr.VCR( - cassette_library_dir = os.path.dirname(os.path.realpath(__file__)) + '/fixtures/', - record_mode = 'once', - match_on = ['url', 'method'], - ) - o.vcr_cassette = o.vcr.use_cassette('{}.yml'.format(o.__name__)).__enter__() o.balanced_api_key = balanced.APIKey().save().secret balanced.configure(o.balanced_api_key) mp = balanced.Marketplace.my_marketplace @@ -53,10 +44,6 @@ def setUp_balanced_resources(o): ).save().href) -def tearDown_balanced(o): - o.vcr_cassette.__exit__(None, None, None) - - class TestBillingBase(Harness): @classmethod @@ -64,11 +51,6 @@ def setUpClass(cls): super(TestBillingBase, cls).setUpClass() setUp_balanced(cls) - @classmethod - def tearDownClass(cls): - tearDown_balanced(cls) - super(TestBillingBase, cls).tearDownClass() - def setUp(self): Harness.setUp(self) setUp_balanced_resources(self) @@ -86,10 +68,6 @@ def setUp(self): Harness.setUp(self) setUp_balanced_resources(self) - @classmethod - def tearDownClass(cls): - tearDown_balanced(cls) - super(TestBalancedCard, cls).tearDownClass() def test_balanced_card_basically_works(self): balanced.Card.fetch(self.card_href) \ @@ -197,11 +175,6 @@ def setUp(self): Harness.setUp(self) setUp_balanced_resources(self) - @classmethod - def tearDownClass(cls): - tearDown_balanced(cls) - super(TestBalancedBankAccount, cls).tearDownClass() - def test_balanced_bank_account(self): balanced.BankAccount.fetch(self.bank_account_href)\ diff --git a/tests/test_pages.py b/tests/test_pages.py index 480d6bf817..d30486b863 100644 --- a/tests/test_pages.py +++ b/tests/test_pages.py @@ -85,7 +85,6 @@ def test_github_proxy(self, requests): actual = self.client.GET('/on/github/lgtest/').body.decode('utf8') assert expected in actual - # This hits the network. XXX add a knob to skip this def test_twitter_proxy(self): expected = "Twitter has not joined" actual = self.client.GET('/on/twitter/twitter/').body.decode('utf8')