Advanced @betamax.use_cassette Techniques for Automated Testing
This article explains why recording and replaying HTTP interactions with Betamax is essential for automated testing, outlines its benefits such as consistency, efficiency, error reduction, regression support, and provides multiple advanced code examples for custom recording modes, request filtering, cassette control, context‑manager usage, and handling dynamic content.
Recording and replaying HTTP interactions is an important technique in automated testing, enhancing test quality, efficiency, and coverage while reducing manual effort and risk.
Consistency verification: By capturing real interactions as a baseline, testers can replay them later to ensure the system behaves consistently across environments and time.
Improved test efficiency: Repeating manual steps is time‑consuming; recording automates these steps so tests run faster and developers can focus on more critical tasks.
Reduced human error: Automation eliminates mistakes that often occur during manual testing of large data sets or complex operations.
Support for regression testing: Whenever code changes, previously recorded test cases can be replayed to verify that existing functionality remains intact.
Simulation of complex scenarios: Recording can capture intricate user behaviors or network conditions and reproduce them accurately in later test runs.
Performance analysis: Recorded interactions can be used for load or stress testing to measure response time, throughput, and resource usage, helping identify bottlenecks.
Lowering the testing barrier: Non‑technical testers can create and run tests without writing code, simply by using a recorder.
Cross‑environment testing: Recordings work across development, testing, and production environments, exposing environment‑specific issues.
Custom recording and playback modes
import betamax
import requests
import unittest
with betamax.Betamax.configure() as config:
config.cassette_library_dir = 'cassettes'
class TestAPI(unittest.TestCase):
@betamax.use_cassette('get_users', record='once')
def test_get_users(self):
# test code ...
@betamax.use_cassette('create_user', record='none')
def test_create_user(self):
# test code ...
if __name__ == '__main__':
unittest.main()The example shows two test methods with different recording modes: record='once' records only the first run, while record='none' disables recording and playback.
Filtering requests and responses
import betamax
import requests
import unittest
with betamax.Betamax.configure() as config:
config.cassette_library_dir = 'cassettes'
class TestAPI(unittest.TestCase):
@betamax.use_cassette('filtering', match_requests_on=['method', 'uri'])
def test_filtering(self):
url = "http://example.com/api/users"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer your_token_here"
}
# Send two identical GET requests with different query parameters
response1 = requests.get(f"{url}?page=1", headers=headers)
response2 = requests.get(f"{url}?page=2", headers=headers)
self.assertEqual(response1.status_code, 200)
self.assertEqual(response2.status_code, 200)
if __name__ == '__main__':
unittest.main()By setting match_requests_on=['method', 'uri'] , Betamax treats requests that differ only in query parameters as the same, reusing the recorded response.
Controlling the cassette inside a test method
import betamax
import requests
import unittest
with betamax.Betamax.configure() as config:
config.cassette_library_dir = 'cassettes'
class TestAPI(unittest.TestCase):
@betamax.use_cassette('control_cassette')
def test_control_cassette(self):
with self.subTest('Record and play'):
url = "http://example.com/api/users"
headers = {"Content-Type": "application/json", "Authorization": "Bearer your_token_here"}
response = requests.get(url, headers=headers)
self.assertEqual(response.status_code, 200)
with betamax.Betamax.current_cassette().use_record_mode('none'):
with self.subTest('No recording or playback'):
url = "http://example.com/api/users"
headers = {"Content-Type": "application/json", "Authorization": "Bearer your_token_here"}
response = requests.get(url, headers=headers)
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main()This demonstrates switching between normal recording/playback and a none mode within the same test, giving fine‑grained control over cassette behavior.
Using a context manager to control the cassette
import betamax
import requests
import unittest
with betamax.Betamax.configure() as config:
config.cassette_library_dir = 'cassettes'
class TestAPI(unittest.TestCase):
def test_context_manager(self):
with betamax.Betamax.configure() as config:
config.default_cassette_options['record_mode'] = 'once'
with betamax.Betamax(session=requests.Session()) as recorder:
url = "http://example.com/api/users"
headers = {"Content-Type": "application/json", "Authorization": "Bearer your_token_here"}
response = recorder.use_cassette('context_manager').get(url, headers=headers)
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main()The context manager sets the default recording mode to once , creates a dedicated recorder object, and uses use_cassette to start and stop recording around the HTTP request.
Handling dynamic content
import betamax
import requests
import unittest
with betamax.Betamax.configure() as config:
config.cassette_library_dir = 'cassettes'
class TestAPI(unittest.TestCase):
@betamax.use_cassette('dynamic_content')
def test_dynamic_content(self):
url = "http://example.com/api/users"
headers = {"Content-Type": "application/json", "Authorization": "Bearer your_token_here"}
# First request gets the user list
response1 = requests.get(url, headers=headers)
self.assertEqual(response1.status_code, 200)
# Extract the first user's ID
user_id = response1.json()['users'][0]['id']
# Second request gets details for that user
detail_url = f"{url}/{user_id}"
response2 = requests.get(detail_url, headers=headers)
self.assertEqual(response2.status_code, 200)
if __name__ == '__main__':
unittest.main()This example shows how Betamax can handle dynamic values (e.g., a user ID extracted from a previous response) so that playback uses the correct data.
Conclusion
These advanced @betamax.use_cassette examples illustrate how flexible recording and playback control can improve the stability and efficiency of automated HTTP testing.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.