Unit Testing and Mock with Python Unittest and Mock Package

Pre-requisites

Visual Studio Code – https://code.visualstudio.com/download  or any code editor

Python 3 – https://www.python.org/downloads/

In this workshop we will write our Unit Test in Python with Unittest

Lets follow below steps to achieve this

  1. Create a folder to store our program
  2. Add file called calculate.py this file does addition of 2 numbers.
  3. Write the code to add 2 given number
  4. Execute the calculate class with the command python calculate.py in your command prompt or terminal. this command will execute and show the result.Screenshot_39.png
  5. Lets add our test file to test this functionality
  6. Add a file called calculate_test.py
  7. Write code to test. In this code we will import Unittest package. The Python unit testing framework, sometimes referred to as “PyUnit,” is a Python language version of JUnit, by Kent Beck and Erich Gamma. unittest 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.To achieve this, unittest supports some important concepts:
    test fixture
    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
    test case is the smallest 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
    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
    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.
  8. In the below code test case is created by unittest.TestCase. The test are writeen which name starts from test_ this naming convention informs the test runner about which methods represent tests and also for easy reading purpose. The setUp() and tearDown() methods allow you to define instructions that will be executed before and after each test method. We will use assertEqual() method to check for an expected result. Run the test and check if test cases passes. Screenshot_1
  9. Lets write one more test to check Exception handling with assertRaises method. In the above Add method from Calculate class takes only numbers. if we pass string then it should throw error. Screenshot_2.png
  10. lets pass string from test file and run the test this time it should fail as Add method can operate only numbers.Screenshot_3.png

Great our sample test works as expected.

Below are the other assert method you could try

Picture1.png

Command line execution of test cases

$ python -m unittest filename.py

unittest supports these command-line options:

-b--buffer
The standard output and standard error streams are buffered during the test run. Output during a passing test is discarded. Output is echoed normally on test fail or error and is added to the failure messages.

-c--catch
Control-C during the test run waits for the current test to end and then reports all the results so far. A second Control-C raises the normal KeyboardInterrupt exception.

See Signal Handling for the functions that provide this functionality.

-f--failfast
Stop the test run on the first error or failure.

Skipping test case

@unittest.skip("demonstrating skipping")

 

Exercise 2 – Build phone book app

Picture2.png

  1. Lets create a Phonebook.py class to have functionality of adding name and phone number and search for given name. In the below program function is_consistent is not implemented, for this exercise we will just return TrueScreenshot_4
  2. Next step is to identify the test cases, identify possible tests who you like to test. below are the list
    1. test lookup entry by name
    2. test missing entry raises
    3. test empty phonebook is consistent
    4. test phonebook with normal entries is consistent
    5. test phonebook with duplicate entries is inconsistent
    6. test phonebook with numbers that prefix one another is inconsistent
    7. test phonebook adds names and numbers
  3. Lets create test file and create unit test for above scenariosScreenshot_6.png
  4. Execute the above test with command
    • python -m unittest
  5. All the test cases should pass. here last 2 test cases will fail as we have not implemented is_consistent functionality rather this methods return True for all. To make these 2 tests to pass modify is_consistent method in phonebook.py

Mocking

When you write tests, you may discover that your code interacts with other systems that are assumed to be tested and fully functional, such as call a database or a web service. In these instances, you don’t want to make those calls for real in your test—for a number of reasons. For example, the database or web service may be down and you don’t want that to cause a failing test as part of your build process, which would produce a false positive. Also, those calls may be slow or cost your company money; therefore, if you are running a build every time you check in, your build could get lengthy or cost the company a large bill. This is where mocking and patching come in. They enable you to swap those real calls for dummy responses. This allows you to test that your code behaves as expected under those conditions.

Install Mock

  • $ pip install mock
  1. Create a file called mock_example_test.py, add below sample code and run the file. Here we are creating Mock object called my_mock and adding mock methods called my_method and setting value as hello. So when we test this it will return us hello like it were returning from database.pss
  2. Lets write another example. Here we have account class which is returning account detail from Database, for this example will not connect to database, but it real world it will be. Screenshot_40.png
  3. Lets create test class and mock data_interface with Mock. Run the testScreenshot_7

Further Reading

https://docs.python.org/3/library/unittest.html

https://www.amazon.com/Testing-Python-Applying-Unit-Acceptance/dp/1118901223

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s