I know it is a bit silly question, but using links provides below, I am still unable to create testsuite.
I have now two test cases (there will be much more), let assume that the name of there are:
class step1(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
def test_case1(self):
[...]
if __name__ == "__main__":
unittest.main()
and:
class step2(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
def test_case2(self):
[...]
if __name__ == "__main__":
unittest.main()
I want to create other file .py file: testsuite, which can aggregate test_case1, test_case2, test_case3...
I tried something like that, for example:
import unittest
import step1
import step2
def suite():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.step1(test_case1))
test_suite.addTest(unittest.step2(test_case2))
if __name__ == "__main__":
result = unittest.TextTestRunner(verbosity=2).run(suite())
sys.exit(not result.wasSuccessful())
Error: AttributeError: 'module' object has no attribute 'step1'
You can use addTest() and pass TestCase instance to it, you also miss return statement:
def suite():
test_suite = unittest.TestSuite()
test_suite.addTest(step1())
test_suite.addTest(step2())
return test_suite
or, in one line using addTests():
test_suite.addTests([step1(), step2()])
Related
I am rapid prototyping so for now I would like to write unit tests together with the code I am testing - rather than putting the tests in a separate file. However, I would only like to build the test an invoke them if we run the code in the containing file as main. As follows:
class MyClass:
def __init(self)__:
# do init stuff here
def myclassFunction():
# do something
if __name__ == '__main__':
import unittest
class TestMyClass(unittest.TestCase):
def test_one(self):
# test myclassFunction()
suite = unittest.TestLoader().loadTestsFromTestCase(TestMyClass)
unittest.TextTestRunner(verbosity=2).run(suite)
This of course doesn't run as unittest is unable to find or make use of the test class, TestMyClass. Is there a way to get this arrangement to work or do I have to pull everything out of the if __name__ == '__main__' scope except the invocation to unittest?
Thanks!
If you move your TestMyClass above of if __name__ == '__main__'
you will get exactly what you want:
Tests will run only when file executed as main
Something like this
import unittest
class MyClass:
def __init(self)__:
# do init stuff here
def myclassFunction():
# do something
class TestMyClass(unittest.TestCase):
def test_one(self):
if __name__ == '__main__':
unittest.main()
I am trying some Python with selenium, I have some defined tests in simpleUsageUnittest.py:
import unittest
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class PythonOrgSearch(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
# #unittest.skip("skip test_001")
def test_001_search_in_python_org(self):
driver = self.driver
driver.get("http://www.python.org")
self.assertIn("Python", driver.title)
elem = driver.find_element_by_name("q")
elem.send_keys("selenium")
elem.send_keys(Keys.RETURN)
# #unittest.skip("skip test_002")
def test_002_goole_and_stack_test_test(self):
driver_g = self.driver
driver_g.get("http://www.google.com")
self.assertIn("Google", driver_g.title)
body_g = driver_g.find_element_by_tag_name("body")
body_g.send_keys(Keys.CONTROL + 't')
driver_g.get("http://stackoverflow.com")
self.assertIn("Stack", driver_g.title)
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main(warnings = 'ignore')
Alone this set is working perfectly, but then I am trying to create some suite, testTestSuite.py:
import unittest
import simpleUsageUnittest
import sys
def suite():
testSuite = unittest.TestSuite()
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch.setUp)
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch.test_001_search_in_python_org)
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch.test_002_goole_and_stack_test_test)
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch.tearDown)
return testSuite
if __name__ == "__main__":
result = unittest.TextTestRunner(verbosity=2).run(suite())
sys.exit(not result.wasSuccessful())
And while running this suite I encounter AttributeError: 'TextTestResult' object has no attribute 'assertIn', and since I dont exactly understand it I cannot fix it ;) If I delete assertIn lines in simpleUsageUnittest.py - then it is working again, but it is of course not what I want to do! Also Asserts in Python 2.7 not working for me example assertIn was not a big help since I am using Python 3.3.5 and Selenium 2.41.0. Can someone explain it to me? Or direct what attributes can I use to save my assert? ;)
Full trace:
C:\Users\zzz\Python\selenium_tutorial>python testTestSuite.py
Traceback (most recent call last):
File "testTestSuite.py", line 14, in <module>
result = unittest.TextTestRunner(verbosity=2).run(suite())
File "C:\Python33\lib\unittest\runner.py", line 168, in run
test(result)
File "C:\Python33\lib\unittest\suite.py", line 67, in __call__
return self.run(*args, **kwds)
File "C:\Python33\lib\unittest\suite.py", line 105, in run
test(result)
File "C:\Users\zzz\Python\selenium_tutorial\simpleUsageUnittest.py", line
18, in test_001_search_in_python_org
self.assertIn("Python", driver.title)
AttributeError: 'TextTestResult' object has no attribute 'assertIn'
SOLUTION
OK, it looks like in my testTestSuite.py, while executing, TextTestRunner treats "self.asserIn" lines in simpleUsageUnittest.py as self == TextTestRunner not as self == TestCase (I dont know if I explain/understand it correctly, but it is how i see it ;)). Here is fixed testTestSuite.py:
import unittest
import simpleUsageUnittest
import sys
def suite():
testSuite = unittest.TestSuite()
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch('test_001_search_in_python_org'))
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch('test_002_goole_and_stack_test_test'))
return testSuite
if __name__ == "__main__":
result = unittest.TextTestRunner(verbosity=2).run(suite())
sys.exit(not result.wasSuccessful())
'setUp' and 'tearDown' are missing because they are called automatically after every 'test'.
SOLUTION
OK, it looks like in my testTestSuite.py, while executing, TextTestRunner treats "self.asserIn" lines in simpleUsageUnittest.py as self == TextTestRunner not as self == TestCase (I dont know if I explain/understand it correctly, but it is how i see it ;)). Here is fixed testTestSuite.py:
import unittest
import simpleUsageUnittest
import sys
def suite():
testSuite = unittest.TestSuite()
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch('test_001_search_in_python_org'))
testSuite.addTest(simpleUsageUnittest.PythonOrgSearch('test_002_goole_and_stack_test_test'))
return testSuite
if __name__ == "__main__":
result = unittest.TextTestRunner(verbosity=2).run(suite())
sys.exit(not result.wasSuccessful())
'setUp' and 'tearDown' are missing because they are called automatically after every 'test'.
I am new to unit testing using python and am designing a simple unit test setup. This is what I have made:
/python_test
__init__.py
unittest_main.py
test_abc/
__init__.py
test_abc.py
test_pqr/
__init__.py
test_pqr.py
All the __init__.py files are empty and the other files have some basic content:
unittest_main.py
import os
import sys
import glob
import inspect
import unittest
from sets import Set
if len(sys.argv) > 1:
testCases = glob.glob('test_*')
testTargets = Set([])
for testTarget in sys.argv:
if testTarget == "test_all":
testTargets = testCases
break
else:
for testCase in testCases:
if testCase == testTarget:
testTargets.add(testCase)
break
if len(testTargets) > 0:
print testTargets
suiteList = []
for testTarget in testTargets:
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],testTarget)))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
suiteList.append(unittest.defaultTestLoader.loadTestsFromModule("python_test"+"."+testTarget+"."+testTarget))
mainSuite = unittest.TestSuite(suiteList)
unittest.TextTestRunner(verbosity=1).run(mainSuite)
else:
"No Proper Test Targets Specified"
else:
print "No Test Targets Specified"
test_abc.py
import unittest
class test_abc(unittest.TestCase):
def setUp(self):
print "Setup Complete"
def tearDown(self):
print "Tear Down Complete"
def test_abc_main(self):
self.assertEqual(1, 2, "test-abc Failure")
if __name__ == "__main__":
unittest.main()
test_pqr.py
import unittest
class test_pqr(unittest.TestCase):
def setUp(self):
print "Setup Complete"
def tearDown(self):
print "Tear Down Complete"
def test_abc_main(self):
self.assertEqual(1, 2, "test-pqr Failure")
if __name__ == "__main__":
unittest.main()
Question:
I am able to test the test cases separately but when I use the parent directly file to run all the tests, nothing happens?
$ ~/src/python_test$ python unittest_main.py test_all
['test_pqr', 'test_abc']
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
The installed Python Version is 2.7.3
Because you're passing module names to the loader, you want to use loadTestsFromName instead of loadTestsFromModule.
I want to write tests for my main file,calc.py, with unittest in module file, MyTests.py.
Here is my main python file, calc.py:
import myTests
def first(x):
return x**2
def second(x):
return x**3
def main():
one = first(5)
two = second(5)
if __name__ == "__main__":
main()
try:
myTests.unittest.main()
except SystemExit:
pass
And here is my MyTests.py file:
import unittest
import calc
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.testInput = 10
def test_first(self):
output = calc.first(self.testInput)
correct = 100
assert(output == correct)
def test_second(self):
output = calc.second(self.testInput)
correct = 1000
assert(output == correct)
When i run my calc.py, i get the following output:
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Why does unittest prints me that "Ran 0 test"?
And what is the right way to write unittest in module?
unittests.main() looks for TestCase instances in the current module. Your module has no such testcases; it only has a myTests global.
Best practice is to run the tests themselves. Add the __main__ section there to the myTests.py file:
import unittest
import calc
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.testInput = 10
def test_first(self):
output = calc.first(self.testInput)
correct = 100
assert(output == correct)
def test_second(self):
output = calc.second(self.testInput)
correct = 1000
assert(output == correct)
if __name__ == '__main__':
unittest.main()
and run python myTests.py instead.
Alternatively, pass in the imported myTests module into unittest.main(). You may want to move the import myTests line down into __main__, because you have a circular import too. That is fine in your case, myTests doesn't use any globals from calc outside of the test cases, but it is better to be explicit about this.
if __name__ == "__main__":
main()
try:
import myTests
myTests.unittest.main(myTests)
except SystemExit:
pass
I have a unittest that tests the connection of an url. Individually it works, but I have several urls to test, so I'm trying to call this test module and batch-test them! But I get errors in calling the test function. Could you help me?
test.py:
class TestConnector(unittest.TestCase):
def setUp(self):
[...]
def test_connection(self, url):
conn = Connector(self.user)
self.assertNotEqual(conn.read(url), None)
if __name__ == '__main__':
unittest.main()
Now I want to test several urls, so I created file with them, and try to call the test function:
import test
with open('URL_list.txt') as f:
urls = f.readlines()
suite = unittest.TestLoader().loadTestsFromModule(test.TestConnector)
for url in urls:
unittest.TextTestRunner().run(suite)
And I get this message as many times as urls I have:
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
----------------------------------------------------------------------
What's wrong?
Your test method is ignored because it takes an argument. Test methods never take an argument. This is quite beside the fact that Python won't ever magically pass a local variable name into a function as an argument; you'd have to explicitly pass it in.
Integrate your url loading into the test itself instead:
class TestConnector(unittest.TestCase):
def setUp(self):
[...]
def test_connections(self):
with open('URL_list.txt') as f:
for url in f:
conn = Connector(self.user)
self.assertNotEqual(conn.read(url.strip()), None)
if __name__ == '__main__':
unittest.main()
or create test methods dynamically:
class TestConnector(unittest.TestCase):
def setUp(self):
[...]
def generate_test(url):
def test(self):
conn = Connector(self.user)
self.assertNotEqual(conn.read(url), None)
if __name__ == '__main__':
with open('URL_list.txt') as f:
for i, url in enumerate(f):
test_name = 'test_{}'.format(i)
setattr(TestConnector, test_name, generate_test(url.strip()))
unittest.main()