Unittest - Part 1
The unittest
unit testing framework was originally inspired by JUnit and has a similar
flavor as major unit testing frameworks in other languages. It supports test
automation, sharing of setup and shutdown code for tests, aggregation of tests
into collections, and independence of the tests from the reporting framework.
unittest
supports some important concepts in an object-oriented way:
test
fixture
A test
fixture represents the preparation needed to perform one or more tests, and any
associated 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.
Basic Example – SimpleAdd.py
import unittest
class simpleTest(unittest.TestCase):
def testAdd(self):
a=10
b=20
c=a+b
self.assertEqual(c,30)
if __name__ == '__main__':
unittest.main()
class simpleTest(unittest.TestCase):
def testAdd(self):
a=10
b=20
c=a+b
self.assertEqual(c,30)
if __name__ == '__main__':
unittest.main()
The following steps are involved in writing a Basic unit test −
Step 1 − Import the unittest module in your program.
Step 2 − Create a testcase by subclassing unittest.TestCase.
Step 3 − Define a test as a method inside the class. Name of
method must start with 'test'.
Step 4 − Each test calls assert function of TestCase class. There
are many types of asserts. Following example calls assertEquals() function.
Step 5 − assertEquals() function compares result of add() function
with arg2 argument and throws assertionError if comparison fails.
Step 6 − Finally, call main() method from the unittest module.
How to run python unittest
module
If you’re using PyCharm IDE, you can simply press ctrl+shift+F10
to run unittest module.
Output will
be
you can use command
prompt to run this module. Open up a terminal and navigate to the folder that
contains your test module(simpleAdd.py):
Passing the
-v option to enable a higher level of verbosity, and produce the following
output:
There are three types of possible test
outcomes :
OK – means all the tests are passed.
FAIL – means
test did not pass and an AssertionError exception is raised.
ERROR – means
test raises an exception other than AssertionError.
These
outcomes are displayed on the console by '.', 'F' and 'E' respectively.
.(DOT) means Pass
F means Fail
E means Error
unittest
supports the following command line options.
1)-h, --help
Show this
message
2)-v,
--verbose
Verbose
output
3)-q, --quiet
Minimal
output
4)-f, --failfast
Stop on first
failure
5)-c, --catch
Catch
control-C and display results
6)-b,
--buffer
Buffer stdout
and stderr during test runs
Ex: python
simpleAdd.py -q
TestFixtures
Fixtures are
resources needed by a test. For example, if you are writing several tests for
the same class, those tests all need an instance of that class to use for
testing. Other test fixtures include database connections and temporary files.
TestCase includes a special hook to configure and clean up any fixtures needed
by your tests. To configure the fixtures, override setUp(). To clean up,
override tearDown().Test fixtures are methods and functions that run before and
after a test.
In the
following example, one test is written inside the TestCase class. The test is
to loginApp into application . The setup() method will launch the chrome
browser of each test and the teardown()
method will be executed at the end of each test.
Script:
from selenium import webdriver
import unittest
from selenium.webdriver.common.by import By
class testFixture(unittest.TestCase):
driver=""
import unittest
from selenium.webdriver.common.by import By
class testFixture(unittest.TestCase):
driver=""
def setUp(self):
base_url = "http://automationpractice.com/"
chromePath = "C:\\executables\\chromedriver.exe"
self.driver = webdriver.Chrome(executable_path=chromePath)
self.driver.get(base_url)
def testLoginApp(self):
LoginLink = (By.XPATH, "//a[@title='Log in to your customer account']")
UserName = (By.XPATH, "//input[@id='email']")
PassWord = (By.XPATH, "//input[@name='passwd']")
LoginBtn = (By.XPATH, "//button[@type='submit' and @id='SubmitLogin']")
self.driver.find_element(By.XPATH,"//a[@title='Log in to your customer account']").click()
self.driver.find_element(By.XPATH, "//input[@id='email']").send_keys("abc111@gmail.com")
self.driver.find_element(By.XPATH, "//input[@name='passwd']").send_keys("abcd1234")
self.driver.find_element(By.XPATH, "//button[@type='submit' and @id='SubmitLogin']").click()
self.driver.implicitly_wait(50)
titleTxt=self.driver.title
self.assertEqual(titleTxt,"My account - My Store")
def tearDown(self):
self.driver.quit()
if __name__=="__main__":
unittest.main()
unittest.main()
Class
Fixture
TestCase class has a setUpClass() method which can be overridden
to execute before the execution of individual tests inside a TestCase class.
Similarly, tearDownClass() method will be executed after all test in the class.
Both the methods are class methods.
from selenium import webdriver
import unittest
from selenium.webdriver.common.by import By
class simpleClassFixtures(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setup at Class level")
base_url = "http://automationpractice.com/"
chromePath = "C:\\executables\\chromedriver.exe"
cls.driver = webdriver.Chrome(executable_path=chromePath)
cls.driver.get(base_url)
def testLoginApp(self):
LoginLink = (By.XPATH, "//a[@title='Log in to your customer account']")
UserName = (By.XPATH, "//input[@id='email']")
PassWord = (By.XPATH, "//input[@name='passwd']")
LoginBtn = (By.XPATH, "//button[@type='submit' and @id='SubmitLogin']")
self.driver.find_element(By.XPATH,"//a[@title='Log in to your customer account']").click()
self.driver.find_element(By.XPATH, "//input[@id='email']").send_keys("abc111@gmail.com")
self.driver.find_element(By.XPATH, "//input[@name='passwd']").send_keys("abcd1234")
self.driver.find_element(By.XPATH, "//button[@type='submit' and @id='SubmitLogin']").click()
self.driver.implicitly_wait(50)
titleTxt=self.driver.title
self.assertEqual(titleTxt,"My account - My Store")
def testsingOut(self):
self.driver.find_element(By.XPATH,"//a[@title='Log me out']").click()
titleTxt = self.driver.title
self.assertEqual(titleTxt, "Login - My Store")
print(titleTxt)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
print("TearDown at Class Level")
import unittest
from selenium.webdriver.common.by import By
class simpleClassFixtures(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setup at Class level")
base_url = "http://automationpractice.com/"
chromePath = "C:\\executables\\chromedriver.exe"
cls.driver = webdriver.Chrome(executable_path=chromePath)
cls.driver.get(base_url)
def testLoginApp(self):
LoginLink = (By.XPATH, "//a[@title='Log in to your customer account']")
UserName = (By.XPATH, "//input[@id='email']")
PassWord = (By.XPATH, "//input[@name='passwd']")
LoginBtn = (By.XPATH, "//button[@type='submit' and @id='SubmitLogin']")
self.driver.find_element(By.XPATH,"//a[@title='Log in to your customer account']").click()
self.driver.find_element(By.XPATH, "//input[@id='email']").send_keys("abc111@gmail.com")
self.driver.find_element(By.XPATH, "//input[@name='passwd']").send_keys("abcd1234")
self.driver.find_element(By.XPATH, "//button[@type='submit' and @id='SubmitLogin']").click()
self.driver.implicitly_wait(50)
titleTxt=self.driver.title
self.assertEqual(titleTxt,"My account - My Store")
def testsingOut(self):
self.driver.find_element(By.XPATH,"//a[@title='Log me out']").click()
titleTxt = self.driver.title
self.assertEqual(titleTxt, "Login - My Store")
print(titleTxt)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
print("TearDown at Class Level")
if
__name__=="__main__":
unittest.main()
unittest.main()
Although setUp() and tearDown() are the methods that allow us to
make sure each test can run independently and in any order.
List of fixture methods are
setUp() / tearDown() – before and after test methods
setUpClass() / tearDownClass() – before and after a class of tests
setUpModule() / tearDownModule() – before and after a module of
tests
Note: If an exception is raised in a setUpModule/setUpclass/setUp
then none of the tests in the module/class will be run and the tearDownModule/tearDownclass/
tearDown will not be run.
Assertions
Python testing framework uses Python's built-in assert() function
which tests a particular condition. If the assertion fails, an AssertionError
will be raised. The testing framework will then identify the test as Failure.
Other exceptions are treated as Error. All the assert methods accept a
msg argument that, if specified, is used as the error message on failure
The following lists the most
commonly used assert methods
1. assertEqual(first, second, msg=None)
Test that first and second are
equal. If the values do not compare equal, the test will fail.
2. assertNotEqual(first, second, msg=None)
Test that first and second are
not equal. If the values do compare equal, the test will fail.
3. assertTrue(expr, msg=None)
Test that expr is true
4. assertFalse(expr, msg=None)
Test that expr is false
5. assertIs(first, second, msg=None)
Test that first and second
evaluate to the same object.
6. assertIsNot(first, second, msg=None)
Test that first and second
don’t evaluate to the same object.
7. assertIsNone(expr, msg=None)
Test that expr is None.
8. assertIsNotNone(expr, msg=None)
Test that expr is not None.
9. assertIn(first, second, msg=None)
Test that first is in second.
10.assertNotIn(first, second, msg=None)
Test that first is not in second.
11.assertIsInstance(obj, cls, msg=None)
Test that obj is (or is not) an
instance of cls (which can be a class or a tuple of classes, as supported by
isinstance()). To check for the exact type, use assertIs(type(obj), cls).
12.assertNotIsInstance(obj, cls, msg=None)
Test that obj is not an instance of cls (which can be a
class or a tuple of classes, as supported by isinstance()). To check for the
exact type, use assertIs(type(obj), cls).
Few of the basic assertion methods are implemented in the below
script.
import unittest
class simpleBasicAssert(unittest.TestCase):
def testBasicAssert(self):
class simpleBasicAssert(unittest.TestCase):
def testBasicAssert(self):
#
Statement 1
self.assertEqual(6 - 2, 4)
self.assertEqual(6 - 2, 4)
#
Statement 2
self.assertNotEqual((10*2),21)
self.assertNotEqual((10*2),21)
#
Statement 3
self.assertTrue(4 + 5 == 9, "The result is False")
self.assertTrue(4 + 5 == 9, "The result is False")
# Statement
4
self.assertTrue(4 + 5 == 10, "4 + 5 == 10 assertion fails")
self.assertTrue(4 + 5 == 10, "4 + 5 == 10 assertion fails")
#
Statement 5
self.assertIn(3, [1, 2, 3])
self.assertIn(3, [1, 2, 3])
#
Statement 6
self.assertNotIn(3, range(5))
self.assertNotIn(3, range(5))
#
Statement 7
self.assertIs(1, [1, 2, 3])
self.assertIs(1, [1, 2, 3])
if __name__=="__main__":
unittest.main()
When the above script is run, Statement 4 will show failure and
others run successfully.
There are also other methods
used to perform more specific checks
1. assertAlmostEqual(first, second, places=7, msg=None, delta=None)
Test that first and second are
approximately equal by computing the difference, rounding to the given number
of decimal places (default 7), and comparing to zero. Note that these methods
round the values to the given number of decimal places (i.e. like the round()
function) and not significant digits. If delta is supplied instead of places
then the difference between first and second must be less or equal to (or
greater than) delta.
2. assertNotAlmostEqual(first, second, places=7, msg=None,
delta=None)
Test that first and second
are not approximately equal by computing
the difference, rounding to the given number of decimal places (default 7), and
comparing to zero. Note that these methods round the values to the given number
of decimal places (i.e. like the round() function) and not significant digits. If
delta is supplied instead of places then the difference between first and
second must be less or equal to (or greater than) delta.
3. assertGreater(first, second, msg=None)
4. assertGreaterEqual(first, second, msg=None)
5. assertLess(first, second, msg=None)
6. assertLessEqual(first, second, msg=None)
Test that first is respectively
>, >=, < or <= than second depending on the method name. If not,
the test will fail.
7. assertRegex(text, regex, msg=None)
Test that a regex search
matches text. In case of failure, the error message will include the pattern
and the text. regex may be a regular expression object or a string containing a
regular expression suitable for use by re.search().
8. assertNotRegex(text, regex, msg=None)
Test that a regex search does not match text. In case of failure, the
error message will include the pattern and the part of text that unexpectedly
matched. regex may be a regular expression object or a string containing a
regular expression suitable for use by re.search().
9. assertCountEqual(first, second, msg=None)
Test that sequence first
contains the same elements as second, regardless of their order. When they
don’t, an error message listing the differences between the sequences will be
generated.
Duplicate elements are not
ignored when comparing first and second. It verifies whether each element has
the same count in both sequences. Equivalent to:
assertEqual(Counter(list(first)), Counter(list(second))) but works with
sequences of unhashable objects as well.
Few Assert methods are implemented in the below script
import unittest
import math
import re
class SimpleCheckAssertTest(unittest.TestCase):
def test1(self):
self.assertAlmostEqual(22.0/7,3.14)
def test2(self):
self.assertNotAlmostEqual(10.0/3,3)
def test3(self):
self.assertGreater(math.pi,3)
def test4(self):
self.assertNotRegexpMatches("Automation Frame work using UnitTest in Python ", "Frame")
def test5(self):
self.assertNotRegexpMatches("Automation Frame work using UnitTest in Python ","Frame")
if __name__ == '__main__':
unittest.main()
import math
import re
class SimpleCheckAssertTest(unittest.TestCase):
def test1(self):
self.assertAlmostEqual(22.0/7,3.14)
def test2(self):
self.assertNotAlmostEqual(10.0/3,3)
def test3(self):
self.assertGreater(math.pi,3)
def test4(self):
self.assertNotRegexpMatches("Automation Frame work using UnitTest in Python ", "Frame")
def test5(self):
self.assertNotRegexpMatches("Automation Frame work using UnitTest in Python ","Frame")
if __name__ == '__main__':
unittest.main()
The above script reports test1 and test5 as Failure.
The list of type-specific
methods automatically used by assertEqual()
1. assertMultiLineEqual(first, second, msg=None)
Test that the multiline string
first is equal to the string second. When not equal a diff of the two strings
highlighting the differences will be included in the error message. This method
is used by default when comparing strings with assertEqual().
2. assertSequenceEqual(first, second, msg=None, seq_type=None)
Tests that two sequences are
equal. If a seq_type is supplied, both first and second must be instances of
seq_type or a failure will be raised. If the sequences are different an error
message is constructed that shows the difference between the two.
This method is not called
directly by assertEqual(), but it’s used to implement assertListEqual() and
assertTupleEqual().
3. assertListEqual(first, second, msg=None)
Tests that two lists are equal.
If not, an error message is constructed that shows only the differences between
the two. An error is also raised if either of the parameters are of the wrong
type. These methods are used by default when comparing lists with assertEqual().
4. assertTupleEqual(first, second, msg=None)
Tests that two tuples are
equal. If not, an error message is constructed that shows only the differences
between the two. An error is also raised if either of the parameters are of the
wrong type. These methods are used by default when comparing tuples with
assertEqual().
5. assertSetEqual(first, second, msg=None)
Tests that two sets are equal.
If not, an error message is constructed that lists the differences between the
sets. This method is used by default when comparing sets or frozensets with
assertEqual().
Fails if either of first or
second does not have a set.difference() method.
6. assertDictEqual(first, second, msg=None)
Test that two dictionaries are
equal. If not, an error message is constructed that shows the differences in
the dictionaries. This method will be used by default to compare dictionaries
in calls to assertEqual().
Few of the assert methods are implemented in the below script
import unittest
class SimpleCoolectionAssertTest(unittest.TestCase):
def test1(self):
self.assertListEqual([2,3,4], [1,2,3,4,5])
def test2(self):
self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
def test3(self):
self.assertDictEqual({1,2,3,4},{1,2,3,5})
def test4(self):
self.assertDictEqual({1: 11, 2: 22}, {3: 33, 2: 22, 1: 11})
if __name__ == '__main__':
unittest.main()
class SimpleCoolectionAssertTest(unittest.TestCase):
def test1(self):
self.assertListEqual([2,3,4], [1,2,3,4,5])
def test2(self):
self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
def test3(self):
self.assertDictEqual({1,2,3,4},{1,2,3,5})
def test4(self):
self.assertDictEqual({1: 11, 2: 22}, {3: 33, 2: 22, 1: 11})
if __name__ == '__main__':
unittest.main()
In the above example, test1 , test3 and test4 show AssertionError.
Error message displays the differences in List ,set and Dictionary objects.
Comments
Post a Comment