How to import SubRequest (pytest)? - python

In the following code, the request has the type of <class '_pytest.fixtures.SubRequest'>. I want to add type hint to the parameter request.
#pytest.fixture
def dlv_service(request: SubRequest): # How to import SubRequest?
print(type(request), request)
filepath = pathlib.Path(request.node.fspath.strpath)
f = filepath.with_name("file.json")
The following import doesn't work.
from pytest.fixtures import SubRequest

I've found one on the internet, hope this will help.
from _pytest.fixtures import SubRequest
I think it's worth trying, but not sure whether it could work, sorry.

For some applications, such as accessing the node property, you can import FixtureRequest, which is part of the public API and a superclass of SubRequest. See yourself:
from _pytest.fixtures import SubRequest
from pytest import FixtureRequest
issubclass(SubRequest, FixtureRequest)
hasattr(FixtureRequest, "node")
Applying this to your example:
from pathlib import Path
import pytest
from pytest import FixtureRequest
#pytest.fixture
def dlv_service(request: FixtureRequest) -> Path:
print(type(request), request)
filepath = Path(request.node.fspath.strpath)
return filepath.with_name("file.json")

Related

Unable to mock function called from another files in python using python-mockito

I am using python-mockito library for mocking. Here's a sample code piece that I am working on.
build_config.py
from read_report_config import *
def config_builder(*some parameters*):
.
.
.
new_enabled_list = read_gsheet_config(logging, "Some sheet name", config_dir, data)
.
.
.
return config_data;
test_build_config.py
from unittest import TestCase
from mockito import when, mock, verifyStubbedInvocationsAreUsed
import requests
from src import build_config, read_report_config
class SimpleMockitoTest(TestCase):
def test_build_config(self):
new_enabled_list = ['hello', 'something', 'it', 'is']
when(read_report_config).read_gsheet_config(...).thenReturn(new_enabled_list)
config_data = build_config.config_builder(*some parameters*)
if __name__ == '__main__':
unittest.main()
Now the problem is that, when I try to test test_build_config, it doesn't mock the read_gsheet_config, it actually runs it, I don't know why?
It's important to understand where to patch.
As answered in this stackoverflow answer
I have to patch it like:
when(build_config).read_gsheet_config(...)thenReturn()

How to mock an import within an import

So I am trying to test an api lookup with my mock data.
I am testing a method within transform.py that imports a module lookup
import lookup
col = lookup.ColFinder()
url = "xyz"
if col.is_present(url):
do this
lookup.py
import secdata
class ColFinder():
def is_present(url):
if url in secdata.CUSTOM_STUFF:
return secdata.CUSTOM_STUFF[url]
secdata.py
secdata.CUSTOM_STUFF=load("some_file")
I want to mock the JSON (file being loaded within secdata.CUSTOM_STUFF)
I have tried mocking using the unittest.mock with some custom config within tests/resources
CUSTOM_CONFIG = secdata.load(os.path.join(os.path.dirname(__file__),'/resources/custom_config.json'))
import mock
#mock.patch("transform.lookup.secdata.CUSTOM_STUFF" , return_value=CUSTOM_CONFIG)
def test_blah_blah(self, *_):
but this doesn't seem to load the file I am trying to reference. Please can someone help me mock this, point out what am I doing wrong.
Thank you in advance.

Python unit test patch failing

So I was following this youtube video:
https://youtu.be/6tNS--WetLI?t=1973
When I replicate what is done in the video, my test fails:
Class:
import requests
class JetpackRebooter:
#staticmethod
def reboot_jetpack(secure_token):
response = requests.post('http://my.jetpack/restarting/reboot/', data={'gSecureToken' : secure_token})
return response.status_code
Unit test:
from src.jetpack_rebooter import JetpackRebooter
from unittest.mock import patch
def test_reboot_jetpack():
secure_token = 'ca26bacf85c6d69d0bdaa3ff07df3cc4118abf45'
with patch("jetpack_rebooter.requests.post") as mocked_post:
mocked_post.return_value.status_code = 200
assert JetpackRebooter.reboot_jetpack(secure_token) == 200
However, changing patch("jetpack_rebooter.requests.post") to patch("requests.post") causes the test to pass. Why is this?
patch("jetpack_rebooter.requests.post") does not work because the module's full import path is not jetpack_rebooter, but src.jetpack_rebooter.
Because of that, patch("src.jetpack_rebooter.requests.post") would work.
However, as src.jetpack_rebooter.requests points to the requests module object, there is no difference between patch("src.jetpack_rebooter.requests.post") and patch("requests.post"); but there would be a difference between patch("src.jetpack_rebooter.requests") and patch("requests").

Patching a function in a file where it is defined

I am trying to learn unittest patching. I have a single file that both defines a function, then later uses that function. When I try to patch this function, its return value is giving me the real return value, not the patched return value.
How do I patch a function that is both defined and used in the same file? Note: I did try to follow the advice given here, but it didn't seem to solve my problem.
walk_dir.py
from os.path import dirname, join
from os import walk
from json import load
def get_config():
current_path =dirname(__file__)
with open(join(current_path, 'config', 'json', 'folder.json')) as json_file:
json_data = load(json_file)
return json_data['parent_dir']
def get_all_folders():
dir_to_walk = get_config()
for root, dir, _ in walk(dir_to_walk):
return [join(root, name) for name in dir]
test_walk_dir.py
from hello_world.walk_dir import get_all_folders
from unittest.mock import patch
#patch('walk_dir.get_config')
def test_get_all_folders(mock_get_config):
mock_get_config.return_value = 'C:\\temp\\test\\'
result = get_all_folders()
assert set(result) == set('C:\\temp\\test\\test_walk_dir')
Try declaring the patch in such way:
#patch('hello_world.walk_dir.get_config')
As you can see this answer to the question you linked, it's recommended that your import statements match your patch statements. In your case from hello_world.walk_dir import get_all_folders and #patch('walk_dir.get_config') doesn't match.

Import error on django models.py

I wrote this funcion on a utils.py located on the app direcroty:
from bm.bmApp.models import Client
def get_client(user):
try:
client = Client.objects.get(username=user.username)
except Client.DoesNotExist:
print "User Does not Exist"
return None
else:
return client
def to_safe_uppercase(string):
if string is None:
return ''
return string.upper()
Then when i use the function to_safe_uppercase on my models.py file, by importing it in this way:
from bm.bmApp.utils import to_safe_uppercase
I got the python error:
from bm.bmApp.utils import to_safe_uppercase
ImportError: cannot import name to_safe_uppercase
I got the solution for this problem when i change the import statement for:
from bm.bmApp.utils import *
But i can't understand why is this, why when i import the specific function i got the error?
You are doing what is known as a Circular import.
models.py:
from bm.bmApp.utils import to_safe_uppercase
utils.py:
from bm.bmApp.models import Client
Now when you do import bm.bmApp.models The interpreter does the following:
models.py - Line 1: try to import bm.bmApp.utils
utils.py - Line 1: try to import bm.bmApp.models
models.py - Line 1: try to import bm.bmApp.utils
utils.py - Line 1: try to import bm.bmApp.models
...
The easiest solution is to move the import inside the function:
utils.py:
def get_client(user):
from bm.bmApp.models import Client
try:
client = Client.objects.get(username=user.username)
except Client.DoesNotExist:
print "User Does not Exist"
return None
else:
return client
def to_safe_uppercase(string):
if string is None:
return ''
return string.upper()
You are creating a circular import.
utils.py
from bm.bmApp.models import Client
# Rest of the file...
models.py
from bm.bmApp.utils import to_safe_uppercase
# Rest of the file...
I would suggest your refactor your code so that you don't have a circular dependency (i.e. utils should not need to import models.py or vice versa).
I'm not sure I can explain the Import error, but I have three ideas. First, your function needs tweaking. You've used a reserved word 'string' as an argument. Consider renaming.
Second, what happens if you invoke ./manage.py shell, and do the import by hand. Does it give you any different?
Third, try deleting your pyc files to force django to recompile python code (this one is a very long shot...but worth eliminating)

Categories