From e290dd30150d0890872ea8d32e467733a2b51c29 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Wed, 8 Mar 2017 11:55:26 -0600 Subject: [PATCH] Allow users to specify request matchers in Betamax The default matchers for Betamax are decent enough for simple GET requests. However, when POSTing data, extra matchers are often required in order to provide quality matching of a request being made to one that has already been recorded. Change-Id: I801e52a028e9293cf28c6894b2fe10384cce3267 Closes-bug: #1671111 --- keystoneauth1/fixture/keystoneauth_betamax.py | 49 ++++++++++++++++++- .../tests/unit/test_betamax_fixture.py | 20 ++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/keystoneauth1/fixture/keystoneauth_betamax.py b/keystoneauth1/fixture/keystoneauth_betamax.py index 38afd0ab..a1aea161 100644 --- a/keystoneauth1/fixture/keystoneauth_betamax.py +++ b/keystoneauth1/fixture/keystoneauth_betamax.py @@ -29,7 +29,38 @@ class BetamaxFixture(fixtures.Fixture): def __init__(self, cassette_name, cassette_library_dir=None, serializer=None, record=False, pre_record_hook=hooks.pre_record_hook, - serializer_name=None): + serializer_name=None, request_matchers=None): + """Configure Betamax for the test suite. + + :param str cassette_name: + This is simply the name of the cassette without any file extension + or containing directory. For example, to generate + ``keystoneauth1/tests/unit/data/example.yaml``, one would pass + only ``example``. + :param str cassette_library_dir: + This is the directory that will contain all cassette files. In + ``keystoneauth1/tests/unit/data/example.yaml`` you would pass + ``keystoneauth1/tests/unit/data/``. + :param serializer: + A class that implements the Serializer API in Betamax. See also: + https://betamax.readthedocs.io/en/latest/serializers.html + :param record: + The Betamax record mode to use. If ``False`` (the default), then + Betamax will not record anything. For more information about + record modes, see: + https://betamax.readthedocs.io/en/latest/record_modes.html + :param callable pre_record_hook: + Function or callable to use to perform some handling of the + request or response data prior to saving it to disk. + :param str serializer_name: + The name of a serializer already registered with Betamax to use + to handle cassettes. For example, if you want to use the default + Betamax serializer, you would pass ``'json'`` to this parameter. + :param list request_matchers: + The list of request matcher names to use with Betamax. Betamax's + default list is used if none are specified. See also: + https://betamax.readthedocs.io/en/latest/matchers.html + """ self.cassette_library_dir = cassette_library_dir self.record = record self.cassette_name = cassette_name @@ -41,9 +72,22 @@ class BetamaxFixture(fixtures.Fixture): self.serializer = serializer self._serializer_name = serializer_name self.pre_record_hook = pre_record_hook + self.use_cassette_kwargs = {} + if request_matchers is not None: + self.use_cassette_kwargs['match_requests_on'] = request_matchers @property def serializer_name(self): + """Determine the name of the selected serializer. + + If a class was specified, use the name attribute to generate this, + otherwise, use the serializer_name parameter from ``__init__``. + + :returns: + Name of the serializer + :rtype: + str + """ if self.serializer: return self.serializer.name return self._serializer_name @@ -84,7 +128,8 @@ def _construct_session_with_betamax(fixture, session_obj=None): fixture.recorder.use_cassette(fixture.cassette_name, serialize_with=serializer, - record=record) + record=record, + **fixture.use_cassette_kwargs) fixture.recorder.start() fixture.addCleanup(fixture.recorder.stop) diff --git a/keystoneauth1/tests/unit/test_betamax_fixture.py b/keystoneauth1/tests/unit/test_betamax_fixture.py index f1b03cce..b5378219 100644 --- a/keystoneauth1/tests/unit/test_betamax_fixture.py +++ b/keystoneauth1/tests/unit/test_betamax_fixture.py @@ -103,3 +103,23 @@ class TestBetamaxFixtureSerializerBehaviour(testtools.TestCase): self.assertIs(serializer.YamlJsonSerializer, fixture.serializer) self.assertEqual('yamljson', fixture.serializer_name) + + def test_no_request_matchers_provided(self): + fixture = keystoneauth_betamax.BetamaxFixture( + cassette_name='fake', + cassette_library_dir='keystoneauth1/tests/unit/data', + ) + + self.assertDictEqual({}, fixture.use_cassette_kwargs) + + def test_request_matchers(self): + fixture = keystoneauth_betamax.BetamaxFixture( + cassette_name='fake', + cassette_library_dir='keystoneauth1/tests/unit/data', + request_matchers=['method', 'uri', 'json-body'], + ) + + self.assertDictEqual( + {'match_requests_on': ['method', 'uri', 'json-body']}, + fixture.use_cassette_kwargs, + )