There are many test runners available for Python. The three most popular test runners are:
unittest
nose or nose2
pytest
PyUnit/ unittest
The one built into the Python standard library is called unittest. In this tutorial, you will be using unittest test cases and the unittest test runner. The principles of unittest are easily portable to other frameworks.
unit-test requires that:
You put your tests into classes as methods
You use a series of special assertion methods in the unittest.TestCase class instead of the built-in assert statement
To convert the test to a unittest test case, you would have to:
Import unittest from the standard library
Create a class called TestSum that inherits from the TestCase class
Convert the test functions into methods by adding self as the first argument
Change the assertions to use the self.assertEqual() method on the TestCase class
Change the command-line entry point to call unittest.main()
Note: Be careful if you’re writing test cases that need to execute in both Python 2 and 3. In Python 2.7 and below, unittest is called unittest2. If you simply import from unittest, you will get different versions with different features between Python 2 and 3.
The Python unit testing framework, sometimes referred to as “PyUnit,” is a Python language version of Junit
unittest module 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
A test fixture represents the preparation needed to perform one or more tests, and any associate cleanup actions.
test case
A test case 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.
A test runner is an object that provides a single method, run(), which accepts a TestCase or TestSuite object as a parameter, and returns a result object. The class TestResult is provided for use as the result object. unittest provides the TextTestRunner as an example test runner which reports test results on the standard error stream by default. Alternate runners can be implemented for other environments (such as graphical environments) without any need to derive from a specific class.
PEP 8 is the Python code style guide, and it sets out rules for things like line length, indentation, multi-line expressions, and naming conventions
1. Pylint
Pylint is a library that checks for PEP 8 style violations and common errors.
can also be run from the command line.
To install, run pip install pylint.
To use Pylint from the command line, run pylint
path/to/dir or pylint [options] path/to/module.py. Pylint will output warnings about style violations and other errors to the console.
You can customize what errors Pylint checks for with a configuration file called pylintrc.
Outsource your code style
Remembering to run linters manually from the command line for each file you change is a pain,
A great solution is to use a library that automatically reformats your code into something that passes PEP 8 for you.
1.Autopep8
Autopep8 automatically formats the code in the module you specify. It will re-indent lines, fix indentation, remove extraneous whitespace, and refactor common comparison mistakes (like with booleans and None).
To install, run pip install --upgrade autopep8.
To reformat code in place, run autopep8 --in-place --aggressive --aggressive <filename>. The aggressive flags (and the number of them) indicate how much control you want to give autopep8 over your code style
Check your test coverage
You’re writing tests, right? Then you will want to make sure new code committed to your codebase is tested and doesn’t drop your overall amount of test coverage.
For measuring test coverage, we have one recommendation: Coverage.
Coverage has several options for the way it reports your test coverage to you, including outputting results to the console or to an HTML page and indicating which line numbers are missing test coverage
To install, run pip install coverage. To run a program and see its output,
run coverage run [path/to/module.py] [args], and you will see your program’s output.
To see a report of which lines of code are missing coverage, run coverage report -m.
Basics of using the logging module to record the events in a file are very simple. For that, simply import the module from the library.
Create and configure the logger. It can have several parameters. But importantly, pass the name of the file in which you want to record the events.
Here the format of the logger can also be set. By default, the file works in append mode but we can change that to write mode if required.
Also, the level of the logger can be set which acts as the threshold for tracking based on the numeric values assigned to each level. There are several attributes which can be passed as parameters.
The list of all those parameters is given in Python Library. The user can choose the required attribute according to the requirement.
After that, create an object and use the various methods as shown in the example.
#importing module
import logging
#Create and configure logger
FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(levelname)s %(message)s'
logging.basicConfig(filename="newfile.log",format= FORMAT,filemode='w')
#Creating an object
logger=logging.getLogger()
#Setting the threshold of logger to DEBUG
logger.setLevel(logging.DEBUG)
#Test messages
logger.debug("Harmless debug Message")
logger.info("Just an information")
logger.warning("Its a Warning")
logger.error("Did you try to divide by zero")
logger.critical("Internet is down")
The above code will generate a file with the provided name
Configuration:
Standard attributes names:
Attribute name
Format
Description
args
You shouldn’t need to format this yourself.
The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).
asctime
%(asctime)s
Human-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
filename
%(filename)s
Filename portion of pathname.
funcName
%(funcName)s
Name of function containing the logging call.
levelname
%(levelname)s
Text logging level for the message (‘DEBUG’, ‘INFO’, ‘WARNING’, ‘ERROR’, ‘CRITICAL’).
levelno
%(levelno)s
Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
lineno
%(lineno)d
Source line number where the logging call was issued (if available).
message
%(message)s
The logged message, computed as msg % args. This is set when Formatter.format() is invoked.
module
%(module)s
Module (name portion of filename).
msecs
%(msecs)d
Millisecond portion of the time when the LogRecord was created.
msg
You shouldn’t need to format this yourself.
The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).
name
%(name)s
Name of the logger used to log the call.
pathname
%(pathname)s
Full pathname of the source file where the logging call was issued (if available).
process
%(process)d
Process ID (if available).
processName
%(processName)s
Process name (if available).
relativeCreated
%(relativeCreated)d
Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
stack_info
You shouldn’t need to format this yourself.
Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.
First, the try clause (the statement(s) between the try and except keywords) is executed.
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then if its type matches the exception named after the except keyword, the except clause is executed, and then execution continues after the try statement.
If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above.
Syntax-
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again..
A try statement may have more than one except clause, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding try clause, not in other handlers of the same try statement. An except clause may name multiple exceptions as a parenthesized tuple, for example
except (RuntimeError, TypeError, NameError):
Order or evoking exceptions:
A class in an except clause is compatible with an exception if it is the same class or a base class thereof (but not the other way around — an except clause listing a derived class is not compatible with a base class). For example, the following code will print B, C, D in that order:
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
Note that if the except clauses were reversed (with exceptB first), it would have printed B, B, B — the first matching except clause is triggered.
Summary: an except clause can capture only those exception class which are Base(or smaller footprint than that of raise exception class)
Supreme Exception Handler:
The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way! It can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try … except statement.
Both patterns and strings to be searched can be Unicode strings as well as 8-bit strings. However, Unicode strings and 8-bit strings cannot be mixed to match a literal backslash, one might have to write ‘\\\\’ as the pattern string, because the regular expression must be \\, and each backslash must be expressed as \\ inside a regular Python string literal.
The solution is to use Python’s raw string notation for regular expression patterns; backslashes are not handled in any special way in a string literal prefixed with ‘r’. So r”\n” is a two-character string containing ‘\’ and ‘n’, while “\n” is a one-character string containing a newline
Python offers two different primitive operations based on regular expressions: re.match() checks for a match only at the beginning of the string, while re.search() checks for a match anywhere in the string.
Example:
>>> re.match("c", "abcdef") # No match
>>> re.search("c", "abcdef") # Match
however that in MULTILINE mode match() only matches at the beginning of the string, whereas using search() with a regular expression beginning with ‘^’ will match at the beginning of each line.
>>> re.match('X', 'A\nB\nX', re.MULTILINE) # No match
>>> re.search('^X', 'A\nB\nX', re.MULTILINE) # Match
For example, if one was a writer and wanted to find all of the adverbs in some text, he or she might use findall() in the following manner:
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)
['carefully', 'quickly']
Use case: parsing log file
import sys
import re
logFileName = open(sys.argv[1], "r")
putputFileName = "parsedLogOutput.txt"
outputfile = open(putputFileName, "w")
lines = logFileName.readlines()
regex = "2019-08-12 03:00:*"
compiledReg = re.compile(regex)
for line in lines:
if re.match(compiledReg, line, flags=0):
outputfile.write(line + "\n")
print(line)
Package and making a module deliverable
Each package in Python is a directory which MUST contain a special file called __init__.py. This file can be empty, and it indicates that the directory it contains is a Python package, so it can be imported the same way a module can be imported.
Example:
we create a directory called foo, which marks the package name, we can then create a module inside that package called bar. We also must not forget to add the __init__.py file inside the foo directory.
To use the module bar, we can import it in two ways:
import foo.bar
Tip:Listing functions of module:
# re is a module and following is script to list all functions:
Import re
find_members = []
for member in dir(re):
if "find" in member:
find_members.append(member)
print(sorted(find_members))
Problem Specific code snippets:
1.Run a linux command
make a command
makecmd = "ls -lrt"
# Execute the command
cwd = subprocess.Popen(makecmd, stdout=subprocess.PIPE, shell=True)
(output, err) = cwd.communicate()
# print the output
print("output: " + str(output))
File Handling
Text File
Excel File
There are different modules for handling excel file like :
XlsxWriter(only for writing),openpyxl module(rw all variation of excels),xlwtmodule, panda module
Working with xlwt- in pyhton
Step 1-Install module:
pip install xlwt
Step 2-code snippet to write to an xml and apply style:
Python Pandas is a data analysis library. It can read, filter and re-arrange small and large datasets and output them in a range of formats including Excel.
Note: If only purpose is writing to excel use native module instead of pandas which internally uses it as it will be over-burden.
Pandas writes Excel files using the XlsxWriter modules