[PYTHON] Utilisez Mock avec pytest

introduction

Quand j'ai écrit le code de test en utilisant pytest, j'ai eu du mal à utiliser Mock, donc je l'ai résumé.

Qu'est-ce que Mock

Mock est un module qui facilite les tests unitaires pour le compte d'objets spécifiques.

Préparation

  1. Installez pytest

    pip install pytest pytest-mock
    
  2. Créez du code à tester

Structure du répertoire

```bash
root
├─src
│   └─script.py ・ ・ ・ Code source à tester
└─tests
    ├─__init__.py ・ ・ ・ fichier vide
    └─script.py ・ ・ ・ code de test
```

Code source à tester

```python:src/script.py
import requests


def sample1(url):
    return sample2(url)


def sample2(url):
    try:
        response = requests.get(url)
        return response.status_code
    except Exception:
        return 0


class SampleClass:
    def __init__(self):
        self._req = requests

    def get(self, url):
        try:
            response = self._req.get(url)
            return response.status_code
        except Exception:
            return 0
```

Effectuer des tests à l'aide de Mock

Se moquer de la fonction

Remplacez la fonction sample2 lors du test de la fonction sample1.

Spécifiez la valeur de retour de la fonction

Code de test

tests/test_script.py


from src.script import sample1


def test_sample1_mock_sample2_200(mocker):
    """
Faites en sorte que la fonction sample2 renvoie 200.
    """
    status_code = 200
    url = "https://hogehoge.com"
    mocker.patch("src.script.sample2", return_value=status_code)
    assert sample1(url) == status_code


def test_sample1_mock_sample2_404(mocker):
    """
Faites en sorte que la fonction sample2 renvoie 404.
    """
    status_code = 404
    url = "https://fugafuga.com"
    mocker.patch("src.script.sample2", return_value=status_code)
    assert sample1(url) == status_code

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 2 items

tests\test_script.py ..                                        [100%] 

========================= 2 passed in 0.19s =========================

Changer dynamiquement la valeur de retour d'une fonction

Code de test

tests/test_script.py


from src.script import sample1


def test_sample1_mock_sample2(mocker):
    """
La fonction sample2 est 200 par url,404,Essayez de renvoyer l'un des 0.
    """
    def return_status_code(url):
        """
200 par url,404,Renvoie l'un de 0
        """
        if url == "https://hogehoge.com":
            return 200
        elif url == "https://fugafuga.com":
            return 404
        else:
            return 0

    mocker.patch("src.script.sample2", side_effect=return_status_code)
    assert sample1("https://hogehoge.com") == 200
    assert sample1("https://fugafuga.com") == 404
    assert sample1("https://higehige.com") == 0

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 1 item

tests\test_script.py .                                         [100%] 

========================= 1 passed in 0.20s =========================

Lever une exception lors de l'appel d'une fonction

Code de test

tests/test_script.py


import pytest
from src.script import sample1


def test_sample1_mock_sample2_exception(mocker):
    """
Soulevez une exception lorsque la fonction sample2 est appelée.
    """
    url = "https://hogehoge.com"
    mocker.patch("src.script.sample2", side_effect=Exception)
    with pytest.raises(Exception):
        sample1(url)

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 1 item

tests\test_script.py .                                         [100%] 

========================= 1 passed in 0.17s =========================

Simulez la fonction du module

Remplacez la fonction get du module de requête lors du test de la fonction sample2.

Spécifiez la valeur de retour de la fonction du module

Code de test

tests/test_script.py


import requests
from src.script import sample2


def test_sample2_mock_requests_200(mocker):
    """
requêtes exécutées par la fonction sample2.Remplacez get.
En outre, la valeur de retour est également le statut dans Mock_Remplacez le code pour qu'il renvoie 200.
    """
    status_code = 200
    url = "https://hogehoge.com"
    response_mock = mocker.Mock()
    response_mock.status_code = status_code
    mocker.patch.object(requests, "get", return_value=response_mock)
    assert sample2(url) == status_code


def test_sample2_mock_requests_404(mocker):
    """
requêtes exécutées par la fonction sample2.Remplacez get.
En outre, la valeur de retour est également le statut dans Mock_Remplacez le code pour qu'il renvoie 404.
    """
    status_code = 404
    url = "https://fugafuga.com"
    response_mock = mocker.Mock()
    response_mock.status_code = status_code
    mocker.patch.object(requests, "get", return_value=response_mock)
    assert sample2(url) == status_code

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 1 item

tests\test_script.py ..                                        [100%] 

========================= 2 passed in 0.22s =========================

Lever une exception lors de l'appel d'une fonction de module

Code de test

tests/test_script.py


import requests
from src.script import sample2


def test_sample2_mock_request_exception(mocker):
    """
demandes avec la fonction sample2.Lève une exception lorsque get est appelé.
    """
    status_code = 0
    url = "https://hogehoge.com"
    mocker.patch.object(requests, "get", side_effect=Exception)
    assert sample2(url) == status_code

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 1 item

tests\test_script.py .                                         [100%] 

========================= 1 passed in 0.19s =========================

Mock la fonction appelée dans la méthode de la classe

Lors du test de la méthode get de la classe SampleClass, remplacez la fonction get de _req appelée à l'intérieur.

Spécifie la valeur de retour d'une fonction appelée dans une méthode de classe

Code de test

tests/test_script.py


from src.script import SampleClass


class TestSampleClass:
    def test_get_200(self, mocker):
        """
Appelé par la méthode get de SampleClass_req.Remplacez get.
En outre, la valeur de retour est également le statut dans Mock_Remplacez le code pour qu'il renvoie 200.
        """
        status_code = 200
        url = "https://hogehoge.com"
        sample = SampleClass()
        response_mock = mocker.Mock()
        response_mock.status_code = status_code
        req_mock = mocker.MagicMock()
        req_mock.get = mocker.Mock(return_value=response_mock)
        mocker.patch.object(sample, "_req", req_mock)
        assert sample.get(url) == status_code

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 1 item

tests\test_script.py .                                         [100%] 

========================= 1 passed in 0.21s =========================

Lever une exception lors de l'appel d'une fonction appelée dans une méthode de classe

Code de test

tests/test_script.py


from src.script import SampleClass


class TestSampleClass:
    def test_get_exception(self, mocker):
        """
Avec la méthode get de SampleClass_req.Lève une exception lorsque get est appelé.
        """
        status_code = 0
        url = "https://hogehoge.com"
        sample = SampleClass()
        req_mock = mocker.MagicMock()
        req_mock.get = mocker.Mock(side_effect=Exception)
        mocker.patch.object(sample, "_req", req_mock)
        assert sample.get(url) == status_code

Résultat d'exécution

 > pytest
======================== test session starts ========================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\root
plugins: cov-2.10.0, mock-3.3.1
collected 1 item

tests\test_script.py .                                         [100%] 

========================= 1 passed in 0.21s =========================

Résumé

Je viens de faire des recherches et de l'essayer moi-même, donc je ne sais pas si c'est la bonne façon de l'utiliser.

Recommended Posts

Utilisez Mock avec pytest
Utilisez mecab-ipadic-neologd avec igo-python
Utilisez RTX 3090 avec PyTorch
Utiliser pipdeptree avec virtualenv
[Python] Utiliser JSON avec Python
Utiliser l'indicateur avec pd.merge
Utiliser Gentelella avec Django
Je veux moquer datetime.datetime.now () même avec pytest!
Testé avec boto3 + mock
Utiliser mecab avec Python 3
Utiliser tensorboard avec Chainer
Utiliser DynamoDB avec Python
Utiliser pip avec MSYS2
Utilisez Python 3.8 avec Anaconda
Utiliser les droits d'auteur avec Spacemacs
Utiliser python avec docker
Utiliser TypeScript avec django-compresseur
Utilisez LESS avec Django
Utiliser MySQL avec Django
Utiliser Enum avec SQLAlchemy
Utiliser tensorboard avec NNabla
Utiliser le GPS avec Edison
Utilisez nim avec Jupyter
Utiliser l'API Trello avec python
Utiliser la mémoire partagée avec une bibliothèque partagée
Utiliser des balises personnalisées avec PyYAML
Utiliser des graphiques directionnels avec networkx
Utiliser TensorFlow avec Intellij IDEA
Utiliser l'API Twitter avec Python
Essayez Google Mock avec C
Utiliser pip avec Jupyter Notebook
Test unitaire du flacon avec pytest
Utiliser DATE_FORMAT avec le filtre SQLAlchemy
Tester la sortie standard avec Pytest
Utiliser TUN / TAP avec Python
Utilisez sqlite3 avec NAO (Pepper)
Utilisez les load_extensions de sqlite avec Pyramid
Utiliser les polices Windows 10 avec WSL
Utilisation du chainer avec Jetson TK1
Utiliser SSL avec Celery + Redis
Utiliser Cython avec Jupyter Notebook
Utilisez Maxout + CNN avec Pylearn2
Utilisez WDC-433SU2M2 avec Manjaro Linux
Utilisez OpenBLAS avec numpy, scipy
Utiliser l'API subsonique avec python3
Utilisation de Sonicwall NetExtener avec Systemd
Utilisez prefetch_related commodément avec Django
Utiliser l'interpréteur AWS avec Pycharm
Utilisation de Bokeh avec IPython Notebook
Utiliser une plage de type Python avec Rust
Utiliser MLflow avec Databricks ④ --Call model -
Utiliser pyright avec CentOS7, emacs lsp-mode
Python: comment utiliser async avec
Utilisation de la base de données SQL d'Azure avec SQL Alchemy
Utiliser la caméra Point Grey avec Python (PyCapture2)
Utilisez vl53l0x avec RaspberryPi (python)
Utilisez PX-S1UD / PX-Q1UD avec Jetson nano
Mock in python - Comment utiliser mox
Utilisez la fonction de prévisualisation avec aws-cli
Pour utiliser virtualenv avec PowerShell