Creating Unittest class inside function not working - python

In the attached script why 0 testcases are running
import unittest
def smg():
def add(x, y):
return x + y
class SimpleTest(unittest.TestCase):
def testadd1(self):
self.assertEquals(add(4, 5), 9)
if __name__ == '__main__':
unittest.main()
smg()
Gives
Ran 0 tests in 0.000s
What can be done to fix it kindly assist

You might be interested with unittest.TextTestRunner:
A basic test runner implementation that outputs results to a stream.
Sample usage:
However, should you want to customize the building of your test suite, you can do it yourself:
def suite():
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase('test_default_widget_size'))
suite.addTest(WidgetTestCase('test_widget_resize'))
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())
Sample run for your case.
src.py
def add(x, y):
print("Add", x, y)
return x + y
test_src.py
import unittest
from src import add
class SimpleTest(unittest.TestCase):
def testadd1(self):
self.assertEqual(add(4, 5), 9)
if __name__ == '__main__':
unittest.main()
Running tests is as how it's done normally
$ python test_src.py # Using unittest
Add 4 5
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
$ pytest -q # Using pytest
.
1 passed in 0.06s
Now if you want to manually call it via function.
run_tests.py
import unittest
import test_src
def suite():
suite = unittest.TestSuite()
suite.addTest(test_src.SimpleTest('testadd1'))
return suite
def run():
runner = unittest.TextTestRunner()
runner.run(suite())
# run() # Uncomment if you want to try to run it as a script e.g. <python run_tests.py>
You can now just import the file and call run() whenever you need:
$ python3
>>> import run_tests
>>> run_tests.run()
Add 4 5
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
>>>

Take out the code inside of smg function and then run tests from your command-line with python -m unittest <Your Filename>.py.
Your code will look like this:
import unittest
def add(x, y):
return x + y
class SimpleTest(unittest.TestCase):
def testadd1(self):
self.assertEquals(add(4, 5), 9)
if __name__ == '__main__':
unittest.main()
Also you may get a deprecation warning for assertEquals. You might want to change it to assertEqual instead.

Related

How to perform a unittest on a unittest

How do you do a unittest on a unittest. I have a unittest and obviously when it is succesfully it generates an ok message in the terminal but I have struggled to find a way of creating a test for the test based upon that.
Basically looking for a way to test if the below test returns ok.
The Test Below:
import unittest
class TestSum(unittest.TestCase):
def test_sum(self):
self.assertEqual(2+2, 4)
if __name__ == '__main__':
unittest.main()
What this returns in the shell :
Ran 1 test in 0.000s
OK
First of all you have to have function that does the calculation, so you pass that function to the test case.
Example:
import unittest
# Defined the function that does the calculation
def sum_numbers(x, y):
return x + y
class TestSum(unittest.TestCase):
def test_sum(self):
self.assertEqual(sum_numbers(2, 2), 4)
if __name__ == '__main__':
unittest.main()
Now this test will evaluate to ok and you can add more test to test_sum

How to run unittest tests using coverage API

I am trying to generate a coverage report using the coverage-API (https://coverage.readthedocs.io/en/6.3.2/api.html#api).
The simple use-case described on the linked page tells me to wrap my executed code inside the snippet they provide. I am using unittest.main() to execute tests. The below code runs without an error but neither is any report information created nor is print("Done.") executed.
I guess unittest.main() calls a sys.exit() somewhere along the way? How does one use the API to execute all unittest-tests?
Example
import coverage
import unittest
def func(input):
return input
class testInput(unittest.TestCase):
def test_func(self):
self.assertEqual(func(1), 1)
if __name__ == '__main__':
cov = coverage.Coverage()
cov.start()
unittest.main()
cov.stop()
cov.save()
cov.html_report()
print("Done.")
Yes, it looks like unittest.main() is calling sys.exit(). Are you sure you need to use the coverage API? You can skip coverage and most of unittest:
# foo.py
import unittest
def func(input):
return input
class testInput(unittest.TestCase):
def test_func(self):
self.assertEqual(func(1), 1)
Then:
$ python -m coverage run -m unittest foo.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
$ python -m coverage report -m
Name Stmts Miss Cover Missing
--------------------------------------
foo.py 6 0 100%
--------------------------------------
TOTAL 6 0 100%
To get the example to work you can simply put the call to unittest.main() in a try/except statement so the cov.stop() will be called once the unit test has completed.
# testInput.py
import coverage
import unittest
def func(input):
return input
class testInput(unittest.TestCase):
def test_func(self):
self.assertEqual(func(1), 1)
if __name__ == '__main__':
cov = coverage.Coverage()
cov.start()
try:
unittest.main()
except: # catch-all except clause
pass
cov.stop()
cov.save()
cov.html_report()
print("Done.")
This will run as desired, including printing Done. at the end:
python3 testInput.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Done.
The HTML coverage report will have been created in the htmlcov directory in the current working directory.

How to use unittest.TestSuite in VS Code?

In the future, I'll need to add many identical tests with different parameters. Now I am making a sample test suite:
import unittest
class TestCase(unittest.TestCase):
def __init__(self, methodName='runTest', param=None):
super(TestCase, self).__init__(methodName)
self.param = param
def test_something(self):
print '\n>>>>>> test_something: param =', self.param
self.assertEqual(1, 1)
if __name__ == "__main__":
suite = unittest.TestSuite()
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(TestCase)
for name in testnames:
suite.addTest(TestCase(name, param=42))
unittest.TextTestRunner(verbosity=2).run(suite)
It gets discovered by VS Code:
start
test.test_navigator.TestCase.test_something
When I run the tests, I don't receive the parameter:
test_something (test.test_navigator.TestCase) ...
>>>>>> test_something: param = None
ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
If I run this file directly, everything works as expected (note param = 42 part)
test_something (__main__.TestCase) ...
>>>>>> test_something: param = 42
ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
So it looks like VS Code is running the tests on its own just by using the discovered classes and ignoring TestSuite completely?
What am I doing wrong?
Thanks.
The problem is your code is in a if __name__ == "__main__" block which is only executed when you point Python directly at the file. So when the extension asks unittest to get all the tests and then run them for us it doesn't run the code in your if __name__ == "__main__" block (which is why it can find it but it doesn't do anything magical).
If you can get it to work using unittest's command-line interface then the extension should run it as you want it to.
The key is to implement the load_tests function:
def load_tests(loader, tests, pattern):
suite = unittest.TestSuite()
testnames = loader.getTestCaseNames(TestCase)
for name in testnames:
suite.addTest(TestCase(name, param=42))
suite.addTest(TestCase(name, param=84))
return suite
The documentation says:
If load_tests exists then discovery does not recurse into the package, load_tests is responsible for loading all tests in the package.
Now my tests run as expected.
P.S. Thanks to Brett Cannon for pointing me to Unit testing framework documentation

Unit test in Python not running

I'm trying to test my code with unit tests, but when I try to run it it just says
Finding files... done.
Importing test modules ... done.
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Why isn't it working?
from Graph import Graph
import unittest
class GraphTest:
def setUp(self):
self.graph = Graph()
for i in range(5):
self.graph.addNode(i,"Node"+i)
self.graph.addEdge(1,5,"Edge1,5")
self.graph.addEdge(5,1,"Edge5,1")
self.graph.addEdge(3,2,"Edge3,2")
def test_Connected(self):
self.assertTrue(self.graph.isConnected(1,5))
self.assertTrue(self.graph.isConnected(5,1))
self.assertTrue(self.graph.isConnected(3,2))
self.assertFalse(self.graph.isConnected(2,3))
self.assertFalse(self.graph.isConnected(1,4))
if __name__ == '__main__':
unittest.main()
You should make your GraphTest a subclass of unittest.TestCase

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