mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-08 16:53:23 +00:00
Add unmodified vcrpy-unittest code
Source commit is a2fd7625fde1ea15c8982759b07007aef40424b3. License is MIT just like vcrpy.
This commit is contained in:
@@ -92,9 +92,72 @@ all
|
||||
Unittest Integration
|
||||
--------------------
|
||||
|
||||
While it's possible to use the context manager or decorator forms with unittest,
|
||||
there's also a ``VCRTestCase`` provided separately by `vcrpy-unittest
|
||||
<https://github.com/agriffis/vcrpy-unittest>`__.
|
||||
Inherit from ``VCRTestCase`` for automatic recording and playback of HTTP
|
||||
interactions.
|
||||
|
||||
.. code:: python
|
||||
|
||||
from vcr_unittest import VCRTestCase
|
||||
import requests
|
||||
|
||||
class MyTestCase(VCRTestCase):
|
||||
def test_something(self):
|
||||
response = requests.get('http://example.com')
|
||||
|
||||
Similar to how VCR.py returns the cassette from the context manager,
|
||||
``VCRTestCase`` makes the cassette available as ``self.cassette``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
self.assertEqual(len(self.cassette), 1)
|
||||
self.assertEqual(self.cassette.requests[0].uri, 'http://example.com')
|
||||
|
||||
By default cassettes will be placed in the ``cassettes`` subdirectory next to the
|
||||
test, named according to the test class and method. For example, the above test
|
||||
would read from and write to ``cassettes/MyTestCase.test_something.yaml``
|
||||
|
||||
The configuration can be modified by overriding methods on your subclass:
|
||||
``_get_vcr_kwargs``, ``_get_cassette_library_dir`` and ``_get_cassette_name``.
|
||||
To modify the ``VCR`` object after instantiation, for example to add a matcher,
|
||||
you can hook on ``_get_vcr``, for example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
class MyTestCase(VCRTestCase):
|
||||
def _get_vcr(self, **kwargs):
|
||||
myvcr = super(MyTestCase, self)._get_vcr(**kwargs)
|
||||
myvcr.register_matcher('mymatcher', mymatcher)
|
||||
myvcr.match_on = ['mymatcher']
|
||||
return myvcr
|
||||
|
||||
See
|
||||
`the source
|
||||
<https://github.com/agriffis/vcrpy-unittest/blob/master/vcr_unittest/testcase.py>`__
|
||||
for the default implementations of these methods, and `VCR.py`_ for more
|
||||
information.
|
||||
|
||||
If you implement a ``setUp`` method on your test class then make sure to call the parent version ``super().setUp()`` in your own in order to continue getting the cassettes produced.
|
||||
|
||||
VCRMixin
|
||||
~~~~~~~~
|
||||
|
||||
In case inheriting from ``VCRTestCase`` is difficult because of an existing
|
||||
class hierarchy containing tests in the base classes, inherit from ``VCRMixin``
|
||||
instead.
|
||||
|
||||
.. code:: python
|
||||
|
||||
from vcr_unittest import VCRMixin
|
||||
import requests
|
||||
import unittest
|
||||
|
||||
class MyTestMixin(VCRMixin):
|
||||
def test_something(self):
|
||||
response = requests.get(self.url)
|
||||
|
||||
class MyTestCase(MyTestMixin, unittest.TestCase):
|
||||
url = 'http://example.com'
|
||||
|
||||
|
||||
Pytest Integration
|
||||
------------------
|
||||
|
||||
1
vcr/unittest/__init__.py
Normal file
1
vcr/unittest/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .testcase import VCRMixin, VCRTestCase
|
||||
44
vcr/unittest/testcase.py
Normal file
44
vcr/unittest/testcase.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
import unittest
|
||||
import vcr
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VCRMixin(object):
|
||||
"""A TestCase mixin that provides VCR integration."""
|
||||
vcr_enabled = True
|
||||
|
||||
def setUp(self):
|
||||
super(VCRMixin, self).setUp()
|
||||
if self.vcr_enabled:
|
||||
kwargs = self._get_vcr_kwargs()
|
||||
myvcr = self._get_vcr(**kwargs)
|
||||
cm = myvcr.use_cassette(self._get_cassette_name())
|
||||
self.cassette = cm.__enter__()
|
||||
self.addCleanup(cm.__exit__, None, None, None)
|
||||
|
||||
def _get_vcr(self, **kwargs):
|
||||
if 'cassette_library_dir' not in kwargs:
|
||||
kwargs['cassette_library_dir'] = self._get_cassette_library_dir()
|
||||
return vcr.VCR(**kwargs)
|
||||
|
||||
def _get_vcr_kwargs(self, **kwargs):
|
||||
return kwargs
|
||||
|
||||
def _get_cassette_library_dir(self):
|
||||
testdir = os.path.dirname(inspect.getfile(self.__class__))
|
||||
return os.path.join(testdir, 'cassettes')
|
||||
|
||||
def _get_cassette_name(self):
|
||||
return '{0}.{1}.yaml'.format(self.__class__.__name__,
|
||||
self._testMethodName)
|
||||
|
||||
|
||||
class VCRTestCase(VCRMixin, unittest.TestCase):
|
||||
pass
|
||||
0
vcr/unittest/tests/__init__.py
Normal file
0
vcr/unittest/tests/__init__.py
Normal file
188
vcr/unittest/tests/test_testcase.py
Normal file
188
vcr/unittest/tests/test_testcase.py
Normal file
@@ -0,0 +1,188 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import os
|
||||
from mock import MagicMock as Mock
|
||||
from unittest import defaultTestLoader, TextTestRunner
|
||||
from vcr_unittest import VCRTestCase
|
||||
|
||||
try:
|
||||
from urllib2 import urlopen
|
||||
except ImportError:
|
||||
from urllib.request import urlopen
|
||||
|
||||
|
||||
def test_defaults():
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
expected_path = os.path.join(os.path.dirname(__file__), 'cassettes')
|
||||
expected_name = 'MyTest.test_foo.yaml'
|
||||
assert os.path.dirname(test.cassette._path) == expected_path
|
||||
assert os.path.basename(test.cassette._path) == expected_name
|
||||
|
||||
|
||||
def test_disabled():
|
||||
|
||||
# Baseline vcr_enabled = True
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert hasattr(test, 'cassette')
|
||||
|
||||
# Test vcr_enabled = False
|
||||
class MyTest(VCRTestCase):
|
||||
vcr_enabled = False
|
||||
def test_foo(self):
|
||||
pass
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert not hasattr(test, 'cassette')
|
||||
|
||||
|
||||
def test_cassette_library_dir():
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
def _get_cassette_library_dir(self):
|
||||
return '/testing'
|
||||
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert test.cassette._path.startswith('/testing/')
|
||||
|
||||
|
||||
def test_cassette_name():
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
def _get_cassette_name(self):
|
||||
return 'my-custom-name'
|
||||
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert os.path.basename(test.cassette._path) == 'my-custom-name'
|
||||
|
||||
|
||||
def test_vcr_kwargs_overridden():
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
def _get_vcr_kwargs(self):
|
||||
kwargs = super(MyTest, self)._get_vcr_kwargs()
|
||||
kwargs['record_mode'] = 'new_episodes'
|
||||
return kwargs
|
||||
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert test.cassette.record_mode == 'new_episodes'
|
||||
|
||||
|
||||
def test_vcr_kwargs_passed():
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
def _get_vcr_kwargs(self):
|
||||
return super(MyTest, self)._get_vcr_kwargs(
|
||||
record_mode='new_episodes',
|
||||
)
|
||||
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert test.cassette.record_mode == 'new_episodes'
|
||||
|
||||
|
||||
def test_vcr_kwargs_cassette_dir():
|
||||
|
||||
# Test that _get_cassette_library_dir applies if cassette_library_dir
|
||||
# is absent from vcr kwargs.
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
def _get_vcr_kwargs(self):
|
||||
return dict(
|
||||
record_mode='new_episodes',
|
||||
)
|
||||
_get_cassette_library_dir = Mock(return_value='/testing')
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert test.cassette._path.startswith('/testing/')
|
||||
assert test._get_cassette_library_dir.call_count == 1
|
||||
|
||||
# Test that _get_cassette_library_dir is ignored if cassette_library_dir
|
||||
# is present in vcr kwargs.
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
def _get_vcr_kwargs(self):
|
||||
return dict(
|
||||
cassette_library_dir='/testing',
|
||||
)
|
||||
_get_cassette_library_dir = Mock(return_value='/ignored')
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert test.cassette._path.startswith('/testing/')
|
||||
assert test._get_cassette_library_dir.call_count == 0
|
||||
|
||||
|
||||
def test_get_vcr_with_matcher(tmpdir):
|
||||
cassette_dir = tmpdir.mkdir('cassettes')
|
||||
assert len(cassette_dir.listdir()) == 0
|
||||
|
||||
mock_matcher = Mock(return_value=True)
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
self.response = urlopen('http://example.com').read()
|
||||
def _get_vcr(self):
|
||||
myvcr = super(MyTest, self)._get_vcr()
|
||||
myvcr.register_matcher('mymatcher', mock_matcher)
|
||||
myvcr.match_on = ['mymatcher']
|
||||
return myvcr
|
||||
def _get_cassette_library_dir(self):
|
||||
return str(cassette_dir)
|
||||
|
||||
# First run to fill cassette.
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert len(test.cassette.requests) == 1
|
||||
assert not mock_matcher.called # nothing in cassette
|
||||
|
||||
# Second run to call matcher.
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert len(test.cassette.requests) == 1
|
||||
assert mock_matcher.called
|
||||
assert repr(mock_matcher.mock_calls[0]) == 'call(<Request (GET) http://example.com>, <Request (GET) http://example.com>)'
|
||||
|
||||
|
||||
def test_testcase_playback(tmpdir):
|
||||
cassette_dir = tmpdir.mkdir('cassettes')
|
||||
assert len(cassette_dir.listdir()) == 0
|
||||
|
||||
# First test actually reads from the web.
|
||||
|
||||
class MyTest(VCRTestCase):
|
||||
def test_foo(self):
|
||||
self.response = urlopen('http://example.com').read()
|
||||
def _get_cassette_library_dir(self):
|
||||
return str(cassette_dir)
|
||||
|
||||
test = run_testcase(MyTest)[0][0]
|
||||
assert b'illustrative examples' in test.response
|
||||
assert len(test.cassette.requests) == 1
|
||||
assert test.cassette.play_count == 0
|
||||
|
||||
# Second test reads from cassette.
|
||||
|
||||
test2 = run_testcase(MyTest)[0][0]
|
||||
assert test.cassette is not test2.cassette
|
||||
assert b'illustrative examples' in test.response
|
||||
assert len(test2.cassette.requests) == 1
|
||||
assert test2.cassette.play_count == 1
|
||||
|
||||
|
||||
def run_testcase(testcase_class):
|
||||
"""Run all the tests in a TestCase and return them."""
|
||||
suite = defaultTestLoader.loadTestsFromTestCase(testcase_class)
|
||||
tests = list(suite._tests)
|
||||
result = TextTestRunner().run(suite)
|
||||
return tests, result
|
||||
Reference in New Issue
Block a user