When I wrote the test code using pytest, I had a hard time using Mock, so I summarized it.
Mock is a module that facilitates unit testing on behalf of specific objects.
Install pytest
pip install pytest pytest-mock
Create code to test
Directory structure
```bash
root
├─src
│ └─script.py ・ ・ ・ Source code to be tested
└─tests
├─__init__.py ・ ・ ・ empty file
└─script.py ・ ・ ・ Test code
```
Source code to be tested
```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
```
Replace the sample2 function when testing the sample1 function.
Test code
tests/test_script.py
from src.script import sample1
def test_sample1_mock_sample2_200(mocker):
"""
Make the sample2 function return 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):
"""
Make the sample2 function return 404.
"""
status_code = 404
url = "https://fugafuga.com"
mocker.patch("src.script.sample2", return_value=status_code)
assert sample1(url) == status_code
Execution result
> 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 =========================
Test code
tests/test_script.py
from src.script import sample1
def test_sample1_mock_sample2(mocker):
"""
sample2 function is 200 by url,404,Try to return one of 0.
"""
def return_status_code(url):
"""
200 by url,404,Returns one of 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
Execution result
> 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 =========================
Test code
tests/test_script.py
import pytest
from src.script import sample1
def test_sample1_mock_sample2_exception(mocker):
"""
Raise an Exception when the sample2 function is called.
"""
url = "https://hogehoge.com"
mocker.patch("src.script.sample2", side_effect=Exception)
with pytest.raises(Exception):
sample1(url)
Execution result
> 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 =========================
Replace the get function in the request module when testing the sample2 function.
Test code
tests/test_script.py
import requests
from src.script import sample2
def test_sample2_mock_requests_200(mocker):
"""
requests executed by the sample2 function.Replace get.
Also, the return value is also status in Mock_Replace code so that it returns 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):
"""
requests executed by the sample2 function.Replace get.
Also, the return value is also status in Mock_Replace code so that it returns 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
Execution result
> 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 =========================
Test code
tests/test_script.py
import requests
from src.script import sample2
def test_sample2_mock_request_exception(mocker):
"""
requests with sample2 function.Raise an Exception when get is called.
"""
status_code = 0
url = "https://hogehoge.com"
mocker.patch.object(requests, "get", side_effect=Exception)
assert sample2(url) == status_code
Execution result
> 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 =========================
When testing the get method of the SampleClass class, replace the get function of _req called inside.
Test code
tests/test_script.py
from src.script import SampleClass
class TestSampleClass:
def test_get_200(self, mocker):
"""
Called by get method of SampleClass_req.Replace get.
Also, the return value is also status in Mock_Replace code so that it returns 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
Execution result
> 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 =========================
Test code
tests/test_script.py
from src.script import SampleClass
class TestSampleClass:
def test_get_exception(self, mocker):
"""
With the get method of SampleClass_req.Raise an Exception when get is called.
"""
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
Execution result
> 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 =========================
I just researched various things and tried it myself, so I don't know if it's the correct way to use it.
Recommended Posts