quarantine diaries weekend 7

diary of a codelovingyogi
3 min readJun 26, 2020

--

(written for weekend of April 25, 2020)

tests refresher and mocking aws services

joined a new team and reviewing sample tests that have been written for our repos. reviewing the various ways that we can mock aws services in our tests.

we are using pytest.

to use pytest:

pip install pytest

most basic setup for tests:

  • in your repository add a tests folder
  • add __init__.py file
  • add a test file prefixed with test_ with your test, ie:
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 4
  • run pytest

python moto library

creates full blank environment mocking aws services, calls to services are mocked out. for example you can create a bucket for testing of code that upload a file, for testing you can fetch the same contents of the file.

for aws secrets manager, believe we can only add secrets via the cli or console. so for my test of fetch secrets, i will mock the fetch command injecting a sample response that would be expected from secrets manager, then assert that the config parser to parse in format expected.

very important to note, even though in documentation, using the decorator does not seem to require `mock.start()` you do still need this whether in your fixture or in your test method.

pytest fixtures

functions that run before each test function that uses it. used to feed some input data to a test, ie. database connections, urls. avoids running the same code to get an expected response for every test that uses it, attach fixture to these tests instead

use the decorator before function:

@pytest.fixture

make sure it has a return value, indicate the function/fixture name as one of the test method’s parameters. the fixture function will get run and feed the fixture’s return value as an input param you can use in the test method.

pytest monkeypatch

also helps with invoking a response that can’t be easily tested ie. network access. docs provide several options:

monkeypatch.setattr(obj, name, value, raising=True)
monkeypatch.delattr(obj, name, raising=True)
monkeypatch.setitem(mapping, name, value)
monkeypatch.delitem(obj, name, raising=True)
monkeypatch.setenv(name, value, prepend=False)
monkeypatch.delenv(name, raising=True)
monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path)

when mocking a class and method(s), use @staticmethod so that you can call the method without having to instantiate the class first.

botocore.stub

according to docs — this allows you to stub out requests so you don’t have to hit an endpoint to write tests. this requires detailing out the expected request and responses for each method you are stubbing.

this did not end up working for me, it seems to still make network calls. maybe i’m misunderstanding what this library is doing for us.

pytest-mock

useful for mocking module functions and class methods. once i got this working it was the most easy and cleanest way to mock functions and methods.

to use, run

pytest-mock

for example, for a requests post method instead of using monkeypatch to mock entire classes and method returns, you can do this instead:

def test_submit_some_event(mocker):
class MockResponse:
@staticmethod
def json():
return MOCK_POST_RESPONSE
mocker.patch.object(requests, 'post')
requests.post.return_value = MockResponse()
submit_some_event([[{'id':'1'}]])
requests.post.assert_called_once()

for checking your test coverage you can run

pip install pytest-cov

if i try running coverage at top repo level

pytest --cov <repo/top folder name> tests

i getting error:

overage.py warning: Module <repo/top folder name> was never imported. (module-not-imported)
Coverage.py warning: No data was collected. (no-data-collected)
WARNING: Failed to generate report: No data to report.

i can get coverage when i run at module level instead:

pytest --cov <module under repo.top folder name> tests/test_lambda_function.py

to see detailed view of code coverage in html format html arg:

pytest --cov <module under repo/top folder name> tests/test_lambda_function.py --cov-report=html

if you are using environment variables in the tested method, you can hardcode values at beginning of your test script:

os.environ['environment'] = 'dev'os.environ['region'] = 'us-east-1'

--

--

diary of a codelovingyogi
diary of a codelovingyogi

Written by diary of a codelovingyogi

quick notes, snippets, bugs, and fixes

No responses yet