KEMBAR78
2.Python_Testing_Using_PyUnit_PyTest.pptx
PyUnit
Overview
• Unit Testing Basics: What, Why, When
• How: Python Unit Test Class
• Unit Test Writing Tips and Resources
Unit Testing Basics
• Functional tests: done by QA to test
functionality according to a test plan based
on requirements and design specs.
• Unit tests: done by developers to test
specific code. Typically “white box” testing.
• Essential part of Extreme Programming and
other agile methods.
Why Write Unit Tests
• Increase developers’ confidence in code. If
someone challenges your work, you can say
“the tests passed.”
• Avoid regression. If unit test suite is run
frequently, you know when new code
breaks old code.
• If you write tests first, you know when
you’re done, i.e., when the tests pass.
• Encourages minimal interfaces and
modularity.
When to Write/Run
Unit Tests
• Always!
• Before you check code into repository, so
you know your code works.
• Before debugging, to ease the process and
help you know when you’re done.
Test Writing Tips
• Make code modular: use interfaces/template classes/abstract base
classes.
• Use mock objects to inspect behavior of
object you’re testing and to stand in for
“heavy” objects, e.g., you don’t want to do
network I/O in a unit test.
• Modular, loosely coupled interfaces make
mock objects possible.
• Excessive coupling is enemy of unit testing.
Using PyUnit to write your own tests
• Installation
The classes needed to write tests are to be
found in the 'unittest' module. This module is
part of the standard Python library for Python
2.1 and later. If you are using an older Python
version, you should obtain the module from
the separate PyUnit distribution.
An introduction to TestCases
• The basic building blocks of unit testing are
'test cases' -- single scenarios that must be set
up and checked for correctness. In PyUnit, test
cases are represented by the TestCase class in
the unittest module. To make your own test
cases you must write subclasses of TestCase.
• An instance of a TestCase class is an object that
can completely run a single test method,
together with optional set-up and tidy-up code.
Creating a simple test case
• The simplest test case subclass will simply override
the runTest method in order to perform specific testing code:
import unittest
class DefaultWidgetSizeTestCase(unittest.TestCase):
def runTest(self):
widget = Widget("The widget")
assert widget.size() == (50,50), 'incorrect default
size'
Note that in order to test something, we just use the
built-in 'assert' statement of Python. If the assertion
fails when the test case runs, an AssertionError will
be raised, and the testing framework will identify the
test case as a 'failure'. Other exceptions that do not
arise from explicit 'assert' checks are identified by
the testing framework as 'errors'.
Re-using set-up code: creating 'fixtures'
• Now, such test cases can be numerous, and their
set-up can be repetitive. In the above case,
constructing a 'Widget' in each of 100 Widget test
case subclasses would mean unsightly duplication.
• Luckily, we can factor out such set-up code by
implementing a hook method called setUp, which
the testing framework will automatically call for us
when we run the test:
import unittest class
SimpleWidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget("The widget")
class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
def runTest(self):
assert self.widget.size() == (50,50), 'incorrect default
size'
class WidgetResizeTestCase(SimpleWidgetTestCase):
def runTest(self):
self.widget.resize(100,150)
assert self.widget.size() == (100,150),  'wrong size
after resize'
• If the setUp method raises an exception while the test is running, the
framework will consider the test to have suffered an error, and
the runTest method will not be executed.
• Similarly, we can provide a tearDown method that tidies up after
the runTest method has been run:
import unittest class
SimpleWidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget("The widget")
def tearDown(self):
self.widget.dispose()
self.widget = None
• If setUp succeeded, the tearDown method will be run regardless of whether
or not runTest succeeded.
• Such a working environment for the testing code is termed a fixture.
TestCase classes with several test methods
• Often, many small test cases will use the same fixture. In this case, we would end up
subclassing SimpleWidgetTestCase into many small one-method classes such
as DefaultWidgetSizeTestCase. This is time-consuming and discouraging
import unittest class
WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget("The widget")
def tearDown(self):
self.widget.dispose()
self.widget = None
def testDefaultSize(self):
assert self.widget.size() == (50,50), 'incorrect default size'
def testResize(self):
self.widget.resize(100,150)
assert self.widget.size() == (100,150),  'wrong size after resize'
TestCase classes with several test methods
• Here we have not provided a runTest method, but have instead provided
two different test methods. Class instances will now each run one of
the test methods, with self.widget created and destroyed separately for
each instance. When creating an instance we must specify the test
method it is to run. We do this by passing the method name in the
constructor:
defaultSizeTestCase = WidgetTestCase("testDefaultSize")
resizeTestCase = WidgetTestCase("testResize")
Running tests
• The unittest module contains a function called main, which can be used to
easily turn a test module into a script that will run the tests it contains.
The main function uses the unittest.TestLoader class to automatically find
and load test cases within the current module.
• Therefore, if you name your test methods using the test* convention, you
can place the following code at the bottom of your test module:
if __name__ == "__main__":
unittest.main()

2.Python_Testing_Using_PyUnit_PyTest.pptx

  • 1.
  • 2.
    Overview • Unit TestingBasics: What, Why, When • How: Python Unit Test Class • Unit Test Writing Tips and Resources
  • 3.
    Unit Testing Basics •Functional tests: done by QA to test functionality according to a test plan based on requirements and design specs. • Unit tests: done by developers to test specific code. Typically “white box” testing. • Essential part of Extreme Programming and other agile methods.
  • 4.
    Why Write UnitTests • Increase developers’ confidence in code. If someone challenges your work, you can say “the tests passed.” • Avoid regression. If unit test suite is run frequently, you know when new code breaks old code. • If you write tests first, you know when you’re done, i.e., when the tests pass. • Encourages minimal interfaces and modularity.
  • 5.
    When to Write/Run UnitTests • Always! • Before you check code into repository, so you know your code works. • Before debugging, to ease the process and help you know when you’re done.
  • 6.
    Test Writing Tips •Make code modular: use interfaces/template classes/abstract base classes. • Use mock objects to inspect behavior of object you’re testing and to stand in for “heavy” objects, e.g., you don’t want to do network I/O in a unit test. • Modular, loosely coupled interfaces make mock objects possible. • Excessive coupling is enemy of unit testing.
  • 7.
    Using PyUnit towrite your own tests • Installation The classes needed to write tests are to be found in the 'unittest' module. This module is part of the standard Python library for Python 2.1 and later. If you are using an older Python version, you should obtain the module from the separate PyUnit distribution.
  • 8.
    An introduction toTestCases • The basic building blocks of unit testing are 'test cases' -- single scenarios that must be set up and checked for correctness. In PyUnit, test cases are represented by the TestCase class in the unittest module. To make your own test cases you must write subclasses of TestCase. • An instance of a TestCase class is an object that can completely run a single test method, together with optional set-up and tidy-up code.
  • 9.
    Creating a simpletest case • The simplest test case subclass will simply override the runTest method in order to perform specific testing code: import unittest class DefaultWidgetSizeTestCase(unittest.TestCase): def runTest(self): widget = Widget("The widget") assert widget.size() == (50,50), 'incorrect default size'
  • 10.
    Note that inorder to test something, we just use the built-in 'assert' statement of Python. If the assertion fails when the test case runs, an AssertionError will be raised, and the testing framework will identify the test case as a 'failure'. Other exceptions that do not arise from explicit 'assert' checks are identified by the testing framework as 'errors'.
  • 11.
    Re-using set-up code:creating 'fixtures' • Now, such test cases can be numerous, and their set-up can be repetitive. In the above case, constructing a 'Widget' in each of 100 Widget test case subclasses would mean unsightly duplication. • Luckily, we can factor out such set-up code by implementing a hook method called setUp, which the testing framework will automatically call for us when we run the test:
  • 12.
    import unittest class SimpleWidgetTestCase(unittest.TestCase): defsetUp(self): self.widget = Widget("The widget") class DefaultWidgetSizeTestCase(SimpleWidgetTestCase): def runTest(self): assert self.widget.size() == (50,50), 'incorrect default size' class WidgetResizeTestCase(SimpleWidgetTestCase): def runTest(self): self.widget.resize(100,150) assert self.widget.size() == (100,150), 'wrong size after resize'
  • 13.
    • If thesetUp method raises an exception while the test is running, the framework will consider the test to have suffered an error, and the runTest method will not be executed. • Similarly, we can provide a tearDown method that tidies up after the runTest method has been run: import unittest class SimpleWidgetTestCase(unittest.TestCase): def setUp(self): self.widget = Widget("The widget") def tearDown(self): self.widget.dispose() self.widget = None • If setUp succeeded, the tearDown method will be run regardless of whether or not runTest succeeded. • Such a working environment for the testing code is termed a fixture.
  • 14.
    TestCase classes withseveral test methods • Often, many small test cases will use the same fixture. In this case, we would end up subclassing SimpleWidgetTestCase into many small one-method classes such as DefaultWidgetSizeTestCase. This is time-consuming and discouraging import unittest class WidgetTestCase(unittest.TestCase): def setUp(self): self.widget = Widget("The widget") def tearDown(self): self.widget.dispose() self.widget = None def testDefaultSize(self): assert self.widget.size() == (50,50), 'incorrect default size' def testResize(self): self.widget.resize(100,150) assert self.widget.size() == (100,150), 'wrong size after resize'
  • 15.
    TestCase classes withseveral test methods • Here we have not provided a runTest method, but have instead provided two different test methods. Class instances will now each run one of the test methods, with self.widget created and destroyed separately for each instance. When creating an instance we must specify the test method it is to run. We do this by passing the method name in the constructor: defaultSizeTestCase = WidgetTestCase("testDefaultSize") resizeTestCase = WidgetTestCase("testResize")
  • 16.
    Running tests • Theunittest module contains a function called main, which can be used to easily turn a test module into a script that will run the tests it contains. The main function uses the unittest.TestLoader class to automatically find and load test cases within the current module. • Therefore, if you name your test methods using the test* convention, you can place the following code at the bottom of your test module: if __name__ == "__main__": unittest.main()