python module learning notes

Keywords: Python server

#My QQ email authorization code: XXXXXXX
1.Python automatically sends mail
import smtplib
from email.mime.text import MIMEText
from email.header import Header

qq_host = ""  # Sending server
qq_port = "465"  # Sending server port
qq_username = ''  # Sending user name
qq_password = "XXXXXXXXX"  # Sending authorization code instead of login password
from_addr = qq_username
to_addr = ['']

msg = MIMEText('Auto send mail test', 'plain', 'utf-8')

msg['From'] = Header(",".join(to_addr))
msg['To'] = Header("chen")
msg['Subject'] = Header('python mail')

server = smtplib.SMTP_SSL(qq_host)
server.connect(qq_host, qq_port)  # Enter the server address and port number
server.login(qq_username, qq_password)  # Enter mailbox user name and authorization code
server.sendmail(from_addr, to_addr, msg.as_string())


2. Make QR code pictures
from MyQR import myqr
	# After scanning the QR code, the displayed content or jump link
	version=5,  # Set fault tolerance
	level='H',  # Control the error correction level, ranging from L, M, Q and H, increasing from left to right
	picture='tu.gif',  # The directory where the picture is located can be a moving picture
	colorized=True,  # Black and white (False) or color (True)
	contrast=1.0,  # It is used to adjust the contrast of the picture. 1.0 represents the original picture. The default is 1.0.
	brightness=1.0,  # It is used to adjust the brightness of the picture. The usage is the same as above.
	save_name='Python.gif',  # Control the output file name. The format can be. jpg,. png,. bmp,. gif

3. Absolute value
import math

# Method 1: condition judgment
def abs_value1():
	a = float(input('1.Please enter a number:'))
	if a >= 0:
		a = a
		a = -a
	print('The absolute value is:%f' % a)

# Method 2: built in function abs()
def abs_value2():
	a = float(input('2.Please enter a number:'))
	a = abs(a)
	print('The absolute value is:%f' % a)

# Method 3: built in module math
def abs_value3():
	a = float(input('3.Please enter a number:'))
	a = math.fabs(a)
	print('The absolute value is:%f' % a)

# Run the function and check it.

4.CSV module
(1) Write file
import csv
with open("demo.csv","w",newline="",encoding="utf-8") as demo :
writer = csv.writer(demo)
writer.writerow(['movie', 'Douban score'])
(2) Read file
with open("demo.csv","r",newline="",encoding="utf-8") as demo:
reader = csv.reader(demo)
for i in reader:
5. openpyxl module to operate Excel file ExcelManual
(1) Reference openpyxl module to create new workbooks and worksheets
import openpyxl
#Reference openpyxl.
wb = openpyxl.Workbook()
#To create a new workbook object is to create a new empty Excel file.
sheet =
#Is to get the activity table of this workbook, usually the first worksheet.
sheet.title = 'new title'
#You can rename the worksheet with. Title. Now the name of the first worksheet will be changed from the original default "sheet1" to "new title".

(2)Write data, operate worksheet
sheet.cell(row=1, column=1).value = "The first method"
sheet['A1'] = 'The second method' 
sheet.append(['Captain America','Iron Man','Spider-Man'])#The third method is to add at the end of the file
(3)Write multiple lines
rows = [['Captain America','Iron Man','Spider-Man'],['yes','Marvel','universe', 'classic','character']]
#First write the multi line content to be written into a list, then put it into a large list and assign it to rows.
for i in rows:
#Traverse the rows and add the traversed content to the table at the same time, so as to realize multi row writing.
#Print rows'Marvel.xlsx')
#Save the new Excel file and name it "Marvel.xlsx". Note: "after successful writing, we must remember to save this Excel file, otherwise it will be written in vain!"

(4)Write data to an existing Workbook
wb = openpyxl.load_workbook('Marvel.xlsx')#Open the workbook with the parameter file path
sheet = wb['new title']#Select form
sheetname = wb.sheetnames
A1_cell = sheet['A1']
A1_value = A1_cell.value
--------Supplementary content---------

(5)Create table( sheet)
# Method 1: insert to last (default)
ws1 = wb.create_sheet("Mysheet") 
# Mode 2: insert to the beginning
ws2 = wb.create_sheet("Mysheet", 0)

(6)Select table( sheet)
# sheet names can be indexed as key s
ws3 = wb["New Title"]
ws4 = wb.get_sheet_by_name("New Title")
ws is ws3 is ws4

(7) View table name( sheet)
# Show all table names#You must add a title to get the table name
['Sheet2', 'New Title',  'Sheet1']
# Traverse all tables
for sheet in  wb:

(8)Get all methods of the form
sheet = wb.worksheets#Get all forms return list
sheet = wb.worksheets[2]#Select one
sheet = wb["sheet1"]#

(9)How to read cells
A1_cell = sheet.cell(1,1)#Enter coordinates
A1_cell = sheet['A1']
cell_range = ws['A1':'C2']#Slice acquisition

(10)Get each row and column
sheet.rows	#It is a generator, which contains the data of each row, and each row is wrapped by a tuple.
sheet.columns	#Similar, but each tuple is the cell of each column.

(11)Gets the maximum rows and columns

(12)Get letters from numbers, get numbers from letters
from openpyxl.utils import get_column_letter, column_index_from_string
# Returns letters based on the numbers in the column
print(get_column_letter(2))  # B
# Returns the number of columns based on letters
print(column_index_from_string('D'))  # 4

(13)Delete sheet
# Mode 1
# Mode II
del wb[sheet]
(19)Cell fill color
from openpyxl.styles import PatternFill
fill = PatternFill(start_color ='FFFF00', end_color = 'FFFF00', fill_type = 'solid')  #Set cell fill yellow
# fill = PatternFill()  #Set cell to no fill
ws1.cell(row = 1, column = 1, value = 10).fill = fill
RGB Color query cross reference table link:
 Original link:

6.os module
import os
#os common methods
os.mkdir("python22") # create a new directory. Only one level directory can be created
os.makedirs('dirname1/dirname2 ') # generates multi-level recursive directories, which can create directories that do not exist at multiple levels
os.rmdir("python22") # delete an empty directory
os.remove(path) # deletes files. Only files can be deleted
Os.removediers (path) # delete empty folder
os.path.exists("python22") # judge whether the folder exists, whether the file exists, and whether the path exists. If it exists, return True; otherwise, return False
os.path.isdir("python22") # determines whether it is a directory, and returns True
os.path.isfile("py22.txt") # judge whether it is a file, and return True
path1 = os.getcwd() # get the working directory of the current file, excluding the file name
path2 = os.path.basename(file) # returns the file name
path3 = os.path.realpath(file) # return absolute path + file name
path4 = os.path.abspath(path) returns the absolute path
path5 = os.path.split(path3) # cuts the current path, cuts off the last level, and returns a tuple, which can be obtained by a[0],a[1]
path6 = os.path.dirname(path) returns the file path of the previous level, removing the first level
os.path.join(path6, "a.txt") # splice the path, and combine the directory and file name into one path
#os supplementary method
The os.unlink() method is used to delete the file and returns an error if the file is a directory.
os.path.abspath(path) returns the absolute path
os.path.basename(path) returns the file name
os.path.commonprefix(list) returns the longest path shared by all paths in the list (multiple paths)
os.path.dirname(path) returns the file path of the previous level, removing the first level
os.path.exists(path) returns True if the path path exists; False if the path does not exist.
os.path.lexists returns True if the path exists, and True if the path is corrupted
os.path.expanduser(path) converts "" and "user" contained in path into user directory
os.path.expandvars(path) replaces the variables contained in the path according to the value of the environment variable“ n a m e " and " name "and" Name "and" {name}“
os.path.getatime(path) returns the most recent access time (floating-point seconds)
os.path.getmtime(path) returns the most recent file modification time
Os.path.gettime (path) returns the creation time of the file path
os.path.getsize(path) returns the file size. If the file does not exist, it returns an error
os.path.isabs(path) determines whether it is an absolute path
os.path.isfile(path) determines whether the path is a file
os.path.isdir(path) determines whether the path is a directory
os.path.islink(path) determines whether the path is a link
os.path.ismount(path) determines whether the path is a mount point
os.path.join(path1[, path2 [,...]]) combines the directory and file name into one path
os.path.normcase(path) converts the case and slash of path
os.path.normpath(path) specifies the path string form
os.path.realpath(path) returns the real path of the path
os.path.relpath(path[, start]) calculates the relative path from start
os.path.samefile(path1, path2) determines whether the directory or file is the same
os.path.sameopenfile(fp1, fp2) determines whether fp1 and fp2 point to the same file
Os.path.sampestat (STAT1, stat2) determines whether stat tuple, STAT1 and stat2 point to the same file
os.path.split(path) divides the path into dirname and basename, and returns a tuple
os.path.splitdrive(path) is generally used in windows to return the tuple composed of drive name and path
Os.path.splittext (path) splits the path and returns the tuple of the path name and file extension
os.path.splitunc(path) divides the path into load points and files
os.path.walk(path, visit, arg) traverses the path and calls the visit function when entering each directory. The visit function must have three parameters (arg, dirname, names),
dirname represents the directory name of the current directory, names represents all file names in the current directory, and args is the third parameter of walk
os.path.supports_unicode_filenames sets whether Unicode pathnames are supported

7.requests library # extension: how to view the robots protocol of the website? It's very simple to add / robots.txt after the domain name of the website.
import requests
URL = ""

res = requests.get(URL)  
#Open the web page and add it to the res variable, or instantiate the Response object

#Print the response status code of the variable res to check whether the request is successful		

res = res.content
#Returns the contents of the Reponse object as binary data

wen = res.text
#Returns the contents of the Response object as a string

#Redefine the encoding of the Reponse object to utf-8.
#The requests library will make its own judgment on the encoding type of data.
#If the judgment is not accurate, there will be a pile of random codes, so we can check the code of the target data,
#Then use res.encoding to define the code as the type consistent with the target data.

with open("Romance of the Three Kingdoms.txt","a")as san:
#--------------Expand save a song-------------------------------------------------------------#
import requests
url = ""
res = requests.get(url)
musik = res.content

with open("English songs.mp3","wb") as m:
print("The song has been saved")

8.BeautifulSoup module parses data + extracts data
(1) Simple version code
import requests
from bs4 import BeautifulSoup

url = ''
res = requests.get (url)

#Print the response status code of the variable res to check whether the request is successful		

soup = BeautifulSoup(res.text,'html.parser')
#Parse the web page into a BeautifulSoup object

item = soup.find('div') 
#Use the find() method to extract the first < div > element and put it into the variable item.

items = soup.find_all('div') 
#Use find_all() extracts all the data that meets the requirements and puts it in the variable items

items = soup.find_all(class_='books') 
# Extract the data we want by matching tags and attributes

print(type(items)) #Print the data type of items

(2)Detailed version code  
#Note: Tag.text presents the text in the Tag object, and uses Tag['href '] to extract the URL.

import requests # Call requests Library

from bs4 import BeautifulSoup # Call the BeautifulSoup library
url = ''

res =requests.get(url)
# Return a response object and assign it to res

#Print the response status code of the variable res to check whether the request is successful	

#Redefine the encoding of the Reponse object to utf-8.

# Parse res to string

soup = BeautifulSoup( html,'html.parser')
# Parse the web page into a BeautifulSoup object

item = soup.find('div') 
#Use the find() method to extract the first < div > element and put it into the variable item.

items = soup.find_all(class_='books')   
# Extract the element we want by matching the attribute class='books'

for item in items:                # Traverse list items
	kind = item.find('h2')               
	# In each element in the list, the matching tag < H2 > extracts data
	title = item.find(class_='title')     
	#  In each element in the list, match the attribute class_='title 'extract data
	brief = item.find(class_='info')     
	# In each element in the list, match the attribute class_='info 'extract data
	# Print text for the type, name, links, and introduction of the book
#------------------For copy and paste---------------------------------------#
#Textgets the plain text information in the tag, even in its sub tag.
#However, only the value of the tag itself can be extracted when extracting the value of the attribute.
import requests
from bs4 import BeautifulSoup 
url = ""

res = requests.get(url)
html = res.text
soup = BeautifulSoup( html,'html.parser') 

items = soup.find_all(class_='books') 
for item in items:
	kind = item.find('h2')
	title = item.find(class_='title') 
	brief = item.find(class_='info') 
#------------------For copy and paste---------------------------------------#

9. Usage of request headers

import requests
url = ''
# This is the url for the song review
headers = {
	# In this case, the request source does not need to add this parameter, just for demonstration
	# The request source carries more information than "origin". In this case, this parameter is not required, but only for demonstration
	'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
	71.0.3578.98 Safari/537.36',
	# Marks the device and browser from which the request is sent
params = {
'cv':'101010  '

res_music = requests.get(url,headers=headers,params=params)
# Initiate request

10.gevent module, concurrent and asynchronous
from gevent import monkey
#Import the monkey module from the gevent library.
#monkey.patch_all() can turn the program into cooperative operation, that is, it can help the program realize asynchrony.
import gevent,time,requests
#Import gevent, time, requests
from gevent.queue import Queue
#Import queue module from gevent Library

start = time.time()

url_list = ['',

work = Queue()
#Create a queue object and assign it to work.
for url in url_list:
#Traversal url_list
	#Use put_ The nowait () function can put all the URLs in the queue.

def crawler():
	while not work.empty():
	#When the queue is not empty, execute the following procedure.
		url = work.get_nowait()
		#Use get_ The nowait () function can take out all the URLs in the queue.
		r = requests.get(url)
		#Grab the URL with the requests.get() function.
		#Print the web address, queue length, and status code of the crawl request.

tasks_list  = [ ]
#Create an empty task list
for x in range(2):
#This is equivalent to creating 2 crawlers
	task = gevent.spawn(crawler)
	#Create a task that executes the crawler() function with the gevent.spawn() function.
	#Add a task to the task list.
#Use the gevent.joinall method to perform all the tasks in the task list, that is, let the crawler start crawling the website.
end = time.time()

11.configparser configuration file
#What is a configuration file. Conf. Ini. Config. Properties. XML
#How to write a configuration file - [section] # fragment name
#option=value can also be used as option: value
#How to read configuration file - configparser
(1) Instance
from configparser import ConfigParser
#Create object, (instantiate class)
cf = ConfigParser()
#Step 1: open the file read()"lemon.conf",encoding="utf-8")
#Step 2 read the content section key: option
res = cf.get("section", "option") # gets the value of [string type]
#res = cf ["section"] ["option"] # the second method reads the value and returns [string type]

(2)Write configuration file
if not self.cp.has_section(section):  # Check whether the section exists. If so, skip if
    self.cp.add_section(section)  # If it does not exist, create a section
self.cp[section][option] = value  # Write an option=value
with open(self.file_name, "w", encoding="utf-8") as f:
    self.cp.write(f)  # Save profile

(2)Other methods
#res = cf.getint("section","option")#Returns the value of [int type]
#res = cf.getfloat("section","option")#Return the value of [floating point type] getboolean
#res = cf.getboolean("section","option")#Returns the value of boolean type
#eval() converts the data in parentheses to the original data type read the contents of the file
#cf.sections(): get all sections and return them in list form
#cf.options(section): get all options under the section
#cf.items(option): get all key value pairs of the section
#cf.get(section,option): get the value of option in the section and return the result of string type

#cf.has_section(section) # Judge whether the section exists. If it exists, it returns True. If it does not exist, it returns False
#cf.has_option("section", "option") # Judge whether the option exists. If it exists, it returns True. If it does not exist, it returns False
#cf.add_section("section") # Create a section
#cf.write(open("file_name","w",encoding="utf-8")) #preservation
#cf.remove_section("section") #All contents under the entire section will be deleted

12.logging module #p Python's own module

# DEBUG 	 The most detailed log information. The typical application scenario is problem diagnosis
# INFO 	 The level of information detail is second only to DEBUG. Usually, only the key node information is recorded to confirm that everything is working as expected
# WARNING 	 Information recorded when something unexpected happens (for example, low disk free space), but the application is still running normally
# ERROR 	 Information recorded when some functions cannot function properly due to a more serious problem
# CRITICAL 	 When a serious error occurs,

# Field / attribute name 	     Use format 	             describe
# asctime 	        % (asctime)s 	             The time of the log is constructed into a readable form. By default, it is' 2016-02-08 12:00:00123 ', accurate to milliseconds
# name 	            % (name)s 	             The name of the logger used is' root 'by default, because the rootLogger is used by default
# filename 	        % (filename)s 	         The file name of the module calling the log output function; The file name part of pathname, including the file suffix
# funcName 	        % (funcName)s 	         Which function sends the log and calls the function name of the log output function
# levelname 	        % (levelname)s 	         Final level of log (modified by filter)
# message  	        % (message)s 	             Log information, text content of log record
# lineno 	        % (lineno)d 	             The line number of the current log and the code line of the statement calling the log output function
# levelno 	        % (levelno)s 	             The log level (10, 20, 30, 40, 50) of the digital form of the log record
# pathname 	        % (pathname)s 	         Full path, the full path name of the module that calls the log output function, which may not be available
# process 	        % (process)s 	             Current process, process ID. Probably not
# processName  	    % (processName)s 	         Process name, Python 3.1 NEW
# thread 	        % (thread)s 	             Current thread, thread ID. Probably not
# threadName 	    % (thread)s 	             Thread name
# module 	        % (module)s 	             The module name of the call log output function, the name part of the filename, does not contain the suffix, that is, the text that does not contain the file suffix
											Piece name
# created 	        % (created)f 	             The current time is represented by UNIX standard floating-point number representing time; The time of the log event -- timestamp, is
											Call at that time time.time()The value returned by the function
# relativeCreated 	% (relativeCreated)d 	     The number of milliseconds since the Logger was created when outputting log information; Log events occur at a time relative to logging
											Relative milliseconds of module load time
# msecs 	            % (msecs)d 	             The millisecond portion of the log event occurrence event. The parameter datefmt is used in logging.basicConfig(), which will be removed
											asctime The millisecond part generated in can be added with this

(1)Module usage
import logging

#  Daily collector Logger default log collector root Logger
#  Log output table handlers console file txt test. log
#  1: Define a daily collector and set the level getLogger
my_logger = logging.getLogger("python22")

#  2: Specify the output channel and also set the level StreamHandLer -- to output to the console and FiLeHandLer to output to the specified file
formatter = logging.Formatter("[%(asctime)s]-[%(name)s]-[%(levelname)s]-[log information]: %(message)s")#Define log format variables

ch = logging.StreamHandler()    # Console channel
ch.setLevel('INFO')   # Level of output to console#The default output level is warning
ch.setFormatter(formatter)  # Format log

fh = logging.FileHandler("test.log" , encoding = "utf-8")  # Document channel
fh.setLevel("INFO")      # Level of output to file#The default output level is warning
fh.setFormatter(formatter)  # Format log

#  3: Docking
my_logger.addHandler(ch)  #  Docking console channel
my_logger.addHandler(fh)  #  Docking document channel

my_logger.debug("Most detailed log information")"Record key node information")
my_logger.warning("Information recorded when something unexpected happens")
my_logger.error("Information recorded when some functions cannot function properly due to a more serious problem")
my_logger.critical("Information recorded when a serious error occurs that prevents the application from continuing to run")

my_logger.removeHandler(ch)#Clear console channel information
my_logger.removeHandler(fh)#Clear file channel information

(2)log Logging rules for logs

(3)Encapsulated into classes for later use

13.unittest unit test module
(1) Write test cases
class TestAdd(unittest.TestCase): # first inherit the TestCase class in the unittest module
def test_01_add(self):
self.assertEqual(add(1,2,3),6, "failed") # assertion

	def test_02_add(self):

	def setUpClass(self):#This is the program to be executed before the use case is executed. It is usually used to load firmware
		print("Start executing use cases")

	def tearDownClass(self):#This is the program to be executed after the use case is executed. It is usually used to close the loaded firmware.
		print("end of execution")
unittest.main()#It is used to run the program and put it at the program entrance

(2)Load test cases and create test packages
#Loading method 1
import unittest
from __0918 task unittest unit testing __ import test_add

def test_add_suite():		#Build a function
	loader = unittest.TestLoader()#Instantiate the TestLoader class, which is used to load test cases
	suite = unittest.TestSuite()#Instantiate TestSuite class, which is used to create test packages and receive loaded test cases

	tests = loader.loadTestsFromModule(test_add) #1. Load test cases through the module where the test class is located
	#loader.loadTestsFromTestCase(test_add)		 #2. Load test cases through test classes. Choose one of the two methods
	suite.addTest(tests)#Load the loaded test cases into the test package
	return suite#Return test package
#Loading method 2
import os
import unittest
# Automatically discover test cases and directly load all test cases in the folder
def test_add_suite():
	loader = unittest.TestLoader()# Initialize loader
	# Auto discover test cases
	start_dir = os.path.dirname(os.path.abspath(__file__))#Folder path. The unit test case file must start with test to be found, or the library file can be changed. Non use case files should not start with test, otherwise they are easy to be executed repeatedly
	suite = path 
	return suite
(3)Execute the test case and put the execution results of the test case on the console	
import unittest
import time
import HTMLTestRunnerNew
from __0918 task unittest unit testing __.test_add_suite import test_add_suite

#Execution method 1: output test cases directly to the console
if __name__ == '__main__':
runner = unittest.TextTestRunner(verbosity=2)#Test runner,
parameter verbosity=0,1,2 Respectively represent the output information. Level 2 is the most detailed
 parameter stream=f Output information to a file. The default is output to the console test cases

#Execution method 2: output test cases to files
if __name__ == '__main__':
# with open("demo1.txt","w",encoding="utf-8") as f:
#     runner = unittest.TextTestRunner(verbosity=2,stream=f)

#Execution method 3: generate HTML Test report#You need to download the HTMLTestRunnerNew module
if __name__ == '__main__':
name_html = "Test report" + str(time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()))+".html"
#Folder names are generated dynamically based on time
with open(name_html, "wb") as f:
	runner = HTMLTestRunnerNew.HTMLTestRunner(stream=f,
											  title='Test report',
											  description='This is a test report for performing addition test cases!',
(4)Other uses 
    1.Skip execution case:
	use skipXxx Decorator to skip test cases.
	unittest A total of 3 decorators are provided:
	ļ¼ unittest.skip(reason),
	@unittest.skipIf(condition, reason) ,
	ļ¼ unittest.skipUnless(condition, reason). 
	among skip Represents unconditional skip, skipIf Representative when condition by True Skip when;
	skipUnless Representative when condition by False Skip when.
	use TestCase of skipTest() Method to skip the test case.
	#Model 1:
	@unittest.skip('Temporary skip test_02_add')
	def test_02_add(self):
	#Model 2:
	def test_02_add(self):
		self.skipTest('Temporary skip test_02_add')
	2.Preconditions and postconditions    
	def setUpClass(cls):
		print("Execute before all use cases, only once")
	def tearDownClass(cls):
		print("Execute after all use cases are executed, only once")
	def setUp(self):
		print("Execute before each use case execution")

	def tearDown(self):
		print("Execute after each use case execution")
(5)Expand, automatically generate folders, and generate dynamic file names
# The test report is placed in a report folder
# 2. Dynamically generate a file name in time
import os
from datetime import datetime

report_dir = os.path.join(start_dir, 'report')
if not os.path.exists(report_dir):#Judge whether the folder exists, and create it if it does not exist
time_str ='%Y%m%d%H%M%S')#Generate dynamic file name (time dynamic)
# report/2019-09-18-20.html
file_name = os.path.join(report_dir, time_str + '.html')
#Put file_ Just pass in the name variable

 assert methods 						Inspection conditions
assertEqual(a, b)				a == b
assertNotEqual(a, b)			a != b
assertTrue(x)					bool(x) is True
assertFalse(x)					bool(x) is False
assertIs(a, b)					a is b
assertIsNot(a, b)				a is not b
assertIsNone(x)					x is None
assertIsNotNone(x)				x is not None
assertIn(a, b)					a in b
assertNotIn(a, b)				a not in b
assertlsInstance(a, b)			isinstance(a, b)
assertNotIsInstance(a, b)		not isinstance(a, b)

(6)Detailed reference document link
	Assertion link:
	Module usage:

14.ddt module and decorator can only be used with unittest
import unittest
from ddt import ddt, data, unpack
from 0918 unittest.add import*

date_dick = [{"a": 1, "b": 1, "c": 2},
			 {"a": 2, "b": 2, "c": 4},
			 {"a": 3, "b": 3, "c": 6},
			 {"a": 4, "b": 4, "c": 8},
			 {"a": 5, "b": 5, "c": 10}]

@ddt  # Decorator, for decoration
class TestAdd(unittest.TestCase):
	@data(*date_dick)  # For decoration methods, add * to unpack and remove a layer of []
	#@unpack  #  Iteration, when removing a layer [], the decorator is not used when passing nested lists in this function
	def test_01_add(self, dick):
		self.assertEqual(add(dick["a"], dick["b"]), dick["c"])

	def setUp(self):
		print("Start executing use cases")

	def tearDown(self):
		print("end of execution")

if __name__ == "__main__":


15.mock data generation and falsification of data
(1) Generate static data
from mock import Mock
res = add(1,2) # here res=8
(2) Generate dynamic data
def demo(a,b)
return a+b

add = Mock(side_effect=demo)
res = add(3,4)  # res=a+b

16.pytest test test framework, install pip install pytest

(1) On Case Writing:
Unittest: the test class inherits unittest.TestCase
pytest: method test in function / class (Test)_ start
(2) On case collection:
unittest: testsuite installs the use case and runs it
pytest: automatically identify use cases
Rules for identifying use cases (rules for writing pytest use cases):
1) Root directory: the root directory of pytest is the directory where you run pytest
2) Files: naming: test_ * Py or *
3) Function: Class: case name: test_ test under the class starting with. test (without _init)_ The first method
(3) Use case execution sequence
1) Sort by file (ascii): for the first identified file, the use cases in it will be executed first
2) File internal - in order of code

Posted by youscript on Sun, 05 Dec 2021 16:08:15 -0800