additional notes on python testing
This commit is contained in:
parent
52f4420b73
commit
5d37a1efb2
2 changed files with 94 additions and 8 deletions
88
zk/Pytest_fixtures.md
Normal file
88
zk/Pytest_fixtures.md
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
---
|
||||||
|
tags: [python, pytest]
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixtures are a way to provide data or state to your tests. Typically, although
|
||||||
|
not exclusively, for processes that you want to reuse accross different `test_`
|
||||||
|
functions. They are defined at the "arrange" stage of testing.
|
||||||
|
|
||||||
|
## Example: testing class methods under test
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Person:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def print_name(self):
|
||||||
|
return f"Your name is {self.name}"
|
||||||
|
```
|
||||||
|
|
||||||
|
To create a fixture of this class:
|
||||||
|
|
||||||
|
```py
|
||||||
|
@pytest.fixture
|
||||||
|
def my_person():
|
||||||
|
person = new Person('Thomas')
|
||||||
|
return person.name()
|
||||||
|
|
||||||
|
test_print_name(my_person):
|
||||||
|
assert(my_person) == 'Thomas'
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
> Note we define our fixture and then inject it into our test function.
|
||||||
|
> Functions request fixtures they require by declaring them as arguments.
|
||||||
|
|
||||||
|
Alternatively you could just return the class from the fixture and test the
|
||||||
|
methods individually within the test function.
|
||||||
|
|
||||||
|
## Integrating with `@patch` to provide mock fixtures
|
||||||
|
|
||||||
|
Say we wanted to mock reading a JSON file.
|
||||||
|
|
||||||
|
We could create a fixture:
|
||||||
|
|
||||||
|
```py
|
||||||
|
|
||||||
|
@pytest fixture
|
||||||
|
def raw_json():
|
||||||
|
return json.dumps({"key": "value"})
|
||||||
|
```
|
||||||
|
|
||||||
|
And pass it in to the mock of the global `open` method:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from unittest.mock import mock_open, patch
|
||||||
|
|
||||||
|
def test_json_parsing(raw_json):
|
||||||
|
with patch("builtins.open", mock_open(read_data=raw_json))
|
||||||
|
# Then assert etc
|
||||||
|
```
|
||||||
|
|
||||||
|
This fixture could then be re-used to test any other method that relies on
|
||||||
|
incoming JSON from a file.
|
||||||
|
|
||||||
|
## Example: setup and teardown - before each and after each
|
||||||
|
|
||||||
|
Fixtures can be leveraged to setup 'before each...' and 'after each...' logic:
|
||||||
|
|
||||||
|
```py
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def setup():
|
||||||
|
os.environ["POCKET_LAMBDA_ENDPOINT"] = "https://some_endpoint.com/{article_type}"
|
||||||
|
yield
|
||||||
|
del os.environ["POCKET_LAMBDA_ENDPOINT"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Here `yield` is a placeholder for the tests that run in between the setup and
|
||||||
|
teardown.
|
||||||
|
|
||||||
|
We use `scope="function"` to signal that this will run before/after any tests
|
||||||
|
that inject the fixture.
|
||||||
|
|
||||||
|
Then to specify the units that will run as the `yield` we just inject `setup`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
def some_function(setup_function):
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
---
|
---
|
||||||
tags: [python, testing]
|
tags: [python, testing, pytest]
|
||||||
---
|
---
|
||||||
|
|
||||||
# Testing Python code
|
|
||||||
|
|
||||||
## `pytest`
|
## `pytest`
|
||||||
|
|
||||||
Pytest is the most popular testing library for Python. It is not included with
|
Pytest is the most popular testing library for Python. It is not included with
|
||||||
the Python standard library so it must be installed with
|
the Python standard library so it must be installed with
|
||||||
[pip](Python_package_management.md).
|
[pip](Python_package_management.md). While it does not include a declaration
|
||||||
While it does not include a declaration library, it is robust enough to handle
|
library, it is robust enough to handle most scenarios having a rich and
|
||||||
most scenarios having a rich and expressive set of constructs and decorators
|
expressive set of constructs and decorators that let you declare what your tests
|
||||||
that let you declare what your tests should do, under what conditions they
|
should do, under what conditions they should run, and how they should interact
|
||||||
should run, and how they should interact with the rest of your system.
|
with the rest of your system.
|
||||||
|
|
||||||
### Using `pytest`
|
### Using `pytest`
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue