<jupyter_start><jupyter_text>Pytest Examples- This notebook summarise some commonly used pytest features- Exhaustice Pytest Examples see [Official Doc](https://docs.pytest.org/en/stable/example/index.html)<jupyter_code>!python -V<jupyter_output>Python 3.6.9<jupyter_text>Pytest with pdb<jupyter_code>import pytest
%%writefile example_0.py
def my_sum(a, b):
  c = a + b
  return c
%%writefile test_example_0.py

from example_0 import my_sum

def test_my_sum():
  res1 = my_sum(1, 2)
  import pdb; pdb.set_trace() # use breakpint() if >= python 3.7
  res2 = my_sum(1, 3)
  import pdb; pdb.set_trace()
  assert res1 == 3
  assert res2 == 4

!pytest -k test_example_0 --pdb<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux2 -- Python 2.7.17, pytest-3.6.4, py-1.8.0, pluggy-0.7.1
rootdir: /content, inifile:
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collected 1 item                                                               [0m

test_example_0.py 
>>>>>>>>>>>>>>>>>>> PDB set_trace (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>
> /content/test_example_0.py(7)test_my_sum()
-> res2 = my_sum(1, 3)
(Pdb) ll
*** NameError: name 'll' is not defined
(Pdb) l
  2  	from example_0 import my_sum
  3  	
  4  	def test_my_sum():
  5  	  res1 = my_sum(1, 2)
  6  	  import pdb; pdb.set_trace()
  7  ->	  res2 = my_sum(1, 3)
  8  	  import pdb; pdb.set_trace()
  9  	  assert res1 == 3
 10  	  assert res2 == 4
[EOF]
(Pdb) res1
3
(Pdb) res2
*** NameError: name 'res2' is not defined
(P[...]<jupyter_text>[Pytest Fixture](https://realpython.com/pytest-python-testing/fixtures-managing-state-and-dependencies)- pytest fixtures are a way of providing data, test doubles, or state setup to your tests. - Fixtures are functions that can return a wide range of values. - Each test that depends on a fixture must explicitly accept that fixture as an argument.  [Fixtures as Function arguments](https://docs.pytest.org/en/stable/fixture.htmlfixtures-as-function-arguments)Test functions can receive fixture objects by naming them as an input argument. For each argument name, a fixture function with that name provides the fixture object. Fixture functions are registered by marking them with `@pytest.fixture`.<jupyter_code>%%writefile sample.py
def format_data_for_display(people):
  result = []
  for i in people:
    # s = f"{i['given_name']} {i['family_name']}: {i['title']}"  # fstring doesn' work well in pytest/unittest
    s = "%s %s: %s"%(i['given_name'], i['family_name'], i['title'])
    result.append(s)
  return result


def format_data_for_excel(people):
  result_list = []

  header = ",".join(people[0].keys())
  result_list.append(header)
  
  header = ",".join(people[0].keys())
  for i in people:
    line = ",".join(i.values())
    result_list.append(line)
  result = "\n".join(result_list)
  return result

%%writefile test_sample.py
from collections import OrderedDict

import pytest
from sample import format_data_for_display, format_data_for_excel

@pytest.fixture
def example_people_data():
    # use OrderedDict to avoid errors caused by dictionary orders
    d1 = OrderedDict([("given_name", "Alfonsa"), 
                      ("family_name", "Ruiz"), 
                      ("title", "Senior Software Engineer")
                      ])
    
    d2 = OrderedDict(
        [
         ("given_name", "Sayid"),
         ("family_name", "Khan"),
         ("title", "Project Manager"),
        ]
    )
    return [d1, d2]


# You can use the fixture by adding it as an argument to your tests. Its value will be the return value of the fixture function:
def test_format_data_for_display(example_people_data):
  res = ["<NAME>: Senior Software Engineer", "<NAME>: Project Manager"]
  assert format_data_for_display(example_people_data) == res


def test_format_data_for_excel(example_people_data):
    res = "given_name,family_name,title\n"\
    "Alfonsa,Ruiz,Senior Software Engineer\n"\
    "Sayid,Khan,Project Manager"
    # assert 0 
    assert format_data_for_excel(example_people_data) == res
!python3 -m pytest -k test_sample<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux2 -- Python 2.7.17, pytest-3.6.4, py-1.8.0, pluggy-0.7.1
rootdir: /content, inifile:
[1m
collecting 0 items                                                             [0m[1m
collecting 2 items                                                             [0m[1m
collected 2 items                                                              [0m

test_sample.py ..[36m                                                        [100%][0m

[32m[1m=========================== 2 passed in 0.02 seconds ===========================[0m<jupyter_text>Monkeypatch Fixture- monkeypatch is a **pytest `fixture`**  [Monkeypatching functions](https://docs.pytest.org/en/stable/monkeypatch.htmlsimple-example-monkeypatching-functions)- Use `monkeypatch.setattr` to patch the __function__ or __property__ with your desired testing behavior<jupyter_code># quick example run to show outputs
from pathlib import Path

print(Path("/chet"))
print(Path.home())
print(Path.home() / ".ssh")
%%writefile ssh.py
from pathlib import Path

def getssh():
    """Simple function to return expanded homedir ssh path."""
    return Path.home() / ".ssh"
%%writefile test_ssh.py
from pathlib import Path

from ssh import getssh

def test_getssh(monkeypatch):
    
    # mocked return function to replace Path.home
    def mockreturn():
        return Path("/abc")  # output: '/abc'

    # patch `Path.home` by `mockreturn`:
    monkeypatch.setattr(Path, "home", mockreturn)

    # Calling getssh() will use mockreturn in place of `Path.home` for this test with the monkeypatch.
    x = getssh()
    assert x == Path("/abc/.ssh")
!python3 -m pytest -k test_ssh<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collected 1 item                                                               [0m

test_ssh.py .[36m                                                            [100%][0m

[32m[1m=========================== 1 passed in 0.03 seconds ===========================[0m<jupyter_text>[More example: build mock classes](https://docs.pytest.org/en/stable/monkeypatch.htmlmonkeypatching-returned-objects-building-mock-classes)<jupyter_code>%%writefile app.py
import requests

def get_json(url):
    """Takes a URL, and returns the JSON."""
    r = requests.get(url)
    return r.json()
%%writefile test_app_v1.py
import requests

import app

# custom class to be the mock return value
# will override the `requests.Response` returned from `requests.get`
class MockResponse:

    # mock json() method always returns a specific testing dictionary
    @staticmethod
    def json():
        return {"mock_key": "mock_response"}


def test_get_json(monkeypatch):

    # Any arguments may be passed and mock_get() will always return our
    # mocked object, which only has the .json() method.
    def mock_get(*args, **kwargs):
        return MockResponse()

    # apply the monkeypatch for `requests.get` to `mock_get`
    monkeypatch.setattr(requests, "get", mock_get)

    # `app.get_json`, which contains `requests.get`, uses the monkeypatch
    result = app.get_json("https://fakeurl")  # = mock_get.json
    assert result["mock_key"] == "mock_response"
!python3 -m pytest -k test_app_v1<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 2 items                                                             [0m[1m
collecting 3 items                                                             [0m[1m
collecting 4 items                                                             [0m[1m
collected 4 items / 3 deselected                                               [0m

test_app_v1.py .[36m                                                         [100%][0m

[32m[1m==================== 1 passed, 3 deselected in 0.09 seconds ====================[0m<jupyter_text>This mock can be shared across tests using a **fixture**:<jupyter_code>%%writefile test_app_v2.py
import pytest
import requests

# app.py that includes the get_json() function
import app

# custom class to be the mock return value of requests.get()
class MockResponse:
    @staticmethod
    def json():
        return {"mock_key": "mock_response"}


# monkeypatched requests.get moved to a fixture
@pytest.fixture
def mock_response(monkeypatch):
    """Requests.get() mocked to return {'mock_key':'mock_response'}."""

    def mock_get(*args, **kwargs):
        return MockResponse()

    monkeypatch.setattr(requests, "get", mock_get)


# notice our test uses the custom fixture instead of monkeypatch directly
def test_get_json(mock_response):
    result = app.get_json("https://fakeurl")
    assert result["mock_key"] == "mock_response"
!python -m pytest -k test_app_v2<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 2 items                                                             [0m[1m
collecting 3 items                                                             [0m[1m
collecting 4 items                                                             [0m[1m
collected 4 items / 3 deselected                                               [0m

test_app_v2.py .[36m                                                         [100%][0m

[32m[1m==================== 1 passed, 3 deselected in 0.09 seconds ====================[0m<jupyter_text>[**Global patch** example](https://docs.pytest.org/en/stable/monkeypatch.htmlglobal-patch-example-preventing-requests-from-remote-operations):If you want to prevent the “requests” library from performing http requests in all your tests, you can do:<jupyter_code>%%writefile conftest.py
import pytest

@pytest.fixture(autouse=True)
def no_requests(monkeypatch):
    """Remove requests.sessions.Session.request for all tests."""
    monkeypatch.delattr("requests.sessions.Session.request")<jupyter_output><empty_output><jupyter_text>[Monkeypatching environment variables](https://docs.pytest.org/en/stable/monkeypatch.htmlmonkeypatching-environment-variables)1. Use`monkeypatch.setenv`2. Alternative ways: [with unittest](https://adamj.eu/tech/2020/10/13/how-to-mock-environment-variables-with-pythons-unittest/)<jupyter_code>! pip install django-environ
%%writefile code.py
import os
import environ

env = environ.Env()

def get_os_user_lower():
    """Simple retrieval function.
    Returns lowercase USER or raises OSError."""
    username = os.getenv("USER")

    if username is None:
        raise OSError("USER environment is not set.")

    return username.lower()

def get_catalog_url():
    is_dev = env.bool("IS_DEV", default=False)
    catalog_url = env.str("CATALOG_URL", default=None)
    if is_dev:
        return catalog_url<jupyter_output>Overwriting code.py<jupyter_text>There are two potential paths: 1. the `USER` environment variable is set to a value. 2. the `USER` environment variable does not exist. Using `monkeypatch` both paths can be safely tested without impacting the running environment:<jupyter_code>%%writefile test_code_v1.py
import pytest

from code import get_os_user_lower, get_catalog_url

def test_upper_to_lower(monkeypatch):
    """Set the USER env var to assert the behavior."""
    monkeypatch.setenv("USER", "TestingUser")
    assert get_os_user_lower() == "testinguser"


def test_raise_exception(monkeypatch):
    """Remove the USER env var and assert OSError is raised."""
    monkeypatch.delenv("USER", raising=False)

    with pytest.raises(OSError):
        _ = get_os_user_lower()

def test_get_url(monkeypatch):
    monkeypatch.setenv("IS_DEV", True)
    monkeypatch.setenv("CATALOG_URL", "www.bingo.com")
    catalog_url = get_catalog_url()
    assert catalog_url == "www.bingo.com"
!python -m pytest -k test_code_v1<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 2 items                                                             [0m[1m
collecting 3 items                                                             [0m[1m
collecting 5 items                                                             [0m[1m
collecting 8 items                                                             [0m[1m
collecting 10 items                                                            [0m[1m
collecting 11 items                                                            [0m[1m
collected 11 items / 8 deselected                                             [...]<jupyter_text>This behavior can be moved into __fixture__ structures and shared across tests:<jupyter_code>%%writefile test_code_v2.py
import pytest

from code import get_os_user_lower

@pytest.fixture
def mock_env_user(monkeypatch):
    monkeypatch.setenv("USER", "TestingUser")


@pytest.fixture
def mock_env_missing(monkeypatch):
    monkeypatch.delenv("USER", raising=False)


# notice the tests reference the fixtures for mocks
def test_upper_to_lower(mock_env_user):
    assert get_os_user_lower() == "testinguser"


def test_raise_exception(mock_env_missing):
    with pytest.raises(OSError):
        _ = get_os_user_lower()
!python -m pytest -k test_code_v2<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 2 items                                                             [0m[1m
collecting 3 items                                                             [0m[1m
collecting 5 items                                                             [0m[1m
collecting 7 items                                                             [0m[1m
collecting 9 items                                                             [0m[1m
collecting 10 items                                                            [0m[1m
collected 10 items / 8 deselected                                             [...]<jupyter_text>[Monkeypatching dictionaries](https://docs.pytest.org/en/stable/monkeypatch.htmlmonkeypatching-dictionaries)`monkeypatch.setitem` can be used to safely set the values of dictionaries to specific values during tests<jupyter_code>%%writefile app.py
DEFAULT_CONFIG = {"user": "user1", "database": "db1"}

def create_connection_string(config=None):
    """Creates a connection string from input or defaults."""
    config = config or DEFAULT_CONFIG
    return f"User Id={config['user']}; Location={config['database']};"
%%writefile test_app_v1.py
import pytest

import app

def test_connection(monkeypatch):

    # Patch the values of DEFAULT_CONFIG to specific testing values only for this test.
    monkeypatch.setitem(app.DEFAULT_CONFIG, "user", "test_user")
    monkeypatch.setitem(app.DEFAULT_CONFIG, "database", "test_db")

    expected = "User Id=test_user; Location=test_db;"

    # the test uses the monkeypatched dictionary settings
    result = app.create_connection_string()
    assert result == expected

def test_missing_user(monkeypatch):

    # patch the DEFAULT_CONFIG t be missing the 'user' key
    monkeypatch.delitem(app.DEFAULT_CONFIG, "user", raising=False)

    # Key error expected because a config is not passed, and the default is now missing the 'user' entry.
    with pytest.raises(KeyError):  # catch expected Exception
        _ = app.create_connection_string()
!python -m pytest -k test_app_v1<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 3 items                                                             [0m[1m
collecting 4 items                                                             [0m[1m
collecting 6 items                                                             [0m[1m
collecting 9 items                                                             [0m[1m
collecting 11 items                                                            [0m[1m
collecting 12 items                                                            [0m[1m
collected 12 items / 10 deselected                                            [...]<jupyter_text>Use modularity of **fixture** to have more flexibility:<jupyter_code>%%writefile test_app_v2.py
import pytest

# app.py with the connection string function
import app

# all of the mocks are moved into separated fixtures
@pytest.fixture
def mock_test_user(monkeypatch):
    """Set the DEFAULT_CONFIG user to test_user."""
    monkeypatch.setitem(app.DEFAULT_CONFIG, "user", "test_user")


@pytest.fixture
def mock_test_database(monkeypatch):
    """Set the DEFAULT_CONFIG database to test_db."""
    monkeypatch.setitem(app.DEFAULT_CONFIG, "database", "test_db")


@pytest.fixture
def mock_missing_default_user(monkeypatch):
    """Remove the user key from DEFAULT_CONFIG"""
    monkeypatch.delitem(app.DEFAULT_CONFIG, "user", raising=False)


# tests reference only the fixture mocks that are needed
def test_connection(mock_test_user, mock_test_database):

    expected = "User Id=test_user; Location=test_db;"

    result = app.create_connection_string()
    assert result == expected


def test_missing_user(mock_missing_default_user):

    with pytest.raises(KeyError):
        _ = app.create_connection_string()

!python -m pytest -k test_app_v2<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 3 items                                                             [0m[1m
collecting 5 items                                                             [0m[1m
collecting 7 items                                                             [0m[1m
collecting 10 items                                                            [0m[1m
collecting 12 items                                                            [0m[1m
collecting 13 items                                                            [0m[1m
collected 13 items / 11 deselected                                            [...]<jupyter_text>`Monkeypatch` 和 `pytest.mark.parametrize`一起先`Monkeypath`, 后`parametrize`<jupyter_code>@pytest.mark.parametrize(
    ["image", "expected_result"],
    [
        (
            image2bytes("/home/lyst/code/tests/gucci-buckle.jpeg"),
            "26c946ce58d6c4b8cf2d2139a50cc130",
        ),
    ],
)
def test_hash_image__md5(monkeypatch, image, expected_result):
    monkeypatch.setattr(images.settings, "IMAGE_HASH_ALGO", "MD5")
    assert images.hash_image(image) == expected_result<jupyter_output><empty_output><jupyter_text>`unittest.mock.patch`- https://realpython.com/python-mock-library/patch-as-a-context-manager- `Monkeypatch`还没有看到可以`mock`而不出`side_effect`/ `return_value`的情况  Patch as decorators**Monkey patching** is the replacement of one object with another at runtime. Now, you’ll use `patch()` to replace your objects in `my_calendar.py`<jupyter_code>%%writefile my_calendar.py

import requests
from datetime import datetime

def is_weekday():
    today = datetime.today()
    # Python's datetime library treats Monday as 0 and Sunday as 6
    return (0 <= today.weekday() < 5)

def get_holidays():
    r = requests.get('http://localhost/api/holidays')
    if r.status_code == 200:
        return r.json()
    return None
%%writefile test_my_calender.py

from requests.exceptions import Timeout

import pytest
from unittest.mock import patch

from my_calendar import get_holidays

@patch('my_calendar.requests')  # mock requests module
def test_get_holidays_timeout(mock_requests):
        mock_requests.get.side_effect = Timeout  # define side_effect of 'requets.get'
        with pytest.raises(Timeout):  # Assertions about expected exceptions
            get_holidays()
            mock_requests.get.assert_called_once()
# use name based test filtering with '-k' flag
!python3 -m pytest -k test_my_calender<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collected 1 item                                                               [0m

test_my_calender.py .[36m                                                    [100%][0m

[32m[1m=========================== 1 passed in 0.10 seconds ===========================[0m<jupyter_text>multiple patch decorators	@patch('p.A', argsA)	@patch('p.B', argsB)	.	.	@patch('p.N', argsN)	def test_all(mockN, ..., mockB, mockA, other_fixtures, monkeypatch):		my beautiful test  Patch as context managers object file:<jupyter_code>%%writefile my_calendar.py

import requests
from datetime import datetime

def is_weekday():
    today = datetime.today()
    # Python's datetime library treats Monday as 0 and Sunday as 6
    return (0 <= today.weekday() < 5)

def get_holidays():
    r = requests.get('http://localhost/api/holidays')
    if r.status_code == 200:
        return r.json()
    return None<jupyter_output><empty_output><jupyter_text>test file:<jupyter_code>%%writefile test_my_calender_v2.py

from requests.exceptions import Timeout

import pytest
from unittest.mock import patch

from my_calendar import get_holidays

def test_get_holidays_timeout():
  with patch('my_calendar.requests') as mock_requests:  # patch request module
    mock_requests.get.side_effect = Timeout  # define side_effect of 'requets.get'
    with pytest.raises(Timeout):  # Assertions about expected exceptions
        get_holidays()
        mock_requests.get.assert_called_once()
!python -m pytest -k test_my_calender_v2<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.6.9, pytest-3.6.4, py-1.9.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 2 items                                                             [0m[1m
collecting 4 items                                                             [0m[1m
collected 4 items / 3 deselected                                               [0m

test_my_calender_v2.py .[36m                                                 [100%][0m

[32m[1m==================== 1 passed, 3 deselected in 0.09 seconds ====================[0m<jupyter_text>different `side_effect`/`return_value` depending on calls<jupyter_code>%%writefile images.py


def download_image(url):
    if url.startswith("https://"):
        return True
    else:
        return False
%%writefile test_image_download.py

import pytest
from unittest.mock import patch

from images import download_image


def side_effect_func(url: str):
    """👀 different side_effect for different inputs"""
    if url.startswith("https://"):
        return True
    else:
        return False


@patch("test_image_download.download_image")
def test_download_image(mock_download_image):

    mock_download_image.side_effect = side_effect_func

    res = []
    for url in ["https://123.com", "file://myfile.jpeg"]:
        res.append(download_image(url))
    assert res == [True, False]
!python -m pytest -k test_image_download<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.12, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collected 1 item                                                               [0m

test_image_download.py .[36m                                                 [100%][0m

[32m[1m=========================== 1 passed in 0.02 seconds ===========================[0m<jupyter_text>mock a constant<jupyter_code>%%writefile my_calendar.py

today = "Monday"

def is_weekday():
    return today

%%writefile test_my_calendar.py
from unittest.mock import patch

from my_calendar import is_weekday


def test_is_weekday():
    with patch("my_calendar.today", "Friday!"):  # patch a constant
        day = is_weekday()
    assert day == "Friday!"
!python -m pytest -k test_my_calendar<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.12, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 2 items                                                             [0m[1m
collected 2 items / 1 deselected                                               [0m

test_my_calendar.py .[36m                                                    [100%][0m

[32m[1m==================== 1 passed, 1 deselected in 0.08 seconds ====================[0m<jupyter_text>auto-speccing[Notion Notes](https://chetsheng.notion.site/Mock-45bf0064b3f64efb863cc73fdfc8b206)Speecing preconfigures mocks to only respond to methods that actually exist in the spec class.   Markers  [Parametrizing tests](https://docs.pytest.org/en/latest/example/parametrize.html)- `@pytest.mark.parametrize` allows one to define multiple sets of arguments and fixtures at the test function or class.<jupyter_code>%%writefile value_check.py

def sum_is_even(a, b):
  return (a+b) % 2 ==0
%%writefile test_value_check.py

import pytest
from value_check import sum_is_even

@pytest.mark.parametrize("v1 , v2, expected_result", [(1, 2, False), (1, 3, True)])  # @pytest.mark.parametrize("inputs, outputs", list-of-tuples, optional-ids)
def test_sum_is_even(v1, v2, expected_result):
  assert sum_is_even(v1, v2) == expected_result

!python3 -m pytest -k value_check<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.6.9, pytest-3.6.4, py-1.9.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 2 items                                                             [0m[1m
collected 2 items                                                              [0m

test_value_check.py ..[36m                                                   [100%][0m

[32m[1m=========================== 2 passed in 0.02 seconds ===========================[0m<jupyter_text>- [Parametrizing fixtures and test functions](https://docs.pytest.org/en/6.2.x/parametrize.htmlpytest-mark-parametrize-parametrizing-test-functions):   - having values only without results also works<jupyter_code>import pytest


@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
    pass<jupyter_output><empty_output><jupyter_text>[Using marks with parametrized fixtures](https://docs.pytest.org/en/stable/fixture.htmlusing-marks-with-parametrized-fixtures)  [freezegun](https://github.com/spulec/freezegun)Freezegun allows your Python tests to travel through time by mocking the `datetime` module.- Once the `decorator` or `context manager` have been invoked, all calls to `datetime.datetime.now()`, `datetime.datetime.utcnow()`, `datetime.date.today()`, `time.time()`, `time.localtime()`, `time.gmtime()`, and `time.strftime()` will return the time that has been frozen. `time.monotonic()` will also be frozen, but as usual it makes no guarantees about its absolute value, only its changes over time.<jupyter_code>!pip install freezegun
from freezegun import freeze_time
import datetime
import unittest

@freeze_time("2012-01-14")
def test():
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

test()
%%writefile events.py
from datetime import datetime, timezone

def create_event(id, state, source):
    event = {
        "id": id,
        "live": {
            "core": {
                "group": {
                    "state": {"current": state},
                    "states": {
                        state: {"source": source, "dt": datetime.now(timezone.utc).isoformat()}
                    },
                }
            }
        },
    }
    return event
%%writefile test_events.py
from datetime import datetime, timezone
import freezegun

from events import create_event

@freezegun.freeze_time("2021-01-01 12:30:00")
def test_create_event():

    event = create_event(id=1, state="applied", source="chet")

    expected = {
        "id": 1,
        "live": {
            "core": {
                "group": {
                    "state": {"current": "applied"},
                    "states": {
                        "applied": {"source": "chet", "dt": datetime.now(timezone.utc).isoformat()}
                    },
                }
            }
        },
    }
    assert event == expected
!python3 -m pytest -k test_events<jupyter_output>[1m============================= test session starts ==============================[0m
platform linux -- Python 3.7.10, pytest-3.6.4, py-1.10.0, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
[1m
collecting 0 items                                                             [0m[1m
collecting 1 item                                                              [0m[1m
collecting 3 items                                                             [0m[1m
collecting 5 items                                                             [0m[1m
collecting 7 items                                                             [0m[1m
collecting 10 items                                                            [0m[1m
collecting 12 items                                                            [0m[1m
collecting 13 items                                                            [0m[1m
collecting 14 items                                                           [...]<jupyter_text>motomoto is used to mock boto3Examples:- `goku/test_model_utils.py`- [https://git.lystit.com/chetsheng/figueres/blob/4241dbae9db230ba45c14925dc42961f35f65b11/tests/figueres/test_utils.py](https://git.lystit.com/chetsheng/figueres/blob/4241dbae9db230ba45c14925dc42961f35f65b11/tests/figueres/test_utils.py)<jupyter_code>!pip install boto3 moto[all]
import tarfile
import tempfile

import boto3
from moto import mock_s3


def download_file_from_s3(bucket: str, remote_object_path: str, local_file_path: str) -> None:
    """
    Downloads a file from s3, and saves it to the local directory specified.
    """
    s3 = boto3.client("s3")
    s3.download_file(Bucket=bucket, Key=remote_object_path, Filename=local_file_path)


@mock_s3
def test_download_file_from_s3():
    resource = boto3.resource("s3", region_name="us-east-1")

    bucket = "lyst-bucket"
    resource.create_bucket(Bucket=bucket)

    path = "some/path/a_file.txt"
    body = "This is some text"
    resource.Object(bucket, path).put(Body=body)

    with tempfile.NamedTemporaryFile() as tmp:
        download_file_from_s3(bucket, path, tmp.name)

        with open(tmp.name) as f:
            content = f.read()
            assert content == body
            print(f"content: {content}")
test_download_file_from_s3()<jupyter_output>content: This is some text<jupyter_text>Factory_boy & Fakerhttps://colab.research.google.com/drive/1ufscOECvZNMSpqkoM-bLHS-3CqStBLt7scrollTo=pklyZcQRCDco  With Django  Test Django ORM`@pytest.mark.django_db`:- This is used to mark a test function as requiring the database. It will ensure the __database is set up correctly for the test__.   - Each test will run __in its own transaction__ which will __be rolled back__ at the end of the test. This behavior is the same as Django’s standard `TestCase` class.Examples: `lyst-gohan/tests/gohan/test_models.py`  Management Command- Example: `judy/tests/judy/management/commands/test_generate_candidates.py` (LYST) Management command + Monkeypatch<jupyter_code><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1377066175200138, 'fraction_numerical': 0.027385820422738006, 'mean_word_length': 2.250982961992136, 'pattern_counts': {'":': 23, '<': 81, '<?xml version=': 0, '>': 121, 'https://': 23, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 203, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '573083', 'license': 'Apache-2.0', 'n_tokens_mistral': 10684, 'n_tokens_neox': 9876, 'n_words': 2442, 'path': 'Python/pytest_examples.ipynb', 'repo_name': 'Chet-Sheng/Speedy', 'size': '34736'}