There's a function result = Downloader.downloadFiles(list_to_download, download_path, username, password) in the file downloadModule, which will return a boolean(True/False) to the 'result' variable. How to write a mock to this call such that result will always return True. Tried the following way but got the following error AttributeError: 'function' object has no attribute 'rsplit'.
#patch(downloadModule.Downloader.downloadFiles)
def test_download_files(self,mock_download_files):
mock_download_files.return_value = True
self.assertEqual(downloadModule.Downloader.downloadFiles(),True)
Missing quotes
I think you have only to add the quotes (') as delimiter for the patch parameter downloadModule.Downloader.downloadFiles.
Your code becomes the following:
#patch('downloadModule.Downloader.downloadFiles')
def test_download_files(self,mock_download_files):
mock_download_files.return_value = True
self.assertEqual(downloadModule.Downloader.downloadFiles(),True)
The complete test file
Below I show the test file where is present the statement:
import downloadModule
which import the module downloadModule. The following is the complete test file that I've used on my system:
import unittest
from unittest.mock import patch
import downloadModule
class MyTestCase(unittest.TestCase):
#patch('downloadModule.Downloader.downloadFiles')
def test_download_files(self, mock_download_files):
mock_download_files.return_value = True
self.assertEqual(downloadModule.Downloader.downloadFiles(), True)
if __name__ == '__main__':
unittest.main()
Related
I want to run a single test and output the result to a txt file. I understood that I can use loadTestsFromName to specify the test. However, I'm getting an error.
test.py
import unittest
import sys
import os
def main(out=sys.stderr, verbosity=2):
loader = unittest.TestLoader()
suite = loader.loadTestsFromName(sys.modules[__name__]=='test1')
unittest.TextTestRunner(out, verbosity=verbosity).run(suite)
class TestClass(unittest.TestCase):
def test1(self):
self.assertEqual(True, True)
if __name__ == '__main__':
with open('test-results.txt', 'w') as f:
main(f)
I run the test by executing python test.py
I'm not sure how to get test1. I tried sys.modules[__name__]=='test1' but it triggered this error.
parts = name.split('.')
AttributeError: 'bool' object has no attribute 'split'
According to the python doc-unittest.TestLoader.loadTestsFromName, below code is work for me.
import unittest
import sys
import os
def main(out=sys.stderr, verbosity=2):
loader = unittest.TestLoader()
suite = loader.loadTestsFromName('__main__.TestClass.test1')
unittest.TextTestRunner(out, verbosity=verbosity).run(suite)
class TestClass(unittest.TestCase):
def test1(self):
self.assertEqual(True, True)
if __name__ == '__main__':
with open('test-results.txt', 'w') as f:
main(f)
Besides, you'd better separate the TestCase to the single module, then change the __main__ to the module name.
I have 3 files:
main.py
from util import ResultGetter
result_getter = ResultGetter()
result = result_getter.get_result()
def function_a():
return result
util.py
class ResultGetter:
def get_result(self):
return False
and test_main.py
import main
from _pytest.monkeypatch import MonkeyPatch
def test_function_a():
def get_new_result():
return True
monkeypatch = MonkeyPatch()
monkeypatch.setattr(main.result_getter, "get_result", get_new_result)
result = main.function_a()
assert(result == True)
I'm attempting to override the behavior of get_result with get_new result and make the assertion True. However it's still pulling in the False from util.py.
I am new to mocking in python, so any help would be appreciated.
The problem here is that this block below is set outside the scope of the function :
result_getter = ResultGetter()
result = result_getter.get_result()
I changed the main.py to :
from util import ResultGetter
def function_a():
return ResultGetter().get_result()
And it worked. The problem here is you can't access the value of the object outside the function with the MonkeyPatch or even with the patch function like :
with patch("__main__.ResultGetter.get_result") as get_new_result:
get_new_result.return_value= True
result = function_a()
Since it's set up beforehands your test from the object result_getter.
Currently trying to write a unittest for a particular function. The error is shown below:
E
======================================================================
ERROR: https://www (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'https://www'
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
While the funtion itself has not been called within the Test function, I am trying to initialize a class Hasher inside the test. Commenting out the initialization line leads to the program running.
class Test(unittest.TestCase):
def test_YT(self):
self.H = Hasher()
self.assertTrue(True)
The code for the class is shown below:
class Hasher:
import hashlib
def __init__(self, hash_algo='md5'):
print('we getting here')
# TODO: support for more hash algos
self.hash_algo = hash_algo
def hash_file(self, filename):
return hashlib.md5(open(filename, 'rb').read()).hexdigest()
def compare_file_txt(self, filename, hash_txt_file):
# Useful for when there is an MD5 txt in the folder
hash1 = self.hash_file(filename)
if hash1 == open(hash_txt_file).readline():
return True
return False
def YT_create_hash(self, link, output_loc='test_hash.txt'):
DL = Downloader()
file_name = DL.YT_extract(link)
hash_txt = self.hash_file(os.getcwd() + '/' + file_name)
o_file = open(output_loc, 'w')
o_file.write(hash_txt)
o_file.close()
There's nothing in the class initialization which indicates that it is using 'https://www', so not really sure where this error is coming from.
My imports are in the form of:
from Hasher import *
from Downloader import *
And my file structure right now is:
It is almost never a good idea to use from my module import *. This can cause clashes with names imported from other modules, bugs due to the wrong function or class used, and unwanted side effects.
Try to always import only needed objects. Use tools like pylint or flake8, or the built-in hints in your IDE to be notified of similar issues.
In this concrete case, the statement from downloader import * most probably caused the problem.
I have a python script which currently takes a command line argument 'path to the json file' and carries out some cleaning up on the data.
I am writing some unit tests where I am trying to pass path to the json file as an arg. It currently comes up with an error when no arg is passed but when it is passed i get the error:
AttributeError: 'module' object has no attribute 'data' which is data.json.
I want to have three separate unit tests each having a different json file to be passed as an argument.
My code is as follows:
import unittest
import sys
import argparse
class TestTransform(unittest.TestCase):
def test_transform(self,input_filename):
target = __import__("cleaning.py")
transform = target
transform.ARGS(input_filename)
self.assertTrue('Pass')
if __name__ == '__main__':
unittest.main()
If I understood your problem correctly here is what I normally do in this case. I override the setUpClass method and make all the inputs to this class attributes that can be accessed by the tests:
class TestTransform():
#classmethod
def setUpClass(self, file_name):
self.input_filename = file_name
#Some other initialization code here
def test_transform(self):
target = __import__("cleaning.py")
transform = target
transform.ARGS(self.input_filename)
self.assertTrue('Pass')
If you then want to make different tests with different input values you can create other classes by subclassing the TestTransform class (and of course the unittest.TestCase):
class Test1(TestTransform, unittest.TestCase):
#classmethod
def setUpClass(self):
input_filename = 'MyFileName'
#Here call the setUpClass from the TestTransform class
TestTransform.setUpClass(input_filename)
I need to write a unit test for credential checking module looks something like below. I apologize I cannot copy the exact code.. but I tried my best to simplify as an example.
I want to patch methodA so it returns False as a return value and test MyClass to see if it is throwing error. cred_check is the file name and MyClass is the class name. methodA is outside of MyClass and the return value checkedcredential is either True or False.
def methodA(username, password):
#credential check logic here...
#checkedcredential = True/False depending on the username+password combination
return checkedcredential
class MyClass(wsgi.Middleware):
def methodB(self, req):
username = req.retrieve[constants.USER]
password = req.retrieve[constants.PW]
if methodA(username,password):
print(“passed”)
else:
print(“Not passed”)
return http_exception...
The unit test I currently have looks like...
import unittest
import mock
import cred_check import MyClass
class TestMyClass(unittest.Testcase):
#mock.patch('cred_check')
def test_negative_cred(self, mock_A):
mock_A.return_value = False
#not sure what to do from this point....
The part I want to write in my unittest is return http_exception part. I am thinking of doing it by patching methodA to return False. After setting the return value, what would be the proper way of writing the unittest so it works as intended?
What you need to do in your unittest to test http_exception return case is:
patch cred_check.methodA to return False
Instantiate a MyClass() object (you can also use a Mock instead)
Call MyClass.methodB() where you can pass a MagicMock as request and check if the return value is an instance of http_exception
Your test become:
#mock.patch('cred_check.methodA', return_value=False, autospec=True)
def test_negative_cred(self, mock_A):
obj = MyClass()
#if obj is a Mock object use MyClass.methodB(obj, MagicMock()) instead
response = obj.methodB(MagicMock())
self.assertIsInstance(response, http_exception)
#... and anything else you want to test on your response in that case
import unittest
import mock
import cred_check import MyClass
class TestMyClass(unittest.Testcase):
#mock.patch('cred_check.methodA',return_value=False)
#mock.patch.dict(req.retrieve,{'constants.USER':'user','constants.PW':'pw'})
def test_negative_cred(self, mock_A,):
obj=MyClass(#you need to send some object here)
obj.methodB()
It should work this way.