What is Python UnitTest Framework

In automation testing, organizing your code is very important and client expects us to write automation scripts according to the manual test cases.

We can get good reporting structure if we can exactly map our automation code with manual test cases.

In Python we can use UnitTest testing framework to organize our automation code and to extract reports

To use the methods present in the UnitTest framework, we have to extend the TestCase class present in the Unittest module


									import unittest
									# extend Testcase class
									class DefaultWidgetSizeTestCase(unittest.TestCase):			
									

test fixture

A test fixture represents the preparation needed to perform one or more tests, and any associate cleanup actions. This may involve, for example, creating temporary or proxy databases, directories, or starting a server process.

test case

A test case is the individual unit of testing. It checks for a specific response to a particular set of inputs. unittest provides a base class, TestCase, which may be used to create new test cases.

test suite

A test suite is a collection of test cases, test suites, or both. It is used to aggregate tests that should be executed together.

test runner

A test runner is a component which orchestrates the execution of tests and provides the outcome to the user. The runner may use a graphical interface, a textual interface, or return a special value to indicate the results of executing the tests.

Things to remember while writing unit tests

There few things you should remember while writing unit test cases, I have listed few below. Comment if you know any other than these, i am happy to add.

1. Each test written must be fully independent.

2. Each test must be able to run alone, regardless the order in which they are called.

3. A testing unit should focus on one tiny bit of functionality and prove it correct.

4. Make tests that run fast. Because even if one single test needs more than a few milliseconds to run, development will be slowed down.

5. Use long and descriptive names for testing functions.

6. Reliable. Tests shouldn’t be bound to a given environment or rely on external factors to work. They should work 100% of the time, or they are not going to fulfill their purpose.

7. Don’t make unnecessary assertions

8. Aim for each unit test method to perform exactly one assertion

9. Do not print anything out in unit tests

10. Put assertion parameters in the proper order

Tests in Unittest Python

We have to write automation test according to your manual testcase, all the test in python unittest starts with test prefix.

Based on the tests only the report will be generated, tests can or fail based on the check points present in the test.


							import unittest

							class Test(unittest.TestCase):
								# test should start with test prefix
								def test_FirstTest(self):
									print("This is to show case the simple Test")

							if __name__ == "__main__":
								unittest.main()			
							
first-test-unittest-python-selenium

Lets open Google page in selenium python using unittest framework.


							import unittest
							from selenium import webdriver

							class BingTest(unittest.TestCase):

								def test_Open_bing(self):
									driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
									driver.get("http://bing.com")
									print("Title is : " + driver.title)

							if __name__ == "__main__":
								unittest.main()			
							
first-selenium-unittest-python

setUp

setUp method will execute before every test method present in the test class, for example if we have 100 test cases and one setup method.

SetUp method will get executed 100 time before executing the test, setUp method will be useful when we want to write some code which is not related without checkpoint in our test case.

Consider this scenario, You have to check title of 100 websites, and you have to open the browser newly for every website. Do you think we should write the browser opening code 100 times, and I know you are thinking that, why cannot I just write the steps in a method and call it in tests.

You can write the common steps in a method, but I donot think you will like to call the method 100 time in your code, Am I right ?.

In above scenario we can put such common code or call to common code in your setUp method, so that it will get executed 100 times.

Note : If there is an error in setUp method then tests will not be executed


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):
									def setUp(self):
									 self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
									 print("Browser Opened")  

									def test_open_chercher_tech(self):
									   self.driver.get("http://chercher.tech")
									   print("Opening CherCherTech")
										
									def test_open_bing(self):
										self.driver.get("http://bing.com")
										print("Opening Bing")
										
									def test_open_google(self):
										self.driver.get("http://google.com")
										print("Opening google")
									
								if __name__ == "__main__":
									unittest.main()			
								
setup-method-unittest-python

Order of Test Execution :

We will not have control over the how the tests are executed; by default python unittest executes them in alphabetical order.

I am still researching on how to give some priority to the tests, so that they will execute in user defined order.

tearDown

tearDown method gets executes just after a test completes its execution, this method is one time defined in class.

tearDown method executes for each and every test case present in the test Class in python unittest

Most of the time tearDown method will contain code to close the browser, or to logout or some completion action.

Both setUp and tearDown can be associated with test in same test class.

If setUp() executed, tearDown() will be run whether the test method successful or not.


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									def setUp(self):
									 self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
									 print("Browser Opened")  

									def test_open_chercher_tech(self):
									   self.driver.get("http://chercher.tech")
									   print("Opening CherCherTech")
									   
									def tearDown(self):
										self.driver.quit()
										print("Browser closed")

								if __name__ == "__main__":
									unittest.main()			
								
setup-teardown-unittest-python-selenium

setUpClass

setUpClass method will be executed before running any test method or setUp or tearDown method present in the test Class

setUpClass method gets executed once per test class. setUpClass is called with the class as the only argument and must be decorated as a classmethod(): For example if you want to open a browser once per test class, then we can use setUpClass.

SetUpClass does not require any setUp method to be present in test class.

If an exception is raised during a setUpClass then the tests in the class are not run and the tearDownClass is not run.


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									@classmethod
									def setUpClass(cls):
										cls.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened in setUpClass method")  

									def test_open_chercher_tech(self):
										self.driver.get("http://chercher.tech")
										print("Opening CherCherTech")

								if __name__ == "__main__":
									unittest.main()			
								
setupclass-python-unittest-selenium

tearDownClass

tearDownClass method will be executed after completing all the test methods and all in a class, so tearDownClass method will be executed just before exiting the class from memory.

tearDownClass method will be executed only once in python unittest, and we should annotate this method as @classmethod.

We can use tearDownClass method whether setUpClass method is present or not in the test class.

Below example shows a test class with setUpClass method, setUp method, test method, tearDown method and tearDownClass method.


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									@classmethod
									def setUpClass(cls):
										cls.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened in setUpClass method")
										
									@classmethod
									def tearDownClass(cls):
										cls.driver.quit()
										print("browser closed in tearDownClass method")

									def setUp(self):
										self.driver.get("http://google.com")
										print("opening google in setUp method")

									def tearDown(self):
										self.driver.back()
										print("Navigating back in tearDown method")

									def test_click_about_link(self):
										self.driver.find_element_by_link_text("About").click()
										print("Clicking on About link in google page in test method")

								if __name__ == "__main__":
									unittest.main()			
								
teardownclass-unittest-python-selenium

setUpModule & tearDownModule

setUpModule will be executed before executing any class or any method present in the test class. this will be executed once per module in python.

tearDownModule will be executed after completing everything present in the python module, This method will be executed once per python module.

setUpModule and tearDownModule methods are newly added to python unittest framework

Execution flow is : setUpModule > setUpClass > setUp > test > tearDown > tearDownClass > tearDownModule, Position of the methods will not alter the flow of the execution.

If an exception is raised in a setUpModule then none of the tests in the module will be run and the tearDownModule also will not be run.


								import unittest

								def setUpModule():
									print("setUpModule")

								def tearDownModule():
									print("tearDownModule")

								class Test(unittest.TestCase):

									@classmethod
									def setUpClass(cls):
										print("setUpClass")
										
									@classmethod
									def tearDownClass(cls):
										print("tearDownClass")

									def setUp(self):
										print("setUp")

									def tearDown(self):
										print("tearDown")

									def test_sample_method(self):
										print("test_sample_method")

								if __name__ == "__main__":
									unittest.main()			
								
setupmodule-python-unittest-selenium

Skipping tests and expected failures

Sometimes we may want to skip a particular test because of some reasons, reasons could be 1. the functionality is broken, 2. applicable to a specific condition, 3. Operating system based testcases so on.

We can skip a test by decorating test method with unittest.SkipTest decorator

When we skip a test, unittest framework de-couples the setUp and tearDown methods associated with it, Unittest will skip all the setup and teardown method


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									def setUp(self):
										self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened")  
									 
									def tearDown(self):
										self.driver.quit()
										print("Browser closed")
									
									@unittest.SkipTest
									def test_open_chercher_tech(self):
										self.driver.get("http://chercher.tech")
										print("Opening CherCherTech")
									   
									def test_open_google(self):
										self.driver.get("http://google.com")
										print("Opening google")
									   
								if __name__ == "__main__":
									unittest.main()			
								
skiptest-basic-example-python-unittest-selenium

Skip Test with reason :

We can give reason why we are skipping the test, in the SkipTest decorator


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									def setUp(self):
										self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened")  
									 
									@unittest.skip("my test, my wish to skip the test")
									def test_open_chercher_tech(self):
										self.driver.get("http://chercher.tech")
										print("Opening CherCherTech")
									   
								if __name__ == "__main__":
									unittest.main()			
								

Skip Test with skipIf :

We can skip the test using specific conditions like using if statements, skipIf method gives the ability to the user to skip the test specific condition.

We can provide reason about the conditions, s the second parameter in the decorator.


								@unittest.skipIf( 2 > 6, "two is always greater than 6, ha ha ha")
								def test_run_based_on_condition(self):
									self.driver.get("http://chercher.tech")
									print("Opening CherCherTech")			
								

Skip Test with skipUnless :

We can skip the methods using skipUnless decorator, this is also similar to the skipIf decorator.

This method will be useful when we are running our testcases based on the operating system.


								import unittest
								import sys
								from selenium import webdriver

								class Test(unittest.TestCase):

									def setUp(self):
										self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened")

									@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
									def test_run_in_windows_only(self):
										self.driver.get("http://chercher.tech")
										print("Opening CherCherTech")

								if __name__ == "__main__":
									unittest.main()			
								

expectedFailure :

expectedFailure decorator helps the user to pass the test case even when there is failure in the test, this method will be useful when you are testing negative test case.


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									def setUp(self):
										self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened")

									def test_run_in_windows_only(self):
										self.driver.get("http://chercher.tech")
										raise Exception()
										print("this should not get printed")

								if __name__ == "__main__":
									unittest.main()			
								


without-expectedfailure-selenium-python-unittest

After adding expectedFailure decorator.


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									def setUp(self):
										self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened")

									@unittest.expectedFailure
									def test_run_in_windows_only(self):
										self.driver.get("http://chercher.tech")
										raise Exception()
										print("this should not get printed")

								if __name__ == "__main__":
									unittest.main()			
								
expectedfailure-python-unittest-selenium

skip Test Class :

Similar to test case we can also skip test class present in the python module; we would be using same above skip decorator with Test class.


								import unittest
								import sys
								from selenium import webdriver
								from unittest.case import skip

								@skip
								class Test(unittest.TestCase):

									def setUp(self):
										self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										print("Browser Opened")

									def test_run(self):
										self.driver.get("http://chercher.tech")
										print("Opening CherCherTech")

								if __name__ == "__main__":
									unittest.main()			
								

fail

fail() method unconditionally fails the test case, it also accepts informational a parameter, and this parameter is optional.


								import unittest

								class Test(unittest.TestCase):

									def testName(self):
										self.fail("To showcase we can fail without any condition")

								if __name__ == "__main__":
									unittest.main()			
								
fail-test-unittest-selenium-python

Assertions in unittest python with selenium

Assertion is nothing but the check point or you can say it as verification for the test case to evaluate some item on the execution.

If we donot provide any assertion inside a test case then there is no way to know whether a test case is failed or not.

I know, you are not thinking about 'why cannot I use if else and print like "this test is failed", because printing may help user which checking the log but how will you tell to you client that i have seen it was printing'.

Assertion helps in report generation, based on the assertions the test execution report will be generated.

If the condition provided in the assertion passes then assertion will not have any effect on the test case but unittest framework fails the testcase if an assertion fails

The TestCase class provides several assert methods to check for and report failures, We will see few of the frequently used assertions

There are few assertion which will accept all the values and few assertions will accept only numeric values, by example or by names itself you can differentiate them


								import unittest

								class Test(unittest.TestCase):
									
									def test_run1(self):
										#assertEqual(actual, expected, errorMessage)
										self.assertEqual(1, 1, "1 is not equal to 1")

									def test_run2(self):
										#assertEqual(actual, expected, errorMessage)
										self.assertEqual("h", "p", "h is not equal to p")
										
								if __name__ == "__main__":
									unittest.main()		
								
assertin-unittest-selenium-python

assertEqual

assertEqual compare the first parameter with the second parameter, if both matches the unittest will continue with the remaining execution but the both the values are different then unit test fails the testcase.

Apart from these two values, assertEqual method accepts third parameter for the informational purpose, the third parameter is nothing but the reason we give why the condition failed.

The informational message will be useful while analyzing the execution results, informational message is optional parameter. Even if we donot pass any informational message the assertEqual method works fine.


								import unittest
								from selenium import webdriver

								class Test(unittest.TestCase):

									def testName(self):
										driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
										driver.get("http://bing.com")
										titleOfWebPage = driver.title
										# verify title is bing
										self.assertEqual("Bing", titleOfWebPage, "webpage title is not matching")

								if __name__ == "__main__":
									unittest.main()			
								

assertNotEqual

assertNotEqual method compares the given two parameters, if both parameter are not same then unittest passes the test case but if both parameter are same then unittest fails the test case.

We can also pass informational message as third parameter and it is optional parameter.


								def testName(self):
									driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
									driver.get("http://bing.com")
									titleOfWebPage = driver.title
									# verify title is bing
									self.assertNotEqual("Google", titleOfWebPage, "webpage title is not matching")			
								

assertTrue

when we have only two parameter we can use assertEqual mthod to check whether both are same or not, but if we have more than two parameters, comparing values with assertEqual method become more difficult

assertTrue method checks whether given parameter is true or not, if value is true then test is passed otherwise test is failed.

assertTrue provides ability to the user for writing relational operators, we can use language specific relational operators to compare values inside the assertTrue method. When we use relational operators, they will result in either True or False


def testName(self):
	driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
	driver.get("http://bing.com")
	titleOfWebPage = driver.title
	# verify title is bing
	self.assertTrue((titleOfWebPage!="Google") & (titleOfWebPage!="ChercherTech"), "webpage title is not matching")

assertFalse

assertFalse method compares whether given value or expression results in false or not

If the result or value is False then unittest passes the testcase but if the result or value is True then unittest fails the test case.

You should try to avoid this method when you are comparing only two values, as assertEqual and assertNotEqual provides better error information

assertIs & assertIsNot

assertIs method verifies whether first parameter is same as second parameter

assertIsNot verifies whether first parameter is not same as second parameter.


def testName(self):
	driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
	driver.get("http://bing.com")
	titleOfWebPage = driver.title
	# verify title is bing
	self.assertIs("Bing", titleOfWebPage, "webpage title is not matching")
			

assertIsNone

assertIsNone method verifies whether give values or expression results in None or not, if the result is none then pyhton unittest will pass the test case otherwise fails the testcase.


def testName(self):
	driver = None
	# verify the object is none or not
	self.assertIsNone(driver, "driver has not been initiated")			

assertIsNotNone

assertIsNotNone method verifies whether give values is not None, if the value is None then the test case will be failed

assertIn & assertNotIn

assertIn method verifies whether the first element is present in the send element, if first element is present in second element then test s passed otherwise test is failed.

assertNotIn method verifies whether the first element is not present in the second element or not, if first element is present then test will be failed otherwise test is passed.

These two methods will be helpful when you want to verify presence of a value in a list, tuple, set, and dictionary


def testName(self):
	sampleSet = set(["Perl", "Python", "Java"])
	# check python is present
	self.assertIn("Python", sampleSet, "item is not present in set")
	# check ruby is not present
	self.assertNotIn("Ruby", sampleSet, "item is present in set")			

assertIsInstance & assertNotIsInstance

assertIsInstance method verifies whether the given object is instance of a class or not, if the object is given class type then the test is passed otherwise test will be failed by unittest

assertNotIsInstance method verifies whether given object is type of class or not, if the object is not the type of class then the test will be passed


def test_verify_type_of_object(self):
	driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
	driver.get("http://bing.com")
	# verify the type of the object
	self.assertIsInstance(driver, WebDriver, "driver is not instance of WebDriver")			

assertListEqual

assertListEqual method compares the given two lists and also print the error message based on the difference between the element if any element is mismatching.

assertTupleEqual

assertTupleEqual method compares the given two Tuples, if the tuple are not same then unittest will fail the testcase and also displays the error message based on the mismatched elements

assertSetEqual

assertSetEqual method compares whether two sets are same or not, If not, an error message is constructed that lists the differences between the sets.

assertDictEqual

assertDictEqual method compares two Dictionaries in python

assertDictContainsSubset

Tests whether the key/value pairs in dictionary actual are a superset of those in expected. If not, an error message listing the missing keys and mismatched values is generated.

Relational comparison :


assertGreater verifies whether first values if greater than second value or not.

assertGreaterEqual verifies whether first parameter is grater or equal to the second parameter.

assertLess verifies whether first parameter is lesser than second parameter or not

assertLessEqual verifies whether first parameter is lesser or equal to the second parameter

Loading tests to suite and running tests

unittest.TestLoader :

The TestLoader class is used to create test suites from classes and modules in the python project.

Basically it loads all the testcases into a pot, so that we can run all the test cases present in the pot. I have used Pot word to show that suite is nothing but the container.


allTests = unittest.TestLoader()
TestLoader class provides different methods to handle the loading of test cases.

loadTestsFromTestCase() :

loadTestsFromTestCase(TestClassName) method loads all the test cases from the given class, a test case instance is created for the method getTestCaseNames() which notifies each test cases present in the Test Class.


allTests = unittest.TestLoader()			
suite = allTests.loadTestsFromTestCase(TestBing, TestCherCherTech)

TextTestRunner :

TextTestRunner class is the basic runner class present python, after loading all the methods using TestLoader and loadTestsFromTestCase, we have start the run using run method present in the TextTestRunner class

run method in TextTestRunner :

run method start the execution of the given suite, run method takes a TestSuite or TestCase instance as parameter (nothing but tests).

run method creates the TestResults by calling some private methods present inside the TextTestRunner class. Prints the test results to the screen using stdout.

Complete program with TestLoader and TextTestRunner

After coupling the TestLoader and TextTestRunner, we have created small piece of program by combining test cases present in two test classes .


import unittest
from unittest.suite import TestSuite
from selenium import webdriver

# first test class
class TestBing(unittest.TestCase):
    
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
        print("Browser Opened in first class")

    def test_open_bing(self):
        self.driver.get("http://bing.com")
        print("bing opened")

# second test class
class TestCherCherTech(unittest.TestCase):
    
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path=r'D:\PATH\chromedriver.exe')
        print("Browser Opened in second class")

    def test_open_bing(self):
        self.driver.get("http://chercher.tech")
        print("Chercher tech opened")
        
if __name__ == "__main__":
    
	# create the suite from the test classes
    suite = TestSuite()
    # load the tests
    tests = unittest.TestLoader()    
    
	# add the tests to the suite
    suite.addTests(tests.loadTestsFromTestCase(TestBing))        
    suite.addTests(tests.loadTestsFromTestCase(TestCherCherTech))
    
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(suite)			
running-suite-selenium-unittest-python

getTestCaseNames() :

getTestCaseNames(testCaseClass) method returns a sorted sequence of method names found within testCaseClass; test case class should be a subclass of TestCase.


import unittest

class Test_Me(unittest.TestCase):

    def test_Java(self):
        print("Java11")
    
    def test_Python(self):
        print("Python")
     
    def test_Typescript(self):
        print("Typescript")

if __name__ == "__main__":
    # load the tests
    tests = unittest.TestLoader()    
   
   # add the tests to the suite
    alltestNames = tests.getTestCaseNames(Test_Me)
    
	# print test method present in test class
    print("Test case Names present  : " ,  alltestNames)			
getTestCaseNames-python-unittest-selenium

loadTestsFromModule() :

loadTestsFromModule(module, pattern=None) method searches module for classes derived from TestCase and creates an instance of the class for each test method defined for the class.
If we load from the Module, then there is no need to load classes present in the module separately.

We can combine the Test classes (and test cases ) from multiple modules, below example shows loading test from different modules.
Please note that I have created modules in different files.


*******************File1 module1*******************	
import unittest

class Test_Module1(unittest.TestCase):

    def test_module1_WELCOME(self):
        print("module1 - welcome")	
		

*******************File2 Module2*******************
import unittest

class TestModule2_HI(unittest.TestCase):

    def test_module2_hi(self):
        print("module2 - hi")

class TestModule2_HELLO(unittest.TestCase):
    
    def test_module2_hello(self):
        print("module2 - hello")
		
		
		
*******************File3 runner-module*******************
from unittest.suite import TestSuite
import unittest
from pythontest import module1, module2

if __name__ == "__main__":
    # create the suite from the test classes
    suite = TestSuite()
    # load the tests
    tests = unittest.TestLoader()    
    # add the tests to the suite from modules
    suite.addTests(tests.loadTestsFromModule(module1))        
    suite.addTests(tests.loadTestsFromModule(module2))
    
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(suite)
	
loadTestsFromModule-unittest-python-selenium

loadTestsFromName :

You can load the test cases based on the string provided, the string either could be a module, or a class inside a module.

For writing module name you donot need any special import, automatically unittest imports the packages. We can also execute test cases present in a class alone, using class name but while using class name we have to modules name as well.

For example, if you have a module get_names_suite containing a class Test_Me with three test methods (test_Java(), test_Python(), and test_Typescript()), the specifier "get_names_suite.Test_Me" would cause this method to return a suite which will run all three test methods.

Using the specifier 'get_names_suite.Test_Me.test_Typescript' would cause it to return a test suite which will run only the test_Typescript() test method


************File namd & module Name is : get_names_suite***********
class Test_Me(unittest.TestCase):

    def test_Java(self):
        print("Java11")
    
    def test_Python(self):
        print("Python")
     
    def test_Typescript(self):
        print("Typescript")
		
************File namd & module Name is : load_name_test***********
import unittest		
if __name__ == "__main__":
    print("Running using loadTestsFromName, module.Class.method")
    # create the suite from the test classes
    suite = TestSuite()
    # load the tests
    tests = unittest.TestLoader()
    # add the tests to the suite from modules
    suite.addTests(tests.loadTestsFromName("get_names_suite.Test_Me.test_Typescript"))
    
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(suite)			
loadTestsFromName-unittest-python-selenium

loadTestsFromNames() :

This method is similar to loadTestsFromName but this method loads accepts more than one name (sequence of names), it return all the test cases from the given module, test class names.

This method accepts different modules, and classes from different modules


import unittest
from unittest.suite import TestSuite

class Test_Tou(unittest.TestCase):

    def test_touch(self):
        print("touchme")
        
class Test_Ting(unittest.TestCase):

    def test_tingle(self):
        print("tingle me")

if __name__ == "__main__":
    # create the suite from the test classes
    suite = TestSuite()
    # load the tests
    tests = unittest.TestLoader()    
    # add the tests to the suite from modules
    suite.addTests(tests.loadTestsFromNames(["load_name_test.Test_Ting", "module1", "module2"]))       
    
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(suite)			
loadTestsFromNames-unittest-pythn-selenium

testMethodPrefix() :

Sometimes we may write or a start the test methods with different prefix than test in such cases we can take help of this method to load the methods with different prefixes.


import unittest
from unittest.suite import TestSuite

class Test(unittest.TestCase):

    def test_sanity_hello(self):
        print("sanity test")
        
    def test_regression_hi(self):
        print("regression test")

if __name__ == "__main__":
    print("Running with test prefix")
    # create the suite from the test classes
    suite = TestSuite()
    # load the tests
    tests = unittest.TestLoader()
    tests.testMethodPrefix = "test_sanity"
    # add the tests to the suite from class 'Test'
    suite.addTests(tests.loadTestsFromTestCase(Test))
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(suite)			
testMethodPrefix-unittest-python-selenium

sortTestMethodsUsing :

sortTestMethodsUsing method helps us to set, how the test cases should be executed in the test class.

getTestCaseNames() method first loads all the test methods into pool, then sortTestMethodsUsing methods sorts the tests present in the pool.

discover :

Find all the test modules by recursing into subdirectories from the specified start directory, and return a TestSuite object containing them. Only test files that match pattern will be loaded. (Using shell style pattern matching.) Only module names that are importable (i.e. are valid Python identifiers) will be loaded.

All test modules must be importable from the top level of the project. If the start directory is not the top level directory then the top level directory must be specified separately.

Below program tries to run the test cases present from the top module but search begins with load_name_test, you can have matches in any module.


import unittest
from unittest.suite import TestSuite
import pythontest
from pythontest import module2

class Test_Tou(unittest.TestCase):

    def test_touch(self):
        print("touchme")
        
class Test_Ting(unittest.TestCase):

    def test_tingle(self):
        print("tingle me")

if __name__ == "__main__":
    print("Running using discover method")
    # create the suite from the test classes
    suite = TestSuite()
    # load the tests
    tests = unittest.TestLoader().discover("load_name_test", "load*test.py")
    # add the tests to the suite from modules
    
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(tests)			
discover-unittest-python-selenium

suiteClass :

suites is nothing but the container of the all the test methods

Create Test Suite

TestSuite :

TestSuite class represents an aggregation of individual test cases and test suites present in the python project.

The class provides the interface needed by the test runner to allow it to be run as any other test case.

Running a TestSuite instance is the same as iterating over the suite, running each test individually.

There are few useful methods present in the Unittest.TestSuite to manipulate the test suite of test cases.

addTest(test) :

addTest method adds a test, test class, test suite to the TestSuite object.


import unittest
from unittest.suite import TestSuite

class Test_Tou(unittest.TestCase):
    def test_touch(self):
        print("touchme")
        
class Test_Ting(unittest.TestCase):
    def test_tingle(self):
        print("tingle me")

if __name__ == "__main__":
    print("Running using test suite with add test")
    # create the suite from the test classes
    suite = TestSuite()
    # load the test from test class
    suite.addTest(Test_Tou("test_touch"))
    
    # run the suite
    runner = unittest.TextTestRunner()
    runner.run(suite)			
addTest-testsuite-unittest-python-selenium

addTests(tests) :

addTests method adds all the tests from an iterable of TestCase and TestSuite instances to this test suite in unittest framework

We can load the test from the Modules, from the Test classes.


import unittest
from unittest.suite import TestSuite
from unittest.loader import TestLoader
from unittest.runner import TextTestRunner

class Test_Tou(unittest.TestCase):
    def test_touch(self):
        print("touchme")

    def test_tingle(self):
        print("tingle me")

if __name__ == "__main__":
    print("Running using test suite with add tests")
    # create the suite from the test classes
    suite = TestSuite()
    # will contains all tests
    tests = TestLoader()  
    # load the test from test class
    suite.addTests(tests.loadTestsFromTestCase(Test_Tou))
    
    # run the suite
    runner = TextTestRunner()
    runner.run(suite)			
addTests-testsuite-unittest-python-selenium

run(result) :

run method runs the tests associated with this suite, collecting the result into the test result object passed as result.

We have to pass TestResult object to this method as parameter, I will give example for this method in TestResult class as this method requires TestResult details as well.

countTestCases() :

countTestCases method returns the number of tests represented by the TestSuite test object, including all individual tests and sub-suites


import unittest
from unittest.suite import TestSuite
from unittest.loader import TestLoader

class Test_Tou(unittest.TestCase):
    def test_touch(self):
        print("touchme")

    def test_tingle(self):
        print("tingle me")

if __name__ == "__main__":
    # create the suite from the test classes
    suite = TestSuite()
    # will contains all tests
    tests = TestLoader()  
    # load the test from test class
    suite.addTests(tests.loadTestsFromTestCase(Test_Tou))
    # number of test cases present
    print("No. of test cases present : ", suite.countTestCases())			
countTestCases-unittest-python-selenium

TestResult Listeners in Unittest python

Test Listeners are nothing but the event listeners, listener methods will be invoked when there even happening around the tests. Events could be like failure, pass, skip and so on.

Lets learn the listeners present in the TestResult class in unittest python framework

startTestRun()

startTestRun() gets a call once before any tests are executed.

stopTestRun() :

stopTestRun gets a call once after all tests are executed. Above two methdo will be useful only when you implement your own run method by extending the TestCase class or TestSuite class, otherwise below two methods will be invoked instead of the above two methods.

startTest(test)

startTest(test) method runs after colleting the test methods and test suite information, runs before running any test method.

startTest method is applicable for each and every test method present in the Test class, for example if you have 10 test method then this method will be executed 10 times

stopTest(test)

stopTest(test) method gets call after the test case has been executed, regardless of the outcome.

stopTest method also applicable each and every method in the test class.

addFailure(test, err) :

addFailure method gets a call when an test case is failed, this method will receive the error as a paremeter

addSuccess(test) :

addSuccess method gets a call whenever a test passes

addSkip(test, reason) :

addSkip method will be executed when a test gets skipped, all the skipped tests will have reason why it is getting skipped (please refer skipTest section)

addExpectedFailure(test, err)

addExpectedFailure method will be executed when a test method fails and that method annotated with expectedFailure() decorator.

addUnexpectedSuccess(test) :

addUnexpectedSuccess method will be executed when a test method passed and that method annotated with expectedFailure() decorator.


import unittest
from unittest.suite import TestSuite
from unittest.case import expectedFailure

class Test_Witch(unittest.TestCase):
    
    def test_1(self):
        self.fail('test1')
        #fails
        
    def test_2(self):
        print('test_2')
        #passes

    @unittest.skip("not developed yet")        
    def test_3(self):
        print("test_3")
        #passes
    
    @expectedFailure  
    def test_4(self):
        self.assertEqual("test_4", "4th test", "test 4 is not same as 4th test")
        #fails
        
    @expectedFailure   
    def test_5(self):
        print("test_5")
        #passes
        
        
class CustomResultListener(unittest.TestResult):
    
    def startTest(self, test):
        print('Starting test : ', test)

    def stopTest(self, test):
        print('Stopping test : ', test)
        
    def addFailure(self, test, err):
        print("Failed test : ", test, " with error ", err)
    
    def addSuccess(self, test):
        print("Test passed : ", test)
    
    def addSkip(self, test, reason):
        print("Test skipped : ", test, "with reason : ", reason)
        
    def addExpectedFailure(self, test, err):
        print("Test Expected Failure : ", test, "with reason ", err)
        
    def addUnexpectedSuccess(self, test):
        print("Test UnExpected Passed : ", test)
    
        
if __name__ == "__main__":        
 
    # load the test from test class
    tests = unittest.defaultTestLoader.loadTestsFromTestCase(Test_Witch)
    # create object for result class we created
    custom_result = CustomResultListener()
    # load tests in to suite
    suite  = TestSuite(tests)
    # run the suite
    final_result = suite.run(custom_result)

    
    

    
			
test-listeners-python-selenium-unittest

About Author

Myself KarthiQ, I am the author of this blog, I know ways to write a good article but some how I donot have the skills to make it to reach people, would you like help me to reach more people By sharing this Article in the social media.

Share this Article Facebook
You can also share knowledge by Adding a topic here


Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions
Copyright © CherCher Tech