BogoToBogo
  • Home
  • About
  • Big Data
  • Machine Learning
  • AngularJS
  • Python
  • C++
  • go
  • DevOps
  • Kubernetes
  • Algorithms
  • More...
    • Qt 5
    • Linux
    • FFmpeg
    • Matlab
    • Django 1.8
    • Ruby On Rails
    • HTML5 & CSS

Python - Unit Testing TDD using unittest.TestCase class 2020

python_logo




Bookmark and Share





bogotobogo.com site search:

Plan

In this chapter, we're going to write and debug a set of functions to convert to and from Hexa numbers.

We can start mapping out what a hexa.py module should do. It will have two main functions, toHexa() and fromHexa(). The toHexa() function should take an integer from 1 to 65536 and return the hexa numeral representation as a string.



TDD

We want test our function toHexa() even before we start to writing. This is so called test-driven development (TDD).

Python has a framework for unit testing named unittest module.





Requirements

The toHexa() function must return the hexa number for all integers from 1 to 65536.

# hexatest.py
import hexa      # This is the code being tested 
import unittest

class Samples(unittest.TestCase):
    pair = ( (1,'1'), (2,'2'), (3,'3'), (4,'4'), (5,'5'),
             (6,'6'), (7,'7'), (8,'8'), (9,'9'), (10,'A'),
             (11,'B'), (12,'C'), (13,'D'), (14,'E'), (15,'F'),
             (16,'10'), (30,'1E'), (127,'7F'), (255,'FF'), (500,'1F4'),
             (1024,'400'), (5100,'13EC'), (65535,'FFFF'), (65536,'10000')
           )

    def testToHexa(self):
        for d, h in self.pair:
            res =  hexa.toHexa(d);
            self.assertEqual(h, res)

if __name__ == '__main__':
    unittest.main()
  1. We subclassed the TestCase class of the unittest module:
    class Samples(unittest.TestCase):
    
    The TestCase class provides many useful methods which we can use in our test case to test specific conditions.
  2. The pair is a tuple of decimal/hexa pairs to test every possible input, but we should try to test all the obvious edge cases.
  3. Here we call the toHexa() function which hasn't been written yet, but once it is, this is the line that will call it. The toHexa() function takes an integer and return a string for hexa.
  4. The TestCase class provides a method, assertEqual(), to check whether the return value from toHexa() and haxa value of pair match. If they don't match, assertEqual() will raise an exception and the test will fail. If the two values are equal, assertEqual() will do nothing.




Start coding toHexa()

Once we have a test case, we can start coding the toHexa() function.

First, we should stub it out as an empty function and make sure the tests fail. If the tests succeed before we've written any code, our tests aren't testing our code at all. We should write a test that fails, then code until it passes.

# hexa.py
def toHexa(n)
    '''convert decimal to hexa'''
    pass

If we test run with hexatest.py, we get the following output:

$ python hexatest.py -v
testToHexa (__main__.Samples) ... FAIL

======================================================================
FAIL: testToHexa (__main__.Samples)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "hexatest.py", line 15, in testToHexa
    self.assertEqual(h, res)
AssertionError: '1' != None

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

When we run the hexatest.py script, it acually runs unittest.main(). Then, it runs each test case which is a method within a class in hexatest.py. Note that each test class must inherit from unittest.TestCase.

For each failed test case, unittest displays the trace information showing exactly what happened. In this case, the call to assertEqual() raised an AssertionError because it was expecting toHex(1) to return '1', but it didn't. That's because there was no explicit return statement, the function returned None, the Python null value.

When a test case doesn't pass, unittest distinguishes between failures and errors:

  1. A failure is a call to assertEqual or assertRaises, that fails because the asserted condition is not true or the expected exception was not raised.
  2. An error is any other sort of exception raised in the code you're testing or the unit test case itself.




Coding Decimal to Hexa
# hexa.py
def toHexa(n):
    '''convert decimal to hexa'''

    map = ('0','1','2','3','4','5','6','7','8','9',
           'A','B','C','D','E','F')

    s = ''
    while(n/16):
        s += map[n % 16]
        n = n/16

    s += map[n % 16]

    # reverse 
    return s[::-1]

Let's test the code interactively:

>>> from hexa import toHexa
>>> toHexa(10)
'A'
>>> toHexa(17)
'11'
>>> toHexa(255)
'FF'
>>> toHexa(5100)
'13EC'
>>> toHexa(65535)
'FFFF'
>>> toHexa(65536)
'10000'

At least the code passed manual test.

But will it pass the test case you wrote?

python hexatest.py -v
testToHexa (__main__.Samples) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

It passed our the test case!





Bad Input A - Negative numbers

Passing the test with good input is not enough. We should also test whether they fail when given bad input. Not just any sort of failure but they must fail in the way we expect.

The toHex() function should raise an OutOfRangeError when given an integer is negative integer. Of course we can fully implement for this negative case, but for the purpose of testing negative integer case, we didn't do it.

Here is the test case file, hexatest2.py:

# hexatest2.py
import hexa2      # This is the code being tested 
import unittest

class Samples(unittest.TestCase):
    pair = ( (1,'1'), (2,'2'), (3,'3'), (4,'4'), (5,'5'),
             (6,'6'), (7,'7'), (8,'8'), (9,'9'), (10,'A'),
             (11,'B'), (12,'C'), (13,'D'), (14,'E'), (15,'F'),
             (16,'10'), (30,'1E'), (127,'7F'), (255,'FF'), (500,'1F4'),
             (1024,'400'), (5100,'13EC'), (65535,'FFFF'), (65536,'10000') )

    def testToHexa(self):
        for d, h in self.pair:
            res =  hexa2.toHexa(d);
            self.assertEqual(h, res)

class BadSamples(unittest.TestCase):
    def testToHexaNegative(self):
        ''' toHex should fail when the input < 0'''
        self.assertRaises(hexa2.OutOfRangeError, hexa2.toHexa, -1)

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

The unittest.TestCase class provides the assertRaises method, which takes the following arguments: the exception we're expecting, the function we're testing, and the arguments we're passing to that function.

The hexa2.py has just pass:

# hexa2.py

def toHexa(n):
    '''convert decimal to hexa'''
    pass

If we run the test:

$ python hexatest2.py -v
testToHexaNegative (__main__.BadSamples)
toHex should fail when the input < 0 ... ERROR
testToHexa (__main__.Samples) ... FAIL

======================================================================
ERROR: testToHexaNegative (__main__.BadSamples)
toHex should fail when the input < 0
----------------------------------------------------------------------
Traceback (most recent call last):
  File "hexatest2.py", line 21, in testToHexaNegative
    self.assertRaises(hexa2.OutOfRangeError, hexa2.toHex, -1)
AttributeError: 'module' object has no attribute 'OutOfRangeError'

======================================================================
FAIL: testToHexa (__main__.Samples)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "hexatest2.py", line 16, in testToHexa
    self.assertEqual(h, res)
AssertionError: '1' != None

----------------------------------------------------------------------
Ran 2 tests in 0.017s

FAILED (failures=1, errors=1)

Looks like we failed. Well, the traceback tells that the module we're testing doesn't have an exception called OutOfRangeError. We passed this exception to the assertRaises() method, because it's the exception we want the function to raise given an out-of-range input. But the exception doesn't exist, so the call to the assertRaises() method failed. It never got a chance to test the toHex() function; it didn't get that far.

So, we need to modify our hexa2.py file to define the OutOfRangeError exception. Now we can write the code to make this test pass.

# hexa2.py

class OutOfRangeError(ValueError):
    pass

def toHexa(n):
    '''convert decimal to hexa'''
    if(n < 0):
        raise OutOfRangeError('number out of range, n < 0 )')

    map = ('0','1','2','3','4','5','6','7','8','9',
           'A','B','C','D','E','F')

    s = ''
    while(n/16):
        s += map[n % 16]
        n = n/16

    s += map[n % 16]

    # reverse 
    return s[::-1]

if the given input (n) is less than 0, raise an OutOfRangeError exception.

python hexatest2.py -v
testToHexaNegative (__main__.BadSamples)
toHex should fail when the input < 0 ... ok
testToHexa (__main__.Samples) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.005s

OK

The dec to hexa conversion code seems to work for big numbers. So, we're not going to check for the big numbers.





Bad Input B - Non-integers

How about the non-integer numbers:

$ python
>>> from hexa2 import toHexa
>>> toHexa(5.0)
Traceback (most recent call last):
  File "", line 1, in 
  File "hexa2.py", line 16, in toHexa
    s += map[n % 16]
TypeError: tuple indices must be integers, not float

Testing for non-integers is not tough. We need to define a NotIntegerError exception.

# hexa3.py

class OutOfRangeError(ValueError): pass
class NotIntegerError(ValueError): pass

def toHexa(n):
    '''convert decimal to hexa'''
    if(n < 0):
        raise OutOfRangeError('number out of range, n < 0 )')

    if not isinstance(n, int):
        raise NotIntegerError('non-integers can not be converted')

    map = ('0','1','2','3','4','5','6','7','8','9',
           'A','B','C','D','E','F')

    s = ''
    while(n/16):
        s += map[n % 16]
        n = n/16

    s += map[n % 16]

    # reverse 
    return s[::-1]

The hexatest3.py looks like this:

# hexatest3.py

import hexa3      # This is the code being tested 
import unittest

class Samples(unittest.TestCase):
    pair = ( (1,'1'), (2,'2'), (3,'3'), (4,'4'), (5,'5'),
             (6,'6'), (7,'7'), (8,'8'), (9,'9'), (10,'A'),
             (11,'B'), (12,'C'), (13,'D'), (14,'E'), (15,'F'),
             (16,'10'), (30,'1E'), (127,'7F'), (255,'FF'), (500,'1F4'),
             (1024,'400'), (5100,'13EC'), (65535,'FFFF'), (65536,'10000') )

    def testToHexa(self):
        for d, h in self.pair:
            res =  hexa3.toHexa(d);
            self.assertEqual(h, res)

class BadSamples(unittest.TestCase):
    def testToHexaNegative(self):
        ''' toHex should fail when the input < 0'''
        self.assertRaises(hexa3.OutOfRangeError, hexa3.toHexa, -1)

    def testToHexaNonInteger(self):
        '''to_roman should fail with non-integer input'''
        self.assertRaises(hexa3.NotIntegerError, hexa3.toHexa, 0.5)

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

Run the test case:

python hexatest3.py -v
testToHexaNegative (__main__.BadSamples)
toHex should fail when the input < 0 ... ok
testToHexaNonInteger (__main__.BadSamples)
to_roman should fail with non-integer input ... ok
testToHexa (__main__.Samples) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.005s

OK

OK. Passed!



Note: The basic idea of this chapter is borrowed from Dive into python3. Here, we used Hexa instead of Roman.





Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

YouTubeMy YouTube channel

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong







Python tutorial



Python Home

Introduction

Running Python Programs (os, sys, import)

Modules and IDLE (Import, Reload, exec)

Object Types - Numbers, Strings, and None

Strings - Escape Sequence, Raw String, and Slicing

Strings - Methods

Formatting Strings - expressions and method calls

Files and os.path

Traversing directories recursively

Subprocess Module

Regular Expressions with Python

Regular Expressions Cheat Sheet

Object Types - Lists

Object Types - Dictionaries and Tuples

Functions def, *args, **kargs

Functions lambda

Built-in Functions

map, filter, and reduce

Decorators

List Comprehension

Sets (union/intersection) and itertools - Jaccard coefficient and shingling to check plagiarism

Hashing (Hash tables and hashlib)

Dictionary Comprehension with zip

The yield keyword

Generator Functions and Expressions

generator.send() method

Iterators

Classes and Instances (__init__, __call__, etc.)

if__name__ == '__main__'

argparse

Exceptions

@static method vs class method

Private attributes and private methods

bits, bytes, bitstring, and constBitStream

json.dump(s) and json.load(s)

Python Object Serialization - pickle and json

Python Object Serialization - yaml and json

Priority queue and heap queue data structure

Graph data structure

Dijkstra's shortest path algorithm

Prim's spanning tree algorithm

Closure

Functional programming in Python

Remote running a local file using ssh

SQLite 3 - A. Connecting to DB, create/drop table, and insert data into a table

SQLite 3 - B. Selecting, updating and deleting data

MongoDB with PyMongo I - Installing MongoDB ...

Python HTTP Web Services - urllib, httplib2

Web scraping with Selenium for checking domain availability

REST API : Http Requests for Humans with Flask

Blog app with Tornado

Multithreading ...

Python Network Programming I - Basic Server / Client : A Basics

Python Network Programming I - Basic Server / Client : B File Transfer

Python Network Programming II - Chat Server / Client

Python Network Programming III - Echo Server using socketserver network framework

Python Network Programming IV - Asynchronous Request Handling : ThreadingMixIn and ForkingMixIn

Python Coding Questions I

Python Coding Questions II

Python Coding Questions III

Python Coding Questions IV

Python Coding Questions V

Python Coding Questions VI

Python Coding Questions VII

Python Coding Questions VIII

Python Coding Questions IX

Python Coding Questions X

Image processing with Python image library Pillow

Python and C++ with SIP

PyDev with Eclipse

Matplotlib

Redis with Python

NumPy array basics A

NumPy Matrix and Linear Algebra

Pandas with NumPy and Matplotlib

Celluar Automata

Batch gradient descent algorithm

Longest Common Substring Algorithm

Python Unit Test - TDD using unittest.TestCase class

Simple tool - Google page ranking by keywords

Google App Hello World

Google App webapp2 and WSGI

Uploading Google App Hello World

Python 2 vs Python 3

virtualenv and virtualenvwrapper

Uploading a big file to AWS S3 using boto module

Scheduled stopping and starting an AWS instance

Cloudera CDH5 - Scheduled stopping and starting services

Removing Cloud Files - Rackspace API with curl and subprocess

Checking if a process is running/hanging and stop/run a scheduled task on Windows

Apache Spark 1.3 with PySpark (Spark Python API) Shell

Apache Spark 1.2 Streaming

bottle 0.12.7 - Fast and simple WSGI-micro framework for small web-applications ...

Flask app with Apache WSGI on Ubuntu14/CentOS7 ...

Selenium WebDriver

Fabric - streamlining the use of SSH for application deployment

Ansible Quick Preview - Setting up web servers with Nginx, configure enviroments, and deploy an App

Neural Networks with backpropagation for XOR using one hidden layer

NLP - NLTK (Natural Language Toolkit) ...

RabbitMQ(Message broker server) and Celery(Task queue) ...

OpenCV3 and Matplotlib ...

Simple tool - Concatenating slides using FFmpeg ...

iPython - Signal Processing with NumPy

iPython and Jupyter - Install Jupyter, iPython Notebook, drawing with Matplotlib, and publishing it to Github

iPython and Jupyter Notebook with Embedded D3.js

Downloading YouTube videos using youtube-dl embedded with Python

Machine Learning : scikit-learn ...

Django 1.6/1.8 Web Framework ...


Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






OpenCV 3 image and video processing with Python



OpenCV 3 with Python

Image - OpenCV BGR : Matplotlib RGB

Basic image operations - pixel access

iPython - Signal Processing with NumPy

Signal Processing with NumPy I - FFT and DFT for sine, square waves, unitpulse, and random signal

Signal Processing with NumPy II - Image Fourier Transform : FFT & DFT

Inverse Fourier Transform of an Image with low pass filter: cv2.idft()

Image Histogram

Video Capture and Switching colorspaces - RGB / HSV

Adaptive Thresholding - Otsu's clustering-based image thresholding

Edge Detection - Sobel and Laplacian Kernels

Canny Edge Detection

Hough Transform - Circles

Watershed Algorithm : Marker-based Segmentation I

Watershed Algorithm : Marker-based Segmentation II

Image noise reduction : Non-local Means denoising algorithm

Image object detection : Face detection using Haar Cascade Classifiers

Image segmentation - Foreground extraction Grabcut algorithm based on graph cuts

Image Reconstruction - Inpainting (Interpolation) - Fast Marching Methods

Video : Mean shift object tracking

Machine Learning : Clustering - K-Means clustering I

Machine Learning : Clustering - K-Means clustering II

Machine Learning : Classification - k-nearest neighbors (k-NN) algorithm




Machine Learning with scikit-learn



scikit-learn installation

scikit-learn : Features and feature extraction - iris dataset

scikit-learn : Machine Learning Quick Preview

scikit-learn : Data Preprocessing I - Missing / Categorical data

scikit-learn : Data Preprocessing II - Partitioning a dataset / Feature scaling / Feature Selection / Regularization

scikit-learn : Data Preprocessing III - Dimensionality reduction vis Sequential feature selection / Assessing feature importance via random forests

Data Compression via Dimensionality Reduction I - Principal component analysis (PCA)

scikit-learn : Data Compression via Dimensionality Reduction II - Linear Discriminant Analysis (LDA)

scikit-learn : Data Compression via Dimensionality Reduction III - Nonlinear mappings via kernel principal component (KPCA) analysis

scikit-learn : Logistic Regression, Overfitting & regularization

scikit-learn : Supervised Learning & Unsupervised Learning - e.g. Unsupervised PCA dimensionality reduction with iris dataset

scikit-learn : Unsupervised_Learning - KMeans clustering with iris dataset

scikit-learn : Linearly Separable Data - Linear Model & (Gaussian) radial basis function kernel (RBF kernel)

scikit-learn : Decision Tree Learning I - Entropy, Gini, and Information Gain

scikit-learn : Decision Tree Learning II - Constructing the Decision Tree

scikit-learn : Random Decision Forests Classification

scikit-learn : Support Vector Machines (SVM)

scikit-learn : Support Vector Machines (SVM) II

Flask with Embedded Machine Learning I : Serializing with pickle and DB setup

Flask with Embedded Machine Learning II : Basic Flask App

Flask with Embedded Machine Learning III : Embedding Classifier

Flask with Embedded Machine Learning IV : Deploy

Flask with Embedded Machine Learning V : Updating the classifier

scikit-learn : Sample of a spam comment filter using SVM - classifying a good one or a bad one




Machine learning algorithms and concepts

Batch gradient descent algorithm

Single Layer Neural Network - Perceptron model on the Iris dataset using Heaviside step activation function

Batch gradient descent versus stochastic gradient descent

Single Layer Neural Network - Adaptive Linear Neuron using linear (identity) activation function with batch gradient descent method

Single Layer Neural Network : Adaptive Linear Neuron using linear (identity) activation function with stochastic gradient descent (SGD)

Logistic Regression

VC (Vapnik-Chervonenkis) Dimension and Shatter

Bias-variance tradeoff

Maximum Likelihood Estimation (MLE)

Neural Networks with backpropagation for XOR using one hidden layer

minHash

tf-idf weight

Natural Language Processing (NLP): Sentiment Analysis I (IMDb & bag-of-words)

Natural Language Processing (NLP): Sentiment Analysis II (tokenization, stemming, and stop words)

Natural Language Processing (NLP): Sentiment Analysis III (training & cross validation)

Natural Language Processing (NLP): Sentiment Analysis IV (out-of-core)

Locality-Sensitive Hashing (LSH) using Cosine Distance (Cosine Similarity)




Artificial Neural Networks (ANN)

[Note] Sources are available at Github - Jupyter notebook files

1. Introduction

2. Forward Propagation

3. Gradient Descent

4. Backpropagation of Errors

5. Checking gradient

6. Training via BFGS

7. Overfitting & Regularization

8. Deep Learning I : Image Recognition (Image uploading)

9. Deep Learning II : Image Recognition (Image classification)

10 - Deep Learning III : Deep Learning III : Theano, TensorFlow, and Keras









Contact

BogoToBogo
contactus@bogotobogo.com

Follow Bogotobogo

About Us

contactus@bogotobogo.com

YouTubeMy YouTube channel
Pacific Ave, San Francisco, CA 94115

Pacific Ave, San Francisco, CA 94115

Copyright © 2024, bogotobogo
Design: Web Master