Run a specific unittest with loadTestsFromName - python

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.

Related

How to write unit test for this particular function in python?

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()

how to get python unit test overwrite variable from imported package

Trying to figure out how to overwrite a variable during unit testing:
#mainscript.py
import json
org_file = 'unitfile.json'
def load_json (file_name):
with open ('{0}'.format(org_file)) as f:
json_object = json.load(f)
return json_object
new_file = load_json(org_file)
def print_me():
return (new_file['text'])
def main():
print_me()
if __name__ == '__main__':
main()
Unit test:
#test_mainscript.py
import json
import mainscript
import unittest
from unittest.mock import patch
class Testmainscript(unittest.TestCase):
# def setUp(self):
# Not needed when using mock
#patch('mainscript.org_file','unitfile2.json')
def test_print_me(self):
self.assertEqual(mainscript.org_file, 'unitfile2.json') # Correctly overwrites file
self.assertEqual(mainscript.print_me(),'Bye World') #does not pass, still reading unitfile.json instead of unitfile2.json
if __name__ == '__main__':
unittest.main()
This test should fail because because I'm overwriting org_file with unitestfile2.json (which contains {'text':'Bye World'}) instead of unittestfile.json (which contains {'text':'Hello World'})
But its currently passing because the variable isn't being overwritten
What you are looking for is called "mocking", an example for your case:
import json
import mainscript
import unittest
from unittest.mock import patch
class Testmainscript(unittest.TestCase):
# def setUp(self):
# Not needed when using mock
#patch('mainscript.org_file', 'unitfile2.json')
def test_print_me(self):
self.assertEqual(mainscript.print_me(),'Hello World')
if __name__ == '__main__':
unittest.main()
I found the issue is that I am overwriting the file as expected but when I call the test I am not using the mocked file. Wrapping the function seemed to work:
#mainscript.py
import json
org_file = 'unitfile.json'
def load_json (json_file):
with open ('{0}'.format(org_file)) as f:
json_object = json.load(f)
return json_object
def print_me(df_file):
return (df_file['text'])
def main():
print_me()
if __name__ == '__main__':
main()
Here I used the wrapped patch as an input
#test_mainscript.py
import json
import mainscript
import unittest
from unittest.mock import patch
class Testmainscript(unittest.TestCase):
#patch('mainscript.org_file','unitfile2.json')
def test_print_me(self):
self.assertEqual(mainscript.org_file, 'unitfile2.json')
self.assertEqual(mainscript.print_me(mainscript.load_json(mainscript.org_file)),'Bye World')
if __name__ == '__main__':
unittest.main()
Test now work:
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

Unable to run addfinalizer function within a fixture with scope as class

Here’s my test code:
import string
import pytest
import tempfile
import os
#pytest.fixture(scope='class')
def TempFile(request):
(tmp_cfg_fd, tmp_cfg_file_path) = tempfile.mkstemp()
os.close(tmp_cfg_fd)
def RemoveTempFile():
print("Removing %r" %(tmp_cfg_file_path))
os.remove(tmp_cfg_file_path)
request.addfinalizer(RemoveTempFile)
return tmp_cfg_file_path
#pytest.mark.usefixtures(TempFile)
class Test:
def test1(self):
print("I'm in test1")
def test2(self):
print("I'm in test2")
When I run py.test on it, I get this error:
test_4.py:17: in <module>
#pytest.mark.usefixtures(TempFile)
test_4.py:14: in TempFile
request.addfinalizer(RemoveTempFile)
E AttributeError: class Test has no attribute 'addfinalizer'
When the fixture has scope='class', then the Test class fails to run addfinalizer.
But if the fixture has scope='function', and I call the TempFile fixture individually in test1 and test2 functions, then addfinalizer runs properly.
How can I get addfinalizer to run with scope='class'?
The usefixtures mark takes an string, if you change the mark into:
#pytest.mark.usefixtures('TempFile')
it will work correctly.

Is there a way in python to execute all functions in a file without explicitly calling them?

Is there a library or a python magic that allows me to execute all functions in a file without explicitly calling them. Something very similar to what pytest is doing - running all functions that start with 'test_...' without ever registering them anywhere.
For example assume I have a file a.py:
def f1():
print "f1"
def f2():
print "f2"
and assume I have file - my main file - main.py:
if __name__ == '__main__':
some_magic()
so when I call:
python main.py
The output would be:
f1
f2
Here's a way:
def some_magic():
import a
for i in dir(a):
item = getattr(a,i)
if callable(item):
item()
if __name__ == '__main__':
some_magic()
dir(a) retrieves all the attributes of module a. If the attribute is a callable object, call it. This will call everything callable, so you may want to qualify it with and i.startswith('f').
Here's another way:
#!/usr/local/bin/python3
import inspect
import sys
def f1():
print("f1")
def f2():
print("f2")
def some_magic(mod):
all_functions = inspect.getmembers(mod, inspect.isfunction)
for key, value in all_functions:
if str(inspect.signature(value)) == "()":
value()
if __name__ == '__main__':
some_magic(sys.modules[__name__])
It will only call functions that don't have any parameters by using inspect.signature(function).
Have you tried callifile?
pip install callifile
and then, in your file:
from callifile.callifile import callifile as callifile
import sys
callifile(module=sys.modules[__name__], verbose=True)
Self-sufficient example:
In a file some_callify.py:
from callifile.callifile import callifile as callifile
import sys
def f_1():
print "bla"
callifile(module=sys.modules[__name__], verbose=True)
Calling in terminal:
python some_callify.py
Gives me the terminal output:
Apply call_all_function_in_this_file on <module '__main__' from 'some_callify.py'>
See if should call callifile
See if should call f_1
Call f_1
bla

Python suite test doesn't run tests

I am trying to code a suite test, I have one module which runs unit test correctly but I intend to add more modules and test them at once, so I have coded the following code:
#main.py
import unittest
from test.Services import TestOS
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTests( TestOS.TestOS() )
unittest.TextTestRunner().run(suite)
TestOS.py
import unittest
from app.Services.OS import OS
class TestOS(unittest.TestCase):
os = OS()
def setUp(self):
pass
def tearDown(self):
pass
def testOSName(self):
self.assertEquals(self.os.getPlatform(), 'Windows')
def testOSVersion(self):
self.assertEquals(self.os.getVersion(), '7')
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()
After running it, I get this output:
Finding files... done.
Importing test modules ... done.
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
It didn't find any test, What's wrong with my code?
suite.addTest( TestOS.TestOS() ) works only if your testcase contains a runTest() function.
Otherwise you need a "TestLoader" to detect the functions of TestOS that start with "test*".
#main.py
import unittest
from test.Services import TestOS
if __name__ == '__main__':
suite = unittest.TestSuite()
tests = unittest.defaultTestLoader.loadTestsFromTestCase(TestOS)
suite.addTests(tests)
unittest.TextTestRunner().run(suite)
modify your setUp method as follows
def setUp(self):
self.os = OS()
pass

Categories