Python has evolved an extensive ecosystem that makes the lives of Python programmers easier and reduces the need for reinventing the wheel. The same concept applies to the work of tool developers, even if the tools they develop do not appear in the final program. This article will introduce the developer tools that Python programmers must know.
For developers, the most practical help is to help them write code documents.
pydoc The module can generate well-formatted documentation for any importable module based on docstrings in the source code. Python includes two testing frameworks to automatically test code and verify the correctness of the code: 1) doctest module, which can extract tests from source code or stand-alone file examples Example. 2) unittest module, this module is a full-featured automated testing framework that provides test fixtures, predefined test suites and Test discovery support. The
trace module can monitor the way Python executes a program and generate a report to display the number of times each line of the program is executed. This information can be used to discover program execution paths that are not covered by the automated test set, and can also be used to study program call graphs to discover dependencies between modules. Writing and executing tests can find problems in most programs. Python makes debugging easier because in most cases, Python can print unhandled errors to the console. We call these errors The information is traceback. If the program is not run in a text console, traceback can also output error information to a log file or message dialog box. When the standard traceback cannot provide enough information, you can use the cgitb module to view detailed information in the stack and source code context at all levels, such as local variables. cgitbThe module can also output these tracking information in the form of HTML to report errors in web applications. Once you find out where the problem lies, you need to use the interactive debugger to enter the code to debug. The
pdb module can do this job well. This module can display the execution path of the program when an error occurs, and can dynamically adjust objects and code for debugging. Once the program has been tested and debugged, the next step is to turn your attention to performance. Developers can use the profile and timit modules to test the speed of the program, find out what is slow in the program, and then correct the problem. This part of the code is independently tuned for tuning. Python programs are executed through an interpreter, and the input to the interpreter is a compiled bytecode version of the original program. This bytecode compiled version can be generated dynamically when the program is executed, or it can be generated when the program is packaged. compileall The module can handle program packaging. It exposes packaging-related interfaces, which can be used by installers and packaging tools to generate files containing module bytecode. At the same time, in the development environment, the compileall module can also be used to verify whether the source file contains syntax errors. At the source code level, the
pyclbr module provides a class viewer to facilitate text editors or other programs to scan interesting characters in Python programs, such as functions or classes. After providing a class viewer, there is no need to introduce code, thus avoiding potential side effects. Documentation strings and
doctest command can detect documentation strings, and Python-related IDEs can also detect documentation strings. Since programmers tend to view docstrings in an interactive shell, it is best to keep these strings short. For example
When writing documentation, a common problem is how to keep the documentation and the actual code in sync. For example, a programmer might modify a function's implementation but forget to update the documentation. To solve this problem, we can use the doctest module. The doctest module collects docstrings, scans them, and executes them as tests. In order to use the doctest module, we usually create a new independent module for testing. For example, if the previous example Test class is contained in the file mult.py, then you should create a new testmult.py file for testing, as follows Display:
In this code, doctest.testmod(module) will execute the test of a specific module and return the number of failed tests and the total number of tests. If all tests pass, no output is produced. Otherwise, you will see a failure report showing the difference between the expected and actual values. If you want to see detailed output of the test, you can use testmod(module, verbose=True).
If you don’t want to create a separate test file, another option is to include the corresponding test code at the end of the file:
If we want to perform this type of test, we can call the doctest module with the -m option. Normally, there is no output when executing tests. If you want to see detailed information, you can add the -v option.
If we want to test the program more thoroughly, we can use the unittest module. Through unit testing, developers can write a series of independent test cases for each element that makes up the program (for example, independent functions, methods, classes, and modules). When testing larger programs, these tests can serve as building blocks to verify the correctness of the program. As our programs grow larger, unit tests for different components can be combined into larger testing frameworks and testing tools. This can greatly simplify the work of software testing and provide convenience for finding and solving software problems.
When using unit testing, we need to define a class that inherits from unittest.TestCase. In this class, each test is defined in the form of a method and named starting with test - for example, 'testsimplestring', 'testtypeconvert' and similar naming methods (it is necessary to emphasize that as long as the method name starts with test, then no matter how you name it, it is OK). Within each test, assertions can be used to check for different conditions.
Practical example:
Suppose you have a method in your program, and the output of this method points to the standard output (sys.stdout). This usually means outputting text information to the screen. If you want to test your code to prove this, just give the corresponding input and the corresponding output will be displayed.
The built-in print function sends output to sys.stdout by default. To test that the output has actually arrived, you can simulate it using a stand-in object and make assertions about the program's expected values. unittest.mockThe patch() method in the module can only replace the object in the context of running the test, and return the original state of the object immediately after the test is completed. The following is the test code for the urlprint() method:
urlprint()函数有三个参数,测试代码首先给每个参数赋了一个假值。变量expected_url包含了期望的输出字符串。为了能够执行测试,我们使用了unittest.mock.patch()方法作为上下文管理器,把标准输出sys.stdout替换为了StringIO对象,这样发送的标准输出的内容就会被StringIO对象所接收。变量fake_out就是在这一过程中所创建出的模拟对象,该对象能够在with所处的代码块中所使用,来进行一系列的测试检查。当with语句完成时,patch方法能够将所有的东西都复原到测试执行之前的状态,就好像测试没有执行一样,而这无需任何额外的工作。但对于某些Python的C扩展来讲,这个例子却显得毫无意义,这是因为这些C扩展程序绕过了sys.stdout的设置,直接将输出发送到了标准输出上。这个例子仅适用于纯Python代码的程序(如果你想捕获到类似C扩展的输入输出,那么你可以通过打开一个临时文件然后将标准输出重定向到该文件的技巧来进行实现)。# mult.py
class Test:
"""
>>> a=Test(5)
>>> a.multiply_by_2()
10
"""
def __init__(self, number):
self._number=number
def multiply_by_2(self):
return self._number*2
# testmult.py
import mult, doctest
doctest.testmod(mult, verbose=True)
# Trying:
# a=Test(5)
# Expecting nothing
# ok
# Trying:
# a.multiply_by_2()
# Expecting:
# 10
# ok
# 3 items had no tests:
# mult
# mult.Test.__init__
# mult.Test.multiply_by_2
# 1 items passed all tests:
# 2 tests in mult.Test
# 2 tests in 4 items.
# 2 passed and 0 failed.
# Test passed.
if __name__ == '__main__':
import doctest
doctest.testmod()
$ python -m doctest -v mult.py
Unit testing and unittest module
# splitter.py
import unittest
def split(line, types=None, delimiter=None):
"""Splits a line of text and optionally performs type conversion.
...
"""
fields = line.split(delimiter)
if types:
fields = [ ty(val) for ty,val in zip(types,fields) ]
return fields
class TestSplitFunction(unittest.TestCase):
def setUp(self):
# Perform set up actions (if any)
pass
def tearDown(self):
# Perform clean-up actions (if any)
pass
def testsimplestring(self):
r = split('GOOG 100 490.50')
self.assertEqual(r,['GOOG','100','490.50'])
def testtypeconvert(self):
r = split('GOOG 100 490.50',[str, int, float])
self.assertEqual(r,['GOOG', 100, 490.5])
def testdelimiter(self):
r = split('GOOG,100,490.50',delimiter=',')
self.assertEqual(r,['GOOG','100','490.50'])
# Run the unittests
if __name__ == '__main__':
unittest.main()
#...
#----------------------------------------------------------------------
#Ran 3 tests in 0.001s
#OK
# url.py
def urlprint(protocol, host, domain):
url = '{}://{}.{}'.format(protocol, host, domain)
print(url)
#urltest.py
from io import StringIO
from unittest import TestCase
from unittest.mock import patch
import url
class TestURLPrint(TestCase):
def test_url_gets_to_stdout(self):
protocol = 'http'
host = 'www'
domain = 'example.com'
expected_url = '{}://{}.{}\n'.format(protocol, host, domain)
with patch('sys.stdout', new=StringIO()) as fake_out:
url.urlprint(protocol, host, domain)
self.assertEqual(fake_out.getvalue(), expected_url)
The above is the detailed content of Developer tools that Python programmers must know. For more information, please follow other related articles on the PHP Chinese website!